循环神经网络(基础篇)Basic_RNN用于处理具有时间序列的数据的问题,采用权重共享的概念来减少需要训练的权重的数量
举例:用前三天的温度、气压、是否下雨,去预测第四天是否下雨,RNN擅长处理带时间序列关系的数据。
实际上我们要考虑x1(第一天的天气状况)、x2(第二天的天气状况)、x3(第三天的天气状况)之间的时间序列的关系,因为第二天的天气状况跟第一天的天气有很大程度的关系,部分以来前一天的天气。
自然语言,金融股市等等,都是根据时间序列的数据,因此我们要采用RNN来处理。
一、RNN Cell
RNN的本质是一个线性层linear,只不过我们是采用共享权重的方式不断地使用一个线性层,将时序数据x1、x2、x3、x4送进 RNN Cell,只不过我们再将x2送进线性层的同时顺手把隐藏层的输出hi一起传回到线性层linear。以此类推,循环计算x3、x4
对于x1也是如此,需要一个h0,如果我们有先验知识,我们就把先验知识作为h0送给RNN,例如我们想通过图像来生成文本,我们就用CNN+fc(全连接测层)生成h0来作为输入。
如果我们没有先验知识我们就把h0设置成与h1、h2。。。都一样的维度。
这些图里的RNN Cell是同一个线性层,拿时序中的不同数据循环的用一个线性层进行计算,因此权重是共享权重。
采用一个线性层不断地循环计算,采用for函数的形式。
下图是RNN Cell具体的计算过程,xt的维度为_,−的维度是_,
在pytorch的框架中,由两种实现RNN的方法,一种是利用RNN Cell,然后自己去写for循环,第二种是利用RNN模块
调用RNN Cell模块需要的参数有两个,
一个是输入数据的特征的维度_、一个是隐藏层的维度_
cell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size)
#调用cell
hidden = cell(input, hidden)
input当前某一个时刻输入值的维度,hidden当前时刻的隐层的维度
举个例子
cell = torch.nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers)
#调用
out, hidden = cell(inputs, hidden)
inputs是全部序列的输入的维度,hidden是所有隐藏层的隐层维度,如下
RNN的唯独参数的配置,和输入的维度,隐层的维度,输出的维度
RNN的结构如下图所示。
举例子
在RNN中还存在其他参数设置 batch_first,
batch_first: if True, the input and output tensors are provided as: ℎ,,_
训练一个序列到序列的转换“hello”-> “ohlol”,因为字符没法往神经网络中输入,所以我们首先先将字符向量化,先根据字符构造一个字典
注意:input与inputs的维度,label与labels的维度
我们想要求每一行最大的列标号,我们就要指定dim=1,表示我们不要列了,保留行的size就可以了。
假如我们想求每一列的最大行标,就可以指定dim=0,表示我们不要行了。
结果:
代码
import torch
input_size = 4
hidden_size = 4
batch_size = 1
idx2char = ['e', 'h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [3, 1, 2, 3, 2]
one_hot_lookup = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
x_one_hot = [one_hot_lookup[x] for x in x_data]
inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
labels = torch.LongTensor(y_data).view(-1, 1)
class Model(torch.nn.Module):
def __init__(self, input_size, hidden_size, batch_size):
super(Model, self).__init__()
self.batch_size = batch_size
self.input_size = input_size
self.hidden_size = hidden_size
self.rnncell = torch.nn.RNNCell(input_size=self.input_size,
hidden_size=self.hidden_size)
def forward(self, input, hidden):
hidden = self.rnncell(input, hidden)
return hidden
def init_hidden(self):
return torch.zeros(self.batch_size,
self.hidden_size)
net = Model(input_size, hidden_size, batch_size)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.1)
if __name__ == '__main__':
for epoch in range(15):
loss = 0
optimizer.zero_grad()
hidden = net.init_hidden()
print('Predicted string: ', end='')
for input, label in zip(inputs, labels):
hidden = net(input, hidden)
loss += criterion(hidden, label)
_, idx = hidden.max(dim=1)
print(idx2char[idx.item()], end='')
loss.backward()
optimizer.step()
print(', Epoch [%d/15] loss=%.4f' % (epoch+1, loss.item()))
import torch
input_size = 4
hidden_size = 4
batch_size = 1
num_layers = 1
seq_len = 5
idx2char = ['e', 'h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [3, 1, 2, 3, 2]
one_hot_lookup = [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
x_one_hot = [one_hot_lookup[x] for x in x_data]
inputs = torch.Tensor(x_one_hot).view(seq_len , batch_size, input_size)
labels = torch.LongTensor(y_data)
class Model(torch.nn.Module):
def __init__(self, input_size, hidden_size, batch_size, num_layers=1):
super(Model, self).__init__()
self.num_layers =num_layers
self.batch_size = batch_size
self.input_size = input_size
self.hidden_size = hidden_size
self.rnn = torch.nn.RNN(input_size=self.input_size,
hidden_size=self.hidden_size,
num_layers=self.num_layers)
def forward(self, input):
hidden = torch.zeros(self.num_layers,
self.batch_size,
self.hidden_size)
out, _ = self.rnn(input, hidden)
return out.view(-1, self.hidden_size)
net = Model(input_size, hidden_size, batch_size, num_layers)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.05)
if __name__ == '__main__':
for epoch in range(15):
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
_, idx = outputs.max(dim=1)
idx = idx.data.numpy()
print('Predicted: ', ''.join([idx2char[x] for x in idx]), end='')
print(', Epoch [%d/15] loss = %.3f' % (epoch + 1, loss.item()))