使用torch实现RNN
(本文对https://blog.csdn.net/out_of_memory_error/article/details/81456501的结果进行了复现。)
在实验室的项目遇到了困难,弄不明白LSTM的原理。到网上搜索,发现LSTM是RNN的变种,那就从RNN开始学吧。
带隐藏状态的RNN可以用下面两个公式来表示:

可以看出,一个RNN的参数有W_xh,W_hh,b_h,W_hq,b_q和H(t)。其中H(t)是步数的函数。
参考的文章考虑了这样一个问题,对于x轴上的一列点,有一列sin值,我们想知道它对应的cos值,但是即使sin值相同,cos值也不同,因为输出结果不仅依赖于当前的输入值sinx,还依赖于之前的sin值。这时候可以用RNN来解决问题
用到的核心函数:torch.nn.RNN() 参数如下:
input_size – 输入
x的特征数量。hidden_size – 隐藏层的特征数量。
num_layers – RNN的层数。
nonlinearity – 指定非线性函数使用
tanh还是relu。默认是tanh。bias – 如果是
False,那么RNN层就不会使用偏置权重 $b_ih$和$b_hh$,默认是Truebatch_first – 如果
True的话,那么输入Tensor的shape应该是[batch_size, time_step, feature],输出也是这样。dropout – 如果值非零,那么除了最后一层外,其它层的输出都会套上一个
dropout层。bidirectional – 如果
True,将会变成一个双向RNN,默认为False。
下面是代码:
# encoding:utf-8
import torch
import numpy as np
import matplotlib.pyplot as plt # 导入作图相关的包
from torch import nn # 定义RNN模型
class Rnn(nn.Module):
def __init__(self, INPUT_SIZE):
super(Rnn, self).__init__() # 定义RNN网络,输入单个数字.隐藏层size为[feature, hidden_size]
self.rnn = nn.RNN(
input_size=INPUT_SIZE,
hidden_size=32,
num_layers=1,
batch_first=True # 注意这里用了batch_first=True 所以输入形状为[batch_size, time_step, feature]
)
# 定义一个全连接层,本质上是令RNN网络得以输出
self.out = nn.Linear(32, 1) # 定义前向传播函数
def forward(self, x, h_state):
# 给定一个序列x,每个x.size=[batch_size, feature].同时给定一个h_state初始状态,RNN网络输出结果并同时给出隐藏层输出
r_out, h_state = self.rnn(x, h_state)
outs = []
for time in range(r_out.size(1)): # r_out.size=[1,10,32]即将一个长度为10的序列的每个元素都映射到隐藏层上.
outs.append(self.out(r_out[:, time, :])) # 依次抽取序列中每个单词,将之通过全连接层并输出.r_out[:, 0, :].size()=[1,32] -> [1,1]
return torch.stack(outs, dim=1), h_state # stack函数在dim=1上叠加:10*[1,1] -> [1,10,1] 同时h_state已经被更新 TIME_STEP = 10
INPUT_SIZE = 1
LR = 0.02 model = Rnn(INPUT_SIZE)
print(model) loss_func = nn.MSELoss() # 使用均方误差函数
optimizer = torch.optim.Adam(model.parameters(), lr=LR) # 使用Adam算法来优化Rnn的参数,包括一个nn.RNN层和nn.Linear层 h_state = None # 初始化h_state为None for step in range(300):
# 人工生成输入和输出,输入x.size=[1,10,1],输出y.size=[1,10,1]
start, end = step * np.pi, (step + 1)*np.pi steps = np.linspace(start, end, TIME_STEP, dtype=np.float32)
x_np = np.sin(steps)
y_np = np.cos(steps) x = torch.from_numpy(x_np[np.newaxis, :, np.newaxis])
y = torch.from_numpy(y_np[np.newaxis, :, np.newaxis]) # 将x通过网络,长度为10的序列通过网络得到最终隐藏层状态h_state和长度为10的输出prediction:[1,10,1]
prediction, h_state = model(x, h_state)
h_state = h_state.data # 这一步只取了h_state.data.因为h_state包含.data和.grad 舍弃了梯度
# 反向传播
loss = loss_func(prediction, y)
optimizer.zero_grad()
loss.backward() # 优化网络参数具体应指W_xh, W_hh, b_h.以及W_hq, b_q
optimizer.step() # 对最后一次的结果作图查看网络的预测效果
plt.plot(steps, y_np.flatten(), 'r-')
plt.plot(steps, prediction.data.numpy().flatten(), 'b-')
plt.show()
最后一步预测和实际y的结果作图如下:

可看出,训练RNN网络之后,对网络输入一个序列sinx,能正确输出对应的序列cosx
使用torch实现RNN的更多相关文章
- PyTorch官方中文文档:torch.nn
torch.nn Parameters class torch.nn.Parameter() 艾伯特(http://www.aibbt.com/)国内第一家人工智能门户,微信公众号:aibbtcom ...
- pytorch实现rnn并且对mnist进行分类
1.RNN简介 rnn,相比很多人都已经听腻,但是真正用代码操练起来,其中还是有很多细节值得琢磨. 虽然大家都在说,我还是要强调一次,rnn实际上是处理的是序列问题,与之形成对比的是cnn,cnn不能 ...
- 从网络架构方面简析循环神经网络RNN
一.前言 1.1 诞生原因 在普通的前馈神经网络(如多层感知机MLP,卷积神经网络CNN)中,每次的输入都是独立的,即网络的输出依赖且仅依赖于当前输入,与过去一段时间内网络的输出无关.但是在现实生活中 ...
- [PyTorch] rnn,lstm,gru中输入输出维度
本文中的RNN泛指LSTM,GRU等等 CNN中和RNN中batchSize的默认位置是不同的. CNN中:batchsize的位置是position 0. RNN中:batchsize的位置是pos ...
- Pytorch基础——使用 RNN 生成简单序列
一.介绍 内容 使用 RNN 进行序列预测 今天我们就从一个基本的使用 RNN 生成简单序列的例子中,来窥探神经网络生成符号序列的秘密. 我们首先让神经网络模型学习形如 0^n 1^n 形式的上下文无 ...
- pytorch RNN层api的几个参数说明
classtorch.nn.RNN(*args, **kwargs) input_size – The number of expected features in the input x hidde ...
- 【学习笔记】RNN算法的pytorch实现
一些新理解 之前我有个疑惑,RNN的网络窗口,换句话说不也算是一个卷积核嘛?那所有的网络模型其实不都是一个东西吗?今天又听了一遍RNN,发现自己大错特错,还是没有学明白阿.因为RNN的窗口所包含的那一 ...
- DeepLearning常用库简要介绍与对比
网上近日流传一张DL相关库在Github上的受关注度对比(数据应该是2016/03/15左右统计的): 其中tensorflow,caffe,keras和Theano排名比较靠前. 今日组会报告上tj ...
- pytorch, LSTM介绍
本文中的RNN泛指LSTM,GRU等等 CNN中和RNN中batchSize的默认位置是不同的. CNN中:batchsize的位置是position 0. RNN中:batchsize的位置是pos ...
随机推荐
- SpringBoot踩坑日记
1.Closing JPA EntityManagerFactory for persistence unit 'default'错误导致springboot启动后终止 --------------- ...
- python中几个双下划线用法的含义
_ _ init() _ _(self[,...]) 我们有时在类定义写__init()__方法,但是有时又没有.__init()__方法相当于其他面向对象的编程语言中的构造方法,也就是类在实例化成对 ...
- LTE常用标识和参数
1 基本标识 1 .1 IMSI 1.2 IMEI 1.3 MSISDN 1.4 TMSI 1.5 MSRN 2 区域类标识 2.1 GCI 其中 LA是GSM(2g)中的位置区,对应4G中的跟踪区T ...
- JVM调优总结(四)-分代垃圾回收详述
为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...
- [计划任务 - dos]制作任务工具
语法 schtasks /create /tn TaskName /tr TaskRun /sc schedule [/mo modifier] [/d day] [/m month[,month.. ...
- 【Python】自己写日志功能
Python有自带的logging模块,用于日志记录,功能很强大,但不好用,使用挺麻烦的,而且发现了几个bug,调用了一个logger.warning()一次,结果日志文件中出现了n行记录,且逐渐变成 ...
- 重学 Java 设计模式:实战适配器模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 擦屁屁纸80%的面积都是保护手的! 工作到3年左右很大一部分程序员都想提升自己的技术 ...
- Java实现 LeetCode 456 132模式
456. 132模式 给定一个整数序列:a1, a2, -, an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj ...
- Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
算法提高 陶陶摘苹果2 时间限制:1.0s 内存限制:256.0MB 问题描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出n个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳, ...
- 第七届蓝桥杯JavaA组国(决)赛部分真题
解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.阶乘位数 阶乘位数 9的阶乘等于:362880 它的二进制表示为:1011000100110000000 这个数字共有19位. 请你计 ...