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

PyTorch实战(7)——循环神经网络

PyTorch实战(7)——循环神经网络

    • 0. 前言
    • 1. 循环神经网络发展历程
      • 1.1 循环神经网络的类型
      • 1.2 循环神经网络
    • 2. RNN 变体
      • 2.1 双向 RNN (Bidirectional RNN)
      • 2.2 长短期记忆网络
      • 2.3 扩展和双向 LSTM
      • 2.4 多维 RNN
      • 2.5 堆叠 LSTM
      • 2.6 GRU
      • 2.7 网格 LSTM
      • 2.8 正交门控循环单元
    • 3. 训练 RNN 实现情感分析
      • 3.1 文本数据集预处理
      • 3.2 模型训练
    • 4. GRU 和注意力机制
      • 4.1 GRU
      • 4.2 基于注意力的模型
    • 小结
    • 系列链接

0. 前言

神经网络作为强大的机器学习工具,能够学习数据集中输入 XXX 与输出 yyy 之间的复杂映射关系。卷积神经网络 (Convolutional Neural Network, CNN) 建立的是 XXXyyy 间的一对一映射关系,即每个输入 XXX 相互独立,每个输出 yyy 也彼此无关。在本节中,我们将探讨循环模型,其处理的数据不再是独立的数据点,而是具有时间关联性的序列数据 [X1,X2,...,Xk][X_1, X_2, ..., X_k][X1,X2,...,Xk][y1,y2,...,yk][y_1, y_2, ..., y_k][y1,y2,...,yk]。例如 X2X_2X2 依赖于 X1X_1X1X3X_3X3 同时依赖于 X2X_2X2X1X_1X1,以此类推。这类网络称为循环神经网络 (Recurrent Neural Network, RNN)。通过引入循环连接权重,能够有效建模数据的时间特性。这有助于保持状态,如下图所示:

RNN

网络能够将时间步 ttt 的中间输出作为时间步 t+1t+1t+1 的输入,同时维护隐藏的内部状态。跨时间步的连接称为循环连接。本节将重点介绍各种循环神经网络架构的发展历程,包括基础 RNN 及其变体、长短期记忆网络 (Long Short-Term Memory, LSTM) 和门控循环单元 ( Gated Recurrent Unit, GRU)。我们将使用 PyTorch 实现这些架构,并在实际序列建模任务中进行训练和测试。除了模型训练和测试,还将学习如何高效地使用 PyTorch 加载和预处理序列数据。通过本节学习,将能够使用 PyTorch 解决序列数据集的机器学习问题。

1. 循环神经网络发展历程

在本节中,我们将探索循环神经网络的发展历程,讨论和分析架构的演变过程,回顾循环神经网络 (Recurrent Neural Network, RNN) 发展的关键节点。在展开介绍之前,我们首先简要回顾不同类型的 RNN 及其与普通前馈神经网络 (Feedforward Neural Network, FFNN) 的关系。

1.1 循环神经网络的类型

与传统监督学习建模一对一关系不同,RNN 能够建模多种类型的输入-输出关系,包括:

  • 多对多(即时型,Instantaneous),例如命名实体识别,给定一段句子/文本,为其中的词语标注命名实体类别,如人名、机构名、地名等
  • 多对多(编码器-解码器型,Encoder-Decoder),例如机器翻译(如将英文翻译为中文),输入一句话或一段文本,将其编码为一个固定大小的表示,然后解码该表示,生成另一种语言中等效的句子或文本
  • 多对一,例如情感分析,给定一句话或一段文本,将其分类为正面、负面、中性等情感类别
  • 一对多,如图像描述生成,给定一张图片,生成描述其内容的句子或文本
  • 一对一(实用性较低),如图像分类,通过顺序处理图像像素。

下图展示了这些 RNN 类型与经典前馈神经网络的对比:

RNN架构

可以看到,循环神经网络架构中包含常规神经网络中没有的循环连接,循环连接在时间维度上展开后,能清晰展示其处理序列数据的特性。下图展示了 RNN 在时间折叠和时间展开两种形式下的结构:

RNN架构

在后续学习中,我们将采用时间展开的形式来演示 RNN 架构。在上图中,用粉色标注的 RNN 层实质上是网络的隐藏层。虽然表面看只有一个隐藏层,但当其沿时间维度展开后,实际会形成 TTT 个隐藏层( TTT 代表序列数据的时间步总数)。RNN 的核心优势在于能处理可变长度的序列数据。对于不同长度的序列,常用的处理方法是对较短的序列进行填充,对较长的序列进行截断。
接下来,我们将从基础 RNN 开始,介绍 RNN 架构的发展历程。

1.2 循环神经网络

循环神经网络 (Recurrent Neural Network, RNN) 的雏形可追溯至 1982 年的 Hopfield 网络,Hopfield 网络是一种特殊类型的 RNN,试图模拟人类记忆的工作方式。随后,David Rumelhart 等人正式确立了 RNN 的基础架构,使其具备处理序列和记忆信息的能力。之后的改进历程如下图所示:

RNN发展历程

虽然该时间轴未涵盖全部演进过程,但标明了关键节点。接下来,我们按时间顺序讨论 RNN 的重要变体,从双向 RNN 开始。

2. RNN 变体

2.1 双向 RNN (Bidirectional RNN)

尽管 RNN 擅长处理序列数据,但研究者发现某些任务(如语言翻译)需要同时考虑前后文信息。例如英语 “I see you” 翻译为法语 “Je te vois” 时,必须完整理解三个英语单词后才能确定法语词序。其中,“te” 表示 “you”,“vois” 表示 “see”。因此,为了正确地将英语翻译成法语,我们需要先知道英语中的三个单词,才能翻译出法语中的第二个和第三个单词。
为了克服这一限制,双向 RNN1997 年被提出。它们与传统 RNN 非常相似,不同之处在于,双向 RNN 内部有两个并行的 RNN 在工作:一个正向处理序列(从开始到结束),另一个逆向处理序列(从结束到开始),其结构如下图所示:

双向RNN

接下来,我们将了解长短期记忆网络 (Long Short-Term Memory, LSTM)。

2.2 长短期记忆网络

虽然传统 RNN 能够处理序列数据并具备记忆能力,但它们面临着梯度爆炸和梯度消失的问题。这是由于将循环网络在时间维度展开后,网络变得极深。为了克服这个问题,长短期记忆网络 (Long Short-Term Memory, LSTM) 通过引入精巧设计的记忆单元取代传统 RNN 单元。传统的 RNN 单元通常使用 sigmoidtanh 激活函数。这些激活函数能够控制输出值的范围,在 sigmoid 激活函数的情况下,从 0 (无信息流)到 1 (完全信息流),在 tanh 激活函数的情况下,从 -11
Tanh 激活函数的另一个优点是,它能够提供均值为 0 的输出值,并且通常能够产生更大的梯度——这两个因素都有助于加速学习(收敛)。当前时间步的输入会与前一时间步的隐藏状态进行拼接,并应用这些激活函数,如下图所示:

Tanh

在反向传播过程中,由于梯度在时间展开的RNN单元间连续相乘,会出现梯度持续衰减或膨胀的现象。这使得传统RNN虽然能记忆短序列信息,却难以处理长序列数据——随着序列增长,梯度连乘次数增加,问题会愈发严重。
LSTM 通过使用门控机制来控制输入和输出,从而解决了这个问题。一个 LSTM 层本质上由多个随时间展开的 LSTM 单元组成。信息以单元状态的形式在单元间传递。这些单元状态通过三种门控结构(输入门、遗忘门、输出门)进行调控,其核心机制如下图所示。

LSTM 示意图

门控机制控制信息流向下一个单元,同时保留或忘记来自前一个单元的信息:

  • 遗忘门:决定保留多少历史记忆( 0表示完全遗忘,1 表示完整保留)
  • 输入门:控制新信息的写入比例
  • 输出门:调节当前状态的输出强度

LSTM 的出现标志着循环网络的重大突破,因为它们能够有效地处理更长的序列。接下来,我们将讨论一些 LSTM 的改进版本。

2.3 扩展和双向 LSTM

原始 LSTM 仅由输入门和输出门组成。随后,提出了带有遗忘门的扩展 LSTM,这种 LSTM 是目前最常用的 LSTM,之后又提出了双向 LSTM,其概念与双向 RNN 类似。

2.4 多维 RNN

多维 RNN (multi-dimensional RNN, MDRNN) 的创新之处在于,RNN 单元之间的单一循环连接被替换为与数据维度相等数量的连接。例如,在视频处理中,连续的二维图像序列就需要建立二维连接,这显著提升了时空数据的建模能力。

2.5 堆叠 LSTM

尽管单层 LSTM 网络能够克服梯度消失和梯度爆炸的问题,但实践表明,堆叠更多的 LSTM 层在学习复杂模式时更为有效,尤其是在各种序列处理任务中,如语音识别。下图展示了一个具有两个 LSTM 层的堆叠 LSTM 模型:

堆叠LSTM

时间维度自然堆叠的 LSTM 单元,通过空间维度叠加获得深度增强。但这些模型的缺点在于:

  • 训练速度显著降低(因深度增加和循环连接)
  • 每次迭代需展开时间维度
  • 无法并行化训练

2.6 GRU

LSTM 单元有两个状态——内部状态和外部状态——以及三个不同的门控——输入门、遗忘门和输出门。门控循环单元 (Gated Recurrent Unit, GRU) 是 LSTM 的轻量级变体,目的是在有效处理梯度爆炸和梯度消失问题的同时,学习长远的依赖关系。GRU 的创新设计包括:

  • 状态精简:合并内外状态为单一状态
  • 门控简化:
    • 重置门(融合输入门和遗忘门功能)
    • 更新门(控制信息流动)

下图展示了一个 GRU 网络:

GRU

2.7 网格 LSTM

网格 LSTM 模型是 MDLSTM 模型的改进,成为多维 RNNLSTM 等效模型。在网格 LSTM 模型中,将 LSTM 单元排布为多维网格,这些单元沿着数据的时空维度以及网络层之间进行连接。

2.8 正交门控循环单元

正交门控循环单元将 GRU 和单位 RNN (Unitary RNN) 的思想结合起来。单位 RNN 基于使用单位矩阵(即正交矩阵)作为 RNN 的隐藏状态循环矩阵来解决梯度爆炸和梯度消失问题。这种方法的有效性在于,梯度的偏差归因于隐藏层到隐藏层的权重矩阵的特征值偏离 1。为了解决这一问题,这些矩阵替换为正交矩阵。
我们已经简要介绍了循环神经网络架构的演变。接下来,我们将通过一个基于 RNN 模型的文本分类实战来深入探讨 RNN。我们还将探索 PyTorch 处理序列数据的核心方法、RNN 模型的构建与评估、以及循环网络在实际任务中的表现分析。

3. 训练 RNN 实现情感分析

本节将使用 PyTorch 框架训练 RNN 模型完成文本分类任务——情感分析。在这个任务中,接收文本序列作为输入,输出 1 (积极情感)或 0 (消极情感)。为了实现文本到数值的转换,我们需要借助分词和词嵌入 (embedding) 技术。
分词是将单词转换为数字索引的过程。经过处理后,每个句子可表示为数字序列,数组中的每个数字代表一个单词。虽然分词提供了每个单词的整数索引,但我们仍然希望将每个单词表示为一个数字向量,作为单词特征空间中的一个特征。这是由于单个数字无法完整表达单词语义信息,我们需要通过可训练的嵌入矩阵将每个单词映射为多维向量,将单词表示为向量的过程称为嵌入。嵌入矩阵可以在模型训练过程中学习,作为单词向量的查找表。例如索引为 123 的单词,其向量表示就是嵌入矩阵第 123 行的向量值。
本节中,将采用单层单向 RNN 结构处理这个二分类任务。在训练模型之前,需要先将原始文本数据转换为数值形式。在训练模型后,对示例文本进行测试。

3.1 文本数据集预处理

(1) 首先,导入所需库:

import os
import time
import numpy as np
from tqdm import tqdm
from string import punctuation
from collections import Counter
import matplotlib.pyplot as pltimport torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

除了导入 torch,还导入了用于文本处理的 punctuationCountermatplotlib 用于显示图像,numpy 用于数组操作,以及 tqdm 用于可视化进度条。

(2) 接下来,从文本文件中读取数据。对在本节,我们将使用 IMDb 情感分析数据集,IMDb 数据集包含若干电影评论文本以及相应的情感标签(积极或消极)。首先,下载该数据集,读取并存储文本列表和相应的情感标签:

review_list = []
label_list = []
for label in ['pos', 'neg']:for fname in tqdm(os.listdir(f'./aclImdb/train/{label}/')):if 'txt' not in fname:continuewith open(os.path.join(f'./aclImdb/train/{label}/', fname), encoding="utf8") as f:review_list += [f.read()]label_list += [label]
print ('Number of reviews :', len(review_list))

输出结果如下所示:

Number of reviews : 25000

(3) 数据加载完成,开始处理文本数据:

review_list = [review.lower() for review in review_list]
review_list = [''.join([letter for letter in review if letter not in punctuation]) for review in tqdm(review_list)]reviews_blob = ' '.join(review_list)
review_words = reviews_blob.split()
count_words = Counter(review_words)total_review_words = len(review_words)
sorted_review_words = count_words.most_common(total_review_words)print(sorted_review_words[:10])

输出结果如下所示:

[('the', 334691), ('and', 162228), ('a', 161940), ('of', 145326), ('to', 135042), ('is', 106855), ('in', 93028), ('it', 77099), ('i', 75719), ('this', 75190)]

可以看到,首先我们将整个文本语料库转换为小写字母,并从评论文本中删除所有标点符号。然后,统计词频生成词汇表。

(4) 继续处理数据,建立单词到索引的映射关系。这一步骤至关重要,因为机器学习模型只理解数字,而不理解单词:

vocab_to_token = {word:idx+1 for idx, (word, count) in enumerate(sorted_review_words)}
print(list(vocab_to_token.items())[:10])

输出结果如下所示:

[('the', 1), ('and', 2), ('a', 3), ('of', 4), ('to', 5), ('is', 6), ('in', 7), ('it', 8), ('i', 9), ('this', 10)]

(5) 我们已获得单词到整数的映射关系(即词汇表),接下来,使用该词汇表,将数据集中的电影评论转换为数字序列:

reviews_tokenized = []
for review in review_list:word_to_token = [vocab_to_token[word] for word in review.split()]reviews_tokenized.append(word_to_token)
print(review_list[0])
print()
print (reviews_tokenized[0])

输出结果如下所示:

输出结果

(6) 将情感标签(积极和消极)转换为数值形式 ,10 分别表示积极和消极:

encoded_label_list = [1 if label =='pos' else 0 for label in label_list]reviews_len = [len(review) for review in reviews_tokenized]reviews_tokenized = [reviews_tokenized[i] for i, l in enumerate(reviews_len) if l>0 ]
encoded_label_list = np.array([encoded_label_list[i] for i, l in enumerate(reviews_len) if l> 0 ], dtype='float32')

(7) 在训练模型之前,我们需要进行序列长度标准化。由于评论长度不一,而 RNN 模型需要固定长度输入。因此,对不同长度的评论进行标准化,使它们都具有相同的长度。定义一个序列长度 L (在本节中为 512),然后对长度小于 L 的序列末尾补零填充,对长度大于 L 的序列截断保留前 512 个词:

def pad_sequence(reviews_tokenized, sequence_length):padded_reviews = np.zeros((len(reviews_tokenized), sequence_length), dtype = int)for idx, review in enumerate(reviews_tokenized):review_len = len(review)if review_len <= sequence_length:zeroes = list(np.zeros(sequence_length-review_len))new_sequence = zeroes+reviewelif review_len > sequence_length:new_sequence = review[0:sequence_length]padded_reviews[idx,:] = np.array(new_sequence)return padded_reviewssequence_length = 512
padded_reviews = pad_sequence(reviews_tokenized=reviews_tokenized, sequence_length=sequence_length)plt.hist(reviews_len)

输出结果如下所示:

可视化

(8) 将数据集分成训练集和验证集,比例为 75:25

train_val_split = 0.75
train_X = padded_reviews[:int(train_val_split*len(padded_reviews))]
train_y = encoded_label_list[:int(train_val_split*len(padded_reviews))]
validation_X = padded_reviews[int(train_val_split*len(padded_reviews)):]
validation_y = encoded_label_list[int(train_val_split*len(padded_reviews)):]

(9) 使用 PyTorch 根据处理后的数据创建数据加载器对象:

train_dataset = TensorDataset(torch.from_numpy(train_X).to(device), torch.from_numpy(train_y).to(device))
validation_dataset = TensorDataset(torch.from_numpy(validation_X).to(device), torch.from_numpy(validation_y).to(device))batch_size = 32
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
validation_dataloader = DataLoader(validation_dataset, batch_size=batch_size, shuffle=True)

(10) 在模型训练前,检查一个批次的数据( 32 条评论及对应标签):

train_data_iter = iter(train_dataloader)
X_example, y_example = next(train_data_iter)
print('Example Input size: ', X_example.size()) # batch_size, seq_length
print('Example Input:\n', X_example)
print()
print('Example Output size: ', y_example.size()) # batch_size
print('Example Output:\n', y_example)

输出结果如下所示:

数据样本

将文本数据集加载并处理成数字索引序列之后,接下来使用 PyTorch 创建 RNN 模型对象并进行训练。

3.2 模型训练

PyTorchnn.RNN 模块可以非常简洁地实现 RNN 层,只需指定输入维度、隐藏层维度和层数即可。

(1) 首先,自定义 RNN 模型类,模型由嵌入层、RNN 层以及最后的全连接层组成:

class RNN(nn.Module):def __init__(self, input_dimension, embedding_dimension, hidden_dimension, output_dimension):super().__init__()self.embedding_layer = nn.Embedding(input_dimension, embedding_dimension)  self.rnn_layer = nn.RNN(embedding_dimension, hidden_dimension, num_layers=1)self.fc_layer = nn.Linear(hidden_dimension, output_dimension)def forward(self, sequence):embedding = self.embedding_layer(sequence)  output, hidden_state = self.rnn_layer(embedding)final_output = self.fc_layer(hidden_state[-1,:,:].squeeze(0))      return final_output

嵌入层使用 nn.Embedding 构建可训练的查找表,存储词嵌入,并通过索引进行检索。在本节中,将嵌入维度设置为 100。这意味着如果词汇表中有 1000 个单词,那么嵌入查找表的大小为 1000x100。例如,单词 “it” 在词汇表中索引 8,则其对应 100 维向量存储在嵌入矩阵第 8 行。也可以使用预训练的嵌入来初始化嵌入查找表,以提高性能,但在本节中,我们从零开始训练嵌入层。

(2) 实例化 RNN 模型:

input_dimension = len(vocab_to_token)+1 # +1 to account for padding
embedding_dimension = 100
hidden_dimension = 32
output_dimension = 1rnn_model = RNN(input_dimension, embedding_dimension, hidden_dimension, output_dimension)optim = torch.optim.Adam(rnn_model.parameters())
loss_func = nn.BCEWithLogitsLoss()rnn_model = rnn_model.to(device)
loss_func = loss_func.to(device)

使用 nn.BCEWithLogitsLoss 模块计算损失。BCEWithLogitsLoss 提供了一个数值稳定的计算过程,整合了 Sigmoid 激活和二元交叉熵损失,二元交叉熵是二分类问题中常用的损失函数。隐藏维度 32 表示 RNN 每个时间步输出的隐藏状态为 32 维向量。

(3) 定义 accuracy_metric() 函数衡量训练模型在验证集上的表现:

def accuracy_metric(predictions, ground_truth):rounded_predictions = torch.round(torch.sigmoid(predictions))success = (rounded_predictions == ground_truth).float() #convert into float for division accuracy = success.sum() / len(success)return accuracy

(4) 定义训练和验证过程:

def train(model, dataloader, optim, loss_func):loss = 0accuracy = 0model.train()for sequence, sentiment in dataloader:optim.zero_grad()     preds = model(sequence.T).squeeze()loss_curr = loss_func(preds, sentiment)accuracy_curr = accuracy_metric(preds, sentiment)loss_curr.backward()optim.step()loss += loss_curr.item()accuracy += accuracy_curr.item()return loss/len(dataloader), accuracy/len(dataloader)def validate(model, dataloader, loss_func):loss = 0accuracy = 0model.eval()with torch.no_grad():for sequence, sentiment in dataloader:preds = model(sequence.T).squeeze()loss_curr = loss_func(preds, sentiment)   accuracy_curr = accuracy_metric(preds, sentiment)loss += loss_curr.item()accuracy += accuracy_curr.item()return loss/len(dataloader), accuracy/len(dataloader)

(5) 开始训练模型:

num_epochs = 10
best_validation_loss = float('inf')for ep in range(num_epochs):time_start = time.time()training_loss, train_accuracy = train(rnn_model, train_dataloader, optim, loss_func)validation_loss, validation_accuracy = validate(rnn_model, validation_dataloader, loss_func)time_end = time.time()time_delta = time_end - time_start  if validation_loss < best_validation_loss:best_validation_loss = validation_losstorch.save(rnn_model.state_dict(), 'rnn_model.pt')print(f'epoch number: {ep+1} | time elapsed: {time_delta}s')print(f'training loss: {training_loss:.3f} | training accuracy: {train_accuracy*100:.2f}%')print(f'validation loss: {validation_loss:.3f} |  validation accuracy: {validation_accuracy*100:.2f}%')print()

输出结果如下所示:

输出结果

(6) 定义辅助函数 sentiment_inference() 来对训练好的模型进行实时推理:

def sentiment_inference(model, sentence):model.eval()sentence = sentence.lower()sentence = ''.join([c for c in sentence if c not in punctuation])tokenized = [vocab_to_token.get(token, 0) for token in sentence.split()]tokenized = np.pad(tokenized, (512-len(tokenized), 0), 'constant')# model inferencemodel_input = torch.LongTensor(tokenized).to(device)model_input = model_input.unsqueeze(1)pred = torch.sigmoid(model(model_input))return pred.item()

(7) 测试该模型在自定义评论文本上的表现:

print(sentiment_inference(rnn_model, "This film is horrible"))
print(sentiment_inference(rnn_model, "Director tried too hard but this film is bad"))
print(sentiment_inference(rnn_model, "This film will be houseful for weeks"))
print(sentiment_inference(rnn_model, "I just really loved the movie"))

输出结果如下所示:

0.028724979609251022
0.3060310184955597
0.9979052543640137
0.9279760122299194

可以看到模型确实捕捉到了正面和负面情感的概念。此外,它能够处理不同长度的序列,即使这些序列都远远短于 512 个单词。

4. GRU 和注意力机制

接下来,我们将简要介绍门控循环单元 (Gated Recurrent Unit, GRU) ,分析其与 LSTM 的异同点,展示如何使用 PyTorch 初始化 GRU 模型,并介绍基于注意力机制的 RNN。最后,我们将说明在序列建模任务中,纯注意力模型(不含循环或卷积结构)如何全面超越各类循环神经网络。

4.1 GRU

GRU 是一种带有两个门控机制(重置门和更新门)以及一个隐藏状态向量的记忆单元。其结构配置比 LSTM 更为简洁,但同样有效地解决了梯度爆炸和梯度消失问题。大量研究已经对 LSTMGRU 的性能进行了比较。大量研究表明:在处理序列任务时,LSTMGRU 都显著优于普通 RNN,但两者在不同任务中各具优势。
GRU 的训练速度通常快于 LSTM。在语言建模等任务中,GRU 仅需少量训练数据即可达到与 LSTM 相当的性能。然而,从理论上讲,LSTM 应能比 GRU 保持更长的序列记忆。PyTorch 提供了 nn.GRU 模块用于初始化 GRU 层,以下代码创建了包含双向 GRU 层的神经网络:

self.gru_layer = nn.GRU(input_size, hidden_size, num_layers, bias, dropout, bidirectional)

4.2 基于注意力的模型

循环神经网络曾在序列数据处理领域具有最优异的性能,但 2017 年出现的纯注意力模型使这些循环网络相形见绌。注意力机制源于人类处理序列(如文本)时的认知特性——我们会动态调整对序列不同部分的关注程度。
例如补全句子 “Martha歌声优美,我迷上了____嗓音” 时,“Martha” 会成为关键注意力点,以推测空缺的词可能是“她”;而补全 "Martha歌声优美,我迷上了她的____"时,"歌声"则成为主要关注对象,以推测空缺的词可能是“声音”、“歌曲”、“歌唱”等。
传统循环架构缺乏这种动态聚焦机制,无法通过专注于序列中的特定部分来预测当前时间步的输出,仅能通过压缩的隐藏状态向量来概括历史序列信息。
注意力循环网络通过在常规循环层之上加入了一个额外的注意力层来引入注意力机制。注意力层学习序列中各历史词的注意力权重。通过计算历史隐藏状态的注意力加权平均得到上下文向量,该向量与当前隐藏状态共同参与输出预测。基于注意力的 RNN 架构如下图所示:

基于注意力机制的RNN架构

该架构在每个时间步计算全局上下文向量,后续改进版则采用局部上下文向量(仅关注前 kkk 个词)。基于注意力的循环神经网络在机器翻译等任务上超越了最先进的循环神经网络模型。
2017<Attention Is All You Need> 论文展示了仅靠注意力机制无需循环层即可解决序列任务。近年来,使用注意力机制的模型在自然语言处理等领域全面超越循环网络,推动深度学习取得重大突破。循环神经网络需要在时间上展开,无法并行计算。而 Transformer 模型完全摒弃循环和卷积结构,兼具并行计算优势和轻量级计算特性。

小结

本节介绍了循环神经网络 (Recurrent Neural Network, RNN) 及其在序列数据处理中的应用。首先对比了卷积神经网络 (Convolutional Neural Network, CNN) 与 RNN 的差异,指出 RNN 通过循环连接建模时序依赖关系。随后详细梳理了 RNN 的发展历程,包括基础 RNN、双向 RNNLSTMGRU 等变体的结构特点及改进动机,其中 LSTM 通过门控机制解决长程依赖问题,GRU 则进一步简化结构。接着通过 IMDb 情感分析实战,演示了如何使用 PyTorch 实现文本预处理、RNN 模型构建及训练评估流程,最后探讨了注意力机制如何提升 RNN 性能。

系列链接

PyTorch实战(1)——深度学习概述
PyTorch实战(2)——使用PyTorch构建神经网络
PyTorch实战(3)——PyTorch vs. TensorFlow详解
PyTorch实战(4)——卷积神经网络(Convolutional Neural Network,CNN)
PyTorch实战(5)——深度卷积神经网络
PyTorch实战(6)——模型微调详解


文章转载自:

http://SST1vPMC.zrbpx.cn
http://b5d32Ff2.zrbpx.cn
http://5SKNQZBO.zrbpx.cn
http://Yg72KYYM.zrbpx.cn
http://L7hGnHAB.zrbpx.cn
http://l2PGbAkh.zrbpx.cn
http://fNDjoI8R.zrbpx.cn
http://EoT1RT7L.zrbpx.cn
http://vSbQLw0d.zrbpx.cn
http://O4ulxlOM.zrbpx.cn
http://IMJQAcVS.zrbpx.cn
http://CubvbL8J.zrbpx.cn
http://XRXygrbw.zrbpx.cn
http://sgmK0z27.zrbpx.cn
http://RU5aDVKU.zrbpx.cn
http://uMkDjYvi.zrbpx.cn
http://tLqUADuX.zrbpx.cn
http://fGBObpC3.zrbpx.cn
http://ToPNUKGq.zrbpx.cn
http://0XAXoGGE.zrbpx.cn
http://aN29oW2U.zrbpx.cn
http://chyXnd8M.zrbpx.cn
http://l91Ur50d.zrbpx.cn
http://cwKdSOD7.zrbpx.cn
http://pZn92BRh.zrbpx.cn
http://EpEmTLEW.zrbpx.cn
http://u2o5OHfa.zrbpx.cn
http://xtZmQSMd.zrbpx.cn
http://JsMMA6c7.zrbpx.cn
http://AeOv6i3c.zrbpx.cn
http://www.dtcms.com/a/382864.html

相关文章:

  • 【LeetCode hot100|Week2】滑动窗口,子串
  • Web与Nginx网站服务(改)
  • Qt Designer与事件处理
  • 347. 前 K 个高频元素
  • Qt之快捷键、事件处理、自定义按键——完成记事本项目
  • 【微服务】SpringBoot 整合Kafka 项目实战操作详解
  • spring-kafka消费异常处理
  • 长城杯2025
  • Android BLE 蓝牙扫描完全指南:使用 RxAndroidBle框架
  • CKS-CN 考试知识点分享(3)---Dockerfile 安全最佳实践
  • 新一代控制理论框架:人机环境系统控制论
  • easyPoi实现动表头Excel的导入和导出
  • 【Zephyr电源与功耗专题】13_PMU电源驱动介绍
  • Coze源码分析-资源库-创建知识库-后端源码-应用/领域/数据访问
  • React Server Components (RSC) 与 App Router 简介:Next.js 的未来范式
  • 状态机SMACH相关教程介绍与应用案例分析——机器人操作进阶系列之一
  • Grafana与Prometheus实战
  • godot+c#操作godot-sqlite并加解密
  • Scikit-learn 机器学习:构建、训练与评估预测模型
  • React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
  • Java分布式编程:RMI机制
  • 5-12 WPS JS宏 Range数组规范性测试
  • MySQL 的安装、启动、连接(Windows、macOS 和 Linux)
  • (附源码)基于Spring Boot的宿舍管理系统设计
  • Mac下Python3安装
  • C++数组与字符串:从基础到实战技巧
  • 第13课:分布式Agent系统
  • Docker 容器化部署核心实战——Nginx 服务配置与正反向代理原理解析
  • 【分享】中小学教材课本 PDF 资源获取指南
  • 如何用 Git Hook 和 CI 流水线为 FastAPI 项目保驾护航?