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

深度学习信号分类:滑动窗口数据增强内存溢出优化求助

优化滑动窗口数据增强的内存占用方案

我明白你现在的困境——小数据集做信号分类,想用滑动窗口扩充数据但内存直接撑爆,12GB都扛不住确实头疼。咱们来一步步优化这段代码,从根本上减少内存消耗:


1. 优先改用生成器/迭代器,按需输出数据

原代码每次循环都把临时窗口数据拼接到大数组里,而numpy数组是不可变的,每次拼接都会创建新数组、拷贝旧数据,内存占用会指数级增长。换成生成器的话,每次只生成当前样本的窗口数据,训练时按需取用,完全不用一次性把所有增强数据都塞进内存。

优化后的代码:

def sliding_window_generator(data, labels, window_sz, n_hop, n_start=0, show_status=False):
    for sample_idx in range(data.shape[0]):
        sample_data = data[sample_idx]
        sample_label = labels[sample_idx]
        # 计算当前样本的窗口起始索引
        start_indices = np.arange(n_start, data.shape[1] - window_sz + n_hop, n_hop)
        for idx in start_indices:
            window = sample_data[idx:idx+window_sz, :]
            yield window, sample_label
        if sample_idx % 100 == 0 and show_status:
            print(f"Sample {sample_idx} processed!")

调用示例(以TensorFlow训练为例):

import tensorflow as tf

# 初始化生成器
generator = sliding_window_generator(
    X_train, y_train, 
    window_sz=4*fs, n_hop=fs//10, n_start=fs*1
)
# 转换为tf.data.Dataset,支持批量、打乱等操作
dataset = tf.data.Dataset.from_generator(
    lambda: generator,
    output_signature=(
        tf.TensorSpec(shape=(4*fs, X_train.shape[2]), dtype=tf.float32),
        tf.TensorSpec(shape=(), dtype=tf.int32)  # 根据你的标签类型调整
    )
)
dataset = dataset.shuffle(1000).batch(32)

# 后续直接用dataset喂给模型训练即可
model.fit(dataset, epochs=10)

2. 若必须保留完整数组:预分配内存再填充

如果你的场景一定要得到完整的增强后数组,那不要反复拼接,先算好总窗口数,一次性分配足够大的数组,直接填充数据,避免多次内存拷贝。

优化后的代码:

def sliding_window_prealloc(data, labels, window_sz, n_hop, n_start=0, show_status=False):
    n_samples, seq_len, feature_dim = data.shape
    # 计算单个样本的窗口数量
    n_windows_per_sample = len(np.arange(n_start, seq_len - window_sz + n_hop, n_hop))
    total_windows = n_samples * n_windows_per_sample
    
    # 一次性分配内存,复用原数据的dtype减少开销
    new_data = np.zeros((total_windows, window_sz, feature_dim), dtype=data.dtype)
    new_lab = np.zeros((total_windows,), dtype=labels.dtype)
    
    current_idx = 0
    for sample_idx in range(n_samples):
        sample_data = data[sample_idx]
        sample_label = labels[sample_idx]
        start_indices = np.arange(n_start, seq_len - window_sz + n_hop, n_hop)
        n_windows = len(start_indices)
        # 批量填充当前样本的所有窗口
        for i, idx in enumerate(start_indices):
            new_data[current_idx + i] = sample_data[idx:idx+window_sz, :]
            new_lab[current_idx + i] = sample_label
        current_idx += n_windows
        
        if sample_idx % 100 == 0 and show_status:
            print(f"Sample {sample_idx} processed!")
    
    return new_data, new_lab

3. 降低数据 dtype 进一步压缩内存

检查一下你的数据类型,如果是float64,可以改成float32(甚至float16,如果模型支持混合精度训练的话),内存占用直接减半:

# 转换数据类型,前提是信号精度允许
X_train = X_train.astype(np.float32)
y_train = y_train.astype(np.int32)  # 标签也可以按需降级

4. 极端场景:分批次保存到磁盘

如果增强后的数据量实在太大,连预分配内存都扛不住,可以分批次处理,把每一批增强数据保存到磁盘(比如用h5py),训练时再分批加载:

import h5py

def sliding_window_batch_save(data, labels, window_sz, n_hop, n_start=0, batch_size=200, save_path='augmented_data.h5'):
    n_samples, seq_len, feature_dim = data.shape
    n_windows_per_sample = len(np.arange(n_start, seq_len - window_sz + n_hop, n_hop))
    total_windows = n_samples * n_windows_per_sample
    
    with h5py.File(save_path, 'w') as f:
        # 创建预留空间的数据集
        dset_data = f.create_dataset('data', shape=(total_windows, window_sz, feature_dim), dtype=data.dtype)
        dset_labels = f.create_dataset('labels', shape=(total_windows,), dtype=labels.dtype)
        
        current_idx = 0
        for batch_start in range(0, n_samples, batch_size):
            batch_end = min(batch_start + batch_size, n_samples)
            batch_data = data[batch_start:batch_end]
            batch_labels = labels[batch_start:batch_end]
            
            for sample_idx_in_batch in range(batch_data.shape[0]):
                sample_data = batch_data[sample_idx_in_batch]
                sample_label = batch_labels[sample_idx_in_batch]
                start_indices = np.arange(n_start, seq_len - window_sz + n_hop, n_hop)
                n_windows = len(start_indices)
                for i, idx in enumerate(start_indices):
                    dset_data[current_idx + i] = sample_data[idx:idx+window_sz, :]
                    dset_labels[current_idx + i] = sample_label
                current_idx += n_windows
                
            print(f"Batch {batch_start//batch_size + 1} processed!")

训练时分批读取:

with h5py.File('augmented_data.h5', 'r') as f:
    data = f['data']
    labels = f['labels']
    # 按需读取批次数据
    batch_data = data[0:32]
    batch_labels = labels[0:32]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:26:52