鱼C论坛

 找回密码
 立即注册
查看: 2855|回复: 0

[学习笔记] RNN:循环神经网络

[复制链接]
发表于 2022-10-9 17:23:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Handsome_zhou 于 2022-10-11 10:09 编辑

循环神经网络是用于序列数据分析的神经网络,
比如:  1)情感分类
          2)机器翻译
          3)序列标注




1101.jpg

上图为循环神经网络的5种不同架构,从左到右:
第一幅图是一个输入(单一标签)对应一个输出(单一标签),即“one to one”方式;第二幅图为一个输入对应多个输出,即“one to many”方式,这种网络架构广泛用于图片的对象识别领域,即输入的是一张图片,输出的是一个文本序列;
第三幅图是多个输入对应一个输出,即“many to one”方式,这种网络架构广泛用于文本分类或视频片段分类的任务,输入的是视频或文本集合,输出的是类别标签;
第四幅图是多个输入对应有间隔的多个输出,即第一种“many to many”方式,这种网络架构就是机器翻译系统,输入的是一种语言的文本,输出的是另一种语言的文本;
第五幅图是多个输入严格对应多个输出,即第二种“many to many”方式,这种网络架构就是NLP中广泛使用的序列标注任务。

应用小例:文本序列的下一个字符预测任务以及时间序列预测任务:

字符预测任务
  1. import torch
  2. from torch import nn
  3. from torch.nn import functional as F
  4. from d2l import torch as d2l

  5. #数据
  6. batch_size, num_steps = 32, 35
  7. train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)

  8. #超参数
  9. num_hiddens = 256
  10. rnn_layer = nn.RNN(len(vocab), num_hiddens)
  11. state = torch.zeros((1, batch_size, num_hiddens))

  12. X = torch.rand(size=(num_steps, batch_size, len(vocab)))
  13. Y, state_new = rnn_layer(X, state)


  14. class RNNModel(nn.Module):
  15.     def __init__(self, rnn_layer, vocab_size, **kwargs):
  16.         super(RNNModel, self).__init__(**kwargs)
  17.         self.rnn = rnn_layer
  18.         self.vocab_size = vocab_size
  19.         self.num_hiddens = self.rnn.hidden_size

  20.         if not self.rnn.bidirectional:
  21.             self.num_directions = 1
  22.             self.linear = nn.Linear(self.num_hiddens, self.vocab_size)
  23.         else:
  24.             self.num_directions = 2
  25.             self.linear = nn.Linear(self.num_hiddens * 2, self.vocab_size)

  26.     def forward(self, inputs, state):
  27.         X = F.one_hot(inputs.T.long(), self.vocab_size)
  28.         X = X.to(torch.float32)
  29.         Y, state = self.rnn(X, state)

  30.         output = self.linear(Y.reshape((-1, Y.shape[-1])))
  31.         return output, state

  32.     def begin_state(self, device, batch_size=1):
  33.         if not isinstance(self.rnn, nn.LSTM):

  34.             return torch.zeros((self.num_directions * self.rnn.num_layers,
  35.                                 batch_size, self.num_hiddens),
  36.                                device=device)
  37.         else:
  38.             return (torch.zeros((self.num_directions * self.rnn.num_layers,
  39.                                  batch_size, self.num_hiddens), device=device),
  40.                     torch.zeros((self.num_directions * self.rnn.num_layers,
  41.                                  batch_size, self.num_hiddens), device=device))


  42. device = d2l.try_gpu()
  43. net = RNNModel(rnn_layer, vocab_size=len(vocab))
  44. net = net.to(device)
  45. result = d2l.predict_ch8('time traveller', 10, net, vocab, device)
  46. print(result)
复制代码

901.jpg



时间序列预测任务
  1. import torch
  2. from torch import nn
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. from torch.autograd import Variable

  6. TIME_STEP = 10  # rnn time step
  7. INPUT_SIZE = 1  # rnn input size
  8. LR = 0.02  # learning rate

  9. #数据
  10. steps = np.linspace(0, np.pi*2, 100, dtype=np.float32)  # float32 for converting torch FloatTensor,生成等间距数组。0到2pi生成100个数
  11. x_np = np.sin(steps)  # 100个数的sin值
  12. y_np = np.cos(steps)  # 100个数的cos值
  13. plt.plot(steps, y_np, 'r_', label='target (cos)')
  14. plt.plot(steps, x_np, 'b_', label='input (sin)')
  15. plt.legend(loc='best')
  16. plt.show()


  17. class RNN(nn.Module):  # 搭建RNN框架
  18.     def __init__(self):
  19.         super(RNN, self).__init__()

  20.         self.rnn = nn.RNN(   # 设置超参数
  21.             input_size=INPUT_SIZE,  #编码大小为1
  22.             hidden_size=32,   #RNN隐藏单元个数为32,hidden_state有32个神经元
  23.             num_layers=1,   # 层数为1
  24.             batch_first=True,  # batch的维度放在第一个
  25.         )
  26.         self.out = nn.Linear(32, 1) #输出层是一个32个输入1个输出的MLP

  27.     #定义前向传播函数
  28.     def forward(self, x, h_state):
  29.         # x (batch_size, time_step, input_size)
  30.         # h_state (n_layers, batch, hidden_size)
  31.         # r_out (batch, time_step, output_size), output_size就是hidden_size
  32.         r_out, h_state = self.rnn(x, h_state)  # 得到更新后的隐状态及输出,输入为之前的记忆和新来的x

  33.         outs = []
  34.         for time_step in range(r_out.size(1)):
  35.             outs.append(self.out(r_out[:, time_step, :]))  # 每个时间点输出一次,到output过一下。将结果存到outs当中。输出列表append每一个时间步的输出就是rnn的总的输出
  36.         return torch.stack(outs, dim=1), h_state  #将list格式的outs转换成tensor格式
  37.    

  38. rnn = RNN()
  39. print(rnn)

  40. #定义优化器,损失函数
  41. optimizer = torch.optim.Adam(rnn.parameters(), lr=LR)
  42. loss_func = nn.MSELoss()
  43. #初始化隐状态
  44. h_state = None

  45. plt.figure(1, figsize=(12, 5))
  46. plt.ion()

  47. #开始训练
  48. for step in range(100):
  49.     start, end = step * np.pi, (step+1)*np.pi

  50.     steps = np.linspace(start, end, TIME_STEP, dtype=np.float32, endpoint=False)  # 取10个点
  51.     x_np = np.sin(steps)  # 获得10个点的sin值
  52.     y_np = np.cos(steps)  # 获得10个点的cos值

  53.     x = Variable(torch.from_numpy(x_np[np.newaxis, :, np.newaxis]))   # 加维度:形状(batch, time_step, input_size)
  54.     y = Variable(torch.from_numpy(y_np[np.newaxis, :, np.newaxis]))

  55.     prediction, h_state = rnn(x, h_state)

  56.     h_state = Variable(h_state.data)   # !!!通过这一步重新将h_state.data包成Variable的形式


  57.     loss = loss_func(prediction, y)
  58.     optimizer.zero_grad()
  59.     loss.backward()
  60.     optimizer.step()

  61.     #plotting
  62.     plt.plot(steps, y_np.flatten(), 'r-')
  63.     plt.plot(steps, prediction.data.numpy().flatten(), 'b-')
  64.     plt.draw(); plt.pause(0.05)


  65. plt.ioff()
  66. plt.show()
复制代码

902.jpg
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-14 00:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表