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

如何压缩.npy数据节省磁盘空间?寻求比np.save更省空间的存储方案

针对大型numpy数据集的压缩与存储优化方案

针对你提到的1.5TB分块numpy数据集(Python 2.7环境,每个.npy为(number_of_examples,224,224,19)的float数组),我分两部分解答你的问题:


1. 高效的数据集压缩方法

这里有几个实用的压缩方案,兼顾压缩率和易用性:

  • 利用numpy内置的压缩功能
    你可以直接用np.savez_compressed替代np.save,它会对数组进行无损压缩,不需要额外依赖。对于float类型的数据,尤其是存在冗余的场景,压缩率通常能达到2-5倍。示例代码:

    import numpy as np
    # 假设你的数据数组是data
    np.savez_compressed('data_1_compressed.npz', data=data)
    # 读取时
    loaded = np.load('data_1_compressed.npz')
    data = loaded['data']
    

    如果你想保留单个文件的结构,也可以手动对.npy文件进行压缩(比如用gzip或zstd命令行工具),但savez_compressed更方便,能直接处理数组读写。

  • 使用高速压缩库(Zstandard/LZ4)
    如果你追求更快的压缩/解压速度和更高的压缩率,可以用Zstandard(zstd)或LZ4这类现代压缩库。以Zstandard为例,Python 2.7可以安装对应版本的zstandard库,然后手动处理数组的字节流压缩:

    import numpy as np
    import zstandard as zstd
    
    # 保存
    data = np.random.rand(100,224,224,19).astype(np.float32)
    compressor = zstd.ZstdCompressor(level=10)  # 压缩级别可调,越高压缩率越高
    compressed_data = compressor.compress(data.tobytes())
    with open('data_1.zst', 'wb') as f:
        f.write(compressed_data)
    
    # 读取
    with open('data_1.zst', 'rb') as f:
        compressed_data = f.read()
    decompressor = zstd.ZstdDecompressor()
    decompressed_data = decompressor.decompress(compressed_data)
    data = np.frombuffer(decompressed_data, dtype=np.float32).reshape((100,224,224,19))
    

    这种方式的压缩速度比numpy内置的更快,压缩率也更优,适合大规模数据集。

  • 批量打包压缩
    如果你有多个子数据集文件,可以用tar结合Zstandard或XZ进行批量打包压缩,命令行操作如下:

    # 把所有data_*.npy打包成tar并以zstd压缩
    tar -I zstd -cf dataset.tar.zst data_*.npy
    # 解压
    tar -I zstd -xf dataset.tar.zst
    

    这种方式适合归档存储,能减少文件系统的碎片化,同时利用批量压缩的优势。


2. 比np.save更省空间的存储方式

除了压缩,换用更高效的存储格式也能大幅减少磁盘占用:

  • HDF5格式(推荐)
    HDF5是专为大型科学数据设计的存储格式,支持内置压缩、分块存储和按需读取,非常适合你的场景。Python 2.7可以使用h5py库来操作,示例代码:

    import h5py
    import numpy as np
    
    # 保存单个数据集,启用gzip压缩(也可以用'lzf'、'zstd'等)
    data = np.random.rand(100,224,224,19).astype(np.float32)
    with h5py.File('data_1.h5', 'w') as f:
        # 设置压缩参数,compression_opts越高压缩率越高
        f.create_dataset('data', data=data, compression='gzip', compression_opts=9)
    
    # 读取时可以按需加载部分数据,不用全读入内存
    with h5py.File('data_1.h5', 'r') as f:
        # 只加载前10个样本
        partial_data = f['data'][:10, ...]
    

    HDF5的压缩率通常比np.save高很多,而且支持复杂的数据结构,还能避免多个小文件的问题(你可以把多个子数据集放到同一个HDF5文件里)。

  • 降低数据精度(如果允许)
    如果你当前用的是float64(双精度),可以先把数组转换为float32(单精度),这能直接减少一半的磁盘占用,而且很多深度学习或数据分析场景下,单精度已经足够满足需求。转换代码很简单:

    data = data.astype(np.float32)
    

    配合上面的压缩或HDF5存储,能进一步节省空间。

  • 自定义二进制格式
    如果你追求极致的空间优化,可以把数组直接转成二进制字节流,再用压缩库处理。这种方式最灵活,但需要自己维护数据的形状、 dtype等元信息,示例:

    import numpy as np
    import zstandard as zstd
    import json
    
    # 保存:先写元信息(形状、dtype),再写压缩后的字节流
    data = np.random.rand(100,224,224,19).astype(np.float32)
    meta = {'shape': data.shape, 'dtype': str(data.dtype)}
    meta_str = json.dumps(meta).encode('utf-8')
    compressor = zstd.ZstdCompressor(level=10)
    compressed_data = compressor.compress(data.tobytes())
    
    with open('data_1.bin.zst', 'wb') as f:
        # 先写元信息长度,再写元信息,再写压缩数据
        f.write(len(meta_str).to_bytes(4, byteorder='big'))
        f.write(meta_str)
        f.write(compressed_data)
    
    # 读取
    with open('data_1.bin.zst', 'rb') as f:
        meta_len = int.from_bytes(f.read(4), byteorder='big')
        meta_str = f.read(meta_len).decode('utf-8')
        meta = json.loads(meta_str)
        compressed_data = f.read()
        decompressor = zstd.ZstdDecompressor()
        decompressed_data = decompressor.decompress(compressed_data)
        data = np.frombuffer(decompressed_data, dtype=meta['dtype']).reshape(meta['shape'])
    

    这种方式的存储开销最小,但需要自己处理元信息的序列化和反序列化,适合对存储有极致要求的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:48:35