HDF5文件学习笔记

HDF5文件学习笔记

1. HDF5简介

1.1 什么是HDF5?

HDF5 (Hierarchical Data Format version 5) 是一种用于存储和组织大量数据的文件格式和库。它特别适合处理大规模科学数据、机器学习模型和数据集。

主要特点:

  • 支持超大文件和超大数据集
  • 层次化组织结构(类似文件系统)
  • 高效的I/O性能
  • 跨平台兼容
  • 支持压缩
  • 广泛应用于深度学习(Keras、PyTorch等)

1.2 基本概念

  • File: HDF5文件本身
  • Group: 类似文件夹,可以包含其他Group或Dataset
  • Dataset: 实际存储数据的多维数组
  • Attribute: 附加到Group或Dataset的元数据

文件结构类似于:

复制代码
my_file.h5
├── group1/
│   ├── dataset1
│   └── dataset2
└── group2/
    └── subgroup/
        └── dataset3

2. 查看HDF5文件结构

2.1 方法一:使用h5py库(推荐)

2.1.1 基本查看
python 复制代码
import h5py
import numpy as np

# 打开文件(只读模式)
with h5py.File('data.h5', 'r') as f:
    # 查看所有顶层keys
    print("顶层keys:", list(f.keys()))
    
    # 递归打印所有结构
    def print_structure(name, obj):
        print(name)
    
    f.visititems(print_structure)
2.1.2 详细查看函数
python 复制代码
def explore_h5_structure(filename):
    """
    详细探索HDF5文件结构
    """
    def print_attrs(name, obj):
        """打印对象的属性"""
        print(f"\n{'='*60}")
        print(f"路径: {name}")
        print(f"类型: {type(obj).__name__}")
        
        # 如果是Dataset,打印详细信息
        if isinstance(obj, h5py.Dataset):
            print(f"形状: {obj.shape}")
            print(f"数据类型: {obj.dtype}")
            print(f"大小: {obj.size} 个元素")
            
        # 打印所有属性
        if len(obj.attrs) > 0:
            print("属性:")
            for key, val in obj.attrs.items():
                print(f"  {key}: {val}")
    
    with h5py.File(filename, 'r') as f:
        print(f"文件: {filename}")
        print(f"顶层组/数据集: {list(f.keys())}")
        f.visititems(print_attrs)

# 使用示例
explore_h5_structure('model.h5')
2.1.3 可视化树状结构
python 复制代码
def print_h5_tree(filename, indent=""):
    """
    以树状结构打印HDF5文件
    """
    def print_tree(name, obj):
        # 计算缩进
        level = name.count('/')
        indent = "│   " * level
        
        if isinstance(obj, h5py.Group):
            print(f"{indent}├── 📁 {name.split('/')[-1]}/")
        elif isinstance(obj, h5py.Dataset):
            shape_str = f"{obj.shape}" if obj.shape else "scalar"
            print(f"{indent}├── 📄 {name.split('/')[-1]} {shape_str} {obj.dtype}")
    
    with h5py.File(filename, 'r') as f:
        print(f"📦 {filename}")
        f.visititems(print_tree)

# 使用示例
print_h5_tree('data.h5')

2.2 方法二:使用HDFView(GUI工具)

HDFView是官方提供的图形化工具,可以可视化浏览HDF5文件。

安装:

bash 复制代码
# 从官网下载
# https://www.hdfgroup.org/downloads/hdfview/

2.3 方法三:使用命令行工具

2.3.1 h5ls命令
bash 复制代码
# 安装HDF5命令行工具
# Ubuntu/Debian:
sudo apt-get install hdf5-tools

# macOS:
brew install hdf5

# 基本使用
h5ls file.h5                    # 列出顶层内容
h5ls -r file.h5                 # 递归列出所有内容
h5ls -d file.h5/dataset_name    # 查看数据集详细信息
h5ls -v file.h5                 # 详细模式
2.3.2 h5dump命令
bash 复制代码
h5dump file.h5                  # 导出完整文件内容
h5dump -H file.h5               # 只显示头部信息(不显示数据)
h5dump -d /dataset_name file.h5 # 导出特定数据集

3. HDF5基本操作

3.1 创建HDF5文件

python 复制代码
import h5py
import numpy as np

# 创建新文件
with h5py.File('example.h5', 'w') as f:
    # 创建数据集
    data = np.random.randn(100, 50)
    f.create_dataset('my_dataset', data=data)
    
    # 创建组
    group = f.create_group('my_group')
    group.create_dataset('nested_data', data=np.arange(10))
    
    # 添加属性
    f.attrs['author'] = 'Josh'
    f.attrs['version'] = 1.0
    group.attrs['description'] = 'Example group'

3.2 读取数据

python 复制代码
with h5py.File('example.h5', 'r') as f:
    # 方法1:直接读取整个数据集
    data = f['my_dataset'][:]
    
    # 方法2:切片读取(节省内存)
    subset = f['my_dataset'][0:10, :]
    
    # 方法3:访问嵌套数据
    nested = f['my_group/nested_data'][:]
    
    # 读取属性
    author = f.attrs['author']
    description = f['my_group'].attrs['description']

3.3 修改现有文件

python 复制代码
# 追加模式
with h5py.File('example.h5', 'a') as f:
    # 添加新数据集
    f.create_dataset('new_dataset', data=np.ones((5, 5)))
    
    # 修改属性
    f.attrs['modified'] = True
    
    # 注意:不能直接修改dataset的形状或类型
    # 需要删除后重新创建

3.4 删除数据

python 复制代码
with h5py.File('example.h5', 'a') as f:
    # 删除数据集或组
    del f['my_dataset']
    
    # 删除属性
    del f.attrs['version']

4. 高级用法

4.1 处理大型数据集(分块读写)

python 复制代码
# 创建大型数据集,使用分块存储
with h5py.File('large_data.h5', 'w') as f:
    # chunks参数指定分块大小
    dset = f.create_dataset('large_array', 
                           shape=(10000, 10000), 
                           dtype='float32',
                           chunks=(1000, 1000),
                           compression='gzip')  # 启用压缩
    
    # 分块写入数据
    for i in range(10):
        data_chunk = np.random.randn(1000, 10000).astype('float32')
        dset[i*1000:(i+1)*1000, :] = data_chunk

# 分块读取
with h5py.File('large_data.h5', 'r') as f:
    dset = f['large_array']
    
    # 只读取需要的部分
    chunk = dset[0:100, 0:100]
    
    # 迭代读取
    for i in range(0, dset.shape[0], 1000):
        data_chunk = dset[i:i+1000, :]
        # 处理数据块...

4.2 压缩选项

python 复制代码
with h5py.File('compressed.h5', 'w') as f:
    data = np.random.randn(1000, 1000)
    
    # GZIP压缩(0-9级别)
    f.create_dataset('gzip_data', data=data, compression='gzip', compression_opts=9)
    
    # LZF压缩(速度快)
    f.create_dataset('lzf_data', data=data, compression='lzf')
    
    # 不压缩
    f.create_dataset('raw_data', data=data)

4.3 数据类型和形状调整

python 复制代码
with h5py.File('flexible.h5', 'w') as f:
    # 可扩展数据集
    dset = f.create_dataset('expandable', 
                           shape=(100,), 
                           maxshape=(None,),  # 可无限扩展
                           dtype='float32')
    
    # 扩展数据集
    dset.resize((200,))
    dset[100:200] = np.random.randn(100)
    
    # 复合数据类型
    dt = np.dtype([('name', 'S50'), ('age', 'i4'), ('score', 'f8')])
    dset_struct = f.create_dataset('structured', shape=(10,), dtype=dt)

5. 实用示例

5.1 保存和加载机器学习模型权重

python 复制代码
import h5py
import numpy as np

# 保存模型权重
def save_model_weights(filename, weights_dict):
    """
    保存模型权重字典到HDF5
    weights_dict: {'layer_name': {'weights': array, 'biases': array}}
    """
    with h5py.File(filename, 'w') as f:
        for layer_name, params in weights_dict.items():
            group = f.create_group(layer_name)
            for param_name, param_value in params.items():
                group.create_dataset(param_name, data=param_value)

# 加载模型权重
def load_model_weights(filename):
    """
    从HDF5加载模型权重
    """
    weights_dict = {}
    with h5py.File(filename, 'r') as f:
        for layer_name in f.keys():
            weights_dict[layer_name] = {}
            for param_name in f[layer_name].keys():
                weights_dict[layer_name][param_name] = f[layer_name][param_name][:]
    return weights_dict

# 使用示例
weights = {
    'layer1': {'weights': np.random.randn(784, 128), 'biases': np.zeros(128)},
    'layer2': {'weights': np.random.randn(128, 10), 'biases': np.zeros(10)}
}
save_model_weights('model_weights.h5', weights)
loaded_weights = load_model_weights('model_weights.h5')

5.2 保存训练数据和标签

python 复制代码
def save_training_data(filename, X_train, y_train, X_val, y_val):
    """
    保存训练数据到HDF5
    """
    with h5py.File(filename, 'w') as f:
        # 创建训练集组
        train_group = f.create_group('train')
        train_group.create_dataset('X', data=X_train, compression='gzip')
        train_group.create_dataset('y', data=y_train, compression='gzip')
        
        # 创建验证集组
        val_group = f.create_group('validation')
        val_group.create_dataset('X', data=X_val, compression='gzip')
        val_group.create_dataset('y', data=y_val, compression='gzip')
        
        # 添加元数据
        f.attrs['num_train_samples'] = len(X_train)
        f.attrs['num_val_samples'] = len(X_val)
        f.attrs['input_shape'] = X_train.shape[1:]

def load_training_data(filename):
    """
    加载训练数据
    """
    with h5py.File(filename, 'r') as f:
        X_train = f['train/X'][:]
        y_train = f['train/y'][:]
        X_val = f['validation/X'][:]
        y_val = f['validation/y'][:]
        
        metadata = {
            'num_train': f.attrs['num_train_samples'],
            'num_val': f.attrs['num_val_samples'],
            'input_shape': f.attrs['input_shape']
        }
    
    return X_train, y_train, X_val, y_val, metadata

5.3 查看Keras模型文件

python 复制代码
def inspect_keras_model(model_path):
    """
    检查Keras模型的HDF5文件结构
    """
    with h5py.File(model_path, 'r') as f:
        # Keras模型通常有这些顶层键
        print("顶层键:", list(f.keys()))
        
        # 查看模型配置
        if 'model_config' in f.attrs:
            import json
            config = json.loads(f.attrs['model_config'])
            print("\n模型配置:")
            print(json.dumps(config, indent=2))
        
        # 查看层权重
        if 'model_weights' in f:
            print("\n模型层:")
            for layer_name in f['model_weights'].keys():
                print(f"\n层: {layer_name}")
                layer_group = f['model_weights'][layer_name]
                for weight_name in layer_group.keys():
                    weight = layer_group[weight_name]
                    print(f"  {weight_name}: shape={weight.shape}, dtype={weight.dtype}")

# 使用示例
inspect_keras_model('my_model.h5')

6. 常见问题和技巧

6.1 内存管理

python 复制代码
# ❌ 错误:一次性加载大文件到内存
with h5py.File('large.h5', 'r') as f:
    data = f['big_dataset'][:]  # 可能导致内存溢出

# ✅ 正确:分批处理
with h5py.File('large.h5', 'r') as f:
    dset = f['big_dataset']
    batch_size = 1000
    for i in range(0, len(dset), batch_size):
        batch = dset[i:i+batch_size]
        # 处理batch...

6.2 检查文件是否存在某个键

python 复制代码
with h5py.File('data.h5', 'r') as f:
    if 'my_dataset' in f:
        data = f['my_dataset'][:]
    
    # 检查嵌套路径
    if 'group1/subgroup/dataset' in f:
        data = f['group1/subgroup/dataset'][:]

6.3 复制数据集

python 复制代码
# 从一个文件复制到另一个文件
with h5py.File('source.h5', 'r') as f_src:
    with h5py.File('dest.h5', 'w') as f_dst:
        # 复制整个组
        f_src.copy('group_name', f_dst)
        
        # 复制特定数据集
        f_src.copy('dataset_name', f_dst, name='new_name')

6.4 性能优化

python 复制代码
# 使用合适的chunk大小
# 经验法则:chunk大小应该在10KB-1MB之间
optimal_chunk = (100, 100)  # 根据访问模式调整

dset = f.create_dataset('data', 
                       shape=(10000, 10000),
                       chunks=optimal_chunk,
                       compression='gzip',
                       compression_opts=4,  # 平衡压缩率和速度
                       shuffle=True)  # 提高压缩效果

7. 快速参考

7.1 常用打开模式

模式 说明
'r' 只读(文件必须存在)
'r+' 读写(文件必须存在)
'w' 创建文件,覆盖已存在的文件
'w-' 或 'x' 创建文件,文件存在则失败
'a' 读写,文件不存在则创建

7.2 常用压缩方法

压缩方法 特点 压缩比 速度
'gzip' 标准压缩
'lzf' 快速压缩 中等
None 无压缩 1:1 最快

7.3 有用的属性和方法

python 复制代码
# Dataset属性
dset.shape      # 形状
dset.dtype      # 数据类型
dset.size       # 元素总数
dset.chunks     # 分块大小
dset.compression  # 压缩方法

# File/Group方法
f.keys()        # 列出键
f.values()      # 列出值
f.items()       # 列出键值对
f.visit(func)   # 遍历所有对象
f.visititems(func)  # 遍历所有对象(带名称)

8. 总结

HDF5是处理大规模科学数据和机器学习数据的强大工具。关键要点:

  1. 层次化结构:使用Group组织数据,类似文件系统
  2. 高效I/O:支持分块读写,避免内存溢出
  3. 压缩支持:节省存储空间
  4. 元数据:使用attributes存储描述信息
  5. 跨平台:Python、MATLAB、R等都支持

最佳实践:

  • 使用压缩节省空间
  • 合理设置chunk大小
  • 为大数据集启用分块读写
  • 添加有意义的attributes
  • 使用上下文管理器(with语句)确保文件正确关闭
相关推荐
d111111111d3 小时前
在STM32函数指针是什么,怎么使用还有典型应用场景。
笔记·stm32·单片机·嵌入式硬件·学习·算法
明洞日记3 小时前
【数据结构手册008】STL容器完全参考指南
开发语言·数据结构·c++
静小谢4 小时前
前后台一起部署,vite配置笔记base\build
前端·javascript·笔记
kingmax542120084 小时前
《数据结构C语言:单向链表-链表基本操作(尾插法建表、插入)》15分钟试讲教案【模版】
c语言·数据结构·链表
AI科技星4 小时前
质量定义方程常数k = 4π m_p的来源、推导与意义
服务器·数据结构·人工智能·科技·算法·机器学习·生活
ask_baidu4 小时前
Doris笔记
android·笔记
Fine姐5 小时前
数据结构04——二叉树搜索树BST
数据结构
嗷嗷哦润橘_5 小时前
AI Agent学习:MetaGPT之我的工作
人工智能·学习·flask
仰泳的熊猫5 小时前
1077 Kuchiguse
数据结构·c++·算法·pat考试