趋近智
训练大型语言模型是一个资源消耗大的过程,通常需要在昂贵的硬件集群上运行数周或数月。因此,复现性不仅是一个科学上的理想,更是工程上的必然要求。如果一次训练运行产生了意想不到的结果,或者你需要回顾几个月前某个特定的模型检查点,你必须能够精确重构该次运行所使用的确切数据集状态。仅仅存储数TB的数据是不够的;你需要数据集版本管理的方法。
与Git等系统能很好地处理代码不同,数据集由于其庞大的体积,带来了独有的版本管理难题。在版本控制系统中直接存储多TB数据集的多个完整副本是不切实际且成本过高的。此外,数据集的“版本”不仅仅是原始文件;它包括用于创建最终训练就绪数据的特定预处理代码、筛选参数 (parameter)、分词 (tokenization)设置和抽样策略。
有效的数据集版本管理在LLM开发背景下提供了几项重要益处:
当我们谈论LLM数据集的版本管理时,我们通常需要追踪几个相互关联的组成部分:
考虑到数据集的规模,版本管理通常涉及管理元数据和指针,而不是直接复制数据本身。以下是一些常见策略:
一种基本方法是为目录或存储前缀采用规范的命名约定,其中包含版本标识符、时间戳或相关的配置哈希值。例如,处理后的数据集可能位于s3://my-llm-datasets/processed/v2.1_vocab32k_cc-2023-03/这样的路径中。
作为补充,你可以创建清单文件(例如,JSON或YAML格式),列出属于特定版本的所有数据文件及其校验和与重要元数据。这个清单文件很小,可以与预处理代码一起轻松地使用Git进行追踪。
import hashlib
import json
import os
from glob import glob
def calculate_sha256(filepath):
"""计算文件的SHA256哈希值。"""
sha256_hash = hashlib.sha256()
with open(filepath, "rb") as f:
# 以4K块读取并更新哈希字符串值
for byte_block in iter(lambda: f.read(4096), b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
def create_dataset_manifest(data_dir, manifest_path, version_info):
"""为目录中的文件创建清单文件。"""
manifest = {
"version_info": version_info,
"files": []
}
# 示例:假设数据文件是.arrow格式
data_files = sorted(glob(os.path.join(data_dir, "*.arrow")))
print(f"正在为 {len(data_files)} 个文件在 {data_dir} 中生成清单...")
for filepath in data_files:
filename = os.path.basename(filepath)
checksum = calculate_sha256(filepath)
manifest["files"].append({
"filename": filename,
"sha256": checksum,
"size_bytes": os.path.getsize(filepath)
})
with open(manifest_path, 'w') as f:
json.dump(manifest, f, indent=2)
print(f"清单已保存至 {manifest_path}")
# --- 示例用法 ---
dataset_directory = "/path/to/processed_data/v2.1_vocab32k_cc-2023-03"
output_manifest = "/path/to/repo/dataset_manifests/v2.1.json"
git_commit_hash = "a1b2c3d4e5f6" # 在实际流程中以编程方式获取此值
version_metadata = {
"dataset_version": "2.1",
"preprocessing_code_commit": git_commit_hash,
"source_info": "Common Crawl 2023年3月快照",
"tokenizer_vocab_size": 32000
}
# 确保输出目录存在
os.makedirs(os.path.dirname(output_manifest), exist_ok=True)
# create_dataset_manifest(dataset_directory, output_manifest, version_metadata)
# 注意:取消注释以上行并替换路径以运行;
# 这仅作说明用途,并假定数据文件存在于指定路径。
print("说明性清单生成设置已完成。")
print(f"将处理的文件位于: {dataset_directory}")
print(f"将清单保存至: {output_manifest}")
print(f"相关元数据: {version_metadata}")
这个清单(v2.1.json)随后可以提交到Git。要使用这个数据集版本,你的训练流程会读取清单,(可选地)验证校验和,并从其存储位置加载列出的文件。
DVC(数据版本控制)、Pachyderm和LakeFS等工具是专门设计用于结合Git处理大型数据文件的。它们的操作原理是在Git中存储元数据和指针,而实际数据则存放在外部存储中(如S3、GCS、HDFS,甚至是本地驱动器)。
例如,DVC通过创建小的.dvc元文件来工作,这些文件包含有关实际数据文件的信息,包括它们的哈希值和存储位置。这些元文件会提交到Git。
一个典型的工作流程可能如下所示:
dvc add s3://my-llm-datasets/processed/v2.1_vocab32k_cc-2023-03
.dvc文件(例如,v2.1_vocab32k_cc-2023-03.dvc),如果数据尚未存在,还可能将其上传到已配置的DVC远程存储。git add v2.1_vocab32k_cc-2023-03.dvc .gitignore; git commit -m "Add dataset v2.1"
.dvc文件被添加到Git,将这个特定的数据版本与代码库版本关联起来。dvc pull v2.1_vocab32k_cc-2023-03.dvc(或者直接 dvc pull)
dvc pull会从远程存储下载.dvc文件中列出的相应数据文件。这些工具通常提供超越基本版本管理的功能,例如数据管道和实验追踪集成。
DVC如何将Git追踪与大型文件存储分离的概述。
许多云存储服务(如Amazon S3或Google Cloud Storage)提供内置的对象版本管理功能。启用此功能后,当对象被覆盖或删除时,会自动保留其先前版本。尽管启用简单,但这种方法通常缺少清单文件或DVC等专用工具所提供的与代码版本和预处理步骤的明确关联。它主要作为备份和恢复机制,而非用于复杂机器学习 (machine learning)流程的完整成熟数据集版本管理系统。在没有额外追踪机制的情况下,更难识别究竟哪一组对象版本对应于特定的训练运行。
真正的复现性需要将版本化数据集与用于训练的特定代码提交以及生成的模型产物和指标关联起来。MLflow、Weights & Biases、Comet ML等实验追踪平台在此处非常有价值。在记录实验时,你应该包含:
这创建了一个完整的、可审计的记录,将输入(代码、数据、配置)与输出(模型、指标)连接起来。
总而言之,管理用于LLM训练的庞大数据集不仅仅是存储问题。实施清晰的数据集版本管理方法,无论是通过规范命名和清单还是通过专用工具,对于复现性、调试、协作以及构建可靠的大型语言模型都十分根本。它确保你对数据准备和训练计算的大量投入能够带来可理解和可重复的结果。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•