如何构建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()

测试结果:

相关推荐
feng995201 小时前
技术伦理双轨认证如何重构AI工程师能力评估体系——基于AAIA框架的技术解析与行业实证研究
人工智能·aaif·aaia·iaaai
2301_776681652 小时前
【用「概率思维」重新理解生活】
开发语言·人工智能·自然语言处理
蜡笔小新..2 小时前
从零开始:用PyTorch构建CIFAR-10图像分类模型达到接近1的准确率
人工智能·pytorch·机器学习·分类·cifar-10
富唯智能2 小时前
转运机器人可以绕障吗?
人工智能·智能机器人·转运机器人
沅_Yuan2 小时前
基于小波神经网络(WNN)的回归预测模型【MATLAB】
深度学习·神经网络·matlab·回归·小波神经网络·wnn
视觉语言导航3 小时前
湖南大学3D场景问答最新综述!3D-SQA:3D场景问答助力具身智能场景理解
人工智能·深度学习·具身智能
AidLux3 小时前
端侧智能重构智能监控新路径 | 2025 高通边缘智能创新应用大赛第三场公开课来袭!
大数据·人工智能
引量AI3 小时前
TikTok矩阵运营干货:从0到1打造爆款矩阵
人工智能·矩阵·自动化·tiktok矩阵·海外社媒
Hi-Dison3 小时前
神经网络极简入门技术分享
人工智能·深度学习·神经网络
奋斗者1号3 小时前
机器学习之决策树模型:从基础概念到条件类型详解
人工智能·决策树·机器学习