目录

一 Liner

二 RNN

三 LSTM

四 LSTM 代码例子


概念介绍可以参考:[深度学习]理解RNN, GRU, LSTM 网络

Pytorch中所有模型分为构造参数和输入和输出构造参数两种类型。

  • 模型构造参数主要限定了网络的结构,如对循环网络,则包括输入维度、隐层\输出维度、层数;对卷积网络,无论卷积层还是池化层,都不关心输入维度,其构造方法只涉及卷积核大小\步长等。这里的参数决定了模型持久化后的大小.
  • 输入和输出的构造参数一般和模型训练相关,都需指定batch大小,seq大小(循环网络)\chanel大小(卷积网络),以及输入\输出维度,如果是RNN还需涉及h0和c0的初始化等。这里的参数决定了模型训练效果。

一 Liner

  • Liner(x_dim,y_dim)
    – 输入x,程序输入(batch,x)
    – 输出y, 程序输出(batch,y)
import torch
import torch.nn as nn
from torch.autograd import Variable as V
line =  nn.Linear(2, 4)  # 输入2维,输出4维
print(line)
print(line.weight) # 参数是随机初始化的,维度为out_dim * in_dim

x = V(torch.randn(5,2)) # batch为5,即一次输入10个x
print(x)
line(x)  # 输出为batch*4

二 RNN

对于不同的网络层,输入的维度虽然不同,但是通常输入的第一个维度都是batch_size,比如torch.nn.Linear的输入(batch_size,in_features),torch.nn.Conv2d的输入(batch_size,  ,)。而RNN的输入却是(seq_len, batch_size, input_size),batch_size位于第二维度!虽然你可以将batch_size和序列长度seq_len对换位置,此时只需要把batch_first设置为True。但是默认情况下RNN输入为啥不是batch first?原因同上,因为cuDNN中RNN的API就是batch_size在第二维度!进一步,为啥cuDNN要这么做呢?

因为batch first意味着模型的输入(一个Tensor)在内存中存储时,先存储第一个sequence,再存储第二个... 而如果是seq_len first,模型的输入在内存中,先存储所有序列的第一个单元,然后是第二个单元... 两种区别如下图所示:

seq_len first意味着不同序列中同一个时刻对应的输入单元在内存中是毗邻的,这样才能做到真正的batch计算。

CNN中和RNNbatchSize的默认位置是不同的。

  • CNN中:batchsize的位置是position 0.
  • RNN中:batchsize的位置是position 1.

首先介绍一下什么是rnn,rnn特别擅长处理序列类型的数据,因为他是一个循环的结构

一个序列的数据依次进入网络A,网络A循环的往后传递。

这里输入X一般是一个sequence, 如[我 爱 上海 小笼包]

对于最简单的 RNN,我们可以使用下面两种方式去调用,分别是 torch.nn.RNNCell() 和 torch.nn.RNN(),这两种方式的区别在于 RNNCell() 只能接受序列中单步的输入,且必须传入隐藏状态,而 RNN() 可以接受一个序列的输入,默认会传入全 0 的隐藏状态,也可以自己申明隐藏状态传入。

  1. 输入大小是三维tensor[seq_len,batch_size,input_dim]
  • input_dim是输入的维度,比如是128
  • batch_size是一次往RNN输入句子的数目,比如是5
  • seq_len是一个句子的最大长度,比如15
    所以千万注意,RNN输入的是序列,一次把批次的所有句子都输入了,得到的ouptuthidden都是这个批次的所有的输出和隐藏状态,维度也是三维。
    **可以理解为现在一共有batch_size个独立的RNN组件,RNN的输入维度是input_dim,总共输入seq_len个时间步,则每个时间步输入到这个整个RNN模块的维度是[batch_size,input_dim]

# 构造RNN网络,x的维度5,隐层的维度10,网络的层数2
rnn_seq = nn.RNN(5, 10,2)
# 构造一个输入序列,长为 6,batch 是 3, 特征是 5
x = V(torch.randn(6, 3, 5))
#out,ht = rnn_seq(x, h0) # h0可以指定或者不指定
out,ht = rnn_seq(x)
# q1:这里out、ht的size是多少呢? out:6*3*10, ht:2*3*10

问题1:这里outhtsize是多少呢?
回答out:6 * 3 * 10, ht: 2 * 3 * 10,out的输出维度[seq_len,batch_size,output_dim],ht的维度[num_layers * num_directions, batch, hidden_size],如果是单向单层的RNN那么一个句子只有一个hidden
问题2out[-1]ht[-1]是否相等?
回答:相等,隐藏单元就是输出的最后一个单元,可以想象,每个的输出其实就是那个时间步的隐藏单元

这就是RNN的基本结构类型。而最早的RNN模型,序列依次进入网络中,之前进入序列的数据会保存信息而对后面的数据产生影响,所以RNN有着记忆的特性,而同时越前面的数据进入序列的时间越早,所以对后面的数据的影响也就越弱,简而言之就是一个数据会更大程度受到其临近数据的影响。但是我们很有可能需要更长时间之前的信息,而这个能力传统的RNN特别弱,于是有了LSTM这个变体。

三 LSTM

这就是LSTM的模型结构,也是一个向后传递的链式模型,而现在广泛使用的RNN其实就是LSTM,序列中每个数据传入LSTM可以得到两个输出,而这两个输出和序列中下一个数据一起又作为传入LSTM的输入,然后不断地循环向后,直到序列结束。

注意共4个非线性变化。其中三个sigmoid变化分别对应的三个门:遗忘门f、输入门(当前状态)i、输出门o。这三个门的取值为[0,1],可以看做选择系数可以很好的控制信息的传导。

LSTM参数

  • input_size 表示的是输入的数据维数
  • hidden_size 表示的是输出维数
  • num_layers 表示堆叠几层的LSTM,默认是1
  • bias True 或者 False,决定是否使用bias, False则b_h=0. 默认为True
  • batch_first True 或者 False,因为nn.lstm()接受的数据输入是(序列长度,batch,输入维数),这和我们cnn输入的方式不太一致,所以使用batch_first,我们可以将输入变成(batch,序列长度,输入维数)
  • dropout 表示除了最后一层之外都引入一个dropout,
  • bidirectional 表示双向LSTM,也就是序列从左往右算一次,从右往左又算一次,这样就可以两倍的输出

LSTM数据格式:

  • num_layers: 我们构建的循环网络有几层lstm

  • num_directions: 当bidirectional=True时,num_directions=2;当bidirectional=False时,num_directions=1

LSTM  Input 数据格式

  LSTM输入的X数据格式尺寸为(seq_len, batch, input_size),此外h0和c0尺寸如下

  • h0(num_layers * num_directions,  batch_size,  hidden_size)

  • c0(num_layers * num_directions,  batch_size,  hidden_size)

LSTM  Output 数据格式

  LSTM输出数据格式尺寸为(seq_len, batch, hidden_size * num_directions);输出的hn和cn尺寸如下

  • hn(num_layers * num_directions,  batch_size,  hidden_size)

  • cn(num_layers * num_directions,  batch_size,  hidden_size)

LSTM的输出多了一个memory单元

# 输入维度 50,隐层100维,两层
lstm_seq = nn.LSTM(50, 100, num_layers=2)
# 输入序列seq= 10,batch =3,输入维度=50
lstm_input = torch.randn(10, 3, 50)
out, (h, c) = lstm_seq(lstm_input) # 使用默认的全 0 隐藏状态

问题1out(h,c)的size各是多少?
回答out:(10 * 3 * 100),(h,c):都是(2 * 3 * 100)
问题2out[-1,:,:]h[-1,:,:]相等吗?
回答: 相等


四 LSTM 代码例子

Example 1

# 输入维度 50,隐层100维,两层
lstm_seq = nn.LSTM(50, 100, num_layers=2)
# 查看网络的权重,ih和hh,共2层,所以有四个要学习的参数
print(lstm_seq.weight_hh_l0.size())
print(lstm_seq.weight_ih_l0.size())
print(lstm_seq.weight_hh_l1.size())
print(lstm_seq.weight_ih_l1.size())
# q1: 输出的size是多少?#torch.Size([400, 100])
#torch.Size([400, 50])
#torch.Size([400, 100])
#torch.Size([400, 100])
# 输入序列seq= 10,batch =3,输入维度=50
lstm_input = V(torch.randn(10, 3, 50))
out, (h, c) = lstm_seq(lstm_input) # 使用默认的全 0 隐藏状态
# q1:out和(h,c)的size各是多少?out:(10*3*100),(h,c):都是(2*3*100)
print(out.shape, h.shape, c.shape)#torch.Size([10, 3, 100]) torch.Size([2, 3, 100]) torch.Size([2, 3, 100])

Example 2

通过这样定义一个一层的LSTM输入是10,输出是30

from torch.autograd import Variable
lstm = nn.LSTM(10, 30, batch_first=True)
print(lstm.weight_hh_l0.size())
print(lstm.weight_ih_l0.size())
print(lstm.bias_hh_l0.size())
print(lstm.bias_ih_l0.size())#torch.Size([120, 30])
#torch.Size([120, 10])
#torch.Size([120])
#torch.Size([120])

可以分别得到权重的维数,注意之前我们定义的4个weights被整合到了一起,比如这个lstm,输入是10维,输出是30维,相对应的weight就是30x10,这样的权重有4个,然后pytorch将这4个组合在了一起,方便表示,也就是lstm.weight_ih_l0,所以它的维数就是120x10

我们定义一个输入

x = Variable(torch.randn((50, 100, 10)))
h0 = Variable(torch.randn(1, 50, 30))
c0 = Variable(torch.randn(1, 50 ,30))
  • x的三个数字分别表示batch_size为50,序列长度为100,每个数据维数为10
  • h0的第二个参数表示batch_size为50,输出维数为30,第一个参数取决于网络层数和是否是双向的,如果双向需要乘2,如果是多层,就需要乘以网络层数
  • c0的三个参数和h0是一致的
out, (h_out, c_out) = lstm(x, (h0, c0))

这样就可以得到网络的输出了,和上面讲的一致,另外如果不传入h0和c0,默认的会传入相同维数的0矩阵

这就是我们如何在pytorch上使用RNN的基本操作了,了解完最基本的参数我们才能够使用其来做应用。


Example 3

使用单向LSTM进行MNIST分类

import torch
from torch import nn
from torch.autograd import Variable
import torchvision.datasets as datasets
import torchvision.transforms as transforms
import numpy as np
import matplotlib.pyplot as plt# 超参数
EPOCH = 1
BATCH_SIZE = 64
TIME_STEP = 28  # rnn time step  / image height
INPUT_SIZE = 28  # rnn input size / image width
LR = 0.01
DOWNLOWD_MNIST = False  # 如果没有下载好MNIST数据,设置为True# 下载数据
# 训练数据
train_data = datasets.MNIST(root='./mnist', train=True, transform=transforms.ToTensor(), download=DOWNLOWD_MNIST)
train_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)# 测试数据
test_data = datasets.MNIST(root='./mnist', train=False, transform=transforms.ToTensor())
test_x = Variable(test_data.test_data).type(torch.FloatTensor)[:2000] / 255.
test_y = np.squeeze(test_data.test_labels.numpy())[:2000]class RNN(nn.Module):def __init__(self):super(RNN, self).__init__()self.rnn = nn.LSTM(input_size=INPUT_SIZE,hidden_size=64,num_layers=2,  # hidden_layer的数目batch_first=True,  # 输入数据的维度一般是(batch, time_step, input),该属性表征batch是否放在第一个维度)self.out = nn.Linear(64, 10)def forward(self, x):# rnn 运行的结果出了每层的输出之外,还有该层要传入下一层进行辅助分析的hidden state,# lstm 的hidden state相比于 RNN,其分成了主线h_n,分线h_cr_out, (h_n, h_c) = self.rnn(x, None)  # x shape ( batch, step, input_size), None 之前的hidden state(没有则填None)out = self.out(r_out[:, -1, :])  # 选取最后一个时刻的output,进行最终的类别判断return outrnn = RNN()
# print(rnn)# 优化器
optimizer = torch.optim.Adam(rnn.parameters(), lr=LR)
# 误差函数
loss_func = nn.CrossEntropyLoss()
for epoch in range(EPOCH):for step, (x, y) in enumerate(train_loader):b_x = Variable(x.view(-1, 28, 28))  # reshape x to (batch, time_step, input_size)b_y = Variable(y)output = rnn(b_x)loss = loss_func(output, b_y)optimizer.zero_grad()loss.backward()optimizer.step()if step % 50 == 0:test_output = rnn(test_x)pred_y = np.squeeze(torch.max(test_output, 1)[1].data.numpy())accuracy = float((pred_y == test_y).astype(int).sum()) / float(test_y.size)print('Epoch: ', epoch, ' | train loss: %.4f' % loss.data.numpy(), ' | test accuracy: %.2f' % accuracy )

# 输出前10个测试数据的测试值
test_output = rnn(test_x[: 10].view(-1, 28, 28))
pred_y = np.squeeze(torch.max(test_output, 1)[1].data.numpy())
print(pred_y, 'prediction number')
print(test_y[:10], 'real number')

由上面代码可以看到输出为:output,(h_n,c_n)=self.rnn(x)

更多的RNN的应用可以看这个资源

[深度学习] Pytorch中RNN/LSTM 模型小结相关推荐

  1. 动手学深度学习(PyTorch实现)(八)--AlexNet模型

    AlexNet模型 1. AlexNet模型介绍 1.1 AlexNet的特点 1.2 AlexNet的结构 1.3 AlexNet参数数量 2. AlexNet的PyTorch实现 2.1 导入相应 ...

  2. [深度学习] PyTorch 实现双向LSTM 情感分析

    一  前言 情感分析(Sentiment Analysis),也称为情感分类,属于自然语言处理(Natural Language Processing,NLP)领域的一个分支任务,随着互联网的发展而兴 ...

  3. 利用深度学习进行生存分析——DeepSuv模型小结

    生存分析是一种典型的医疗时间事件(time-event)分析场景,其主要分析序列研究中事件(如复发.死亡.治愈等)随着时间变化的统计规律,从而发现其中的敏感/危险因子. 其经典的统计学手段主要有: ( ...

  4. 动手学深度学习(PyTorch实现)(七)--LeNet模型

    LeNet模型 1. LeNet模型 2. PyTorch实现 2.1 模型实现 2.2 获取数据与训练 1. LeNet模型 LeNet分为卷积层块和全连接层块两个部分.下面我们分别介绍这两个模块. ...

  5. 动手学深度学习(PyTorch实现)(十三)--ResNet模型

    ResNet模型 1. ResNet介绍 2. ResNet结构 3. ResNet的PyTorch实现 3.1 导入所需要的包 3.2 构建ResNet网络 3.3 开始训练 注:本文部分内容参考博 ...

  6. 动手学深度学习(PyTorch实现)(十一)--GoogLeNet模型

    GoogLeNet模型 1. GoogLeNet介绍 1.1 背景 1.2 GoogLeNet网络结构 2. PyTorch实现 2.1 导入相应的包 2.2 定义Inception块结构 2.3 定 ...

  7. 动手学深度学习(PyTorch实现)(九)--VGGNet模型

    VGGNet模型 1. VGGNet模型介绍 1.1 VGGNet的结构 1.2 VGGNet结构举例 2. VGGNet的PyTorch实现 2.1 导入相应的包 2.2 基本网络单元block 2 ...

  8. 动手学深度学习(PyTorch实现)(十)--NiN模型

    NiN模型 1. NiN模型介绍 1.1 NiN模型结构 1.2 NiN结构与VGG结构的对比 2. PyTorch实现 2.1 导入相应的包 2.2 定义NiN block 2.3 全局最大池化层 ...

  9. 深度学习------pytorch,RNN:句子预测,股票预测

    1. torch股票预测 import torch import torch.nn as nn from torch.autograd import Variable import numpy as ...

最新文章

  1. 【Java8新特性】关于Java8的Stream API,看这一篇就够了!!
  2. 《趣学Python编程》——2.3 使用变量
  3. eclipse mysql 线程池_JAVA5线程池使用
  4. 隔行换色案例||全选和全不选||QQ表情选择||多选下拉列表左右移动
  5. MySQL中如何查询数据(上)
  6. SQLite AND/OR 运算符(http://www.w3cschool.cc/sqlite/sqlite-and-or-clauses.html)
  7. django学习笔记之forloop
  8. linux内核分析与移植,内核分析移植
  9. 关于tensorflow2.0的弊端
  10. Java基于Redis的分布式锁
  11. 浅析foreach原理
  12. 学计算机 数学日记,数学日记3篇
  13. php挑战答题,挑战答题小程序5.3.1开源
  14. 软件测试缺陷报告的5c标准
  15. jzoj2555 雾雨魔理沙
  16. 《神雕侠侣》古墓派玉女功养生修炼
  17. 程序员必知的编程5祖师爷,不要说你不知道!
  18. Linux编程基础案例:第4章Shell编程
  19. xp系统总是弹出宽带连接服务器,如何处理xp电脑总是弹出宽带连接
  20. aac蓝牙编解码协议_「干货」蓝牙耳机编码格式(SBC、AAC、aptX)都有啥区别?...

热门文章

  1. hibernate 出现Could not parse mapping document from resource 报错
  2. mysql多线程查询_MySQL 利用多线程提升查询性能的一种思路
  3. 226. Invert Binary Tree 1
  4. (笔记)java环境变量设置
  5. android R.id.转化为view
  6. 写文件头的算法流程及C代码实现
  7. file_get_contents()采集不到原因
  8. 用asp.net 2.0实现网站二级域名(转)
  9. Ubuntu16.04 php7.0+mysql5.7+apache2环境搭配
  10. android支持色彩管理软件,安卓首家!OPPO全链路色彩管理系统亮相:全局支持10bit照片视频...