torch学习(六) rnn package

本文详细介绍了深度学习框架的安装与使用,重点阐述了RNN和LSTM的训练流程与原理,并通过实例展示了如何利用RNN进行语言模型训练,以及如何使用Sequencer封装RNN来提高预测效率。此外,文章还概述了LSTM的基本公式与实现方式,为读者提供了深入理解深度学习的基础知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、安装
luarocks install moses
luarocks install fs
luarocks install dpnn
luarocks install rnn

二、使用rnn训练语言模型
1.训练rnn
到example目录下面执行:
recurrent-language-model.lua --cuda --useDevice 2 --progress --zeroFirst --cutoffNorm 4 --rho 10

下载的语料:~/data
结果和日志存在用户的~目录下面

三、RNN
(一)、AbstractRecurrent
Recurrent和LSTM的抽象类
rnn  = nn. AbstractRecurrent(rho)
参数rho表示BPTT的最大步数。

(二)、Recurrent
1. nn.Recurrent(start, input, feedback, [transfer, rho, merge])
start:如果是size表示隐层大小,等鉴于nn.Add(start);如果是Module,相当于在输入和transfer之间插入的层。
input:输入到隐层的weight矩阵
feedback;前一时刻隐层到当前时刻隐层的weight矩阵
transfer:非线性Module,隐层的输入到输出的激活函数
rho:BPTT的最大步数,由于vanishing gradient影响,一般设为5
merge:table Module,用于整合input和feedback的输出。
2.执行过程
对于一个输入sequence,一步一步的执行,forward保留每一步的input和Module.output;backward不会产生gradInput,只是保留每一步的gradOutput和scale;调用 updateParametersbackwardThroughTime真正执行BPTT
例子:
require  'rnn'

batchSize  =  8
rho  =  5
hiddenSize  =  10
nIndex  =  10000 -- RNN
= nn. Recurrent(
   hiddenSize, nn. LookupTable(nIndex, hiddenSize), 
   nn. Linear(hiddenSize, hiddenSize), nn. Sigmoid(), 
   rho
)

rnn  = nn. Sequential()
rnn: add(r)
rnn: add(nn. Linear(hiddenSize, nIndex))
rnn: add(nn. LogSoftMax())

criterion  = nn. ClassNLLCriterion()

-- dummy dataset (task is to predict next item, given previous)
sequence  = torch. randperm(nIndex)

offsets  = {}
for i = 1,batchSize  do
    table.insert(offsets,  math.ceil( math.random() *batchSize))
end
offsets  = torch. LongTensor(offsets)

lr  =  0.1
updateInterval  =  4
=  1 while  true  do
    -- a batch of inputs
    local input  = sequence: index( 1, offsets)
    local output  = rnn: forward(input)
    -- incement indices
   offsets: add( 1)
    for j = 1,batchSize  do
      if offsets[j]  > nIndex  then
         offsets[j]  =  1
      end
    end
    local target  = sequence: index( 1, offsets)
    local err  = criterion: forward(output, target)
    print(err)
    local gradOutput  = criterion: backward(output, target)
    -- the Recurrent layer is memorizing its gradOutputs (up to memSize)
   rnn: backward(input, gradOutput)

   i  = i  +  1
    -- note that updateInterval < rho
    if i  % updateInterval  ==  0  then
      -- backpropagates through time (BPTT) :
      -- 1. backward through feedback and input layers,
      -- 2. updates parameters
      rnn: backwardThroughTime()
      rnn: updateParameters(lr)
      rnn: zeroGradParameters()
    end end
例子的几点注释:
-- offsets: sequece的下标
-- input: sequece下标对应的数值
-- batchSize: 一次前后向的个数
-- updateinterval: BPTT计算更新参数的间隔时间
-- rho: 保存t到t-rho个结果,updateinterval<rho(否则前面的中间结果都没有保存)
-- input: 比如输入nIndex=5,batchSize=3,input={2,4,1},实际用向量表示如下:
--        (参考nn.Lookuptable的说明文档)
--        0 0 1
--        1 0 0
--        0 0 0
--        0 1 0
--        0 0 0
-- output:输出的对应于3*5的矩阵
3.使用Sequencer封装RNN
使用Sequence封装以后,就可以将t到t+updateInterval时间段内的序列使用一次forward和backward搞定(如果不封装的话,需要对每一个t进行一次前后向,优势在于可以进行实时预测)。
require  'rnn'

batchSize  =  8
rho  =  5
hiddenSize  =  10
nIndex  =  10000 -- RNN
= nn. Recurrent(
   hiddenSize, nn. LookupTable(nIndex, hiddenSize), 
   nn. Linear(hiddenSize, hiddenSize), nn. Sigmoid(), 
   rho
)

rnn  = nn. Sequential()
rnn: add(nn. Sequencer(r))
rnn: add(nn. Sequencer(nn. Linear(hiddenSize, nIndex)))
rnn: add(nn. Sequencer(nn. LogSoftMax()))

criterion  = nn. SequencerCriterion(nn. ClassNLLCriterion())

-- dummy dataset (task is to predict next item, given previous)
sequence  = torch. randperm(nIndex)

offsets  = {}
for i = 1,batchSize  do
    table.insert(offsets,  math.ceil( math.random() *batchSize))
end
offsets  = torch. LongTensor(offsets)

lr  =  0.1
=  1 while  true  do
    -- prepare inputs and targets
    local inputs, targets  = {},{}
    for step = 1,rho  do
      -- a batch of inputs
      table.insert(inputs, sequence: index( 1, offsets))
      -- incement indices
      offsets: add( 1)
      for j = 1,batchSize  do
          if offsets[j]  > nIndex  then
            offsets[j]  =  1
          end
      end
      -- a batch of targets
      table.insert(targets, sequence: index( 1, offsets))
    end

    local outputs  = rnn: forward(inputs)
    local err  = criterion: forward(outputs, targets)
    print(i, err /rho)
   i  = i  +  1
    local gradOutputs  = criterion: backward(outputs, targets)
   rnn: backward(inputs, gradOutputs)
   rnn: updateParameters(lr)
   rnn: zeroGradParameters()
end

四、LSTM
1.概况

i[t]  = σ(W[x ->i]x[t]  + W[h ->i]h[t− 1+ W[c ->i]c[t− 1+ b[ 1 ->i])      ( 1)
f[t]  = σ(W[x ->f]x[t]  + W[h ->f]h[t− 1+ W[c ->f]c[t− 1+ b[ 1 ->f])      ( 2)
z[t]  =  tanh(W[x ->c]x[t]  + W[h ->c]h[t− 1+ b[ 1 ->c])                   ( 3)
c[t]  = f[t]c[t− 1+ i[t] z(t)                                         ( 4)
o[t]  = σ(W[x ->o]x[t]  + W[h ->o]h[t− 1+ W[c ->o]c[t]  + b[ 1 ->o])        ( 5)
h[t]  = o[t] tanh(c[t])                                                ( 6)
2.实现
nn.LSTM(inputSize, outputSize, [rho])  
成员函数包括
  • buildGate : builds generic gate that is used to implement the input, forget and output gates;
  • buildInputGate : builds the input gate (eq. 1). Currently calls buildGate;
  • buildForgetGate : builds the forget gate (eq. 2). Currently calls buildGate;
  • buildHidden : builds the hidden (eq. 3);
  • buildCell : builds the cell (eq. 4);
  • buildOutputGate : builds the output gate (eq. 5). Currently calls buildGate;
  • buildModel : builds the actual LSTM model which is used internally (eq. 6).
五、 reference
https://github.com/Element-Research/rnn
### 使用 PyTorch 实现 RNN 的方法 PyTorch 提供了一个强大的工具集来构建和训练循环神经网络(RNN)。它本质上是一个支持 GPU 加速的 NumPy 替代品,具有更高层次的功能用于深度学习模型开发[^1]。 #### 创建简单的 RNN 模型 以下是使用 PyTorch 构建基本 RNN 模型的一个简单例子: ```python import torch import torch.nn as nn class SimpleRNN(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(SimpleRNN, self).__init__() self.hidden_size = hidden_size self.rnn = nn.RNN(input_size, hidden_size, batch_first=True) self.fc = nn.Linear(hidden_size, output_size) def forward(self, x): h0 = torch.zeros(1, x.size(0), self.hidden_size).to(x.device) # 初始化隐藏状态 out, _ = self.rnn(x, h0) # 前向传播通过 RNN 层 out = self.fc(out[:, -1, :]) # 获取最后一个时间步的结果并通过全连接层 return out # 参数设置 input_size = 10 hidden_size = 20 output_size = 5 model = SimpleRNN(input_size, hidden_size, output_size) criterion = nn.MSELoss() # 定义损失函数 optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # 定义优化器 # 随机输入数据 batch_size = 3 sequence_length = 5 inputs = torch.randn(batch_size, sequence_length, input_size) targets = torch.randn(batch_size, output_size) # 训练过程 for epoch in range(100): # 进行多次迭代 outputs = model(inputs) # 前向传播 loss = criterion(outputs, targets) # 计算损失 optimizer.zero_grad() # 清除梯度 loss.backward() # 反向传播计算梯度 optimizer.step() # 更新参数 print(f'Final Loss: {loss.item()}') ``` 上述代码展示了如何定义一个带有单层 RNN 和线性输出层的模块化结构。`nn.RNN` 是核心组件,负责处理序列数据并返回最终的时间步特征表示[^3]。 #### 自动求导机制 PyTorch 的自动求导功能 `autograd` 能够简化复杂张量操作下的梯度计算流程。当调用 `.backward()` 方法时,框架会自动生成所有必要的偏导数以便更新权重矩阵和其他可学习参数[^2]。 #### 处理更复杂的场景 如果需要实现变体形式如 LSTM 或 GRU,则可以分别替换为对应的类 `nn.LSTM`, `nn.GRU`. 此外还可以考虑双向模式以及堆叠多层单元以增强表达能力: ```python rnn_layer = nn.LSTM( input_size=input_dim, hidden_size=hidden_dim, num_layers=num_layers, bidirectional=True ) ``` 以上配置允许我们探索更加丰富的动态特性而无需手动调整内部细节太多次序关系[^4]. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值