使用pytorch框架nn.RNN实现循环神经网络

首先,读取周杰伦专辑歌词数据集。

import time
import math
import numpy as np
import torch
from torch import nn, optim
import torch.nn.functional as Fimport sys
sys.path.append("..") device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
def load_data_jay_lyrics():"""加载周杰伦歌词数据集"""with zipfile.ZipFile('../../data/jaychou_lyrics.txt.zip') as zin:with zin.open('jaychou_lyrics.txt') as f:corpus_chars = f.read().decode('utf-8')corpus_chars = corpus_chars.replace('\n', ' ').replace('\r', ' ')corpus_chars = corpus_chars[0:10000]idx_to_char = list(set(corpus_chars))char_to_idx = dict([(char, i) for i, char in enumerate(idx_to_char)])vocab_size = len(char_to_idx)corpus_indices = [char_to_idx[char] for char in corpus_chars]return corpus_indices, char_to_idx, idx_to_char, vocab_size(corpus_indices, char_to_idx, idx_to_char, vocab_size) = load_data_jay_lyrics()

定义模型

PyTorch中的nn模块提供了循环神经网络的实现。下面构造一个含单隐藏层、隐藏单元个数为256的循环神经网络层rnn_layer:

num_hiddens = 256
# rnn_layer = nn.LSTM(input_size=vocab_size, hidden_size=num_hiddens) # 已测试
rnn_layer = nn.RNN(input_size=vocab_size, hidden_size=num_hiddens)

这里rnn_layer的输入形状为(时间步数, 批量大小, 输入个数)。

  • 其中输入个数即one-hot向量长度(词典大小)。
  • rnn_layer作为nn.RNN实例,在前向计算后会分别返回输出和隐藏状态h
    • 其中输出指的是隐藏层在各个时间步上计算并输出的隐藏状态,它们通常作为后续输出层的输入。该“输出”本身并不涉及输出层计算,形状为(时间步数, 批量大小, 隐藏单元个数)
    • nn.RNN实例在前向计算返回的隐藏状态指的是隐藏层在最后时间步的隐藏状态:当隐藏层有多层时,每一层的隐藏状态都会记录在该变量中;
    • 对于像长短期记忆(LSTM),隐藏状态是一个元组(h, c),即hidden state和cell state。

循环神经网络(LSTM)的输出如下:

输出形状为(时间步数, 批量大小, 隐藏单元个数),隐藏状态h的形状为(层数, 批量大小, 隐藏单元个数)。

num_steps = 35
batch_size = 2
state = None
X = torch.rand(num_steps, batch_size, vocab_size)
Y, state_new = rnn_layer(X, state)
print(Y.shape, len(state_new), state_new[0].shape)

输出:

torch.Size([35, 2, 256]) 1 torch.Size([2, 256])

如果rnn_layer是nn.LSTM实例,继承Module类来定义一个完整的循环神经网络。

  • 它首先将输入数据使用one-hot向量表示后输入到rnn_layer中
  • 然后使用全连接输出层得到输出。
  • 输出个数等于词典大小vocab_size。
def one_hot(x, n_class, dtype=torch.float32): # X shape: (batch), output shape: (batch, n_class)x = x.long()res = torch.zeros(x.shape[0], n_class, dtype=dtype, device=x.device)res.scatter_(1, x.view(-1, 1), 1)return resdef to_onehot(X, n_class):  # X shape: (batch, seq_len), output: seq_len elements of (batch, n_class)return [one_hot(X[:, i], n_class) for i in range(X.shape[1])]class RNNModel(nn.Module):def __init__(self, rnn_layer, vocab_size):super(RNNModel, self).__init__()self.rnn = rnn_layerself.hidden_size = rnn_layer.hidden_size * (2 if rnn_layer.bidirectional else 1) self.vocab_size = vocab_sizeself.dense = nn.Linear(self.hidden_size, vocab_size)self.state = Nonedef forward(self, inputs, state): # inputs: (batch, seq_len)# 获取one-hot向量表示X = to_onehot(inputs, self.vocab_size) # X是个listY, self.state = self.rnn(torch.stack(X), state)# 全连接层会首先将Y的形状变成(num_steps * batch_size, num_hiddens),它的输出# 形状为(num_steps * batch_size, vocab_size)output = self.dense(Y.view(-1, Y.shape[-1]))return output, self.state

训练模型

定义一个预测函数

def predict_rnn_pytorch(prefix, num_chars, model, vocab_size, device, idx_to_char,char_to_idx):state = Noneoutput = [char_to_idx[prefix[0]]] # output会记录prefix加上输出for t in range(num_chars + len(prefix) - 1):X = torch.tensor([output[-1]], device=device).view(1, 1)if state is not None:if isinstance(state, tuple): # LSTM, state:(h, c)  state = (state[0].to(device), state[1].to(device))else:   state = state.to(device)(Y, state) = model(X, state)if t < len(prefix) - 1:output.append(char_to_idx[prefix[t + 1]])else:output.append(int(Y.argmax(dim=1).item()))return ''.join([idx_to_char[i] for i in output])

使用权重为随机值的模型来预测一次。

model = RNNModel(rnn_layer, vocab_size).to(device)
predict_rnn_pytorch('分开', 10, model, vocab_size, device, idx_to_char, char_to_idx)

实现训练函数

def data_iter_consecutive(corpus_indices, batch_size, num_steps, device=None):if device is None:device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')corpus_indices = torch.tensor(corpus_indices, dtype=torch.float32, device=device)data_len = len(corpus_indices)batch_len = data_len // batch_sizeindices = corpus_indices[0: batch_size*batch_len].view(batch_size, batch_len)epoch_size = (batch_len - 1) // num_stepsfor i in range(epoch_size):i = i * num_stepsX = indices[:, i: i + num_steps]Y = indices[:, i + 1: i + num_steps + 1]yield X, Ydef grad_clipping(params, theta, device):norm = torch.tensor([0.0], device=device)for param in params:norm += (param.grad.data ** 2).sum()norm = norm.sqrt().item()if norm > theta:for param in params:param.grad.data *= (theta / norm)def train_and_predict_rnn_pytorch(model, num_hiddens, vocab_size, device,corpus_indices, idx_to_char, char_to_idx,num_epochs, num_steps, lr, clipping_theta,batch_size, pred_period, pred_len, prefixes):loss = nn.CrossEntropyLoss()optimizer = torch.optim.Adam(model.parameters(), lr=lr)model.to(device)state = Nonefor epoch in range(num_epochs):l_sum, n, start = 0.0, 0, time.time()data_iter = data_iter_consecutive(corpus_indices, batch_size, num_steps, device) # 相邻采样for X, Y in data_iter:if state is not None:# 使用detach函数从计算图分离隐藏状态, 这是为了# 使模型参数的梯度计算只依赖一次迭代读取的小批量序列(防止梯度计算开销太大)if isinstance (state, tuple): # LSTM, state:(h, c)  state = (state[0].detach(), state[1].detach())else:   state = state.detach()(output, state) = model(X, state) # output: 形状为(num_steps * batch_size, vocab_size)# Y的形状是(batch_size, num_steps),转置后再变成长度为# batch * num_steps 的向量,这样跟输出的行一一对应y = torch.transpose(Y, 0, 1).contiguous().view(-1)l = loss(output, y.long())optimizer.zero_grad()l.backward()# 梯度裁剪grad_clipping(model.parameters(), clipping_theta, device)optimizer.step()l_sum += l.item() * y.shape[0]n += y.shape[0]try:perplexity = math.exp(l_sum / n)except OverflowError:perplexity = float('inf')if (epoch + 1) % pred_period == 0:print('epoch %d, perplexity %f, time %.2f sec' % (epoch + 1, perplexity, time.time() - start))for prefix in prefixes:print(' -', predict_rnn_pytorch(prefix, pred_len, model, vocab_size, device, idx_to_char,char_to_idx))
num_epochs, batch_size, lr, clipping_theta = 250, 32, 1e-3, 1e-2 # 注意这里的学习率设置
pred_period, pred_len, prefixes = 50, 50, ['分开', '不分开']
train_and_predict_rnn_pytorch(model, num_hiddens, vocab_size, device,corpus_indices, idx_to_char, char_to_idx,num_epochs, num_steps, lr, clipping_theta,batch_size, pred_period, pred_len, prefixes)

(pytorch-深度学习)使用pytorch框架nn.RNN实现循环神经网络相关推荐

  1. 深度学习入门(五十六)循环神经网络——循环神经网络RNN

    深度学习入门(五十六)循环神经网络--循环神经网络RNN 前言 循环神经网络--循环神经网络RNN 课件 潜变量自回归模型 循环神经网络 使用循环神经网络的语言模型 困惑度(perplexity) 梯 ...

  2. 深度学习入门(六十四)循环神经网络——编码器-解码器架构

    深度学习入门(六十四)循环神经网络--编码器-解码器架构 前言 循环神经网络--编码器-解码器架构 课件 重新考察CNN 重新考察RNN 编码器-解码器架构 总结 教材 1 编码器 2 解码器 3 合 ...

  3. PyTorch 深度学习:38分钟快速入门——RNN 做图像分类

    RNN 特别适合做序列类型的数据,那么 RNN 能不能想 CNN 一样用来做图像分类呢?下面我们用 mnist 手写字体的例子来展示一下如何用 RNN 做图像分类,但是这种方法并不是主流,这里我们只是 ...

  4. TensorFlow 2.0深度学习算法实战教材---第11章 循环神经网络

    人工智能的强力崛起,可能是人类历史上最好的事情,也可能是最糟糕的事情.−史蒂芬•霍金 卷积神经网络利用数据的局部相关性和权值共享的思想大大减少了网络的参数量,非常适合于图片这种具有空间(Spatial ...

  5. pytorch深度学习框架—torch.nn模块(一)

    pytorch深度学习框架-torch.nn模块 torch.nn模块中包括了pytorch中已经准备好的层,方便使用者调用构建的网络.包括了卷积层,池化层,激活函数层,循环层,全连接层. 卷积层 p ...

  6. pytorch深度学习框架--gpu和cpu的选择

    pytorch深度学习框架–gpu和cpu的选择 基于pytorch框架,最近实现了一个简单的手写数字识别的程序,我安装的pytorch是gpu版(你也可以安装cpu版本的,根据个人需要),这里我介绍 ...

  7. pytorch深度学习简介(包括cnn,rnn等我只挑我感觉有必要记录)

    一,深度学习基础 1. 了解常见的四个机器学习方法 监督学习.无监督学习.半监督学习.强化学习是我们日常接触到的常见的四个机器学习方法: 监督学习:通过已有的训练样本(即已知数据以及其对应的输出)去训 ...

  8. 人工智能:PyTorch深度学习框架介绍

    目录 1.PyTorch 2.PyTorch常用的工具包 3.PyTorch特点 4.PyTorch不足之处 今天给大家讲解一下PyTorch深度学习框架的一些基础知识,希望对大家理解PyTorch有 ...

  9. Pytorch深度学习(2) -- RNN及其进阶模型实现 ( GRU LSTM Deep-Rnn Bi-Rnn)

    Pytorch深度学习(2) -- RNN及其进阶模型实现 0 预测训练函数 1.RNN实现 RNN小结 2.GRU实现 GRU小结 3.LSTM实现 LSTM小结 4.Deep-RNN 加入参数nu ...

最新文章

  1. 《树莓派渗透测试实战》——总结
  2. linux下编辑aacc.sh脚本命令,Shell命令实战详解
  3. 全国计算机等级考试题库二级C操作题100套(第12套)
  4. C#趣味程序---求两个数的最大公约数和最小公倍数
  5. 设计抗住千万级流量的架构思路(转)
  6. Git学习(2)Git 安装
  7. 三列自适应布局(圣杯布局)
  8. Odoo免费开源MES功能应用简介
  9. 史上最全破解安卓APK和反编译
  10. 为什么使用Linux
  11. 深入浅出ES6的标准内置对象Proxy
  12. cloudera mysql_安装cloudera manager使用mysql作为元数据库
  13. 制作世界人口地图json--10.4学习日记
  14. 这几年我看过的书,力荐书单(含技术和非技术)
  15. 数字计算机模拟人脑,人造突触问世 计算机模拟人脑不是梦
  16. python类初始化返回实例_Python基础——类、实例及初始化
  17. Spring(eclipse)简要笔记
  18. 公司要新招美女跟我学docker,你来吗?
  19. 《保健养生》---保健专家齐国力[2]
  20. 新手小白如何精准引流?新手小白精准引流思路

热门文章

  1. hbase java api最新版本_HBase基本命令与新版本Java API
  2. netty cpu 占用率 高_Netty 是如何支撑高性能网络通信的?
  3. 计算机管理中添加用户属性,如何在计算机右键菜单栏中添加属性选项
  4. 不在 sudoers 文件中。此事将被报告_快餐包装中检出致癌物质?麦当劳、汉堡王回应!...
  5. 接口500什么原因_80%小餐饮店几乎都“活“不过500天,为什么?都在这5个原因里...
  6. layui option 动态添加_layui select动态添加option的实例
  7. easyexcel导出百万级数据_百万级别数据Excel导出优化
  8. python打印长方形_利用python打印出菱形、三角形以及矩形的方法实例
  9. java重定向链接页面变小_java web的进来看一下!页面重定向的异常!帮忙看一下!谢谢了!...
  10. pdf无法启动因计算机丢失,解决打开 PDF 文件时出现的文档损坏错误