pytorch入门10--循环神经网络(RNN)
创始人
2025-05-28 15:49:17
0

一、简要介绍
RNN适用了处理序列性的数据,并利用权重共享机制(即一个RNN网络使用多次)。序列性数据用一个例子来理解,比如我们想要预知某一天是否会下雨,我们采集了大量天数的气象信息,气象信息包括温度、气压和降雨,我们分四天为一组,前三天(用x1,x2,x3表示)就是一个序列,第四天作为已知结果,通过第四天的已知结果与模型的估计值进行比较求损失、求梯度来优化模型参数。使用序列模型的意义在于数据前后之间有一定的联系或影响,即x2的数据依赖于x1,x3的数据依赖于x2,x4的数据依赖于x3,即前三天气象信息与是否降雨对第四天有一定的影响(天气的变化是比较缓和的,很少出现断崖式的变化,所以可以根据前些天的天气预知后一天的天气)。注意,这里的x1,x2,x3是一个序列,而x1,x2,x3三个张量又各自包含三个特征值,分别表示温度、气压和天气。
除了天气、股市等信息外,自然语言也是具有序列关系的信息。

二、RNN神经网络
RNN cell本质上是一个也是线性层(Linear Layer,进行w*x+b的线性变换)。区别在于RNN cell的网络是共享的,即使用多次。
在这里插入图片描述
上图中的左边部分是RNN模型的一般书写模式,右边部分是其展开模式。,这里的X1,X2,X3,X4就是之前提到过的序列。h0可以是初始化全为0的张量。先将X1和h0(h表示hidden,即隐层)输入RNN cell(RNN 神经网络),输出结果为h1,再将x2和h1输入相同的RNN cell输入结果h2,依次类推,最终输出结果h4。可以看出h2的结果融合了x1与x2的信息,h3的结果融合了x1、x2与x3的信息,h4的结果融合了x1、x2、x3与x4的信息。
RNN网络的每一个隐藏层的具体过程:
在这里插入图片描述
input_size表示输入的维度,输入Xt先做一个线性变换,h(t-1)是上一层隐层的输出,也对其做一个线性变换,再将 两个线性变换的结果相加,最后使用激活函数tanh()使结果位于(-1,1)的区间内,ht为该隐层的输出。
实际上,两个线性运算可以写成一个线性运算:
在这里插入图片描述
RNN cell的公式:
在这里插入图片描述
三、代码实现
自定义一个RNN cell,只需输入参数input_size(即输入值的维度,即Xi有几个分量,是几维张量)和hidden_size(隐藏层的维度,即hi有几个分量)。

# 声明一个RNN cell
cell = torch.nn.RNNCell(input_size = input_size, hidden_size = hidden_size)
# 调用RNN cell,并把下列语句写下一个for循环里(实现序列多此调用RNN cell)
hidden = cell(input, hidden)

注意:input.shape为[batch, input_size],batch为批量的大小,数据集的大小,即input.shape=batch.size*input_size的二维张量,hidden.shape为[batch, hidden_size]。输出的hidden.shape为[batch, hidden_size]。
实例:
(1)使用RNN cell
RNN的输入张量的shape为[batchSize, inputSize],输出张量的维度为[batchSize, hiddenSize]。数据集(dataset)的shape定义为[seqLen,batchSize,inputSize],这里的seqLen即为序列长度。

import torchbatch_size = 1 # 批量大小
seq_len = 3
input_size = 4
hidden_size = 2cell = torch.nn.RNNCell(input_size = input_size, hidden_size = hidden_size)dataset = torch.randn(seq_len,batch_size,input_size)
hidden = torch.zeros(batch_size,hidden_size) # h0# 对dataset进行遍历,每次取出序列中的一个元素,即先取x1,再去x2,最后取x3
for idx,input in enumerate(dataset):print('=' * 20,idx,'='*20)print('Input size:',input.shape)hidden = cell(input, hidden) # cell中的hidden为上一次输出的隐层,等号左边的hidden为这一次的隐层。print('outputs size',hidden.shape)print(hidden)

(2)使用RNN
在这里插入图片描述

# num_layers表示隐层的层数(后面图解)
cell = torch.nn.RNN(input_size = input_size, hidden_size = hidden_size, num_layers= num_layers)
# 调用
out, hidden = cell(inputs,hidden) #input为输入的序列[x1,x2,x3,..,xN],input.shape为[seqLen, batch, input_size]
# cell中的hidden表示h0,out表示[h1,h1,...,hN),等号左边的hidden为hN。hidden.shape为[numLayers, batch, hidden_size]
# output.shape为[seqLen, batch, hiddden_size]

在这里插入图片描述
上图的numLayers即为3,表示三层隐藏层,同一种颜色的RNN cell为同一层(其实同一种颜色是同一个RNN cell)。

import torchbatch_size = 1 # 批量大小
seq_len = 3
input_size = 4
hidden_size = 2
num_layers = 1cell = torch.nn.RNN(input_size = input_size, hidden_size = hidden_size,num_layers=num_layers)inputs = torch.zeros(seq_len,batch_size,input_size)
hidden = torch.zeros(num_layers,batch_size,hidden_size)out, hidden = cell(inputs,hidden)print('Output size:', output.size)
print('Output:', output)
print('Hidden size:', hidden.size)
print('Hidden:', hidden) 

四、实例
在这里插入图片描述
训练目标,将输入的“hello"经过RNN网络根据每一个隐藏层的结果输出为“ohlol”。
1.将单词转化为张量
使用独热(one-hot)编码:
在这里插入图片描述
对于hello的每一个字符都对应一个索引值,将hello转化为索引值得数组,再根据独热编码得方法转化为等长得向量,可以用一个一维含四个特征值得张量表示。注意每一次RNNcell输出的hi是一个含有四个元素的张量,通过softmax函数决定是输出结果是e,h,l,o中的哪一类:
在这里插入图片描述

import torchinput_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_sizeself.input_size = input_sizeself.hidden_size = hidden_sizeself.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# 生成初始的h0def init_hidden(self):return torch.zeros(self.batch_size,self.hidden_size)net = Model(input_size,hidden_size,batch_size)# 损失函数
criterion = torch.nn.CrossEntryLoss()
# 优化器
optimizer = torch.optim.Adam(net.parameters(),lr=0.1)# 训练模型
for epoch in range(15):loss = 0optimizer.zero_grad()hidden = net.init_hidden()print("Predicted stringL:",end='')for input,label in zip(inputs,labels):hidden = net(input,hidden)loss += criterion(hidden,label)_,idx = hiddden.max(dim=1)print(idx2char[idx.item()],end='')loss.backward()optimizer.step()print(',Epoch[%d/15] loss=%.4f' % (epoch+1,loss.item()))

使用RNN的书写形式:

# 定义模型
class Model(torch.nn.Module):def __init__(self,input_size,hidden_size,batch_size,numlayers=1):super(Model,self).__init__()self.numlayers = num_layersself.batch_size = batch_sizeself.input_size = input_sizeself.hidden_size = hidden_sizeself.rnn = torch.nn.RNN(input_size = self.input_size,hidden_size=self.hidden_size,num_layers = num_layers)def forward(self,input):hidden = torch.zeros(self.num_layers,self.batch_size,slef.hidden_size)out,_=self.rnn(input,hidden)return out.view(-1,self.hidden_size) # out.shape为[seqLen*batchSize,hiddenSize]# 生成初始的h0def init_hidden(self):return torch.zeros(self.batch_size,self.hidden_size)net = Model(input_size,hidden_size,batch_size)
# 损失函数
criterion = torch.nn.CrossEntryLoss()
# 优化器
optimizer = torch.optim.Adam(net.parameters(),lr=0.1)# 训练模型
for epoch in range(15):optimizer.zero_grad()outputs = net(inputs)loss = criterion(outputs,labels)loss.backwrd()optimizer.step()_,idx= outputs.max(dim=1)idx = idx.data.numpy()

2.使用嵌入层代替独热编码(embedding)
独热编码有许多缺点,维度大、张量稀疏、是硬编码(不是通过提取特征得到的)。因此想到使用低维的(lower-dimension),稠密的(dense),学习到的张量(learn from data)。
embedding即把一个高位的、稀疏的样本映射到一个低维的、稠密的空间(即数据降维):
在这里插入图片描述
加入嵌入层后:
在这里插入图片描述

加入嵌入层的网络结构:

# 参数
num_class = 4
input_size = 4
hidden_size = 8
embedding_size = 10
num_layers = 2
batch_size = 1
seq_len = 5#准备数据
idx2char = ['e','h','l','o']
x_data = [1,0,2,2,3]
y_data = [3,1,2,3,2]inputs = torch.LongTensor(x_data)
labels = torch.LongTensor(y_data).view(-1,1)class Model(torch.nn.Module):def __init__(self):super(Model,self).__init__()self.emb = torch.nn.Embedding(input_size,embedding_size) # 加入嵌入层,self.emb.shape为[inputSize,embeddingSize]self.rnn = torch.nn.RNN(input_size =embedding_size,hidden_size=self.hidden_size,num_layers = num_layers,batch_first=True)# batch_first=True时input.shape为[batchSize,seqLen,embeddingSize],# output.shape为[batchSize,seqLen,hiddenSize] self.fc = torch.nn.Linear(hidden_size,num_class) # 完成输出类别的变换def forward(self,x):hidden = torch.zeros(num_layers,x.size(0),slef.hidden_size)x = self.emb(x)x,_=self.rnn(x,hidden)x =self.fc(x)return x.view(-1,num_class) # out.shape为[seqLen*batchSize,hiddenSize]# 生成初始的h0def init_hidden(self):return torch.zeros(self.batch_size,self.hidden_size)

相关内容

热门资讯

关于先进个人主要事迹材料 关于先进个人主要事迹材料  在我们平凡的日常里,说到事迹,大家肯定都不陌生吧,事迹是为了表扬先进、弘...
办贷款收入证明范本 办贷款收入证明范本  办贷款收入证明范本(精选15篇)  在日常学习、工作抑或是生活中,说到证明,大...
消防安全检查简报 消防安全检查简报(精选6篇)  在日新月异的现代社会中,大家总少不了接触一些耳熟能详的简报吧,简报不...
中学生一日常规 中学生一日常规1、每天各班值日生早到校15分钟,打扫卫生,其他同学到校后立即到教室内学习。不准玩耍或...
个人先进的事迹材料 个人先进的事迹材料(精选5篇)  在学习、工作、生活中,大家对事迹材料都不陌生吧,事迹材料可以起到宣...
袁隆平的优秀事迹 袁隆平的优秀事迹  个人事迹的写法  个人事迹首先需要表明个人的基本信息,主要包括姓名,性别,出生日...
公司差旅管理制度 公司差旅管理制度  在社会发展不断提速的今天,大家逐渐认识到制度的重要性,制度是要求成员共同遵守的规...
班级管理方案 班级管理方案范文(通用10篇)  为保证事情或工作高起点、高质量、高水平开展,我们需要提前开始方案制...
高考录取通知 高考录取通知模板合集5篇  在发展不断提速的社会中,用到通知的地方越来越多,通知大多属于知照性的下行...
销售部工作管理制度 销售部工作管理制度  现如今,制度的使用频率呈上升趋势,制度具有使我们知道,应该做什么,不应该做什么...
全国卫生专业技术资格考试网上... 全国卫生专业技术资格考试网上报名系统  2017年卫生专业技术资格考试网上报名、现场确认、网上缴费的...
医院卫生消毒制度 医院卫生消毒制度  在生活中,需要使用制度的场合越来越多,制度是各种行政法规、章程、制度、公约的总称...
店铺财务管理制度 店铺财务管理制度(通用7篇)  在快速变化和不断变革的今天,我们每个人都可能会接触到制度,制度是要求...
酒店安全疏散设施管理制度内容 酒店安全疏散设施管理制度内容  安全疏散设施是酒店重要的消防安全设备,加强对安全疏散设施的管理,确保...
乐于助人事迹材料 乐于助人事迹材料  在平平淡淡的学习、工作、生活中,大家对事迹材料都再熟悉不过了吧,事迹材料属于事务...
优秀教师的事迹材料 优秀教师的事迹材料范文2000字(精选5篇)  在日常学习、工作和生活中,大家都写过事迹材料,肯定对...
单位车辆管理制度 单位车辆管理制度  为合理有效使用车辆,最大限度节约成本,提高使用效率,并确保车辆安全、良好地运行特...
写论文的格式 写一篇论文的格式1 题名1.1 题名的概念  题名,又叫文题、题目、标题(或称“总标题”,以区别于“...
火锅店厨房管理制度 火锅店厨房管理制度  在现在的社会生活中,越来越多人会去使用制度,制度是在一定历史条件下形成的法令、...
车辆维修管理制度 车辆维修管理制度范本(精选11篇)  在不断进步的社会中,制度使用的频率越来越高,制度就是在人类社会...