You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch简易RNN训练报错:RuntimeError维度不匹配求助

PyTorch RNN序列预测报错:RuntimeError 解决方案

错误详情

运行RNN训练代码时触发如下错误:

RuntimeError: For unbatched 2-D input, hx should also be 2-D but got 3-D tensor

错误原因

定义RNN时设置了batch_first=True,要求输入张量形状为**(批量大小, 序列长度, 输入特征数),但当前输入数据X_train/X_test是2维张量(样本数, T),缺少了输入特征维度(这里输入特征数为1)。PyTorch将这种2维输入判定为无批量的输入**(即把第一维度当成序列长度,第二维度当成输入特征数),但我们初始化的隐藏状态h0是3维张量(层数, 批量大小, 隐藏层大小),两者维度不匹配,导致报错。

修复方案

给输入数据添加输入特征维度,将形状从(N, T)调整为(N, T, 1),有两种实现方式:

方式1:在Numpy数据预处理阶段修改

将数据集构建后的X reshape代码修改为:

X = np.array(X).reshape(-1, T, 1)  # 新增最后一个维度对应输入特征数1

方式2:在转换为PyTorch Tensor后修改

在生成X_train和X_test后添加维度扩展:

X_train = torch.from_numpy(X[:-N//2].astype(np.float32)).unsqueeze(-1)
X_test = torch.from_numpy(X[-N//2:].astype(np.float32)).unsqueeze(-1)

完整修正代码

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

# 生成原始数据
N = 1000
series = np.sin(0.1 * np.arange(N))  # 可添加噪声:+ np.random.randn(N)*0.1

# 可视化数据
plt.plot(series)
plt.show()

# 构建数据集
T = 10  # 用前10个时间步预测下一个时间步
X = []
Y = []

for t in range(len(series) - T):
    x = series[t:t+T]
    X.append(x)
    y = series[t+T]
    Y.append(y) 

# 调整X的形状为(样本数, 序列长度, 输入特征数)
X = np.array(X).reshape(-1, T, 1)
Y = np.array(Y).reshape(-1, 1) 
N = len(X) 
print("X.shape", X.shape, "Y.shape", Y.shape)

# 设置计算设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)

# 定义简易RNN模型
class simpleRNN(nn.Module):
    def __init__(self, n_inputs, n_hidden, n_rnnlayers, n_outputs):
        super(simpleRNN,self).__init__()
        self.D = n_inputs
        self.M = n_hidden
        self.K = n_outputs
        self.L = n_rnnlayers

        self.rnn = nn.RNN(
            input_size=self.D,
            hidden_size=self.M,
            num_layers=self.L,
            nonlinearity='relu',
            batch_first=True
        )
        self.fc = nn.Linear(self.M, self.K)  

    def forward(self, X):
        # 初始化隐藏状态
        h0 = torch.zeros(self.L, X.size(0), self.M).to(device) 

        # 获取RNN输出
        out, _ = self.rnn(X, h0) 

        # 取最后一个时间步的输出传入全连接层
        out = self.fc(out[:, -1, :]) 
        return out

# 实例化模型
model = simpleRNN(n_inputs=1, n_hidden=5, n_rnnlayers=1, n_outputs=1)
model.to(device)

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

# 转换数据为Tensor并移动到设备
X_train = torch.from_numpy(X[:-N//2].astype(np.float32)).to(device)
Y_train = torch.from_numpy(Y[:-N//2].astype(np.float32)).to(device)
X_test = torch.from_numpy(X[-N//2:].astype(np.float32)).to(device)
Y_test = torch.from_numpy(Y[-N//2:].astype(np.float32)).to(device)

# 训练函数
def full_gd(model, criterion, optimizer, X_train, Y_train, X_test, Y_test, epochs=200):
    train_losses = np.zeros(epochs)
    test_losses = np.zeros(epochs)
    
    for i in range(epochs):
        optimizer.zero_grad()

        # 前向传播
        outputs = model(X_train)
        loss = criterion(outputs, Y_train)

        # 反向传播与优化
        loss.backward()
        optimizer.step()

        # 记录损失
        train_losses[i] = loss.item()

        # 计算测试损失
        test_outputs = model(X_test)
        test_loss = criterion(test_outputs, Y_test)
        test_losses[i] = test_loss.item()

        if (i+1) % 5 == 0:
            print(f"Epoch {i+1}/{epochs}, Train_loss: {loss.item():.4f}, Test_loss: {test_loss.item():.4f}")

    return train_losses, test_losses

# 启动训练
train_losses, test_losses = full_gd(model, criterion, optimizer, X_train, Y_train, X_test, Y_test)

内容的提问来源于stack exchange,提问作者CMDTAUSIF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 06:06:30