💓 博客主页:瑕疵的CSDN主页
📝 Gitee主页:瑕疵的gitee主页
⏩ 文章专栏:《热点资讯》

时间序列预测翻车实录:PyTorch 数据维度坑了我一整天

目录

    深夜写时间序列预测,又栽了。模型报错:RuntimeError: Expected 2D tensor, got 1D tensor。我盯着屏幕,心想“这不就个LSTM嘛,至于吗?” 结果折腾到三点,才明白是数据格式在作妖。

    问题出在哪?
    我用股票收盘价数据训练LSTM,原始数据是单列数组(1000个点)。直接喂给模型:

    raw_data = torch.randn(1000)  # 1D tensor
    model(raw_data)  # 报错:Expected 2D tensor, got 1D
    

    报错信息清清楚楚——LSTM需要二维输入,但我的数据是扁平的1D。新手常见坑:以为时间序列就是普通数据,没处理序列结构。

    核心根源
    时间序列预测的核心是“时间步长”。模型要的是 [batch, sequence_length, features] 格式。

    • 错误:原始数据是 (n,),LSTM以为是单个样本的特征(比如输入10个特征,但这里只有1个值)。
    • 正确:必须把连续数据切片成序列,比如用前10天预测第11天。
      我踩过的坑:以为batch_first=True能自动修复维度,结果没用。数据形状不对,再牛的模型也崩。

    错误示范 vs 正确姿势
    先看错误代码(血泪教训):

    # 错误示范:直接喂1D数据,维度不匹配
    import torch
    import torch.nn as nn
    
    raw_data = torch.randn(1000)  # 原始数据:1D [1000]
    
    model = nn.LSTM(
        input_size=1,          # 特征数=1(单列数据)
        hidden_size=50,
        batch_first=True       # 重要!但没救维度问题
    )
    
    # 尝试输入:直接传1D,报错
    output, _ = model(raw_data)  # RuntimeError: Expected 2D tensor
    

    再看正确姿势(亲测有效):

    # 正确姿势:用Dataset处理序列,确保形状 [batch, seq_len, features]
    from torch.utils.data import Dataset, DataLoader
    
    class TimeSeriesDataset(Dataset):
        def __init__(self, data, seq_len):
            self.data = data
            self.seq_len = seq_len  # 每个序列长度(如10天)
    
        def __len__(self):
            return len(self.data) - self.seq_len  # 可切片的样本数
    
        def __getitem__(self, idx):
            # 输入:前 seq_len 个点 [seq_len, features]
            # 目标:下一个点 [1]
            return (
                self.data[idx:idx+self.seq_len],  # shape: [seq_len]
                self.data[idx+self.seq_len]       # shape: []
            )
    
    # 准备数据(seq_len=10,预测10天后)
    dataset = TimeSeriesDataset(raw_data, seq_len=10)
    dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
    
    # 训练时:确保输入是 [batch, seq_len, features]
    for inputs, targets in dataloader:
        # inputs shape: [batch, seq_len] -> 需转成 [batch, seq_len, 1](单特征)
        inputs = inputs.unsqueeze(-1)  # 添加特征维度
        output, _ = model(inputs)      # 现在 shape: [batch, seq_len, hidden]
    

    关键点:

    1. unsqueeze(-1)[batch, seq_len] 变成 [batch, seq_len, 1],匹配LSTM的input_size=1
    2. Dataset自动切片,避免手动处理维度。
    3. batch_first=True 要和DataLoader配合用,否则维度顺序乱。

    避坑总结

    • 时间序列数据别直接喂!必须用Dataset分块成序列。
    • 训练前打印形状:print(inputs.shape),别猜。
    • 单特征时,unsqueeze(-1)是保命操作。
    • LSTM的input_size必须等于特征数(单列=1)。
      我测试过,用这个姿势,模型终于跑通了。之前被坑两天,现在写代码都带检查维度的肌肉记忆。

    时间序列预测,数据处理是命根子。别急着调模型,先搞定数据形状。否则,你就是在给报错当陪练。

    Logo

    免费领 200 小时云算力,进群参与显卡、AI PC 幸运抽奖

    更多推荐