赞
踩
原文链接:https://xiets.blog.csdn.net/article/details/131712791
版权声明:原创文章禁止转载
专栏目录:PyTorch 专栏(总目录)
PyTorch 相关网站:
循环神经网络(Recurrent Neural Network, RNN)是以 序列(Sequence)数据作为输入,沿序列的演进方向进行 递归(Recurrent)且所有循环单元节点按链式连接的一类神经网络。循环神经网络具有记忆性,对序列数据的非线性特征进行学习时具有一定优势。还有 RNN 的加强版 长短期记忆网络(LSTM, Long Short-Term Memory)和 门控循环单元网络(GRU, Gated Recurrent Unit networks)拥有更强的“记忆力”。
循环神经网络相关模型:recurrent-layers
RNN 相关类:
普通神经网络的数据是单向传递的,而循环神经网络(RNN)的数据是循环传递的,即后面的输入依赖于前面的输出。例如样本 xt 和一个隐藏向量 ht 一起输入 RNN 网络层处理后输出 yt 和 ht+1,yt 就是样本 xt 对应的输出,而 ht+1 作为下一次输入的一部分和 xt+1 一起输入网络层得到 yt+1 和 ht+2,以此不断循环传递。
对于首个样本(首次输入)x0,需要手动或自动初始化一个初始隐藏向量 h0。
循环神经网络(RNN)结构示意图:
由于循环神经网络的循环和记忆特性,因此非常适合用于处理序列问题。例如:将英文翻译成中文时,输入的是英文句子,输出的是中文句子;用于语音识别时,输入的是音频数据序列,输出的是文本序列。再比如根据过去 N 天的天气预测未来的天气等。
nn.RNNCell
是循环神经网络(RNN)中隐藏层的基础单元,其结构示意图:
RNNCell 数学表达式: h’ = tanh(Wih*x + bih + Whh*h + bhh)
,如果非线性是 “relu”,则使用 ReLU 替换 tanh。
从公式可以看出,RNNCell 的数学本质是将 xt 和 ht 分别进行线性变换并相加,随后经过非线性激活函数,得到下一个输入的 ht+1。
nn.RNNCell
类详情:
class torch.nn.RNNCell(input_size, hidden_size, bias=True, nonlinearity='tanh', device=None, dtype=None)
"""
具有 tanh 或 ReLU 非线性的 RNN 单元 (是一个 nn.Module), 支持 单样本处理 和 批样本处理。
参数:
input_size (int) 输入 x 中预期的特征数量 (单个样本的特征数)
hidden_size (int) 隐藏状态 h 中的特征数
bias (bool) 如果是 False, 则该层不使用偏置权重 b_ih 和 b_hh, 默认为 True
nonlinearity (str) 要使用的非线性函数, 可以是 "tanh" 或 "relu", 默认为 "tanh"
输入: input, hidden
input (Tensor) 包含输入特征的张量
hidden (Tensor) 包含初始隐藏状态的张量, 如果未提供则默认为 zeros。
输出: hidden'
hidden' (Tensor) 包含批次中每个样本的下一个隐藏状态张量
形状:
input: (N, H_in) 或 (H_in,)
包含输入特征的张量, H_in = input_size, H_in 表示单个样本的输入特征数量。
如果输入的是单个样本数据, 则形状为 (H_in,); 如果是批处理, 则形状为 (N, H_in), N 表示批大小 (样本数量)。
hidden: (N, H_out) 或 (H_out,)
包含初始隐藏状态的张量, H_out = hidden_size, 如果未提供则默认为 zeros 张量。
如果输入的是单个样本数据, 则形状为 (H_out,); 如果是批处理, 则形状为 (N, H_out), N 表示批大小 (对应输入的每一个样本)。
output (hidden'): (N, H_out) 或 (H_out,)
包含用于下一个样本的输入的隐藏状态张量, H_out = hidden_size。
如果输入的是单个样本数据, 则形状为 (H_out,); 如果是批处理, 则形状为 (N, H_out), N 表示批大小 (对应输入的每一个样本)。
变量:
weight_ih (Tensor) 可学习的 输入隐藏权重(input-hidden weights), 形状为 (hidden_size, input_size)
weight_hh (Tensor) 可学习的 隐藏权重(hidden-hidden weights), 形状为 (hidden_size, hidden_size)
bias_ih 可学习的 输入隐藏偏差(input-hidden bias), 形状为 (hidden_size)
bias_hh 可学习的 隐藏偏差(hidden-hidden bias), 形状为 (hidden_size,)
"""
nn.RNNCell
类代码示例:
import torch
from torch import nn
# 创建 RNNCell (nn.Module) 实例, 样本输入特征数为2, 隐藏状态特征数为3
rnn_cell = nn.RNNCell(input_size=2, hidden_size=3, dtype=torch.float32)
print(rnn_cell)
# 输出: RNNCell(2, 3)
# -------------------------------------------------------------------------------------
# 输入数据 (单样本, 有2个特征)
input0 = torch.tensor([1, 2], dtype=torch.float32)
# 初始隐藏状态 (和 input0 一起输入 RNNCell 单元隐藏状态张量, 有3个特征)
hidden0 = torch.tensor([1, 2, 3], dtype=torch.float32)
# 输入 RNNCell 单元 (单样本输入), 返回 输入用于下一个样本输入的隐藏状态张量
hidden1 = rnn_cell(input0, hidden0)
print(hidden1)
# 输出: tensor([0.2513, 0.9635, 0.6665], grad_fn=<SqueezeBackward1>)
# -------------------------------------------------------------------------------------
# 下一个输入数据 (下一个样本)
input1 = torch.tensor([3, 4], dtype=torch.float32)
# 把 当前输入 和 上一个样本返回的隐藏状态张量 一起输入 RNNCell, 返回 输入用于下一个样本输入的隐藏状态张量
hidden2 = rnn_cell(input1, hidden1)
print(hidden2)
# 输出: tensor([0.8123, 0.8857, 0.9854], grad_fn=<SqueezeBackward1>)
# -------------------------------------------------------------------------------------
# 再下一个数据
input2 = torch.tensor([5, 6], dtype=torch.float32)
hidden3 = rnn_cell(input2, hidden2)
print(hidden3)
# 输出: tensor([0.9777, 0.9607, 0.9995], grad_fn=<SqueezeBackward1>)
# -------------------------------------------------------------------------------------
# 批样本数据处理
# -------------------------------------------------------------------------------------
# 输入也可以批数据, input0_ls 批数据有 3 个样本 (每个样本2个特征)
input0_ls = torch.tensor([[1, 2], [11, 12], [21, 22]], dtype=torch.float32)
# 隐藏状态也必须是批数据, hidden0_ls 表示有 3 个隐藏状态 (每1个样本对应1个隐藏状态), 每个隐藏状态有 3 个特征
hidden0_ls = torch.tensor([[1, 2, 3], [1, 2, 3], [1, 2, 3]], dtype=torch.float32)
# 批数据输入 RNNCell 单元, 返回用于下一批样本输入的隐藏状态张量, 形状为 (3, 3), 每1个样本 对应 一个隐藏状态(包括3个特征)
hidden1_ls = rnn_cell(input0_ls, hidden0_ls)
print(hidden1_ls)
# 输出:
# tensor([[0.2513, 0.9635, 0.6665],
# [0.9999, 0.9999, 1.0000],
# [1.0000, 1.0000, 1.0000]], grad_fn=<TanhBackward0>)
# -------------------------------------------------------------------------------------
# 下一批数据
input1_ls = torch.tensor([[3, 4], [13, 14], [23, 24]], dtype=torch.float32)
hidden2_ls = rnn_cell(input1_ls, hidden1_ls)
print(hidden2_ls)
# 输出:
# tensor([[0.8123, 0.8857, 0.9854],
# [1.0000, 0.9996, 1.0000],
# [1.0000, 1.0000, 1.0000]], grad_fn=<TanhBackward0>)
# -------------------------------------------------------------------------------------
# 再下一批数据
input2_ls = torch.tensor([[5, 6], [15, 16], [25, 26]], dtype=torch.float32)
hidden3_ls = rnn_cell(input2_ls, hidden2_ls)
print(hidden3_ls)
# 输出:
# tensor([[0.9777, 0.9607, 0.9995],
# [1.0000, 0.9999, 1.0000],
# [1.0000, 1.0000, 1.0000]], grad_fn=<TanhBackward0>)
# 注意:
# 批样本处理时, 同一批次的多个样本相互独立, 即不是序列组成, 多个批数据相同位置的样本才是组成的序列。
# 如多批数据:
# 第1批: [[1, 2], [11, 12], [21, 22]]
# 第2批: [[3, 4], [13, 14], [23, 24]]
# 第3批: [[5, 6], [15, 16], [25, 26]]
#
# [1, 2], [3, 4], [5, 6] 是一个序列,
# 即 样本[1, 2] 输出的隐藏状态作为 样本[3, 4] 的输入隐藏状态, 样本[3, 4] 的输出隐藏状态作为 样本[5, 6] 的输入隐藏状态。
#
# 同样的 [11, 12], [13, 14], [15, 16] 是一个序列; [21, 22], [23, 24], [25, 26] 也是一个序列。
#
# [1, 2], [11, 12], [21, 22] 并不是一个序列, 而是由多个序列中的一个样本组成的一批数据。
nn.RNN
包含多层 nn.RNNCell
的神经网络层。nn.RNNCell 处理序列时,需要将序列中的样本按顺序逐个循环输入。而 nn.RNN 模块可以直接把一个序列当做输入,内部自动使用 RNNCell 逐个循环处理每一个样本,最后输出由每一个样本对应的输出组成的一个输出序列和最后一个样本输出的隐藏向量 h。
nn.RNN
类详情:
class torch.nn.RNN(*args, **kwargs)
"""
包含多层 RNNCell 的神经网络层。支持 单序列处理 和 批序列处理。序列是由多个样本按顺序组成的一组样本。
参数:
input_size 输入 x 中预期的特征数量 (单个样本的特征数)
hidden_size 隐藏状态 h 中的特征数 (也是 x 对应输出 y 的特征数)
num_layers 循环层数, 包含的 RNNCell 数量。例如设置 num_layers=2 意味着将两个 RNNCell 堆叠在一起
形成一个堆叠的 RNN, 第二个 RNNCell 接收第一个 RNNCell 的输出并计算最终结果。默认值为 1。
nonlinearity 要使用的非线性函数, 可以是 "tanh" 或 "relu", 默认为 "tanh"。
bias 如果是 False, 则 RNNCell 层不使用偏置权重 b_ih 和 b_hh, 默认为 True。
batch_first 批序列数据处理时, 最先一维是否作为批大小(有多少条序列)。
如果 batch_first=True, 则输入和输出张量的形状组成为 (batch, seq, feature),
而不是 (seq, batch, feature)。默认为 False。请注意, 此参数不适用于 隐藏状态 或 Cell状态。
batch 表示批大小, 即有多少条序列。
seq 表示一条序列的长度, 即一条序列中的样本数量。
feature 表示一个样本的特征数。
dropout 如果非0, 则在除最后一层之外的每个 RNNCell 层的输出上引入一个 Dropout 层, dropout 概率等于此值。
默认值为 0。
bidirectional 如果为 True, 则成为双向 RNN。默认:False。
还可指定设备和数据类型, 如 device="cuda", dtype=torch.float64。
输入: input, h_0
input 输入张量。
如果非批处理: 形状为 (L, H_in)。
如果是批处理: batch_first=False 时, 形状为 (L, N, H_in);
batch_first=True 时, 形状为 (N, L, H_in)。
N 表示批大小, 即有多少条序列。
L 表示表示一条序列的长度, 即一条序列中的样本数量。
D 如果是双向 RNN, 则 D=2, 否则 D=1。
H_in 表示一个样本的特征数, 即 H_in == input_size。
h_0 初始隐藏状态张量。
如果非批处理: 形状为 (D * num_layers, H_out)。
如果是批处理: 则形状为 (D * num_layers, N, H_out)。
请注意, 隐藏状态张量形状不受 batch_first 参数影响。
如果未提供, 默认为 zeros 张量。
H_out 表示隐藏状态特征数 (也是 x 对应输出 y 的特征数), 即 H_out == hidden_size。
输出: output, h_n
output 输出张量。
如果非批处理: 形状为 (L, D * H_out)。
如果是批处理: batch_first=False 时, 形状为 (L, N, D * H_out);
batch_first=True 时, 形状为 (N, L, D * H_out)。
h_n 输出的隐藏状态张量, 形状与 h_0 相同, 作为下一批数据的隐藏状态输入。
变量:
weight_ih_l[k] 第 k 层的可学习的输入隐藏权重, 形状为 (hidden_size, input_size)
weight_hh_l[k] 第 k 层的可学习的隐藏权重, 形状为 (hidden_size, hidden_size)
bias_ih_l[k] 第 k 层的可学习的输入隐藏偏置, 形状为 (hidden_size,)
bias_hh_l[k] 第 k 层的可学习的隐藏-隐藏偏差, 形状为 (hidden_size,)
"""
nn.RNN
类代码示例:
import torch
from torch import nn
# RNN 网络实例: 样本输入特征数为2, 隐藏层特征数为3, RNNCell层数为4, 用于批处理时最先一维作为批大小
rnn = nn.RNN(input_size=2, hidden_size=3, num_layers=4, batch_first=True, dtype=torch.float32)
#
# 单序列处理
#
# 一条输入序列: 包括3个样本, 每个样本2个特征
input_seq_0 = torch.tensor([[1, 2],
[3, 4],
[5, 6]], dtype=torch.float32)
# 初始隐藏状态: 有4个RNNCell层(num_layers), 每层有3个输出特征(hidden_size)
hidden_0 = torch.tensor([[1, 2, 3],
[3, 4, 5],
[7, 8, 9],
[1, 4, 9]], dtype=torch.float32)
# 输入RNN网络: 返回 输出序列 和 用于下一次输入的隐藏状态
output_seq_0, hidden_1 = rnn(input_seq_0, hidden_0)
print(output_seq_0.shape) # 输出: torch.Size([3, 3])
print(hidden_1.shape) # 输出: torch.Size([4, 3])
#
# 批序列处理
#
# 输入的批序列: 2条输入序列, 每条序列3个样本, 每个样本2个特征, 形状为 (2, 3, 2)
input_seq_ls_0 = torch.tensor([[[1, 2],
[3, 4],
[5, 6]],
[[7, 8],
[9, 10],
[11, 12]]], dtype=torch.float32)
# 初始隐藏状态: 形状为 (num_layers, seq_n, hidden_size), seq_n 表示输入序列的条数
hidden_ls_0 = torch.randn((4, 2, 3), dtype=torch.float32)
# 批序列输入RNN网络, 返回 输出批序列 和 用于下一次输入的隐藏状态
input_seq_ls_1, hidden_ls_1 = rnn(input_seq_ls_0, hidden_ls_0)
print(input_seq_ls_1.shape) # 输出: torch.Size([2, 3, 3])
print(hidden_ls_1.shape) # 输出: torch.Size([4, 2, 3])
使用 RNN 模型,根据 sin 序列去预测 cos 序列,即输入一条 sin 序列,输出对应的一条 cos 序列:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Optional
import matplotlib.pyplot as plt
import torch
from torch import nn
from torch import optim
class RNNNet(nn.Module):
"""
神经网络模型
"""
def __init__(self, *, input_size: int, hidden_size: int):
super().__init__()
self.hidden_size = hidden_size
# 循环神经网络层
self.rnn = nn.RNN(
input_size=input_size,
hidden_size=hidden_size,
num_layers=1,
dtype=torch.float32,
)
# 线性输出层, 把 RNN 层的多个输出经过全连接层转换为 1 个特征输出
self.out = nn.Linear(in_features=hidden_size, out_features=1, dtype=torch.float32)
def forward(self, inputs: torch.Tensor, hidden_state: Optional[torch.Tensor]):
"""
前向传播
"""
rnn_outputs, hidden_state = self.rnn(inputs, hidden_state)
outputs = self.out(rnn_outputs)
return outputs, hidden_state
def main():
# 网络模型: 样本的输入特征数为1, 隐藏层的特征数为20
rnn_net = RNNNet(input_size=1, hidden_size=20)
# 优化器: Adam优化器, 学利率为 0.001
optimizer = optim.Adam(rnn_net.parameters(), lr=0.001)
# 损失函数: 均方误差损失函数
loss_func = nn.MSELoss()
# 随机生成初始隐藏向量
hidden_state = torch.randn((1, 20), dtype=torch.float32)
# plt 开启交互式模式
plt.ion()
steps = 1000
# 从 [0, 1002*pi] 对应的 sin 值组成的序列分段依次输入 RNN 模型, 每次输入长度跨度为 2*pi 的序列
for step in range(0, steps + 1, 2):
start, end = step * torch.pi, (step + 2) * torch.pi
steps_seq = torch.linspace(start, end, 100, dtype=torch.float32)
# 输入 sin序列, 形状为 (seq_len, features), seq_len 表示本次输入序列的长度(样本个数), features 表示样本的输入特征数
inputs_sin_seq = torch.sin(steps_seq).reshape((-1, 1))
# 目标 cos序列
targets_cos_seq = torch.cos(steps_seq).reshape((-1, 1))
# 前向传播: 输入一个 sin序列, 输出 另一个序列(需要拟合目标cos序列的序列)
# sin序列 和 初始隐藏向量 输入 RNN模型, 返回 预测的输出序列 和 用于下一次输入的隐藏向量
predicts_cos_seq, hidden_state = rnn_net(inputs_sin_seq, hidden_state)
# 对 预测的输出序列 和 目标cos序列 求损失值
loss = loss_func(predicts_cos_seq, targets_cos_seq)
# 模型参数梯度清零
optimizer.zero_grad()
# 误差反向传播
loss.backward()
# 更新模型参数
optimizer.step()
# 隐藏状态张量不需要自动计算梯度, 必须使用不带梯度的张量才能用于下次输入
hidden_state = hidden_state.data
# 定时显示训练状态
if (step % 100 == 0) or (step == steps - 2):
# 清除当前绘图区域
plt.cla()
# 绘制绘图区域的标题
plt.title(f"step: {step}/{steps}, loss = {loss.item():.6f}")
# 绘制 目标cos序列 (红色实线)
plt.plot(steps_seq, targets_cos_seq.data.numpy().reshape((-1,)), "r-", label="target")
# 绘制 预测的输出序列 (蓝色虚线), 根据训练次数观察 预测输出序列 与 目标cos序列 的拟合程度
plt.plot(steps_seq, predicts_cos_seq.data.numpy().reshape((-1,)), "b--", label="predict")
# 绘制标签
plt.legend()
# 重绘图形
plt.draw()
# 短暂暂停以运行 GUI 事件循环, 并更新窗口 (没有更新窗口, 前面 draw 绘制的不会显示)
plt.pause(0.01)
# plt 关闭交互式模式
plt.ioff()
# plt 显示图形 (关闭了交互式模式, 显示时阻塞)
plt.show()
if __name__ == "__main__":
main()
其中几次训练拟合结果:
长短期记忆网络(LSTM, Long Short-Term Memory)是一种加强版的时间循环神经网络,可以解决一般循环神经网络(RNN)存在的长期依赖问题,以及长序列训练过程中的梯度消失和梯度爆炸问题。
nn.RNN
和 nn.LSTM
均继承自 nn.RNNBase
。与 RNN 不同的是,LSTM 的输入和输入包括两个隐藏向量:隐藏状态(hidden_state) 和 单元状态(cell_state)。
RNN 和 LSTM 结构比较:
LSTM 相关的类:
nn.LSTMCell
类详情:
class torch.nn.LSTMCell(input_size, hidden_size, bias=True, device=None, dtype=None)
"""
长短期记忆 (LSTM) 单元, LSTM 网络组成的单元。
参数:
input_size (int) 输入 x 中预期的特征数量 (单个样本的特征数)
hidden_size (int) 隐藏状态 h 中的特征数
bias (bool) 如果是 False, 则该层不使用偏置权重 b_ih 和 b_hh, 默认为 True
输入: input, (h_0, c_0)
input 包含输入特征的张量, 形状为 (batch, input_size) 或 (input_size)
h_0 包含初始隐藏状态的张量, 形状为 (batch, hidden_size) 或 (hidden_size)
c_0 包含初始单元状态的张量, 形状为 (batch, hidden_size) 或 (hidden_size)
input, h_0, c_0 非批处理时形状为一维, 批处理时形状为二维。如果 (h_0, c_0) 未提供, 则默认均值 zeros 张量。
输出: (h_1, c_1)
h_1 包含下一个隐藏状态的张量, 形状为 (batch, hidden_size) 或 (hidden_size)
c_1 包含下一个单元状态的张量, 形状为 (batch, hidden_size) 或 (hidden_size)
变量:
weight_ih (Tensor) 可学习的 输入隐藏权重, 形状为 (4*hidden_size, input_size)
weight_hh (Tensor) 可学习的 隐藏权重, 形状为 (4*hidden_size, hidden_size)
bias_ih 可学习的 输入隐藏偏差, 形状为 (4*hidden_size)
bias_hh 可学习的 隐藏偏差, 形状为 (4*hidden_size)
"""
nn.LSTMCell
类代码示例:
lstm_cell = nn.LSTMCell(input_size=10, hidden_size=20)
inputs = torch.randn((2, 3, 10)) # (time_steps, batch, input_size)
hx, cx = torch.randn((3, 20)), torch.randn((3, 20)) # (batch, hidden_size)
for i in range(inputs.shape[0]):
input = inputs[i]
hx, cx = lstm_cell(input, (hx, cx))
# batch表示单条序列的长度(样本数量), input_size表示单个样本的特征数
nn.LSTM
类详情:
class torch.nn.LSTM(*args, **kwargs)
"""
将多层长短期记忆 (LSTM) RNN 应用于输入序列(包含多个 LSTMCell 的神经网络模型)。
LSTM 类的各参数与 RNN 基本相同。
参数:
input_size 输入x中预期特征的数量
hidden_size 隐藏状态h中的特征数
num_layers 循环层数, 包含的 LSTMCell 数量, 默认为 1。
bias 如果是 False, 则 RNNCell 层不使用偏置权重 b_ih 和 b_hh, 默认为 True。
batch_first 如果 True,则输入和输出张量作为 (batch, seq, feature) 而不是 (seq, batch, feature) 提供。
dropout 如果非0, 则在除最后一层之外的每个 LSTMCell 层的输出上引入一个 Dropout 层, dropout 概率等于此值。默认值为 0。
bidirectional 如果 True, 则成为双向 LSTM。默认: False。
proj_size 如果 > 0, 将使用具有相应大小投影的 LSTM, 默认为 0。
输入: input, (h_0, c_0)
input 输入张量。
如果非批处理: 形状为 (L, H_in)。
如果是批处理: batch_first=False 时, 形状为 (L, N, H_in);
batch_first=True 时, 形状为 (N, L, H_in)。
N 表示批大小, 即有多少条序列。
L 表示表示一条序列的长度, 即一条序列中的样本数量。
D 如果是双向 RNN, 则 D=2, 否则 D=1。
H_in 表示一个样本的特征数, 即 H_in == input_size。
h_0 初始隐藏状态张量。
如果非批处理: 形状为 (D * num_layers, H_out)。
如果是批处理: 则形状为 (D * num_layers, N, H_out)。
请注意, 隐藏状态张量形状不受 batch_first 参数影响。
如果未提供, 默认为 zeros 张量。
H_out = proj_size if (proj_size > 0) else hidden_size
c_0 初始化单元状态张量。
如果非批处理: 形状为 (D * num_layers, H_cell)。
如果是批处理: 则形状为 (D * num_layers, N, H_cell)。
请注意, 单元状态张量形状不受 batch_first 参数影响。
如果未提供, 默认为 zeros 张量。
H_cell = hidden_size
输出: output, (h_n, c_n)
output 输出张量。
如果非批处理: 形状为 (L, D * H_out)。
如果是批处理: batch_first=False 时, 形状为 (L, N, D * H_out);
batch_first=True 时, 形状为 (N, L, D * H_out)。
h_n 输出的隐藏状态张量, 形状与 h_0 相同, 作为下一批数据的隐藏状态输入。
当 bidirectional=True 时, h_n 将分别包含最终前向和反向隐藏状态的串联。
c_n 输出的单元状态张量, 形状与 c_0 相同, 作为下一批数据的单元状态输入。
当 bidirectional=True 时, c_n 将分别包含最终正向和反向单元状态的串联。
变量:
包含每一层 LSTMCell 的变量。
"""
nn.LSTM
类代码示例:
lstm = nn.LSTM(input_size=10, hidden_size=20, num_layers=2, batch_first=True)
input = torch.randn(3, 5, 10) # (batch_size, batch, input_size)
h0 = torch.randn(2, 3, 20) # (num_layers, batch_size, hidden_size)
c0 = torch.randn(2, 3, 20) # (num_layers, batch_size, hidden_size)
output, (hn, cn) = lstm(input, (h0, c0))
# output: (batch_size, batch, hidden_size)
# batch_size表示有多少条序列, batch表示单条序列的长度(样本数量), input_size表示单个样本的特征数
门控循环单元网络(GRU, Gated Recurrent Unit networks)也是一种增强版的循环神经网络(RNN)。和 LSTM 一样,也是为了解决长期依赖问题,以及反向传播中的梯度问题。GRU 的实验效果和 LSTM 相似,但 GRU 更容易计算,可以节省计算资源。
GRU 的构造参数、输入和输出结构与普通的 RNN 一样。
GRU 相关类:
nn.GRUCell
类代码示例:
gru_cell = nn.GRUCell(input_size=10, hidden_size=20)
inputs = torch.randn((6, 3, 10)) # (time_steps, batch, input_size)
hx = torch.randn((3, 20)) # (batch, hidden_size)
for i in range(inputs.shape[0]):
input = inputs[i]
hx = gru_cell(input, hx)
# batch表示单条序列的长度(样本数量), input_size表示单个样本的特征数
nn.GRU
类代码示例:
gru = nn.GRU(input_size=10, hidden_size=20, num_layers=2, batch_first=True)
input = torch.randn(3, 5, 10) # (batch_size, batch, input_size)
h0 = torch.randn(2, 3, 20) # (num_layers, batch_size, hidden_size)
output, hn = gru(input, h0)
print(output.shape)
# output: (batch_size, batch, hidden_size)
# batch_size表示有多少条序列, batch表示单条序列的长度(样本数量), input_size表示单个样本的特征数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。