循环神经网络 (RNN)
核心思想:像人一样拥有记忆能力。用以往的记忆和当前的输入,生成输出。
应用场景:1.文本生成 2.语音识别 3.机器翻译 4.生成图像描述 5.视频标记
缺点:
RNN 有短期记忆问题,无法处理很长的输入序列
RNN 是一种死板的逻辑,越晚的输入影响越大,越早的输入影响越小,且无法改变这个逻辑。容易出现梯度消失或梯度爆炸。
长短期记忆网络 (LSTM)
LSTM 是一种特定类型的 RNN,旨在解决长序列中的梯度消失问题。LSTM 通过一种特殊的单元结构来记住信息的长短期依赖。
LSTM的原理
LSTM 通过以下几个门来控制信息的流动:
LSTM的梯度反向传播过程可能会涉及到复杂的计算和动态规划技巧,因为每个时间步的梯度都依赖于前面时间步的计算结果。在实际应用中,可以使用成熟的深度学习框架(如TensorFlow或PyTorch)来实现LSTM的训练和推断过程。
import torch
import torch.nn as nn
import torch.optim as optim
# 定义LSTM模型
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers):
super(LSTMModel, self).__init__()
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size) # 全连接层,以输出序列的每一个时间步的预测
def forward(self, x):
# x形状为 (batch_size, seq_length, input_size)
lstm_out, _ = self.lstm(x) # lstm_out为每个时间步的输出
predictions = self.fc(lstm_out[:, -1, :]) # 只获取最后一个时间步的输出
return predictions
# 超参数
input_size = 10 # 输入特征的维度
hidden_size = 20 # 隐藏层的节点数量
output_size = 1 # 预测输出的维度
num_layers = 2 # LSTM层的数量
num_epochs = 100 # 训练轮次
learning_rate = 0.01 # 学习率
# 创建模型实例
model = LSTMModel(input_size, hidden_size, output_size, num_layers)
criterion = nn.MSELoss() # 损失函数
optimizer = optim.Adam(model.parameters(), lr=learning_rate) # 优化器
# 假设输入数据和目标输出
# 生成模拟数据,[batch_size, seq_length, input_size]
x_train = torch.randn(100, 5, input_size) # 100个样本,每个样本5个时间步
y_train = torch.randn(100, output_size) # 100个对应的目标值
# 训练过程
for epoch in range(num_epochs):
model.train() # 设置模型为训练模式
optimizer.zero_grad() # 清空之前的梯度
# 前向传播
outputs = model(x_train) # 获取模型的预测
# 计算损失
loss = criterion(outputs, y_train)
print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')
# 反向传播与优化
loss.backward() # 计算梯度
optimizer.step() # 更新参数
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
# 生成模拟数据(股票价格时间序列)
def create_dataset(data, time_step=1):
X, Y = [], []
for i in range(len(data) - time_step - 1):
X.append(data[i:(i + time_step)])
Y.append(data[i + time_step])
return np.array(X), np.array(Y)
# 超参数
input_size = 1 # 输入特征的维度(股票价格)
hidden_size = 20 # 隐藏层的节点数量
output_size = 1 # 输出的维度(预测的价格)
num_layers = 2 # LSTM层的数量
num_epochs = 100 # 训练轮次
learning_rate = 0.01 # 学习率
time_step = 10 # 使用过去10个时间步作预测
# 生成模拟时间序列数据
np.random.seed(0) # 为了可重现性
data = np.sin(np.linspace(0, 100, 500)) + np.random.normal(0, 0.1, 500) # 正弦波 + 添加噪声
data = data.astype(np.float32)
# 划分数据集
train_size = int(len(data) * 0.8)
train_data, test_data = data[:train_size], data[train_size:]
# 创建训练和测试数据集
X_train, y_train = create_dataset(train_data, time_step)
X_test, y_test = create_dataset(test_data, time_step)
# 转换为PyTorch张量并增加维度
X_train = torch.from_numpy(X_train).unsqueeze(-1) # (samples, time step, input size)
y_train = torch.from_numpy(y_train).unsqueeze(-1) # (samples, output size)
X_test = torch.from_numpy(X_test).unsqueeze(-1)
y_test = torch.from_numpy(y_test).unsqueeze(-1)
# 定义LSTM模型
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers):
super(LSTMModel, self).__init__()
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size) # 全连接层
def forward(self, x):
lstm_out, (h_n, c_n) = self.lstm(x) # lstm_out为每个时间步的输出
# lstm_out的形状为 (batch_size, seq_length, hidden_size)
predictions = self.fc(lstm_out[:, -1, :]) # 只获取最后一个时间步的输出
return predictions
# 创建模型实例
model = LSTMModel(input_size, hidden_size, output_size, num_layers)
criterion = nn.MSELoss() # 均方误差损失函数
optimizer = optim.Adam(model.parameters(), lr=learning_rate) # Adam优化器
# 训练过程
for epoch in range(num_epochs):
model.train() # 设置模型为训练模式
optimizer.zero_grad() # 清空之前的梯度
# 前向传播
outputs = model(X_train) # 获取模型的预测
loss = criterion(outputs, y_train) # 计算损失
# 反向传播与优化
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(): # 不计算梯度
predicted = model(X_test)
# 绘制预测结果
plt.figure(figsize=(12, 6))
plt.plot(np.arange(len(data)), data, label='True Data', color='blue')
plt.plot(np.arange(len(train_data) + time_step, len(data) - 1), predicted.numpy(), label='Predicted Data', color='red')
plt.title('Stock Price Prediction')
plt.xlabel('Time Step')
plt.ylabel('Stock Price')
plt.legend()
plt.show()
GRU(门控循环单元)
GRU(门控循环单元)也是一种循环神经网络(RNN)的变体。与LSTM相比,GRU的结构相对简单。
GRU的结构由两部分组成:更新门和重置门。更新门用于控制上一时刻隐藏状态对当前时刻隐藏状态的贡献程度,而重置门用于控制当前输入对当前时刻隐藏状态的更新程度。
LSTM与GRU比较
1结构复杂性:
LSTM:有三个门(输入门、遗忘门、输出门),每个门都有自己的权重和偏置。
GRU:只有两个门(重置门和更新门),整体结构更加简洁,参数更少,计算效率更高。
2记忆能力:
LSTM:通过单独的细胞状态来保存信息,能够获得更强的长期记忆能力。
GRU:通过更新门控制信息的传递,相对而言稍微简化了记忆机制,但在很多实际应用中也能有效捕捉长期依赖。
3性能:
LSTM:对长序列学习效果较好,但相对复杂的结构会导致训练时间更长。
GRU:由于结构简单,通常在小样本和短序列任务上能够表现出更快的收敛速度,公式的计算量也较小。
4适用场景:
在某些应用中(如语音识别、自然语言处理),GRU 通常能与 LSTM 竞争甚至超越其性能。
LSTM 更适合需要复杂记忆机制的任务,尤其是在长序列情况下。
GRU 可以通过构建一个与 LSTM 类似的模型来实现。下面是使用 PyTorch 实现 GRU 的示例代码:
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
# 生成模拟数据(股价时间序列)
def create_dataset(data, time_step=1):
X, Y = [], []
for i in range(len(data) - time_step - 1):
X.append(data[i:(i + time_step)])
Y.append(data[i + time_step])
return np.array(X), np.array(Y)
# 超参数设置
input_size = 1 # 输入特征的维度(股价)
hidden_size = 20 # 隐藏层的单元数量
output_size = 1 # 输出的维度(预测的股价)
num_layers = 2 # GRU层的数量
num_epochs = 100 # 训练轮次
learning_rate = 0.01 # 学习率
time_step = 10 # 使用过去10个时间步作为输入预测
# 生成模拟时间序列数据
np.random.seed(0) # 为了可重现性
data = np.sin(np.linspace(0, 100, 500)) + np.random.normal(0, 0.1, 500) # 生成正弦波 + 添加噪声
data = data.astype(np.float32)
# 划分数据集
train_size = int(len(data) * 0.8)
train_data, test_data = data[:train_size], data[train_size:]
# 创建训练和测试数据集
X_train, y_train = create_dataset(train_data, time_step)
X_test, y_test = create_dataset(test_data, time_step)
# 转换为 PyTorch 张量并增加维度
X_train = torch.from_numpy(X_train).unsqueeze(-1) # (样本数, 时间步, 输入特征数)
y_train = torch.from_numpy(y_train).unsqueeze(-1) # (样本数, 输出特征数)
X_test = torch.from_numpy(X_test).unsqueeze(-1)
y_test = torch.from_numpy(y_test).unsqueeze(-1)
# 定义 GRU 模型
class GRUModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers):
super(GRUModel, self).__init__()
self.gru = nn.GRU(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size) # 全连接层
def forward(self, x):
gru_out, _ = self.gru(x) # gru_out为每个时间步的输出
predictions = self.fc(gru_out[:, -1, :]) # 取最后一个时间步的输出
return predictions
# 创建模型实例
model = GRUModel(input_size, hidden_size, output_size, num_layers)
criterion = nn.MSELoss() # 均方误差损失函数
optimizer = optim.Adam(model.parameters(), lr=learning_rate) # Adam 优化器
# 训练过程
for epoch in range(num_epochs):
model.train() # 设置模型为训练模式
optimizer.zero_grad() # 清空之前的梯度
# 前向传播
outputs = model(X_train) # 获取模型的预测
loss = criterion(outputs, y_train) # 计算损失
# 反向传播与优化
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(): # 不计算梯度
predicted = model(X_test)
# 绘制预测结果
plt.figure(figsize=(12, 6))
plt.plot(np.arange(len(data)), data, label='True Data', color='blue')
plt.plot(np.arange(len(train_data) + time_step, len(data) - 1), predicted.numpy(), label='Predicted Data', color='red')
plt.title('Stock Price Prediction Using GRU')
plt.xlabel('Time Step')
plt.ylabel('Stock Price')
plt.legend()
plt.show()