【深度学习基础模型】递归神经网络 (Recurrent Neural Networks, RNN) 详细理解并附实现代码。

【深度学习基础模型】递归神经网络 (Recurrent Neural Networks, RNN)

【深度学习基础模型】递归神经网络 (Recurrent Neural Networks, RNN)


文章目录


参考地址:https://www.asimovinstitute.org/neural-network-zoo/

论文地址:https://www.sciencedirect.com/science/article/abs/pii/036402139090002E

欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!

1.算法原理介绍:递归神经网络 (Recurrent Neural Networks, RNN)

1.1 递归神经网络 (RNN) 概述

递归神经网络 (RNN) 是前馈神经网络 (FFNN) 的扩展,其主要特点是引入了时间维度上的依赖关系,使得网络具有记忆功能

RNN 通过在不同时间步上共享权重,并通过递归连接在时间序列上传播信息,从而能够处理时间序列数据或顺序依赖性任务

相比于传统的 FFNN,RNN 可以理解输入序列的顺序,并根据序列中前面的信息来调整当前的输出。

1.2 RNN 的关键特性

  • 时间依赖性:RNN 中的每个神经元不仅接收当前时刻的输入,还接收上一个时刻的隐藏状态。这个特性使得 RNN 可以在序列数据中传播信息。
  • 权重共享:所有时刻的隐藏层共享相同的权重矩阵,使得RNN能够处理可变长度的输入序列。
  • 递归连接:通过递归连接,RNN 可以将前一时刻的隐藏状态作为当前时刻的输入,从而在时间步之间传播信息。

1.3 RNN 的工作原理

在一个标准的RNN 中,给定输入序列 X = ( x 1 , x 2 , ... , x T ) X=(x_1,x_2,...,x_T) X=(x1,x2,...,xT),隐藏状态 h t h_t ht的更新公式如下:
h t = σ ( W i h x t + W h h h t − 1 + b h ) h_t=σ(W_{ih}x_t+W_{hh}h_{t-1}+b_h) ht=σ(Wihxt+Whhht−1+bh)

其中:

  • h t h_t ht是当前时刻的隐藏状态。
  • W i h W_{ih} Wih是输入到隐藏状态的权重矩阵。
  • W h h W_{hh} Whh是隐藏状态之间的递归权重矩阵。
  • x t x_t xt是当前时间步的输入。
  • b h b_h bh是偏置项。
  • σ σ σ是激活函数(如 tanh 或 ReLU)。

最终,输出层的输出 y t y_t yt计算如下:
y t = σ ( W h o h t + b o ) y_t=σ(W_{ho}h_t+b_o) yt=σ(Whoht+bo)

1.4 RNN 的问题:梯度消失与梯度爆炸

由于 RNN 在每个时间步上进行梯度传播,如果序列较长,梯度在反向传播时会呈指数增长或减少,导致梯度爆炸或梯度消失问题 。这限制了 RNN 处理长期依赖关系的能力。在实际应用中,长短期记忆网络 (LSTM) 和门控循环单元 (GRU) 被提出用来解决这个问题

1.5 RNN 的应用

RNN 广泛用于处理与序列相关的任务,常见应用包括:

  • 自然语言处理 (NLP):如文本生成、机器翻译、文本分类、情感分析等。
  • 语音识别:将语音信号作为输入序列,通过 RNN 处理时间依赖性。
  • 时间序列预测:例如股票价格预测、天气预报等。

2.Python 实现 RNN 的应用实例

我们将使用 Python 和深度学习框架 PyTorch 实现一个简单的 RNN,用于文本分类任务。

2.1代码实现:递归神经网络的实现及文本分类应用

csharp 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import numpy as np

# 创建简单的文本数据
# 假设我们有两个类别的文本数据,每个句子都是单词的索引表示
# 类别 0: "I love machine learning", "deep learning is great"
# 类别 1: "I hate spam emails", "phishing attacks are bad"
X = [
    [1, 2, 3, 4],     # "I love machine learning"
    [5, 6, 7, 8],     # "deep learning is great"
    [1, 9, 10, 11],   # "I hate spam emails"
    [12, 13, 14, 15]  # "phishing attacks are bad"
]
y = [0, 0, 1, 1]  # 标签,0表示积极类别,1表示消极类别

# 转换为Tensor格式
X = torch.tensor(X, dtype=torch.long)
y = torch.tensor(y, dtype=torch.long)

# 定义数据集和数据加载器
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)

# 定义 RNN 模型
class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, num_layers):
        super(RNN, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.embedding = nn.Embedding(input_size, hidden_size)  # 嵌入层,将输入单词的索引转换为向量
        self.rnn = nn.RNN(hidden_size, hidden_size, num_layers, batch_first=True)  # RNN层
        self.fc = nn.Linear(hidden_size, output_size)  # 全连接层,用于分类输出

    def forward(self, x):
        # 初始化隐藏状态,形状为 (num_layers, batch_size, hidden_size)
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        
        # 通过嵌入层转换输入
        out = self.embedding(x)
        
        # 通过 RNN 层
        out, _ = self.rnn(out, h0)
        
        # 取最后一个时间步的隐藏状态作为输出
        out = out[:, -1, :]
        
        # 通过全连接层得到最终的分类输出
        out = self.fc(out)
        return out

# 模型参数
input_size = 16  # 假设我们有16个不同的单词
hidden_size = 8  # 隐藏层大小
output_size = 2  # 二分类问题
num_layers = 1  # RNN层数

# 创建 RNN 模型
model = RNN(input_size, hidden_size, output_size, num_layers)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()  # 分类任务使用交叉熵损失函数
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 20
for epoch in range(num_epochs):
    for data, labels in dataloader:
        # 前向传播
        outputs = model(data)
        loss = criterion(outputs, labels)
        
        # 反向传播和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    
    if (epoch+1) % 5 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# 测试模型
with torch.no_grad():
    test_sentence = torch.tensor([[1, 2, 3, 4]])  # 测试句子 "I love machine learning"
    prediction = model(test_sentence)
    predicted_class = torch.argmax(prediction, dim=1)
    print(f'Predicted class: {predicted_class.item()}')

2.2代码解释

1.定义 RNN 模型:

  • self.embedding = nn.Embedding(input_size, hidden_size):这是嵌入层,用于将输入的单词索引(如"1, 2, 3, 4")转换为高维向量表示。
  • self.rnn = nn.RNN(hidden_size, hidden_size, num_layers, batch_first=True):定义 RNN 层,输入大小为 hidden_size,输出也为 hidden_size,序列是按批次为第一维度(batch_first=True)。
  • self.fc = nn.Linear(hidden_size, output_size):全连接层,将最后一个时间步的 RNN 输出映射为类别预测(输出大小为2,表示二分类任务)。

2.RNN 的前向传播:

  • h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device):初始化隐藏状态为0。
  • out, _ = self.rnn(out, h0):RNN 前向传播,得到每个时间步的隐藏状态。
  • out = out[:, -1, :]:取最后一个时间步的输出,作为最终输出。
  • out = self.fc(out):通过全连接层进行分类。

3.数据集生成与加载:

  • 我们使用了简单的二分类文本数据(表示为单词索引序列),并转换为 PyTorch 的 TensorDatasetDataLoader

4.训练与测试:

  • 使用 Adam 优化器和交叉熵损失函数训练模型,并在每 5 个 epoch 打印一次损失。
  • 在测试阶段,我们用一个测试句子进行分类预测,并打印出预测的类别。

3.总结

递归神经网络 (RNN) 是处理序列数据的重要工具,适用于自然语言处理、语音识别、时间序列预测等任务。然而,RNN 存在梯度消失与梯度爆炸问题,尤其是在处理长序列时

在实际应用中,RNN 已被改进为 LSTM 和 GRU 等架构,解决了这些问题。通过 PyTorch 实现的 RNN 示例展示了其在文本分类中的应用。

相关推荐
拜刊物苏哲19 分钟前
【机器学习(七)】分类和回归任务-K-近邻 (KNN)算法-Sentosa_DSML社区版
机器学习·分类·回归·k近邻算法
啥都生19 分钟前
YOLO11震撼发布!
人工智能·计算机视觉·目标跟踪
@技术无疆20 分钟前
Python 机器学习:预测国庆黄金周的消费趋势
开发语言·人工智能·python·深度学习·神经网络·机器学习·小程序
计算机科研之友(Friend)39 分钟前
物联网(二)——MDPI特刊推荐
人工智能·物联网·计算机网络·搜索引擎·计算机视觉·网络安全
zqh1767364646944 分钟前
阿里云ACP认证考试题库
大数据·数据库·人工智能·阿里云·云计算
拜刊物苏哲1 小时前
【机器学习(八)】分类和回归任务-因子分解机(Factorization Machines,FM)-Sentosa_DSML社区版
机器学习·分类·回归
程序员陆通1 小时前
Meta Llama 3.2发布:小型文本模型与多模态视觉能力,AI的未来已来!
人工智能·llama
吃什么芹菜卷1 小时前
机器学习:opencv--摄像头OCR
人工智能·笔记·opencv·计算机视觉·ocr
中云时代-防御可测试-小余1 小时前
国产游戏出海火热另一面:AI和API快速成长引发网络安全挑战
人工智能·tcp/ip·web安全·游戏·网络安全·udp·ddos