当前位置: 首页 > news >正文

【ShuQiHere】用类来实现LSTM:让你的模型拥有更强的记忆力

【ShuQiHere】

欢迎回到ShuQiHere!今天我们要来聊一聊LSTM(Long Short-Term Memory),一种非常流行的循环神经网络(RNN)变种。LSTM以其卓越的记忆能力和处理长序列数据的强大性能而闻名。今天,我们将用类的方式来实现LSTM,并将其应用于手写数字识别任务中。

1. 什么是LSTM?

LSTM是一种特殊的RNN,它通过引入“门”的机制,能够更好地捕捉长时间跨度的依赖关系。这些“门”控制着信息的流动,使得LSTM可以在训练过程中更有效地保留或舍弃信息,从而避免了传统RNN中常见的梯度消失问题。

1.1 LSTM 的核心结构

LSTM的核心在于它的三个门:遗忘门输入门输出门。这些门就像是信息流的交通灯,控制着信息在网络中的去留。

  • 遗忘门:决定当前信息是否需要被保留。
  • 输入门:决定是否将新的信息添加到当前的状态中。
  • 输出门:决定当前的隐状态如何影响最终的输出。

这些门的工作原理可以通过以下公式描述:

f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) (遗忘门) f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) \quad \text{(遗忘门)} ft=σ(Wf[ht1,xt]+bf)(遗忘门)

i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) (输入门) i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) \quad \text{(输入门)} it=σ(Wi[ht1,xt]+bi)(输入门)

C ~ t = tanh ⁡ ( W C ⋅ [ h t − 1 , x t ] + b C ) (候选状态) \tilde{C}_t = \tanh(W_C \cdot [h_{t-1}, x_t] + b_C) \quad \text{(候选状态)} C~t=tanh(WC[ht1,xt]+bC)(候选状态)

C t = f t ∗ C t − 1 + i t ∗ C ~ t (新的细胞状态) C_t = f_t * C_{t-1} + i_t * \tilde{C}_t \quad \text{(新的细胞状态)} Ct=ftCt1+itC~t(新的细胞状态)

o t = σ ( W o ⋅ [ h t − 1 , x t ] + b o ) (输出门) o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) \quad \text{(输出门)} ot=σ(Wo[ht1,xt]+bo)(输出门)

h t = o t ∗ tanh ⁡ ( C t ) (最终的隐状态) h_t = o_t * \tanh(C_t) \quad \text{(最终的隐状态)} ht=ottanh(Ct)(最终的隐状态)

看起来有点复杂?没关系,我们一步一步来,接下来我们会用代码来实现这些公式。

2. 用类实现LSTM

让我们直接进入正题,用Python的类来实现一个LSTM模型。这种方法不仅让代码更具结构性,也使得模型的各个部分更易于理解和扩展。

2.1 定义LSTM模型类

首先,我们来定义一个LSTMModel类。这个类将包含LSTM的所有层,并且通过__init__call方法来实现模型的初始化和前向传播。

import tensorflow as tf
from tensorflow.keras import layers, modelsclass LSTMModel(tf.keras.Model):def __init__(self, units, input_shape, output_dim):super(LSTMModel, self).__init__()# LSTM层:核心的循环神经网络层self.lstm = layers.LSTM(units, input_shape=input_shape)# 全连接层:用于最终的分类self.fc = layers.Dense(output_dim, activation='softmax')def call(self, inputs):# 前向传播:定义数据如何从输入流向输出x = self.lstm(inputs)output = self.fc(x)return output
2.2 分析代码
  • __init__方法:这里定义了LSTM模型的两部分:

    1. LSTM层:这是模型的核心部分,负责处理序列数据,捕捉长时间依赖关系。
    2. 全连接层:最后,通过全连接层将LSTM的输出映射到我们需要的分类结果上。
  • call方法:这个方法定义了前向传播的逻辑,即数据如何流经网络,最终生成输出。

3. 数据准备与预处理

在进入模型训练之前,我们需要准备数据。我们将使用MNIST手写数字数据集,演示LSTM在图像分类任务中的应用。

# 加载并预处理 MNIST 数据集
(train_data, train_labels), (test_data, test_labels) = tf.keras.datasets.mnist.load_data()# 数据预处理:将图像归一化并调整形状
train_data = train_data / 255.0
test_data = test_data / 255.0# 将数据形状调整为 (batch_size, timesteps, input_dim)
train_data = train_data.reshape(-1, 28, 28)
test_data = test_data.reshape(-1, 28, 28)# 将标签转换为one-hot编码
train_labels = tf.keras.utils.to_categorical(train_labels, 10)
test_labels = tf.keras.utils.to_categorical(test_labels, 10)
  • load_data:加载MNIST数据集,包含60000张训练图像和10000张测试图像。
  • reshape:将图像调整为LSTM需要的输入形状,即每张图像为28个时间步(对应图像的行),每个时间步有28个特征(对应图像的列)。

4. 训练和评估LSTM模型

数据准备好后,我们可以开始训练我们的LSTM模型了。

# 初始化模型
model = LSTMModel(units=128, input_shape=(28, 28), output_dim=10)# 编译模型:选择优化器、损失函数和评估指标
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])# 训练模型
history = model.fit(train_data, train_labels, epochs=5, batch_size=64, validation_data=(test_data, test_labels))
  • model.compile:选择adam作为优化器,categorical_crossentropy作为损失函数,因为我们要解决的是多分类问题(0到9的数字分类)。
  • model.fit:训练模型,设置epochs为5,批次大小为64。

最后,我们在测试集上评估模型的表现:

# 评估模型在测试集上的表现
test_loss, test_acc = model.evaluate(test_data, test_labels, verbose=2)
print('\nTest accuracy:', test_acc)

5. 进一步优化LSTM模型

LSTM本身已经非常强大,但我们仍然可以通过一些优化来提升模型的性能。

5.1 增加更多层

如果任务的复杂性较高,我们可以在LSTM层前后添加更多层,以增强模型的表达能力。

# 多层LSTM模型示例
class MultiLayerLSTMModel(tf.keras.Model):def __init__(self, units, input_shape, output_dim):super(MultiLayerLSTMModel, self).__init__()self.lstm1 = layers.LSTM(units, return_sequences=True, input_shape=input_shape)self.lstm2 = layers.LSTM(units)self.fc = layers.Dense(output_dim, activation='softmax')def call(self, inputs):x = self.lstm1(inputs)x = self.lstm2(x)output = self.fc(x)return output
  • return_sequences=True:允许LSTM层返回每个时间步的输出,这样我们就可以堆叠多个LSTM层。
5.2 使用Dropout和正则化

为了防止模型过拟合,我们可以使用Dropout层和正则化技术。

# 在LSTM模型中添加Dropout层
class LSTMModelWithDropout(tf.keras.Model):def __init__(self, units, input_shape, output_dim):super(LSTMModelWithDropout, self).__init__()self.lstm = layers.LSTM(units, dropout=0.2, recurrent_dropout=0.2, input_shape=input_shape)self.fc = layers.Dense(output_dim, activation='softmax')def call(self, inputs):x = self.lstm(inputs)output = self.fc(x)return output
  • dropoutrecurrent_dropout:在LSTM层中使用Dropout可以有效减少过拟合的风险。

6. 总结

在这篇博客中,我们深入探讨了LSTM的结构与原理,并通过类的方式实现了一个LSTM模型。通过LSTM,我们能够更好地捕捉序列数据中的长时依赖关系。这在手写数字识别任务中具有重要意义,尤其是当我们将图像视为时间序列时。希望这些内容对你理解和应用LSTM有所帮助,快试试将它运用到你的项目中吧!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 区块链知识体系fisco-bcos实战
  • Nature同款富集分析结果条形图叠加基因
  • ros发布图像
  • nacos配置持久化到Mysql数据库
  • Gartner发布2024年应用安全成熟度曲线:26项应用安全最新技术发展及应用状况和趋势
  • 深入解析Python的Pandas库:数据分析的利器(二)
  • 解决STM32使用J-Link可以擦除和读取但是无法烧录问题
  • Linux文件编程(进阶)
  • 每日刷一刷力扣SQL(八)
  • 综合评价 | 基于层次-熵权-变异系数-正态云组合法的综合评价模型(Matlab)
  • java 使用 aws s3 sdk 通过分段下载来实现 html 页面 video 的断点播放、拖动进度播放
  • 小程序面试题一
  • 【SAM下游任务微调】TS-SAM: Fine-Tuning Segment-Anything Model for Downstream Tasks
  • DDoS攻击的应对策略
  • 小程序学习day13-API Promise化、全局数据共享(状态管理)、分包
  • [PHP内核探索]PHP中的哈希表
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • CSS盒模型深入
  • Druid 在有赞的实践
  • express + mock 让前后台并行开发
  • mysql 5.6 原生Online DDL解析
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • vue 个人积累(使用工具,组件)
  • 从0到1:PostCSS 插件开发最佳实践
  • 大整数乘法-表格法
  • 工程优化暨babel升级小记
  • 聚簇索引和非聚簇索引
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 智能网联汽车信息安全
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​Python 3 新特性:类型注解
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • #100天计划# 2013年9月29日
  • #微信小程序(布局、渲染层基础知识)
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (30)数组元素和与数字和的绝对差
  • (7)svelte 教程: Props(属性)
  • (floyd+补集) poj 3275
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (二)换源+apt-get基础配置+搜狗拼音
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (转)EOS中账户、钱包和密钥的关系
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .net开发引用程序集提示没有强名称的解决办法
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • .考试倒计时43天!来提分啦!
  • @ConfigurationProperties注解对数据的自动封装
  • @RequestMapping 的作用是什么?