LSTM
LSTM是Long Short Term Memory Networks 的缩写,翻译就是长的短时记忆问题。主要还是解决短时记忆问题。只不过这种短时记忆比较长,能在一定程度上解决长时依赖的问题。循环神经网络都是循环链式的结构,LSTM也不例外。LSTM在本质上和标准的RNN是一 样的,只不过LSTM内部计算更复杂,参数更多,输入输出数目也多。pytorch中有现成的LSTM网络,我们可以直接拿来用。LSTM有三个门分别是输入门、遗忘门、输出门。其中最重要的就是遗忘门,遗忘门决定哪些记忆将被长时间的保留,哪些记忆会被去掉。
LSTM网络结构:
LSTM是一个循环链式结构,其实上面这三个框是同一个框在t-1、t、t+1三个时刻。
绿色框是遗忘门:
首先将t-1时刻的网络的输出
和这一步的网络的输入
结合起来,然后做线性变化
,然后再经过sigmoid激活函数,将结果映射到0-1作为记忆衰减系数,记作
。可以看到网络具体要保存多少的记忆是由前一段时间的输出和这一刻的输入共同决定的。
红色框是输入门:
这部分主要是计算t时刻学到的记忆是如何计算的。计算如上图,也是先进行线性变换再经sigmoid函数激活。计算得到的
是当前学习到记忆的衰减系数。
是当前学习到的记忆,也是线性变换+tanh激活函数。最后将t-1时刻的衰减系数
乘t-1时刻的记忆
,加上该时刻t下学到的记忆
乘以它对应的衰减系数
.这样便得到了t时刻状态下的记忆状态
,如下图:
蓝色框是输出门:
当前时刻t的网络输出
取决于当前时刻t的记忆状态
和t时刻的输入
、t-1时刻的输出
.具体计算看上图中。
总结:
上面介绍了LSTM的内部结构的网络结构和计算方式,它和传统循环神经网络最大的不同就在于三个门,实际在每篇使用LSTM的论文中,作者都会在标准的LSTM上做稍微修改,这些变式网络结构并不村存在哪一个是最好的说法,只是针对特定的任务,特定的网络结构往往表现得更好。和LSTM使用广泛的还有GRU。
pytorch的LSTM API
class torch.nn.LSTM(*args, **kwargs)
其中参数分别是:
- input_size:输入特征维度
- hidden_size:输出特征维度
- num_layers:LSTM隐层的层数,默认为1
- bias:是否使用偏置
- batch_first:True则输入输出的数据格式为 (batch, seq, feature)
- dropout:除最后一层,每一层的输出都进行dropout:,参数范围0-1
- bidirectional:True则为双向LSTM,默认为False
代码:
import torch
import torchvision
from torchvision import transforms
from torch import nn
from torch import optim
from torch.autograd import Variable
import torch.nn.functional as F
EPOCH=10
BATCH_SIZE=100
LR=0.01
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
])
trainsets = torchvision.datasets.CIFAR10(root='./cifar10/',train=True,download=True,transform=transform)
trainloader = torch.utils.data.DataLoader(trainsets,batch_size=BATCH_SIZE,shuffle=True)
testsets = torchvision.datasets.CIFAR10(root='./cifar10',train=False,download=True,transform=transform)
test_x=Variable(torch.Tensor(testsets.data[:200]).cuda()/255)
test_y=Variable(torch.Tensor(testsets.targets[:200]).cuda())
#test_y=Variable(torch.LongTensor(testsets.targets[:200]).cuda())
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.LSTM = nn.LSTM(32*3,128,batch_first=True,num_layers=3)#将彩色图片输入给LSTM怎么办
self.line=nn.Linear(128,128)
self.output = nn.Linear(128,10)
def forward(self,x):
out,(h_n,c_n) = self.LSTM(x)
out=self.line(out[:,-1,:])
return self.output(out)
if __name__ == '__main__':
net = Net()
print('parameters:', sum(param.numel() for param in net.parameters()))#计算网络需要计算的参数量
net.cuda()
Loss = nn.CrossEntropyLoss()
Opt = optim.Adam(net.parameters(),lr=LR)
for epoch in range(EPOCH):
K=0
for step,(data,target) in enumerate(trainloader):
data = Variable(data)
target = Variable(target)
data = data.view(-1,32,32*3)
data=data.cuda()
target=target.cuda()
out = net(data)
loss = Loss(out,target)
Opt.zero_grad()
loss.backward()
Opt.step()
#print(loss)
if step%50==0:
K=K+1
test_x=test_x.view(-1,32,32*3)
test_out = net(test_x)
pred_y = torch.max(test_out, 1)[1].cuda().data
num=0
for i in range(test_y.size(0)):
if test_y[i].float()==pred_y[i].float():
num=num+1
accuracy = num / test_y.size(0)
#accuracy = torch.sum(pred_y == test_y).type(torch.FloatTensor) / test_y.size(0)
print('Epoch: ', epoch, '|K:',K,'| train loss: %.4f' % loss.data.cpu().numpy(), '| test accuracy: %.2f' % accuracy)
#print(loss.data.item())