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

如何降低LSTM时间序列数据集构建过程中的内存占用?

解决LSTM时间序列数据集内存占用过高的问题

这确实是处理高维时间序列时很头疼的内存瓶颈问题——你的原数据已经是(8392, 41164)的大矩阵,滑动窗口后生成的三维数组吃掉50GB内存完全合理。我来分享几个实用的解决方案,从简单到进阶,帮你把内存占用砍下来:

1. 优先降低数据精度(最快见效)

默认情况下NumPy数组用float64存储,这对很多深度学习任务来说精度过剩。如果你的数据不需要这么高的精度,直接转换成float32甚至float16(TensorFlow/PyTorch都支持),内存占用直接减半或降到原来的1/4:

# 转换原数据精度
X = X.astype('float32')
y = y.astype('float32')

# 再用你原来的create_dataset函数
Xs, ys = create_dataset(X, y, time_steps=14)

这样处理后,你的数据集内存占用会从50GB降到25GB左右,如果用float16能压到12.5GB,几乎是零成本的优化。

2. 使用生成器/迭代器,避免一次性加载全部数据

你的原代码会把所有滑动窗口数据都存入列表再转成数组,相当于在内存里存了两份大数据(原数据+生成的三维数组)。改用生成器,每次只生成一个batch的数据,内存里只保留当前batch的内容:

自定义生成器(兼容Keras)

import numpy as np

def lstm_data_generator(X, y, time_steps, batch_size):
    num_samples = len(X) - time_steps
    while True:
        # 按batch遍历数据
        for start_idx in range(0, num_samples, batch_size):
            end_idx = min(start_idx + batch_size, num_samples)
            # 提取当前batch的滑动窗口
            X_batch = X[start_idx : end_idx + time_steps].reshape(
                (end_idx - start_idx, time_steps, X.shape[1])
            )
            y_batch = y[start_idx + time_steps : end_idx + time_steps]
            yield X_batch, y_batch

训练模型时直接用这个生成器:

batch_size = 32
steps_per_epoch = (len(X) - 14) // batch_size

model.fit(
    lstm_data_generator(X, y, 14, batch_size),
    steps_per_epoch=steps_per_epoch,
    epochs=10
)

如果用TensorFlow,更推荐用tf.data.Dataset来构建管道,它还支持并行加载、预取等优化:

import tensorflow as tf

def create_tf_dataset(X, y, time_steps, batch_size):
    dataset = tf.data.Dataset.from_tensor_slices((X, y))
    # 滑动窗口转换
    dataset = dataset.window(time_steps + 1, shift=1, drop_remainder=True)
    dataset = dataset.flat_map(lambda x, y: tf.data.Dataset.zip((x.batch(time_steps), y.skip(time_steps).take(1))))
    dataset = dataset.batch(batch_size).prefetch(tf.data.AUTOTUNE)
    return dataset

train_dataset = create_tf_dataset(X, y, 14, 32)
model.fit(train_dataset, epochs=10)

这种方式下,内存占用只会是一个batch的大小,几十MB到几百MB不等,完全解决内存溢出问题。

3. 用NumPy视图创建滑动窗口,避免数据复制

如果你一定要用数组形式而不是生成器,可以用np.lib.stride_tricks.as_strided创建滑动窗口的视图——它不会复制原数据,只是改变数组的步长信息,内存占用和原数据几乎一样:

def create_dataset_view(X, y, time_steps):
    num_samples = len(X) - time_steps
    # 创建滑动窗口视图,无数据复制
    Xs = np.lib.stride_tricks.as_strided(
        X,
        shape=(num_samples, time_steps, X.shape[1]),
        strides=(X.strides[0], X.strides[0], X.strides[1]),
        writeable=False  # 设为不可写,防止意外修改原数据
    )
    ys = y[time_steps:]
    return Xs, ys

⚠️ 注意:这个方法是“视图”而非复制,所以如果原数据被修改,Xs也会跟着变。建议使用前把原数据设为只读,或者确保不会修改原数据。

4. 特征降维(从根源减少数据量)

你的数据有41164个特征,这可能是内存占用高的核心原因——哪怕每个特征只占4字节(float32),一个样本就要占411644≈160KB,8378个样本就是8378160KB≈1.3GB,再乘以14个时间步就是18GB左右(加上y的话接近20GB,再算上原数据的话确实会到50GB)。

如果这些特征有冗余,用降维方法把特征数砍下来:

  • PCA:保留大部分方差,把特征数降到几百甚至几十:
from sklearn.decomposition import PCA

# 保留95%的方差,自动计算需要的特征数
pca = PCA(n_components=0.95)
X_reduced = pca.fit_transform(X)

# 再用降维后的数据创建LSTM数据集
Xs, ys = create_dataset(X_reduced, y, time_steps=14)
  • Autoencoder:用深度学习模型学习特征的低维表示,适合非线性的特征冗余。
  • 特征选择:用互信息、方差阈值等方法筛选出和y相关的特征,去掉无用特征。

降维不仅能大幅降低内存,还能减少模型的训练时间,降低过拟合风险,一举多得。


内容的提问来源于stack exchange,提问作者BAGUS SATYA MAS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 19:17:30