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

多独立CSV数据集下LSTM时间序列预测的PyTorch实现疑问

问题描述

我正尝试训练一个LSTM模型,以5个特征作为网络输入来预测单个目标变量。我的数据集存储在多个独立CSV文件中,每个文件对应一个独立场景,时间范围从t=0s到t=100s,时间步长为1s,因此无法将它们按顺序堆叠。例如,若有50个CSV文件,每个文件包含100行(对应时间步)和6列(5个特征+1个目标变量),即每个文件是尺寸为(100*6)的二维矩阵。

我的目标是让LSTM接收长度为3的特征序列作为输入,逐次预测从t=0到t=100的未来单个目标值。我计划将50个数据集划分为训练集、验证集和测试集,现存在以下疑问:

  1. 如何高效地为训练集创建PyTorch Dataset和DataLoader?
  2. 为每个训练文件单独创建Dataset和DataLoader,逐个遍历所有训练文件,累加每个文件的损失后取平均值,这种方式是否合理?
  3. 由于所有数据都是时间序列数据(时间的函数),在使用DataLoader时是否应该设置shuffle=True?

我是机器学习初学者,具备相关基础。我曾尝试按问题2的方式创建Dataset和DataLoader,但未成功,希望获得相关技术反馈。


解答

1. 高效构建Dataset与DataLoader

推荐实现一个场景级的自定义Dataset,无需提前加载所有数据到内存,而是在取样本时动态读取单个CSV文件并生成序列。这种方式内存友好,且能统一管理所有训练样本。

自定义Dataset代码示例

import torch
import pandas as pd
from torch.utils.data import Dataset, DataLoader
from glob import glob

class SceneTimeSeriesDataset(Dataset):
    def __init__(self, csv_paths, seq_len=3):
        self.csv_paths = csv_paths
        self.seq_len = seq_len
        # 单个文件可生成的样本数:总时间步 - 序列长度 + 1
        self.samples_per_file = 100 - seq_len + 1

    def __len__(self):
        # 总样本数 = 文件数 × 单文件样本数
        return len(self.csv_paths) * self.samples_per_file

    def __getitem__(self, idx):
        # 定位当前样本所属的文件和在文件内的位置
        file_idx = idx // self.samples_per_file
        sample_pos = idx % self.samples_per_file

        # 读取CSV并拆分特征与目标
        df = pd.read_csv(self.csv_paths[file_idx])
        features = df.iloc[:, :5].astype(float).values  # 前5列是特征
        targets = df.iloc[:, 5].astype(float).values    # 第6列是目标变量

        # 生成输入序列(长度为3的特征序列)
        input_seq = torch.tensor(features[sample_pos : sample_pos+self.seq_len], dtype=torch.float32)
        # 生成对应目标:根据你的需求二选一
        # 需求1:用[t, t+1, t+2]的特征预测t+2的目标值
        target = torch.tensor(targets[sample_pos+self.seq_len-1], dtype=torch.float32)
        # 需求2:用[t, t+1, t+2]的特征预测t+3的目标值(注意要确保sample_pos+seq_len < 100)
        # target = torch.tensor(targets[sample_pos+self.seq_len], dtype=torch.float32)

        return input_seq, target

构建DataLoader

先划分训练/验证/测试的CSV路径:

# 获取所有CSV文件路径
all_csvs = glob("./your_data_dir/*.csv")
# 按7:2:1划分训练/验证/测试集
train_csvs = all_csvs[:35]
val_csvs = all_csvs[35:45]
test_csvs = all_csvs[45:]

# 创建Dataset和DataLoader
train_dataset = SceneTimeSeriesDataset(train_csvs, seq_len=3)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)  # shuffle的问题见下文
val_loader = DataLoader(SceneTimeSeriesDataset(val_csvs), batch_size=32, shuffle=False)
test_loader = DataLoader(SceneTimeSeriesDataset(test_csvs), batch_size=32, shuffle=False)

2. 单文件单独创建Dataset的方式是否合理?

这种方式可行但不推荐,主要问题在于:

  • 训练效率低:每个文件单独遍历,相当于频繁切换训练数据源,模型参数更新会过度受单个场景数据影响,容易导致泛化性差
  • 手动累加损失易出错:比如忘记梯度清零、损失计算时混淆样本数与文件数,导致梯度更新异常

如果坚持用这种方式,需要注意:

  • 每个文件训练前必须调用optimizer.zero_grad()清零梯度
  • 累加损失时要除以总训练样本数(不是文件数),确保损失均值计算正确
  • 保持每个文件的批次大小一致,避免梯度波动过大

3. DataLoader是否需要shuffle=True?

  • 训练集建议设shuffle=True:打乱不同场景的样本,让模型在混合场景的批次中训练,避免过度拟合单个场景的时间模式,提升泛化能力。注意这里的shuffle只是打乱样本的顺序,单个样本内部的时间序列(比如t0,t1,t2的特征)依然保持连续性,不会破坏时间逻辑。
  • 验证/测试集必须设shuffle=False:评估模型时需要保持时间序列的连续性,模拟实际场景中从t=0到t=100的连续预测,这样得到的评估结果才真实有效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:43:18