循环神经网络RNN

embedded/2024/11/8 22:00:06/

概念

大家在学习深度学习时,都是按照“人工神经网络”、“卷积神经网络”的顺序来学习的。我们在学习的过程中可能会发现这样网络可能不适用一些带有“时间序列”的问题。

比如下面,要预测股票价格:

时间特征1特征2特征3特征4价格
2024-11-140.560.340.780.91456
2024-11-150.660.480.690.71987

我们使用“人工神经网络”和“卷积神经网络”时,不能将“时间考虑在内”,但是尝试告诉我们,股票也会受到前面时间环境的影响,因此,我们需要构建一个新的模型,用来解决这个问题。

下面先看一下RNN的结构:

我们来解释一下这个结构,这里面x1、x2、x3...并不是指一个特征值,而是指一条记录。就如同上面的一条记录(2024-11-4,0.56,0.34,0.78,0.91)。这个结构的意思是,将前面的输出作为一个参数去帮助后面的一条记录的训练。

其数学推导式如下:

其中,g为响应的激活函数,w为响应的权重矩阵。

相应的:

a^{i}=g_{a}(w_{aa}a^{i-1}+w_{ax}x^{i}+b_{a})

y^{i}=g_{y}(w_{ya}a^{i-1}+w_{yx}x^{i}+b_{y})

任务

自动寻找句子中的人名:

1、The courses are taught by Flare Zhao and David Chen.

我们可以将每个单词作为一条记录,进行输入,然后每个单词也有一个对应的输出,比如:

RNN常见的结构

多输入,多输出

如:

输入:x1,x2,x3,...,xi

输出:y1,y2,y3,...,yi

多输入,单输出

如:

输入:x1,x2,x3,...,xi

输出:y

可以应用于情感识别

例子:i feel happy watching the movie.

判断为:positive

单个输入,多个输出

这样的结构可以应用于:序列数据生成,比如文本生成等。

多输入,多输出(结构不相等)

可以应用于,语言翻译等。

RNN的缺陷

普通的RNN有一个明显的缺陷,那就是前面的信息在传递给后面时,信息的“强度”会越来越小。

比如上面“蓝色”的圈,每次传递一层,其重要性就会减少一些。所以,有很多重要的信息可能会丢失。

例子

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np# 生成示例数据(模拟时间序列数据)
data = [[0.56, 0.34, 0.78, 0.91, 456],[0.66, 0.48, 0.69, 0.71, 987],[0.72, 0.55, 0.67, 0.65, 1001],  # 添加更多数据以增强示例
]# 转换为numpy数组
data = np.array(data, dtype=np.float32)# 功能函数:创建序列数据的X和Y
def create_sequences(data, seq_length):xs = []ys = []for i in range(len(data) - seq_length):x = data[i:i + seq_length, :-1]  # 使用前四列作为输入y = data[i + seq_length, -1]  # 使用最后一列作为输出(价格)xs.append(x)ys.append(y)return np.array(xs), np.array(ys)seq_length = 2  # 序列长度(调整以获得不同的输入)
X, y = create_sequences(data, seq_length)# 转换为Tensor
X = torch.from_numpy(X)
y = torch.from_numpy(y).view(-1, 1)# 定义LSTM模型
class StockPricePredictor(nn.Module):def __init__(self, input_size, hidden_size, output_size, num_layers=1):super(StockPricePredictor, self).__init__()self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)self.fc = nn.Linear(hidden_size * seq_length, output_size)def forward(self, x):# 初始隐藏和单元状态h0 = torch.zeros(1, x.size(0), hidden_size)  # 隐藏层c0 = torch.zeros(1, x.size(0), hidden_size)  # 细胞状态out, _ = self.lstm(x, (h0, c0))  # LSTM输出out = out.reshape(out.shape[0], -1)out = self.fc(out)return out# 模型参数
input_size = 4  # 输入特征的数量
hidden_size = 50  # 隐藏层大小
output_size = 1  # 输出的特征数量(即价格)
num_epochs = 100  # 训练迭代次数
learning_rate = 0.001  # 学习率# 模型实例化
model = StockPricePredictor(input_size, hidden_size, output_size)# 损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)# 训练模型
for epoch in range(num_epochs):output = model(X)loss = criterion(output, y)optimizer.zero_grad()loss.backward()optimizer.step()if (epoch + 1) % 10 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')# 测试模型
with torch.no_grad():test_seq = torch.tensor(data[:seq_length, :-1], dtype=torch.float32).view(1, seq_length, -1)predicted_price = model(test_seq)print(f'Predicted next day price: {predicted_price.item()}')

1. 创建序列数据的X和Y

在时间序列预测中,我们通常需要根据过去的数据来预测未来的值。为了做到这一点,我们需要将原始数据转换成一组输入-输出对,这样才能用于模型训练。

示例数据转换

假设我们有以下数据(每行表示一天):

时间特征1特征2特征3特征4价格
2024-11-140.560.340.780.91456
2024-11-150.660.480.690.71987
2024-11-160.720.550.670.651001

我们想根据前两天的特征预测第三天的价格。对于这个例子,let seq_length = 2(代表使用的过去两天数据来预测)。这里的目标是将这些数据转换成多个"输入-输出"对。

转换后的数据(示例)

  • 输入 (X):
    • [[0.56, 0.34, 0.78, 0.91], [0.66, 0.48, 0.69, 0.71]]
  • 输出 (Y):
    • [1001]

解释:

  • X 是一个二维数组,每个内部数组包含 seq_length 天的特征数据。
  • Y 是目标值,就是我们要预测的第三天的价格。

这样做的目的是让模型学习到“给定过去的特征,输出未来的价格”。

2. LSTM的初始化

在代码中的这一行:

self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)

这行代码定义了一个LSTM层用于RNN模型。

参数解释
  • input_size: 输入数据的特征数量。在我们的例子中,每天有4个特征(例如:特征1到特征4),因此 input_size = 4。

  • hidden_size: 隐藏状态的维度。它决定了LSTM层的输出特征维度,并影响模型的记忆能力。通常,增加hidden_size能提高模型的复杂性和其潜在的预测能力,但也会增加计算复杂度。

  • num_layers: LSTM层的堆叠数量。这允许我们构造一个深度LSTM网络,单一层通常能处理简单问题,但对于复杂的时间依赖关系,堆叠多个LSTM层可能提高模型效果。

  • batch_first=True: 指定输入数据的维度顺序。在PyTorch中,默认的LSTM输入是 (seq_length, batch_size, input_size)。当 batch_first=True 时,输入的维度变为 (batch_size, seq_length, input_size),这通常更符合直觉,因为批次维度是第一位的。这个参数的设置将影响输入数据的格式。


http://www.ppmy.cn/embedded/136000.html

相关文章

3种最难学习和最容易学习的 3 种编程语言

无论您是想改变职业方向还是扩展程序员的技能,您选择学习的语言都会显着影响您的时间投入和前景。 一些语言使用熟悉的语法,欢迎为繁重的工作提供最少的代码命令,并且是开源的,具有有用的开发人员社区,可指导用户充分利…

js下载excel示例demo

<Buttontype{"primary"}key"out"onClick{async ()>{const ExportJsonExcel require("js-export-excel");const datas selectedRowsState //确保勾到的数据是一个列表&#xff0c;列表中每个值是字典const option {};const dataTable […

内网部署web项目,外网访问不了?只有局域网能访问!怎样解决?

相关技术 要实现“内网部署&#xff0c;外网访问”&#xff0c;可以使用内网穿透、VPN技术、DMZ主机、端口映射等方法。以下是对这些方法的详细解释&#xff1a; 一、内网穿透 内网穿透是一种技术&#xff0c;它通过将内网设备映射到公网上的方式&#xff0c;实现外网访问内…

面相小白的php反序列化漏洞原理剖析

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理反序列化漏洞的一些成因原理 建议学习反序列化之前 先对php基础语法与面向对象有个大体的了解 (我觉得我整理的比较细致&#xff0c;了解这俩是个啥就行) 漏洞实战情况 这个漏洞黑盒几乎不会被发现&am…

正则表达式 - 简介

正则表达式 - 简介 正则表达式&#xff08;Regular Expression&#xff0c;简称Regex&#xff09;是一种用于处理字符串的强大工具&#xff0c;它允许用户通过特定的模式&#xff08;pattern&#xff09;来搜索、匹配、查找和替换文本中的数据。正则表达式广泛应用于文本编辑器…

在PHP中使用UTF-8编码防止乱码需要注意以下几点‌:

在PHP中使用UTF-8编码防止乱码需要注意以下几点‌&#xff1a; ‌设置PHP文档编码为UTF-8‌&#xff1a;在PHP代码的最开始使用header()函数设置文档的编码为UTF-8。例如&#xff1a;header("Content-Type: text/html; charsetutf-8");‌12。 ‌确保文件编码为UTF-8…

Docker 基础命令简介

目录 Docker 基础命令 1. Docker 版本信息 2. 获取 Docker 帮助 3. 列出所有运行中的容器 4. 运行一个新的容器 5. 查看容器日志 6. 停止容器 7. 启动已停止的容器 8. 删除容器 9. 列出所有镜像 10. 拉取镜像 11. 构建镜像 12. 删除镜像 13. 执行命令 14. 查看容…

Dubbo负载均衡

负载均衡策略与配置细节 Dubbo 内置了 client-based 负载均衡机制&#xff0c;如下是当前支持的负载均衡算法&#xff0c;结合上文提到的自动服务发现机制&#xff0c;消费端会自动使用 Weighted Random LoadBalance 加权随机负载均衡策略 选址调用。 如果要调整负载均衡算法…