如何构建LSTM神经网络模型

一、了解LSTM

1. 核心思想

首先,LSTM 是 RNN(循环神经网络)的变体。它通过引入细胞状态C(t) 贯穿于整个网络模型,达到长久记忆的效果,进而解决了 RNN 的长期依赖问题。

2. 思维导图

每个LSTM层次都有三个重要的门结构,从前往后依次是遗忘门 (forget gate layer)、输入门 (input gate layer)、输出门(output gate layer)。

还有两个重要的状态,分别是细胞状态 (cell state)、隐藏状态 (hidden state),即图示中的 C(t) 和 h(t) 。其中细胞状态不仅记忆某个时间步的信息,而是对整个时间序列保持较为稳定的记忆,是一种长期 "记忆信息" 。对于隐藏状态来说,它更多地关注当前时间步以及上一个时间步的输出,是一种短期 "记忆信息" 。

具体内容如下面思维导图所示:


二、利用pytorch构建LSTM

1. 构造神经网络模型

1.1 LSTM层
python 复制代码
self.lstm = nn.LSTM(
    input_size=28,  # 每次输入特征数量为28
    hidden_size=64,  # 表示每个时间步的输出会有 64 个特征
    num_layers=1,  # LSTM隐藏层的层数
    batch_first=True  # 输入数据的格式是"批次在第一位"
)
  • input_size: 这告诉模型,每次输入的数据有多少个特征(比如一张28x28像素的图像,每一行就是一个时间步)。也就是图示中的 x(t) 。
  • hidden_size:这是模型的"记忆"大小。即细胞状态C(t) 和隐藏状态 h(t) 的容量。
  • num_layers:等于1则代表只使用一层 LSTM 网络。
  • batch_first:这个参数表示输入数据的维度格式是(批次,时间步、特征数),即批次在第一维。
1.2 全连接层
python 复制代码
self.out = nn.Linear(
    in_features=64,
    out_features=10  # 将LSTM层提取到的64个特征进一步转化为10个输出(0~9)
)
  • in_features:全连接层的输入大小,来自LSTM的输出,每个时间步的特征数是64(即 hidden_size )
  • out_features:全连接层的输出大小是10,通常表示有10个类别。
1.3 Softmax层
python 复制代码
self.softmax = nn.Softmax(dim=1)

这一层主要是将全连接层的输出转化为概率分布。如果使用的是交叉熵代价函数(CrossEntropyLoss),可以不加这层。

2. 前向传播

  1. 在前面LSTM层中batch_first参数设置了输入数据的维度格式,即(批次,时间步、特征数)。所以首先要做的就是调整输入的维度格式。这里每个样本是 28 个时间步,每个时间步有 28 个特征(像是一个28x28的图像)

    python 复制代码
    x = x.view(-1, 28, 28)
  2. 让输入数据通过LSTM层,并最终输出三个信息,分别是 output,h_n 和 c_n。output 包含了每个时间步的输出信息(理解为LSTM分析每个时间步得到的结果)。h_n 是最后一个时间步的隐藏状态,c_n 是记忆状态。我们重点关注 h_n,因为它代表了 LSTM 在处理完所有时间步后的总结。

    python 复制代码
    output, (h_n, c_n) = self.lstm(x)
  3. 接下来从隐藏状态中拿到最后一个时间步 h_n 的输出 output_in_last_timestep。可以理解为,LSTM看完了所有时间步之后,得到了它对整个序列的理解。

    python 复制代码
    output_in_last_timestep = h_n[-1, :, :]

最后LSTM的输出被送到全连接层,转化成10个数字,这些数字代表模型对每个类别的预测分数。并通过Softmax转化为概率。

python 复制代码
x = self.out(output_in_last_timestep)
x = self.softmax(x)

构造好的LSTM神经网络模型代码如下所示:

python 复制代码
class LSTM(nn.Module):
    def __init__(self):
        super(LSTM, self).__init__()
        self.lstm = nn.LSTM(
            input_size=28,  # 每次输入特征数量
            hidden_size=64,  
            num_layers=1,  # LSTM隐藏层的层数
            batch_first=True  
        )
        self.out = nn.Linear(
            in_features=64,
            out_features=10  # 将LSTM层提取到的64个特征进一步转化为10个输出(0~9)
        )
        self.softmax = nn.Softmax(dim=1)

    def forward(self, x):
        x = x.view(-1, 28, 28)  # 将输入调整成一个 (批次大小, 时间步数, 特征数) 的形式
        output, (h_n, c_n) = self.lstm(x)
        output_in_last_timestep = h_n[-1, :, :]  # 从隐藏状态中拿到最后一个时间步的输出
        x = self.out(output_in_last_timestep)  # LSTM的输出被送到全连接层,转化成10个数字
        x = self.softmax(x)  
        return x

三、测试 LSTM 神经网络模型

用MNIST数据集测试代码如下:

python 复制代码
# 训练集
train_dataset = datasets.MNIST(root='./',
                               train=True,
                               transform=transforms.ToTensor(),  # 数据转换为张量格式
                               download=True)
# 测试集
test_dataset = datasets.MNIST(root='./',
                              train=False,
                              transform=transforms.ToTensor(),
                              download=True)

# 批次大小
batch_size = 100
# 装载训练集
train_loader = DataLoader(dataset=train_dataset,
                          batch_size=batch_size,  # 每次加载多少条数据
                          shuffle=True)  # 生成数据前打乱数据

# 装载测试集
test_loader = DataLoader(dataset=test_dataset,
                         batch_size=batch_size,
                         shuffle=True)

LR = 0.001  # 学习率
model = LSTM()  # 模型
crossEntropy_loss = nn.CrossEntropyLoss()  # 交叉熵代价函数
optimizer = optim.Adam(model.parameters(), LR)


def train():
    model.train()
    for i, data in enumerate(train_loader):
        inputs, labels = data  # 获得一个批次的数据和标签
        out = model(inputs)  # 获得模型预测输出(64张图像,10个数字的概率)
        loss = crossEntropy_loss(out, labels)  # 使用交叉熵损失函数时,可以直接使用整型标签,无须独热编码
        optimizer.zero_grad()  # 梯度清0
        loss.backward()  # 计算梯度
        optimizer.step()  # 修改权值


def test():
    model.eval()
    correct = 0
    for i, data in enumerate(test_loader):
        inputs, labels = data  # 获得一个批次的数据和标签
        out = model(inputs)  # 获得模型预测结构(64,10)
        _, predicted = torch.max(out, 1)  # 获得最大值,以及最大值所在位置
        correct += (predicted == labels).sum()  # 判断64个值有多少是正确的
    print("测试集正确率:{}\n".format(correct.item() / len(test_loader)))


# 训练20个周期
for epoch in range(20):
    print("Epoch:{}".format(epoch))
    train()
    test()

测试结果:

相关推荐
佚明zj2 分钟前
全卷积和全连接
人工智能·深度学习
qzhqbb3 小时前
基于统计方法的语言模型
人工智能·语言模型·easyui
冷眼看人间恩怨3 小时前
【话题讨论】AI大模型重塑软件开发:定义、应用、优势与挑战
人工智能·ai编程·软件开发
2401_883041083 小时前
新锐品牌电商代运营公司都有哪些?
大数据·人工智能
AI极客菌4 小时前
Controlnet作者新作IC-light V2:基于FLUX训练,支持处理风格化图像,细节远高于SD1.5。
人工智能·计算机视觉·ai作画·stable diffusion·aigc·flux·人工智能作画
阿_旭4 小时前
一文读懂| 自注意力与交叉注意力机制在计算机视觉中作用与基本原理
人工智能·深度学习·计算机视觉·cross-attention·self-attention
王哈哈^_^4 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
Power20246665 小时前
NLP论文速读|LongReward:基于AI反馈来提升长上下文大语言模型
人工智能·深度学习·机器学习·自然语言处理·nlp
数据猎手小k5 小时前
AIDOVECL数据集:包含超过15000张AI生成的车辆图像数据集,目的解决旨在解决眼水平分类和定位问题。
人工智能·分类·数据挖掘
好奇龙猫5 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法