序列数据总是处理不好?用循环神经网络RNN建模时序依赖
关键词:循环神经网络、RNN、词嵌入、PyTorch、序列建模、文本生成
目录
- 一、为什么传统神经网络搞不定序列数据
- [1.1 序列数据的核心特征](#1.1 序列数据的核心特征 "#11-%E5%BA%8F%E5%88%97%E6%95%B0%E6%8D%AE%E7%9A%84%E6%A0%B8%E5%BF%83%E7%89%B9%E5%BE%81")
- [1.2 RNN的应用场景全景](#1.2 RNN的应用场景全景 "#12-rnn%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E5%85%A8%E6%99%AF")
- 二、自然语言处理为什么需要序列模型
- [2.1 NLP的核心挑战](#2.1 NLP的核心挑战 "#21-nlp%E7%9A%84%E6%A0%B8%E5%BF%83%E6%8C%91%E6%88%98")
- [2.2 从规则到深度学习的范式转变](#2.2 从规则到深度学习的范式转变 "#22-%E4%BB%8E%E8%A7%84%E5%88%99%E5%88%B0%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0%E7%9A%84%E8%8C%83%E5%BC%8F%E8%BD%AC%E5%8F%98")
- 三、词嵌入层:如何让机器理解词语语义
- [3.1 One-Hot编码的致命缺陷](#3.1 One-Hot编码的致命缺陷 "#31-one-hot%E7%BC%96%E7%A0%81%E7%9A%84%E8%87%B4%E5%91%BD%E7%BC%BA%E9%99%B7")
- [3.2 词嵌入的工作原理](#3.2 词嵌入的工作原理 "#32-%E8%AF%8D%E5%B5%8C%E5%85%A5%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86")
- [3.3 PyTorch词嵌入层实战](#3.3 PyTorch词嵌入层实战 "#33-pytorch%E8%AF%8D%E5%B5%8C%E5%85%A5%E5%B1%82%E5%AE%9E%E6%88%98")
- 四、RNN核心原理:网络的"记忆"机制
- [4.1 隐藏状态:RNN的记忆单元](#4.1 隐藏状态:RNN的记忆单元 "#41-%E9%9A%90%E8%97%8F%E7%8A%B6%E6%80%81rnn%E7%9A%84%E8%AE%B0%E5%BF%86%E5%8D%95%E5%85%83")
- [4.2 RNN神经元内部计算过程](#4.2 RNN神经元内部计算过程 "#42-rnn%E7%A5%9E%E7%BB%8F%E5%85%83%E5%86%85%E9%83%A8%E8%AE%A1%E7%AE%97%E8%BF%87%E7%A8%8B")
- [4.3 文本生成的完整流程](#4.3 文本生成的完整流程 "#43-%E6%96%87%E6%9C%AC%E7%94%9F%E6%88%90%E7%9A%84%E5%AE%8C%E6%95%B4%E6%B5%81%E7%A8%8B")
- [4.4 PyTorch RNN层API实战](#4.4 PyTorch RNN层API实战 "#44-pytorch-rnn%E5%B1%82api%E5%AE%9E%E6%88%98")
- 五、实战:用RNN实现AI歌词生成器
- [5.1 数据集准备与词表构建](#5.1 数据集准备与词表构建 "#51-%E6%95%B0%E6%8D%AE%E9%9B%86%E5%87%86%E5%A4%87%E4%B8%8E%E8%AF%8D%E8%A1%A8%E6%9E%84%E5%BB%BA")
- [5.2 构建Dataset对象](#5.2 构建Dataset对象 "#52-%E6%9E%84%E5%BB%BAdataset%E5%AF%B9%E8%B1%A1")
- [5.3 搭建文本生成网络](#5.3 搭建文本生成网络 "#53-%E6%90%AD%E5%BB%BA%E6%96%87%E6%9C%AC%E7%94%9F%E6%88%90%E7%BD%91%E7%BB%9C")
- [5.4 训练函数编写](#5.4 训练函数编写 "#54-%E8%AE%AD%E7%BB%83%E5%87%BD%E6%95%B0%E7%BC%96%E5%86%99")
- [5.5 预测函数与歌词生成](#5.5 预测函数与歌词生成 "#55-%E9%A2%84%E6%B5%8B%E5%87%BD%E6%95%B0%E4%B8%8E%E6%AD%8C%E8%AF%8D%E7%94%9F%E6%88%90")
- 常见问题
- 和AI大模型开发的关系
- 总结
一、为什么传统神经网络搞不定序列数据
1.1 序列数据的核心特征
在处理图像分类、表格数据等任务时,传统的前馈神经网络表现不错。但当我们面对序列数据时,这些网络就力不从心了。
什么是序列数据?简单说就是后面的数据跟前面的数据有关系的数据。
举个例子:
- 时间序列:今天的气温和昨天有关,明天的气温又和今天有关
- 文本序列:"我"后面接"爱"再接"你",顺序不能颠倒
- 语音信号:当前发音和前面的发音有连续性
序列数据的核心特点:上下文依赖。 当前时刻的输出不仅取决于当前时刻的输入,还取决于历史输入。
图一:序列数据与传统数据对比

传统前馈神经网络处理每个输入时都是"失忆"的------它不记得之前处理过什么。但序列任务恰恰需要"记住"历史信息,这就是RNN登场的理由。
1.2 RNN的应用场景全景
RNN专为序列数据设计,主要应用在以下领域:
| 应用领域 | 具体任务 | 序列特征 |
|---|---|---|
| 自然语言处理 | 文本生成、机器翻译、情感分析 | 词语顺序决定语义 |
| 时间序列预测 | 股票预测、气象预报、传感器分析 | 历史值影响未来值 |
| 语音识别 | 语音转文字 | 发音具有连续性 |
| 音乐生成 | 自动作曲 | 音符之间存在和声关系 |
这些任务的共同点是:输入或输出(或两者)都是具有顺序依赖的序列。
二、自然语言处理为什么需要序列模型
2.1 NLP的核心挑战
自然语言处理(Natural Language Processing, NLP)研究的是让计算机算法理解人类语言。
人类语言有几个让计算机头疼的特点:
- 非结构化:不像数据库表格那样规整,语言是自由流动的文本
- 歧义性:同一个词在不同语境下意思不同("银行"可以是金融机构,也可以是河岸)
- 顺序敏感:"猫追狗"和"狗追猫"完全是两个故事
- 上下文依赖:代词"它"指代什么,需要往前文找答案
图二:NLP技术体系

(图二:NLP涵盖语法分析、语义理解、情感分析、机器翻译等多个技术方向)
2.2 从规则到深度学习的范式转变
早期的NLP系统依赖人工编写的规则(正则表达式、语法树等),但这种方式:
- 规则覆盖有限,遇到新表达就失效
- 无法处理语言的模糊性和创造性
- 维护成本极高
深度学习时代,我们让模型自己从数据中学习语言规律,RNN就是其中关键的一环------它通过循环结构天然地捕捉序列中的上下文关系。
三、词嵌入层:如何让机器理解词语语义
3.1 One-Hot编码的致命缺陷
在深度学习处理文本之前,我们需要先把文字转换成数字。最直观的方法是One-Hot编码:
假设词表有10000个词,"猫"是第5个词,那么它的One-Hot编码就是:
csharp
[0, 0, 0, 0, 1, 0, 0, ..., 0] # 长度为10000,只有第5位是1
这种方式有两个致命问题:
- 维度灾难:词表越大,向量越长,计算量爆炸
- 语义丢失:"猫"和"狗"的One-Hot向量正交(内积为0),无法体现它们的相似性
3.2 词嵌入的工作原理
词嵌入(Word Embedding)的核心思想是:用低维稠密向量表示词语,让语义相似的词在向量空间中距离更近。
图三:词嵌入层工作流程

(图三:词嵌入将离散的词索引映射为连续的低维稠密向量)
工作流程:
- 构建词表:统计语料中所有不重复的词,每个词分配一个唯一索引
- 初始化嵌入矩阵 :形状为
[词数量, 嵌入维度],比如100个词 × 128维 - 查表操作:输入词索引,输出对应的嵌入向量
训练过程中,这个嵌入矩阵会不断更新,最终学会捕捉词语之间的语义关系。比如"猫"和"狗"的向量会靠得很近,而"猫"和"汽车"会相距甚远。
3.3 PyTorch词嵌入层实战
PyTorch提供了nn.Embedding层来实现词嵌入:
python
import torch
import torch.nn as nn
import jieba
def demonstrate_word_embedding():
"""演示词嵌入层的使用"""
# 示例文本:AI技术相关
text = '大模型正在改变软件开发的方式,RAG技术让企业知识库焕发新生。'
# 1. 分词
words = jieba.lcut(text)
print(f'分词结果: {words}')
# 2. 去重构建唯一词表
unique_words = list(set(words))
print(f"唯一词数量: {len(unique_words)}")
# 3. 构建词嵌入层
# num_embeddings: 词表大小
# embedding_dim: 每个词的向量维度
embed_layer = nn.Embedding(num_embeddings=len(unique_words), embedding_dim=8)
print(f"词嵌入层: {embed_layer}")
# 4. 获取每个词的向量表示
for i, word in enumerate(unique_words):
word_vector = embed_layer(torch.tensor(i))
print(f'{word: <4} -> {word_vector}')
if __name__ == '__main__':
demonstrate_word_embedding()
输出结果:
css
分词结果: ['大模型', '正在', '改变', '软件', '开发', '的', '方式', ',', 'RAG', '技术', '让', '企业', '知识库', '焕发', '新生', '。']
唯一词数量: 16
词嵌入层: Embedding(16, 8)
大模型 -> tensor([ 0.5234, -1.2341, 0.8765, ...], grad_fn=<EmbeddingBackward0>)
正在 -> tensor([-0.3421, 0.7654, -1.1234, ...], grad_fn=<EmbeddingBackward0>)
...
关键点:
- 词嵌入层的参数就是那个嵌入矩阵,形状为
[词数量, 嵌入维度] - 初始值是随机的,随着训练会学到语义信息
- 每个词对应矩阵中的一行,输入索引就是行号
四、RNN核心原理:网络的"记忆"机制
4.1 隐藏状态:RNN的记忆单元
RNN之所以能处理序列数据,核心在于它的**隐藏状态(Hidden State)**机制。
图四:RNN展开结构示意图

(图四:RNN在每个时间步共享参数,隐藏状态h携带历史信息传递给下一步)
理解RNN的关键点:
- 同一个神经元,重复使用 :虽然图上画了多个神经元,但实际上是同一个神经元在不同时间步被重复调用
- 隐藏状态是桥梁:每个时间步的输出隐藏状态会作为下一个时间步的输入之一
- 信息传递:隐藏状态携带了从序列开始到当前时刻的所有历史信息
用API客服场景来理解:
- 用户说:"我的订单" → RNN记住"订单"这个关键词
- 用户接着说:"还没收到" → RNN结合"订单"+"还没收到",判断是物流查询意图
- 如果顺序反过来:"还没收到" + "我的订单",语义完全不同
4.2 RNN神经元内部计算过程
每个时间步,RNN神经元执行两步计算:
第一步:更新隐藏状态
arduino
h_t = tanh(W_ih * x_t + b_ih + W_hh * h_{t-1} + b_hh)
其中:
x_t:当前时间步的输入(比如当前词的词向量)h_{t-1}:上一时间步的隐藏状态W_ih、b_ih:输入到隐藏层的权重和偏置W_hh、b_hh:隐藏状态到隐藏层的权重和偏置tanh:激活函数,将输出压缩到-1, 1
第二步:计算当前输出
arduino
y_t = W_hy * h_t + b_y
其中:
h_t:当前隐藏状态W_hy、b_y:隐藏状态到输出的权重和偏置y_t:当前时间步的预测输出
图五:RNN神经元内部计算流程

(图五:每个时间步接收当前输入和上一时刻隐藏状态,输出新隐藏状态和预测结果)
4.3 文本生成的完整流程
以AI客服自动回复生成为例,输入"您好,请问",预测下一个词:
- 初始化 :
h_0 = [0, 0, ..., 0](全零向量) - 时间步1 :输入"您好"的词向量 → 计算得到
h_1和输出y_1 - 时间步2 :输入"请问"的词向量 +
h_1→ 计算得到h_2和输出y_2 - 输出映射 :将
h_2通过全连接层 → 得到词表上每个词的概率分布 - 选择词:取概率最高的词作为预测结果
图六:文本生成逐步预测过程

(图六:RNN逐步生成文本,每个时间步基于当前隐藏状态预测下一个词的概率分布)
4.4 PyTorch RNN层API实战
python
import torch
import torch.nn as nn
def demonstrate_rnn_layer():
"""演示PyTorch RNN层的输入输出"""
# 构建RNN层
# input_size: 输入特征维度(通常等于词嵌入维度)
# hidden_size: 隐藏状态维度
# num_layers: RNN层数
rnn = nn.RNN(input_size=128, hidden_size=256, num_layers=1)
# 准备输入数据
# 形状: [seq_len, batch_size, input_size]
# 5个时间步(句子长度),32个句子(batch),每个词128维
inputs = torch.randn(5, 32, 128)
# 初始隐藏状态
# 形状: [num_layers, batch_size, hidden_size]
h0 = torch.zeros(1, 32, 256)
# 前向传播
output, hn = rnn(inputs, h0)
print(f"输入形状: {inputs.shape}") # [5, 32, 128]
print(f"输出形状: {output.shape}") # [5, 32, 256]
print(f"隐藏状态形状: {hn.shape}") # [1, 32, 256]
if __name__ == '__main__':
demonstrate_rnn_layer()
维度解析:
output:每个时间步的输出,形状[seq_len, batch, hidden_size]hn:最后一个时间步的隐藏状态,形状[num_layers, batch, hidden_size]- 如果要做文本生成,需要的是每个时间步的
output;如果要做序列分类,通常取最后一个时间步的hn
五、实战:用RNN实现AI歌词生成器
5.1 数据集准备与词表构建
我们收集了某知名歌手的歌词数据集,训练一个能自动生成歌词的RNN模型。
python
import jieba
def build_vocabulary():
"""构建歌词词表"""
file_path = 'data/lyrics_corpus.txt'
unique_words = []
all_words = []
# 读取并分词
for line in open(file_path, 'r', encoding='utf-8'):
words = jieba.lcut(line.strip())
all_words.append(words)
# 去重并保持顺序
for word in words:
if word not in unique_words:
unique_words.append(word)
# 构建词到索引的映射
word_to_idx = {word: idx for idx, word in enumerate(unique_words)}
# 将整个语料转换为索引序列
corpus_idx = []
for words in all_words:
for word in words:
corpus_idx.append(word_to_idx[word])
# 行间用空格分隔
corpus_idx.append(word_to_idx[' '])
return unique_words, word_to_idx, len(unique_words), corpus_idx
if __name__ == "__main__":
unique_words, word_to_idx, vocab_size, corpus = build_vocabulary()
print(f"词表大小: {vocab_size}")
print(f"语料总词数: {len(corpus)}")
5.2 构建Dataset对象
为了支持批量训练,需要构建PyTorch Dataset:
python
import torch
class LyricsDataset(torch.utils.data.Dataset):
"""歌词序列数据集"""
def __init__(self, corpus_idx, seq_length):
self.corpus_idx = corpus_idx
self.seq_length = seq_length
self.total_words = len(corpus_idx)
# 可提取的样本数量
self.num_samples = self.total_words // self.seq_length
def __len__(self):
return self.num_samples
def __getitem__(self, idx):
# 计算起始位置,防止越界
start = min(max(idx, 0), self.total_words - self.seq_length - 1)
end = start + self.seq_length
# 输入序列
x = self.corpus_idx[start: end]
# 目标序列(输入序列后移一位)
y = self.corpus_idx[start + 1: end + 1]
return torch.tensor(x), torch.tensor(y)
if __name__ == "__main__":
unique_words, word_to_idx, vocab_size, corpus = build_vocabulary()
dataset = LyricsDataset(corpus, seq_length=32)
print(f"样本数量: {len(dataset)}")
x, y = dataset[0]
print(f"输入序列: {x}")
print(f"目标序列: {y}")
关键设计:
- 输入
x和目标y的关系:y是x向后移动一个位置 - 这就是"根据前N个词预测下一个词"的序列生成任务
5.3 搭建文本生成网络
python
import torch.nn as nn
class LyricGenerator(nn.Module):
"""歌词生成网络"""
def __init__(self, vocab_size):
super(LyricGenerator, self).__init__()
# 词嵌入层:词表大小 -> 128维
self.embedding = nn.Embedding(vocab_size, 128)
# RNN层:128维输入 -> 256维隐藏状态
self.rnn = nn.RNN(128, 256, num_layers=1)
# 输出层:256维 -> 词表大小(每个词的预测分数)
self.fc = nn.Linear(256, vocab_size)
def forward(self, x, hidden):
# x形状: [batch, seq_len]
# 词嵌入: [batch, seq_len, 128]
embed = self.embedding(x)
# RNN需要[seq_len, batch, input_size]格式
# transpose后: [seq_len, batch, 128]
output, hidden = self.rnn(embed.transpose(0, 1), hidden)
# 全连接层需要二维输入
# reshape: [seq_len * batch, 256]
# 输出: [seq_len * batch, vocab_size]
output = self.fc(output.reshape(-1, output.shape[-1]))
return output, hidden
def init_hidden(self, batch_size):
# 初始化隐藏状态: [num_layers, batch, hidden_size]
return torch.zeros(1, batch_size, 256)
网络架构总结:
scss
词索引 → Embedding(128维) → RNN(256维隐藏) → Linear(词表大小) → 每个词的分数
5.4 训练函数编写
python
from torch.utils.data import DataLoader
import torch.optim as optim
import time
def train_model():
"""训练歌词生成模型"""
# 构建词表
unique_words, word_to_idx, vocab_size, corpus = build_vocabulary()
# 数据集和数据加载器
dataset = LyricsDataset(corpus, seq_length=32)
dataloader = DataLoader(dataset, shuffle=True, batch_size=5)
# 模型、损失函数、优化器
model = LyricGenerator(vocab_size)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-3)
# 训练循环
epochs = 10
for epoch in range(epochs):
start_time = time.time()
total_loss = 0.0
iter_count = 0
for x, y in dataloader:
# 初始化隐藏状态
hidden = model.init_hidden(batch_size=5)
# 前向传播
output, hidden = model(x, hidden)
# 调整y的形状以匹配output
# y: [batch, seq_len] -> [seq_len * batch]
y_flat = torch.transpose(y, 0, 1).reshape(-1)
# 计算损失
loss = criterion(output, y_flat)
# 反向传播
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
iter_count += 1
avg_loss = total_loss / iter_count
elapsed = time.time() - start_time
print(f'Epoch {epoch+1:3d} | Loss: {avg_loss:.5f} | Time: {elapsed:.2f}s')
# 保存模型
torch.save(model.state_dict(), 'model/lyric_generator.pth')
print("模型已保存")
if __name__ == "__main__":
train_model()
训练输出:
yaml
Epoch 1 | Loss: 1.84424 | Time: 5.75s
Epoch 2 | Loss: 0.21154 | Time: 5.91s
Epoch 3 | Loss: 0.12014 | Time: 5.85s
...
Epoch 10 | Loss: 0.09568 | Time: 5.77s
5.5 预测函数与歌词生成
python
def generate_lyrics(start_word, length=50):
"""生成歌词"""
unique_words, word_to_idx, vocab_size, _ = build_vocabulary()
# 加载训练好的模型
model = LyricGenerator(vocab_size)
model.load_state_dict(torch.load('model/lyric_generator.pth'))
model.eval()
# 初始化
hidden = model.init_hidden(batch_size=1)
word_idx = word_to_idx[start_word]
generated = [word_idx]
# 逐步生成
for _ in range(length):
output, hidden = model(torch.tensor([[word_idx]]), hidden)
# 取概率最高的词
word_idx = torch.argmax(output).item()
generated.append(word_idx)
# 转换为文本
result = ''.join([unique_words[idx] for idx in generated])
print(result)
if __name__ == '__main__':
generate_lyrics('星空', length=50)
生成结果示例:
星空下的约定 还记得那年夏天
我们坐在屋顶数星星 你说未来要去远方
星空 星空 一片一片 像我们的梦想
一步一步 走向未知的远方
常见问题
Q1:RNN为什么会有梯度消失/爆炸问题?
RNN的隐藏状态计算涉及连乘操作(W_hh在多个时间步重复使用)。当序列很长时:
- 如果
W_hh的特征值 < 1,连乘后梯度趋近于0(消失) - 如果
W_hh的特征值 > 1,连乘后梯度趋近于无穷(爆炸)
解决方案 :使用LSTM/GRU替代标准RNN,或者使用梯度裁剪(torch.nn.utils.clip_grad_norm_)。
Q2:词嵌入维度怎么选?
经验法则:
- 小词表(<10000词):50~128维
- 中等词表(10000
100000词):128300维 - 大词表(>100000词):300维以上
维度太低无法捕捉语义,太高容易过拟合且计算量大。
Q3:训练时loss下降但生成结果不通顺怎么办?
这是典型的"过拟合训练数据但泛化能力差"问题:
- 增加训练数据量
- 降低学习率,增加训练轮数
- 添加Dropout层防止过拟合
- 尝试更大的hidden_size让模型有更强的表达能力
Q4:RNN只能从左到右处理序列吗?
标准RNN是单向的(从左到右)。如果需要双向上下文,可以使用nn.RNN(bidirectional=True),它会同时从左到右和从右到左处理序列,最后拼接两个方向的隐藏状态。
和AI大模型开发的关系
RNN虽然是较早期的序列建模技术,但在大模型时代仍有重要价值:
场景一:轻量级文本分类器
对于不需要大模型的简单分类任务,RNN是高效选择:
python
import torch.nn as nn
class SimpleTextClassifier(nn.Module):
"""基于RNN的轻量级文本分类器"""
def __init__(self, vocab_size, num_classes):
super().__init__()
self.embedding = nn.Embedding(vocab_size, 64)
self.rnn = nn.RNN(64, 128, bidirectional=True)
self.fc = nn.Linear(256, num_classes) # 双向所以维度翻倍
def forward(self, x):
embed = self.embedding(x)
_, hidden = self.rnn(embed.transpose(0, 1))
# 拼接双向最后一个隐藏状态
hidden_cat = torch.cat([hidden[-2], hidden[-1]], dim=-1)
return self.fc(hidden_cat)
# 使用示例:客服工单分类
classifier = SimpleTextClassifier(vocab_size=5000, num_classes=5)
# 5个类别:物流查询、退换货、投诉、咨询、其他
场景二:流式语音识别的前端处理
python
class StreamingFeatureExtractor(nn.Module):
"""流式音频特征提取器(用于实时语音识别)"""
def __init__(self, input_dim, hidden_dim):
super().__init__()
# 先用CNN提取局部频谱特征
self.cnn = nn.Conv1d(input_dim, 64, kernel_size=3, padding=1)
# 再用RNN建模时序依赖
self.rnn = nn.GRU(64, hidden_dim, num_layers=2)
def forward(self, audio_features, hidden):
# audio_features: [batch, seq_len, input_dim]
cnn_out = self.cnn(audio_features.transpose(1, 2)).transpose(1, 2)
rnn_out, new_hidden = self.rnn(cnn_out.transpose(0, 1), hidden)
return rnn_out, new_hidden
场景三:对话系统的意图识别
python
class IntentRecognizer(nn.Module):
"""对话意图识别器"""
def __init__(self, vocab_size, intent_num):
super().__init__()
self.embedding = nn.Embedding(vocab_size, 128)
self.rnn = nn.LSTM(128, 256, num_layers=1, batch_first=True)
self.attention = nn.Linear(256, 1)
self.classifier = nn.Linear(256, intent_num)
def forward(self, input_ids):
# 词嵌入
embed = self.embedding(input_ids)
# LSTM编码
rnn_out, _ = self.rnn(embed)
# 简单注意力加权
weights = torch.softmax(self.attention(rnn_out), dim=1)
context = torch.sum(weights * rnn_out, dim=1)
# 分类
return self.classifier(context)
场景四:大模型输出后处理
python
class LLMOutputRefiner(nn.Module):
"""大模型输出的后处理校正器"""
def __init__(self, vocab_size):
super().__init__()
# 用小型RNN校正大模型生成的文本
self.rnn = nn.GRU(vocab_size, 128, num_layers=1)
self.corrector = nn.Linear(128, vocab_size)
def forward(self, llm_output_probs):
# llm_output_probs: 大模型输出的概率分布序列
# 用RNN捕捉序列一致性,修正不合理之处
rnn_out, _ = self.rnn(llm_output_probs.transpose(0, 1))
corrected = self.corrector(rnn_out)
return corrected
总结
今天我们系统学习了循环神经网络RNN的核心知识:
- 序列数据的本质:前后数据存在依赖关系,传统前馈网络无法处理
- 词嵌入层:将离散词语转换为低维稠密向量,解决One-Hot编码的语义丢失问题
- RNN记忆机制:通过隐藏状态在时间步之间传递信息,实现序列建模
- 文本生成实战:从词表构建、Dataset设计、网络搭建到训练预测的完整流程
RNN是理解序列建模的基石,虽然后续有LSTM、GRU、Transformer等更强大的架构,但RNN的核心思想------用隐藏状态携带历史信息------贯穿了整个序列模型的发展史。
#循环神经网络 #RNN #自然语言处理 #PyTorch #文本生成 #词嵌入 #序列建模