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

深度学习学习经验——循环神经网络(RNN)

循环神经网络(Recurrent Neural Network, RNN)

循环神经网络(Recurrent Neural Network, RNN)是一种适合处理序列数据的神经网络,它能够利用历史信息来预测当前输出,适用于时间序列预测、自然语言处理等任务。RNN 的关键在于它具有“记忆”功能,可以将前一时刻的信息传递到下一时刻。RNN 的这种特性主要体现在它的隐藏状态(Hidden State)和时间步长(Time Step)的循环更新机制上。

1. 时间步长输入与隐藏状态的循环更新机制

RNN 的核心是通过时间步长(Time Step)来处理序列数据。假设我们有一个长度为 T 的输入序列 ( { x 1 , x 2 , . . . , x T } (\{x_1, x_2, ..., x_T\} ({x1,x2,...,xT}),RNN 会逐步处理每一个输入,并更新它的隐藏状态。

1.1 隐藏状态初始化

在时间步长开始前,我们需要初始化 RNN 的隐藏状态。通常情况下,隐藏状态初始化为全零向量。

import numpy as np# 定义隐藏状态维度
hidden_size = 4# 初始化隐藏状态为全零向量
h_t = np.zeros(hidden_size)
1.2 逐步输入时间步长

在每一个时间步长 t,RNN 接受当前的输入 x_t 和前一时刻的隐藏状态 h_{t-1},然后通过一个激活函数(通常是 tanh 或 ReLU)计算当前的隐藏状态 h_t

隐藏状态的更新公式为:

h t = tanh ⁡ ( W h x ⋅ x t + W h h ⋅ h t − 1 + b h ) h_t = \tanh(W_{hx} \cdot x_t + W_{hh} \cdot h_{t-1} + b_h) ht=tanh(Whxxt+Whhht1+bh)

其中:

  • ( W h x (W_{hx} (Whx) 是输入到隐藏层的权重矩阵
  • ( W h h (W_{hh} (Whh) 是隐藏层到隐藏层的权重矩阵
  • ( b h (b_h (bh) 是偏置项
  • ( tanh ⁡ (\tanh (tanh) 是激活函数

输出 (y_t) 可以通过一个线性变换计算:

y t = W h y ⋅ h t + b y y_t = W_{hy} \cdot h_t + b_y yt=Whyht+by

# 定义时间步长输入的维度
input_size = 3# 定义权重矩阵和偏置项
W_hx = np.random.randn(hidden_size, input_size)
W_hh = np.random.randn(hidden_size, hidden_size)
b_h = np.random.randn(hidden_size)# 定义一个示例输入序列
x_t = np.random.randn(input_size)# 更新隐藏状态
h_t = np.tanh(np.dot(W_hx, x_t) + np.dot(W_hh, h_t) + b_h)
print(f"时间步长 t 的隐藏状态: {h_t}")
1.3 循环更新机制

在整个序列处理中,RNN 会不断重复上述过程,依次处理序列中的每个元素,逐步更新隐藏状态。最后,隐藏状态会包含输入序列的全局信息。

# 定义一个输入序列
sequence_length = 5
input_sequence = [np.random.randn(input_size) for _ in range(sequence_length)]# 循环更新隐藏状态
h_t = np.zeros(hidden_size)  # 重置隐藏状态
for t in range(sequence_length):x_t = input_sequence[t]h_t = np.tanh(np.dot(W_hx, x_t) + np.dot(W_hh, h_t) + b_h)print(f"时间步长 {t+1} 的隐藏状态: {h_t}")

2. 完整代码示范

以下是将上述步骤整合在一起的完整代码:

import numpy as np# 定义参数
hidden_size = 4
input_size = 3
sequence_length = 5# 初始化隐藏状态
h_t = np.zeros(hidden_size)# 初始化权重矩阵和偏置项
W_hx = np.random.randn(hidden_size, input_size)
W_hh = np.random.randn(hidden_size, hidden_size)
b_h = np.random.randn(hidden_size)# 定义输入序列
input_sequence = [np.random.randn(input_size) for _ in range(sequence_length)]# 循环遍历序列中的每一个时间步长
for t in range(sequence_length):x_t = input_sequence[t]h_t = np.tanh(np.dot(W_hx, x_t) + np.dot(W_hh, h_t) + b_h)print(f"时间步长 {t+1} 的隐藏状态: {h_t}")

RNN 的时间步长输入和隐藏状态的循环更新机制使得它可以有效地处理序列数据。每个时间步长的输入 x_t 会结合前一时刻的隐藏状态 h_{t-1},更新当前的隐藏状态 h_t,从而逐步捕获输入序列中的全局信息。

应用案例

通过一个更具体的例子来讲解循环神经网络(RNN),并使用 PyTorch 实现它。我们将以天气预测为例,假设我们有过去几天的温度数据,并希望预测未来一天的温度。

1. 问题描述

假设我们有一个城市过去 5 天的温度数据 ( [ T − 4 , T − 3 , T − 2 , T − 1 , T 0 ] ([T_{-4}, T_{-3}, T_{-2}, T_{-1}, T_0] ([T4,T3,T2,T1,T0]),希望预测今天的温度 (T_1)。这是一个典型的序列预测问题,RNN 可以通过“记住”过去的信息来预测未来的值。

2. 预测未来温度

在每一个时间步长 (t),RNN 接受当前的输入 (x_t)(即当天的温度)和前一时刻的隐藏状态 (h_{t-1})(记忆了前几天的信息),然后计算当前的隐藏状态 (h_t) 和输出 (y_t)。RNN 的关键在于它的隐藏状态通过时间步长不断更新,将前面时间步长的信息传递到当前。

回到我们之前的公式中:

h t = tanh ⁡ ( W h x ⋅ x t + W h h ⋅ h t − 1 + b h ) h_t = \tanh(W_{hx} \cdot x_t + W_{hh} \cdot h_{t-1} + b_h) ht=tanh(Whxxt+Whhht1+bh)

其中:

  • ( W h x (W_{hx} (Whx) 是输入到隐藏层的权重矩阵
  • ( W h h (W_{hh} (Whh) 是隐藏层到隐藏层的权重矩阵
  • ( b h (b_h (bh) 是偏置项
  • ( tanh ⁡ (\tanh (tanh) 是激活函数

输出 (y_t) 可以通过一个线性变换计算:

y t = W h y ⋅ h t + b y y_t = W_{hy} \cdot h_t + b_y yt=Whyht+by

在我们的问题中,RNN 将根据前几天的温度预测今天的温度。我们将输入序列 ( [ T − 4 , T − 3 , T − 2 , T − 1 , T 0 ] ([T_{-4}, T_{-3}, T_{-2}, T_{-1}, T_0] ([T4,T3,T2,T1,T0]) 传递给 RNN,并获取最后一步的输出 ( y 5 (y_5 (y5),这就是我们预测的今天的温度。

3. 使用 PyTorch 实现 RNN

我们现在使用 PyTorch 实现这个天气预测的模型。

3.1 导入必要的库
import torch
import torch.nn as nn
import numpy as np
3.2 定义 RNN 模型
class WeatherRNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(WeatherRNN, self).__init__()self.hidden_size = hidden_sizeself.rnn = nn.RNN(input_size, hidden_size, batch_first=True)self.fc = nn.Linear(hidden_size, output_size)def forward(self, x):h_0 = torch.zeros(1, x.size(0), self.hidden_size)  # 初始化隐藏状态out, h_n = self.rnn(x, h_0)  # 计算所有时间步长的输出out = self.fc(out[:, -1, :])  # 取最后一个时间步长的输出并通过线性层return out

在这个模型中,我们定义了一个简单的 RNN 结构。input_size 是输入的特征数,hidden_size 是隐藏状态的维度,output_size 是输出的特征数。在前向传播中,输入 x 被传入 RNN 层,然后通过全连接层得到输出。

3.3 准备数据

假设我们有一组温度数据,我们将其转换为 PyTorch 张量并进行训练。

# 生成示例数据
data = np.array([[30, 31, 32, 33, 34],  # 第一个样本[32, 33, 34, 35, 36],  # 第二个样本[35, 36, 37, 38, 39]], # 第三个样本dtype=np.float32)labels = np.array([35, 37, 40], dtype=np.float32)  # 对应的目标值# 转换为 PyTorch 张量
data = torch.from_numpy(data).unsqueeze(-1)  # 添加特征维度
labels = torch.from_numpy(labels).unsqueeze(-1)
3.4 训练模型

我们将数据传入模型并进行训练。

# 定义超参数
input_size = 1
hidden_size = 10
output_size = 1
num_epochs = 100
learning_rate = 0.01# 实例化模型
model = WeatherRNN(input_size, hidden_size, output_size)# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)# 训练模型
for epoch in range(num_epochs):model.train()outputs = model(data)loss = criterion(outputs, labels)optimizer.zero_grad()loss.backward()optimizer.step()if (epoch+1) % 10 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

在这个训练过程中,我们使用了均方误差(MSE)作为损失函数,并使用 Adam 优化器来最小化损失。模型会通过多次迭代不断调整参数,以减少预测值和真实值之间的误差。

3.5 使用模型进行预测

训练完成后,我们可以使用训练好的模型进行预测。

model.eval()
with torch.no_grad():test_input = torch.tensor([[36, 37, 38, 39, 40]], dtype=torch.float32).unsqueeze(-1)predicted_temperature = model(test_input)print(f"预测的温度: {predicted_temperature.item():.2f}")

4. 完整代码

以下是完整的代码实现:

import torch
import torch.nn as nn
import numpy as npclass WeatherRNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(WeatherRNN, self).__init__()self.hidden_size = hidden_sizeself.rnn = nn.RNN(input_size, hidden_size, batch_first=True)self.fc = nn.Linear(hidden_size, output_size)def forward(self, x):h_0 = torch.zeros(1, x.size(0), self.hidden_size)out, h_n = self.rnn(x, h_0)out = self.fc(out[:, -1, :])return out# 生成示例数据
data = np.array([[30, 31, 32, 33, 34],[32, 33, 34, 35, 36],[35, 36, 37, 38, 39]],dtype=np.float32)labels = np.array([35, 37, 40], dtype=np.float32)data = torch.from_numpy(data).unsqueeze(-1)
labels = torch.from_numpy(labels).unsqueeze(-1)# 定义超参数
input_size = 1
hidden_size = 10
output_size = 1
num_epochs = 100
learning_rate = 0.01# 实例化模型
model = WeatherRNN(input_size, hidden_size, output_size)# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)# 训练模型
for epoch in range(num_epochs):model.train()outputs = model(data)loss = criterion(outputs, labels)optimizer.zero_grad()loss.backward()optimizer.step()if (epoch+1) % 10 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')# 进行预测
model.eval()
with torch.no_grad():test_input = torch.tensor([[36, 37, 38, 39, 40]], dtype=torch.float32).unsqueeze(-1)predicted_temperature = model(test_input)print(f"预测的温度: {predicted_temperature.item():.2f}")

5. 总结

通过这个天气预测的例子,我们直观地理解了 RNN 如何在时间步长上逐步处理输入,并通过隐藏状态记忆过去的信息,从而预测未来的值。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • VMware Workstation Pro for Personal Use (For Windows) 17.0.0
  • rabbitMQ安装与简单demo
  • [数据集][目标检测]航拍屋顶检测数据集VOC+YOLO格式458张3类别
  • python办公自动化:使用`python-docx`根据模板自动化生成文档
  • 【漏洞复现】SuiteCRM responseEntryPoint Sql注入漏洞
  • 【收藏】SaaS企业如何利用KOL营销实现用户增长
  • 【电脑使用耳机录音注意事项】
  • 一文搞定MybatisPlus
  • CentOS 7 部署iscsid 存储服务
  • ffmpeg最新5.1.6版本源码安装
  • 邻接表的具体实例
  • Linux简单介绍(1)
  • CVPR 2024论文分享┆LMDrive:基于大模型的闭环端到端自动驾驶
  • 【Unity3D小技巧】Unity3D中实现对InputField的自定义输入限制实例
  • [数据集][目标检测]铁轨缺陷检测数据集VOC+YOLO格式4020张4类别
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • JavaScript HTML DOM
  • JavaScript 奇技淫巧
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • Javascript基础之Array数组API
  • node 版本过低
  • React Transition Group -- Transition 组件
  • Redis 懒删除(lazy free)简史
  • Redux 中间件分析
  • XML已死 ?
  • 经典排序算法及其 Java 实现
  • 前端存储 - localStorage
  • 前端相关框架总和
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 什么是Javascript函数节流?
  • 数组大概知多少
  • 一文看透浏览器架构
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 积累各种好的链接
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • (C语言)二分查找 超详细
  • (k8s中)docker netty OOM问题记录
  • (定时器/计数器)中断系统(详解与使用)
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转)Oracle存储过程编写经验和优化措施
  • (转)scrum常见工具列表
  • (转)项目管理杂谈-我所期望的新人
  • **CI中自动类加载的用法总结
  • .NET CLR Hosting 简介
  • .net framework 4.8 开发windows系统服务
  • .NET/C#⾯试题汇总系列:集合、异常、泛型、LINQ、委托、EF!(完整版)
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • /bin/bash^M: bad interpreter: No such file or directory
  • ::before和::after 常见的用法
  • @hook扩展分析
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • [20140403]查询是否产生日志