代码功能

正弦函数数据:
使用正弦函数 y = sin(x) 生成序列数据,作为目标预测的基准。
将数据分成序列块(长度为 seq_length),并构造输入 x_train 和输出 y_train。
训练损失可视化:
在训练过程中记录每个 epoch 的损失,并绘制损失曲线。
预测结果可视化:
使用训练好的模型对正弦波后续部分进行预测。
通过滑动窗口机制逐步预测整个序列,并绘制真实值与预测值的对比图。
输出:
损失曲线:
观察损失如何随着训练迭代逐渐下降。
正弦波预测:
蓝色线为真实的正弦波,红色虚线为模型预测值,观察模型对序列的拟合能力。
在这里插入图片描述
在这里插入图片描述

代码

import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np

# 定义超参数
input_size = 1    # 输入特征维度
hidden_size = 20  # 隐藏层维度
output_size = 1   # 输出特征维度
seq_length = 10   # 序列长度
num_epochs = 200  # 训练轮数
learning_rate = 0.01

# 定义 RNN 模型
class RNNModel(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(RNNModel, self).__init__()
        self.hidden_size = hidden_size
        self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)  # RNN 层
        self.fc = nn.Linear(hidden_size, output_size)  # 全连接层

    def forward(self, x):
        h0 = torch.zeros(1, x.size(0), self.hidden_size)  # 初始化隐藏状态
        out, _ = self.rnn(x, h0)  # RNN 前向传播
        out = self.fc(out[:, -1, :])  # 只取最后一个时间步的输出
        return out

# 生成正弦函数数据
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

# 创建训练数据(分段序列)
x_train = []
y_train = []
for i in range(len(x) - seq_length):
    x_train.append(y[i:i + seq_length])
    y_train.append(y[i + seq_length])
x_train = torch.tensor(x_train, dtype=torch.float32).unsqueeze(-1)  # 增加特征维度
y_train = torch.tensor(y_train, dtype=torch.float32).unsqueeze(-1)

# 模型实例化
model = RNNModel(input_size, hidden_size, output_size)

# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 训练模型
losses = []
for epoch in range(num_epochs):
    model.train()
    outputs = model(x_train)
    loss = criterion(outputs, y_train)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    losses.append(loss.item())

    if (epoch + 1) % 20 == 0:
        print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')

# 绘制训练损失
plt.figure(figsize=(10, 5))
plt.plot(losses, label="Training Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.title("Training Loss Over Epochs")
plt.legend()
plt.show()

# 测试模型
model.eval()
with torch.no_grad():
    test_input = y[:seq_length]  # 取初始正弦序列
    test_input = torch.tensor(test_input, dtype=torch.float32).unsqueeze(0).unsqueeze(-1)  # 调整形状
    predictions = []
    for _ in range(len(x) - seq_length):
        pred = model(test_input)
        predictions.append(pred.item())
        # 滑动窗口更新输入
        pred = pred.unsqueeze(-1)  # 确保形状为 [batch_size, 1, 1]
        test_input = torch.cat((test_input[:, 1:, :], pred), dim=1)


# 绘制预测结果
plt.figure(figsize=(10, 5))
plt.plot(x, y, label="True Sine Wave", color="blue")
plt.plot(x[seq_length:], predictions, label="Predicted Wave", color="red", linestyle="--")
plt.xlabel("x")
plt.ylabel("y")
plt.title("True vs Predicted Sine Wave")
plt.legend()
plt.show()

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐