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

如何加载gzip压缩的二进制文件及处理tar.gz机器学习数据集

基础概念解答(面向零基础)

1. 什么是.tar文件,为什么数据集都爱用这个格式

你可以把.tar理解成一个未压缩的文件打包盒:它的作用不是压缩缩小体积,而是把成千上万个零散的文件(比如数据集里几万张图片、对应的标签文本、说明文档)整合成单个文件,方便传输、校验完整性,不会出现传一半丢几个小文件的情况。
而.tar.gz就是先把所有零散文件打包成一个.tar的整包,再用gzip算法给这个整包做压缩缩小体积,相当于“先把所有文件装进纸箱封好,再用真空压缩袋抽走空气缩小体积”。

绝大多数公开数据集用这个格式的原因很简单:

  • 跨平台通用:Windows、macOS、Linux所有系统都原生支持解压,不存在专属格式打不开的问题
  • 保留文件结构:解压后会自动还原原来的文件夹层级(比如图片在images文件夹、标签在labels文件夹),不会搞混文件对应关系
  • 压缩效率合适:gzip对文本、图像这类数据集常见文件的压缩率不错,压缩解压速度也快,不会让你等几个小时解压

2. 用代码解压.tar.gz文件的逐行解释

Python环境下不用额外装复杂工具,用标准库就能完成解压,以下是最通用的实现版本,逐行说明作用:
首先导入需要的内置模块,不需要额外pip安装:

import tarfile
import os
  • tarfile是Python自带的专门处理tar格式包的库
  • os是Python自带的处理文件路径、文件夹操作的库

接下来写解压逻辑,替换路径即可直接使用:

# 定义你下载好的.tar.gz文件的本地存储路径
compressed_file_path = "./SUN_attribute.tar.gz"
# 定义解压后文件要存放的目标文件夹路径,不存在则自动创建
extract_target_path = "./datasets/SUN"

# 校验目标文件夹是否存在,不存在则递归新建
if not os.path.exists(extract_target_path):
    os.makedirs(extract_target_path)

# 打开压缩包,"r:gz"模式代表以读取方式打开、支持gzip压缩的tar包
with tarfile.open(compressed_file_path, "r:gz") as tar:
    # 将压缩包内所有内容按原有目录结构,解压到指定目标路径
    tar.extractall(path=extract_target_path)

逐行逻辑说明:

  • 前两行路径定义:明确告诉代码待解压文件位置、解压后存储位置,替换为自己的本地路径即可
  • os.path.exists判断逻辑:避免目标文件夹已存在时报错,无需手动提前新建文件夹
  • tarfile.open部分:相当于用解压软件双击打开压缩包,with语法会在解压完成后自动关闭文件,不会出现文件占用问题
  • tar.extractall:执行实际解压操作,保留压缩包内原有的文件夹层级

如果是单独的.gz文件(不是.tar.gz,比如MNIST的单文件压缩包),用gzip库即可,逻辑类似:

import gzip
import shutil

with gzip.open("./train-images-idx3-ubyte.gz", "rb") as f_in:
    with open("./train-images-idx3-ubyte", "wb") as f_out:
        shutil.copyfileobj(f_in, f_out)

这段代码的作用是读取gz压缩的单文件二进制内容,写入到同目录下的无压缩文件中,完成单文件解压。


3. 解压后的二进制文件是什么,怎么转成模型能用的数组

首先要建立一个基础认知:所有计算机里的文件本质上全是二进制文件,就是一堆0和1的组合。你平时看到的.txt、.jpg、.csv只是行业通用约定了不同的01排列规则(也就是文件格式规范),对应软件按照规则读取,就能显示成你能看懂的文字、图片。
你解压MNIST得到的“二进制文件”不是什么特殊格式,就是MNIST官方按照自定义的排列规则,把所有图片像素、标签值直接存储的连续01序列,没有加jpg、png这类图片格式的额外头信息,所以直接用图片查看器打不开,看起来就是“无法识别的二进制文件”。

要把它转成PyTorch能用的数组,只需要按照官方给出的排列规则,把这些01序列读出来转成张量即可。以MNIST图片文件为例,官方公开的格式规则是:

  • 最开始4个字节:魔术码,用来标记这是图片文件还是标签文件,实际使用时可以忽略
  • 接下来4个字节:存储总图片数量,比如训练集对应值为60000
  • 接下来4个字节:存储单张图片高度,MNIST固定为28
  • 接下来4个字节:存储单张图片宽度,MNIST固定为28
  • 后续所有字节:按顺序存储每个像素的灰度值,每个像素占1个字节,值范围为0-255

对应的读取代码逐行解释:

import numpy as np
import torch

# 以二进制只读模式打开解压好的MNIST图片文件
with open("./train-images-idx3-ubyte", "rb") as f:
    # 读取前4个字节,按照32位大端整数格式解析为魔术码
    magic_num = np.frombuffer(f.read(4), dtype=np.dtype(">i4"))[0]
    # 读取接下来4个字节,解析为总图片数量
    img_count = np.frombuffer(f.read(4), dtype=np.dtype(">i4"))[0]
    # 读取接下来4个字节,解析为单张图片高度
    img_height = np.frombuffer(f.read(4), dtype=np.dtype(">i4"))[0]
    # 读取接下来4个字节,解析为单张图片宽度
    img_width = np.frombuffer(f.read(4), dtype=np.dtype(">i4"))[0]
    # 读取剩余所有字节,按0-255无符号整数解析,重构为[图片数, 高度, 宽度]维度的数组
    images = np.frombuffer(f.read(), dtype=np.uint8).reshape(img_count, img_height, img_width)
    # 把numpy数组转为PyTorch张量,同时将像素值归一化到0-1区间,可直接送入DataLoader使用
    images_tensor = torch.from_numpy(images).float() / 255.0

核心逻辑非常简单:不管是什么格式的二进制数据集,只要找到官方给出的格式说明(即多少字节对应什么内容、数值是什么存储类型),按顺序读取对应长度的字节,按指定类型解析,再重构为需要的维度即可,本质和按说明书拼乐高没有区别。

小提示:使用SUN、ImageNet这类普通图片数据集时,不需要手动读取二进制转数组,解压完成后直接用PyTorch的ImageFolder类就能自动按文件夹结构读取图片、匹配标签,比MNIST这种存为二进制序列的格式操作更简单。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:54:24