news 2026/4/23 3:18:06

MindSpore开发之路:构建循环神经网络(RNN):`RNN`, `LSTM`, `Embedding`层

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MindSpore开发之路:构建循环神经网络(RNN):`RNN`, `LSTM`, `Embedding`层

1. RNN是什么

对于序列数据,CNN那种“一视同仁”的局部感知能力就不太够用了,因为序列中的每个元素都可能与它之前的所有元素相关。这时,我们就需要一种新的网络结构——循环神经网络(Recurrent Neural Network, RNN)。

RNN就像一个拥有“记忆”的阅读者。当它处理序列中的一个元素时(比如一个单词),它不仅会关注这个单词本身,还会参考它对前面所有单词的“记忆”。这种循环往复、承前启后的机制,使得RNN在自然语言处理(NLP)、时间序列预测等领域取得了巨大成功。

本篇文章将带您走进RNN的世界,重点介绍在MindSpore中构建RNN模型所需的三个核心“零件”。

2. RNN的核心“零件”

处理序列数据,尤其是文本数据时,我们通常需要以下三个关键组件的配合。

2.1 词嵌入层 (nn.Embedding):文字到向量的桥梁

计算机无法直接理解“你好”、“世界”这样的文字。为了让神经网络能够处理文本,我们首先需要将每个字或词转换成一个固定长度的数字向量。这个过程就叫做词嵌入(Word Embedding)。

  • 工作原理:nn.Embedding层就像一本“密码本”(或字典)。你首先要确定你的词汇表有多大(vocab_size),以及你想用多长的向量来表示一个词(embedding_size)。nn.Embedding层内部会维护一个vocab_size * embedding_size大小的查询表。当你输入一个词的索引(一个整数)时,它就会从表中查出对应的向量作为输出。
  • 关键参数:
    • vocab_size(int): 词汇表的大小。例如,如果你的词典里有1000个不同的词,这个值就是1000。
    • embedding_size(int): 用来表示一个词的向量的维度。
  • 代码示例:
import mindspore from mindspore import nn, Tensor import numpy as np # 假设我们的词汇表大小为1000,每个词用100维的向量表示 vocab_size = 1000 embedding_size = 100 # 定义一个Embedding层 embedding_layer = nn.Embedding(vocab_size, embedding_size) # 假设我们有一句话,它包含4个词,其在词典中的索引分别是 1, 5, 99, 0 # 输入的shape通常是 (batch_size, sequence_length) input_indices = Tensor([[1, 5, 99, 0]], mindspore.int32) # 将索引输入Embedding层 output_vectors = embedding_layer(input_indices) print("输入索引的尺寸:", input_indices.shape) print("输出词向量的尺寸:", output_vectors.shape) # (1, 4, 100)

2.2 循环神经网络层 (nn.RNN):最初的“记忆”单元

nn.RNN是MindSpore中基础的循环神经网络层。

  • 工作原理:RNN的核心在于其内部的“循环”。对于一个长度为L的序列,RNN层会按时间步从t=0t=L-1依次处理每个元素的向量。在每个时间步t,它会接收两个输入:
  1. 当前时间步的输入向量x_t
  2. 上一个时间步的隐藏状态h_{t-1}(可以理解为“短期记忆”)。

它将这两个输入融合,计算出当前时间步的输出output_t和新的隐藏状态h_t,然后将h_t传递给下一个时间步。这个h_t就构成了RNN的“记忆”。

  • 关键参数:
    • input_size(int): 输入向量的维度(通常等于embedding_size)。
    • hidden_size(int): 隐藏状态向量的维度。
    • batch_first(bool): 如果为True,则输入和输出Tensor的维度顺序为(batch, seq_len, input_size),这通常更直观。
  • 代码示例:
# 承接上例,词向量维度为100,我们设定RNN的隐藏层维度为32 input_size = 100 hidden_size = 32 seq_len = 4 # 序列长度 batch_size = 1 # 批量大小 # 定义一个RNN层 # batch_first=True 让输入的第一维是batch_size rnn_layer = nn.RNN(input_size, hidden_size, batch_first=True) # 将Embedding层的输出作为RNN的输入 # output_vectors 的 shape 是 (1, 4, 100) output, hidden_state = rnn_layer(output_vectors) print("RNN输出(所有时间步)的尺寸:", output.shape) # (1, 4, 32) print("RNN最后一个时间步的隐藏状态尺寸:", hidden_state.shape) # (1, 1, 32)
局限性:基础的RNN存在一个著名的问题——梯度消失/爆炸。当序列很长时,它很难学习到序列开头的“长期依赖”信息,就像一个人记性不好,读到后面就忘了前面讲了什么。

2.3 长短期记忆网络层 (nn.LSTM):更强大的“记忆”单元

为了解决RNN的“记性差”的问题,研究者们设计了长短期记忆网络(Long Short-Term Memory, LSTM)。LSTM是RNN的一种变体,也是目前应用最广泛的循环神经网络之一。

  • 工作原理:LSTM的核心在于其内部精巧的“门控机制”。相比于RNN简单的隐藏状态,LSTM引入了一个细胞状态(Cell State),可以看作是“长期记忆”。它还设计了三个“门”来控制信息的流动:
  1. 遗忘门(Forget Gate):决定从长期记忆中丢弃哪些信息。
  2. 输入门(Input Gate):决定将哪些新的信息存入长期记忆。
  3. 输出门(Output Gate):决定从长期记忆中输出哪些信息作为当前时间步的隐藏状态。

通过这套机制,LSTM能够有选择地记忆和遗忘,从而有效地捕捉长距离依赖关系。

  • 关键参数:与nn.RNN基本相同。
  • 代码示例:
# 定义一个LSTM层,参数与RNN类似 lstm_layer = nn.LSTM(input_size, hidden_size, batch_first=True) # 将同样的词向量输入LSTM层 # LSTM的输出包含 output, (h_n, c_n) output, (h_n, c_n) = lstm_layer(output_vectors) print("LSTM输出(所有时间步)的尺寸:", output.shape) # (1, 4, 32) print("LSTM最后一个时间步的隐藏状态尺寸:", h_n.shape) # (1, 1, 32) print("LSTM最后一个时间步的细胞状态尺寸:", c_n.shape) # (1, 1, 32)

3. 组装一个简单的序列处理模型

现在,我们将这三个“零件”组装起来,构建一个可用于文本分类等任务的基础模型结构。

import mindspore from mindspore import nn class SimpleSentimentClassifier(nn.Cell): def __init__(self, vocab_size, embedding_size, hidden_size, num_classes): super(SimpleSentimentClassifier, self).__init__() # 1. Embedding层 self.embedding = nn.Embedding(vocab_size, embedding_size) # 2. LSTM层 self.lstm = nn.LSTM(embedding_size, hidden_size, batch_first=True) # 3. 全连接层 (分类器) self.fc = nn.Dense(hidden_size, num_classes) def construct(self, x): # x 的 shape: (batch_size, seq_len) # 1. 经过Embedding层 # embedded 的 shape: (batch_size, seq_len, embedding_size) embedded = self.embedding(x) # 2. 经过LSTM层 # lstm_out shape: (batch_size, seq_len, hidden_size) # h_n shape: (1, batch_size, hidden_size) lstm_out, (h_n, c_n) = self.lstm(embedded) # 3. 我们通常取最后一个时间步的输出来代表整句话的语义 # last_output shape: (batch_size, hidden_size) last_output = lstm_out[:, -1, :] # 4. 经过全连接层得到分类结果 # logits shape: (batch_size, num_classes) logits = self.fc(last_output) return logits # 实例化网络 model = SimpleSentimentClassifier(vocab_size=1000, embedding_size=100, hidden_size=32, num_classes=2) # 假设是二分类(如情感积极/消极) print(model)

4. 总结

在本篇文章中,我们学习了处理序列数据的利器——循环神经网络,并掌握了其在MindSpore中的三个核心组件:

  • nn.Embedding:将离散的词符转换为密集的向量,是处理文本数据的第一步。
  • nn.RNN:基础的循环网络层,通过传递隐藏状态来维持“短期记忆”。
  • nn.LSTM:RNN的强大变体,通过精巧的门控机制实现了“长短期记忆”,能更好地捕捉序列中的长距离依赖。

通过组合这三个组件,我们构建了一个简单的序列处理模型,为后续进行文本分类、机器翻译等NLP实战任务奠定了基础。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 20:47:12

【建议收藏】大模型理论与实践:一文掌握核心技术路线

文章通过类比人类成长历程,系统梳理了大模型的理论知识路线,包括发展历程、基于Transformer的主流框架、RAG与Fine-tuning技术的比较与应用场景,以及人类对齐的RLHF技术。文章指出,预训练是构建大语言模型的基础阶段,而…

作者头像 李华
网站建设 2026/4/19 6:06:11

COMSOL三维摩擦发电机数值计算模拟:不同电极摩擦产生的电荷密度与电势、电场分布研究

comsol三维摩擦发电机数值计算模拟,不同电极摩擦产生的电荷密度引起的电势和电场分布摩擦发电机数值模拟这活儿,说难不难但细节多得能逼疯强迫症。前几天在COMSOL里折腾三维模型时,突然发现不同电极材料摩擦后的电荷密度分布就像两个性格迥异…

作者头像 李华
网站建设 2026/4/20 22:43:05

全网最全9个论文写作工具,一键生成论文工具推荐!

全网最全9个论文写作工具,一键生成论文工具推荐! 论文写作的“加速器”:AI 工具如何改变研究生的学习方式 在当今学术研究日益复杂的背景下,研究生们面对的不仅是繁重的课程任务,还有论文写作带来的巨大压力。尤其是在…

作者头像 李华
网站建设 2026/4/22 7:57:34

Z-Image-Edit支持视频帧编辑吗?未来可能性探讨

Z-Image-Edit 支持视频帧编辑吗?未来可能性探讨 在短视频、AI生成内容(AIGC)和智能影视制作高速发展的今天,一个自然的问题浮出水面:我们能否用像 Z-Image-Edit 这样的图像编辑大模型,来实现对视频的逐帧智…

作者头像 李华