一、概述

  循环神经网络(Recurrent Neural Network, RNN)是一种专门设计用于处理序列数据(如文本、语音、时间序列等)的神经网络模型。其核心思想是通过引入时间上的循环连接,使网络能够保留历史信息并影响当前输出。

二、模型原理

  RNN的关键特点是隐藏状态的循环传递,即当前时刻的输出不仅依赖于当前输入,还依赖于之前所有时刻的信息,这种机制使RNN能够建模序列的时序依赖性。一个隐含层神经元的结构示意图如下

  对于时间步\(t\),有

\[h_t=\left( W_xx_t+W_hh_{t-1}+b_h \right)
\]
\[y_t=g\left( W_yh_t+b_y \right)
\]

其中,\(h_t\) 是当前隐含状态,\(x_t\) 是当前输入,\(y_t\) 是当前输出,\(W_x,W_h,W_y\) 是权重矩阵,\(f,g\) 是激活函数。

  RNN在时间步上展开后,可视为多个共享参数的重复模块链式连接。序列结构过程如图所示

三、优势与局限性

1. 主要优势

参数共享:所有时间步共享同一组权重,大幅减少参数量。

记忆能力:隐藏状态能够“记忆”,存储历史信息。

灵活输入输出:支持多种序列任务(如一对一、一对多、多对多)。

2. 局限性

梯度问题:传统RNN难以训练长序列(梯度消失/爆炸)。

计算效率:无法并行处理序列(因时间步需顺序计算)。

四、应用场景

自然语言处理:语言模型(如 GPT 早期基于 RNN)、文本生成、机器翻译、情感分析。

语音处理:语音识别(如结合 CTC 损失函数)、语音合成。

时间序列分析:股票价格预测、传感器数据异常检测、天气预测。

视频处理:视频内容理解(如动作识别,结合 CNN 提取空间特征)。

五、Python实现示例

(环境:Python 3.11,PyTorch 2.4.0)

import matplotlib
matplotlib.use('TkAgg') import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import numpy as np
import matplotlib.pyplot as plt # 设置matplotlib的字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 'SimHei' 是黑体,也可设置 'Microsoft YaHei' 等
plt.rcParams['axes.unicode_minus'] = False # 正确显示负号 # 设置随机种子以确保结果可复现
torch.manual_seed(42)
np.random.seed(42) # 生成示例时间序列数据
def generate_data(n_samples=1000, seq_length=20):
"""生成简单的正弦波时间序列数据"""
x = np.linspace(0, 10 * np.pi, n_samples + seq_length)
y = np.sin(x) # 创建序列和目标
sequences = []
targets = []
for i in range(n_samples):
sequences.append(y[i:i + seq_length])
targets.append(y[i + seq_length]) # 转换为PyTorch张量
sequences = torch.FloatTensor(sequences).unsqueeze(2) # [样本数, 序列长度, 特征数]
targets = torch.FloatTensor(targets).unsqueeze(1) # [样本数, 1] # 分割训练集和测试集
train_size = int(0.8 * n_samples)
train_data = TensorDataset(sequences[:train_size], targets[:train_size])
test_data = TensorDataset(sequences[train_size:], targets[train_size:]) return train_data, test_data # 定义RNN模型
class SimpleRNN(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(SimpleRNN, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers # RNN层
self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True) # 全连接输出层
self.fc = nn.Linear(hidden_size, output_size) def forward(self, x):
# 初始化隐藏状态
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device) # 前向传播RNN
out, _ = self.rnn(x, h0) # 我们只需要最后一个时间步的输出
out = self.fc(out[:, -1, :])
return out # 训练函数
def train_model(model, train_loader, criterion, optimizer, device, epochs=100):
model.train()
for epoch in range(epochs):
total_loss = 0
for inputs, targets in train_loader:
inputs, targets = inputs.to(device), targets.to(device) # 清零梯度
optimizer.zero_grad() # 前向传播
outputs = model(inputs)
loss = criterion(outputs, targets) # 反向传播和优化
loss.backward()
optimizer.step() total_loss += loss.item() if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch + 1}/{epochs}], Loss: {total_loss / len(train_loader):.4f}') # 评估函数
def evaluate_model(model, test_loader, device):
model.eval()
predictions = []
actuals = [] with torch.no_grad():
for inputs, targets in test_loader:
inputs, targets = inputs.to(device), targets.to(device)
outputs = model(inputs) predictions.extend(outputs.cpu().numpy())
actuals.extend(targets.cpu().numpy()) return np.array(predictions), np.array(actuals) # 主函数
def main():
# 设备配置
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 超参数
input_size = 1 # 输入特征维度
hidden_size = 64 # 隐藏层维度
num_layers = 1 # RNN层数
output_size = 1 # 输出维度
seq_length = 20 # 序列长度
batch_size = 32 # 批次大小
learning_rate = 0.001 # 学习率 # 生成数据
train_data, test_data = generate_data(seq_length=seq_length)
train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_data, batch_size=batch_size) # 初始化模型
model = SimpleRNN(input_size, hidden_size, num_layers, output_size).to(device) # 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate) # 训练模型
print("开始训练模型...")
train_model(model, train_loader, criterion, optimizer, device) # 评估模型
print("评估模型...")
predictions, actuals = evaluate_model(model, test_loader, device) # 可视化结果
plt.figure(figsize=(10, 6))
plt.plot(actuals[:50], label='实际值')
plt.plot(predictions[:50], label='预测值')
plt.title('RNN模型预测结果')
plt.xlabel('样本')
plt.ylabel('值')
plt.legend()
plt.show() if __name__ == "__main__":
main()

示例实现过程包括以下几个部分:

  数据生成:创建了一个简单的正弦波时间序列数据集,用于训练和测试模型。

  模型架构:定义了一个简单的 RNN 模型,包含一个 RNN 层处理序列输入、一个全连接层将 RNN 的输出映射到预测值

  训练流程:实现了完整的训练循环,包括前向传播、计算损失、反向传播和参数更新。

  评估和可视化:训练完成后,模型在测试数据上进行评估,并可视化预测结果与实际值的对比。

  示例展示了 RNN 在时间序列预测任务中的基本用法。可以通过调整超参数(如隐藏层大小、学习率、RNN 层数等)来优化模型性能,也可将此框架应用到其他序列数据相关的预测任务中。

End.

循环神经网络(RNN)模型的更多相关文章

  1. 循环神经网络RNN模型和长短时记忆系统LSTM

    传统DNN或者CNN无法对时间序列上的变化进行建模,即当前的预测只跟当前的输入样本相关,无法建立在时间或者先后顺序上出现在当前样本之前或者之后的样本之间的联系.实际的很多场景中,样本出现的时间顺序非常 ...

  2. 循环神经网络(RNN)模型与前向反向传播算法

    在前面我们讲到了DNN,以及DNN的特例CNN的模型和前向反向传播算法,这些算法都是前向反馈的,模型的输出和模型本身没有关联关系.今天我们就讨论另一类输出和模型间有反馈的神经网络:循环神经网络(Rec ...

  3. 循环神经网络(RNN, Recurrent Neural Networks)介绍(转载)

    循环神经网络(RNN, Recurrent Neural Networks)介绍    这篇文章很多内容是参考:http://www.wildml.com/2015/09/recurrent-neur ...

  4. 通过keras例子理解LSTM 循环神经网络(RNN)

    博文的翻译和实践: Understanding Stateful LSTM Recurrent Neural Networks in Python with Keras 正文 一个强大而流行的循环神经 ...

  5. 循环神经网络RNN及LSTM

    一.循环神经网络RNN RNN综述 https://juejin.im/entry/5b97e36cf265da0aa81be239 RNN中为什么要采用tanh而不是ReLu作为激活函数?  htt ...

  6. 从网络架构方面简析循环神经网络RNN

    一.前言 1.1 诞生原因 在普通的前馈神经网络(如多层感知机MLP,卷积神经网络CNN)中,每次的输入都是独立的,即网络的输出依赖且仅依赖于当前输入,与过去一段时间内网络的输出无关.但是在现实生活中 ...

  7. 循环神经网络(RNN, Recurrent Neural Networks)介绍

    原文地址: http://blog.csdn.net/heyongluoyao8/article/details/48636251# 循环神经网络(RNN, Recurrent Neural Netw ...

  8. 循环神经网络(RNN)的改进——长短期记忆LSTM

     一:vanilla RNN 使用机器学习技术处理输入为基于时间的序列或者可以转化为基于时间的序列的问题时,我们可以对每个时间步采用递归公式,如下,We can process a sequence ...

  9. 吴恩达deepLearning.ai循环神经网络RNN学习笔记_看图就懂了!!!(理论篇)

    前言 目录: RNN提出的背景 - 一个问题 - 为什么不用标准神经网络 - RNN模型怎么解决这个问题 - RNN模型适用的数据特征 - RNN几种类型 RNN模型结构 - RNN block - ...

  10. 吴恩达deepLearning.ai循环神经网络RNN学习笔记_没有复杂数学公式,看图就懂了!!!(理论篇)

    本篇文章被Google中国社区组织人转发,评价: 条理清晰,写的很详细! 被阿里算法工程师点在看! 所以很值得一看! 前言 目录: RNN提出的背景 - 一个问题 - 为什么不用标准神经网络 - RN ...

随机推荐

  1. 跨平台Windows和Linux(银河麒麟)操作系统OCR识别应用

    1 运行效果 代码下载链接: https://pan.baidu.com/s/1NUfLTjk6kzXJKsaH7yo4qA?pwd=rk5c 提取码: rk5c. 在银河麒麟桌面操作系统V10(SP ...

  2. Polar困难模式部分题解

    choose from pwn import *from LibcSearcher import *context.terminal = ["tmux","splitw& ...

  3. 【ARM+Qt+OpenCV】基于ARM的双目图像采集系统

    点击查看代码 系统使用ARM处理器,运行linux系统,Qt创建工程编写主程序,可以使用OpenCV进行图像处理. 通过两个摄像头采集会图像,在LCD上进行显示,然后通过LCD上的按钮实现退出程序.保 ...

  4. MSBuild属性

    MSBuild 属性 MSBuild属性是键值对的集合,提前声明好这些属性之后,整个项目的生成都可以引用这些属性. 属性名不区分大小写. 属性都是写在 PropertyGroup 标签中. 1.声明属 ...

  5. 【插件介绍】Mesh2Geom插件

    Mesh to Geometry Plugin,来自达索官方论坛社区 原帖链接:Mesh to Geometry Plugin plugin feature: 允许Abaqus 用户从网格文件生成几何 ...

  6. PPT_标题

    一 调节字体大小 1.字体-字魂71号-御守锦书 2.更改字体大小(138.96.80.80.96.138) 3.字体背景 复制背景图片->选择ppt文字->设置图片格式->选择来自 ...

  7. C/C++显示类型转换的位拓展方式

    最近用verilator写模块的tb,在这里卡了好久(测半天都是C++写的问题) 要点 变量从小位宽到大位宽显示类型转换(explicit cast)时的位拓展方式,取决于转换前变量的符号性. 倘若转 ...

  8. go kratos protobuf 接收动态JSON数据

    前言 google.protobuf.Struct 是 Google Protocol Buffers 中的一种特殊类型,用于表示动态的键值对数据.它可以存储任意类型的数据,并提供了方便的方法来访问和 ...

  9. Ansible忽略任务失败

    在默认情况下,任务失败时会中止剧本任务,不过可以通过忽略失败的任务来覆盖此类行为.在可能出错且不影响全局的段中使用ignore_errors关键词来达到目的. 环境: 受控主机清单文件: [dev] ...

  10. Docker图形化工具Portainer安装

    Docker方式安装 我们可以直接使用 **Docker** 的方式来安装 首先创建数据卷,实现数据持久化 docker volume create portainer_db 启动 **Partain ...