
MMPT 数据集构建实战基于 S3D 特征提取与去重预分词的 Howto100M 多模态数据预处理全流程【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilmMMPTMasked Multimodal Pre-training即 Kosmos-2 中基于 fairseq 的多模态预训练框架的DATASET.md专门面向“视频-文本”数据这一最棘手环节给出了从原始视频下载到可直接喂入训练器的 S3D 特征与 BERT token 分片ShardedTensor的完整工程化方案。本文以该文档为骨架结合仓库内scripts/video_feature_extractor、scripts/text_token_extractor与mmpt/processors、mmpt/utils等源码逐层拆解 Howto100M 的预处理管线并说明 Youcook、MSRVTT 等下游数据集的接入方式帮助读者理解并复现 MMPT 的数据准备全流程。一、数据预处理的整体布局视频与文本两条管线MMPT 承认“视频数据的下载与处理是最具挑战性的环节”因此将预处理工作拆成两个独立脚本目录视频特征提取scripts/video_feature_extractor深度改编自 antoine77340 的 video_feature_extractor 项目文本预分词scripts/text_token_extractor。两条管线最终汇聚到统一的ShardedTensor存储格式训练阶段由 mmpt/datasets/mmdataset.py 与 mmpt/datasets/fairseqmmdataset.py 消费。整个数据流的完整装配关系meta 处理器、视频处理器、文本处理器、aligner 如何组合可以在 projects/task/how2.yaml 中看到dataset: meta_processor: ShardedHow2MetaProcessor train_path: data/how2/how2_s3d_train.lst val_path: data/how2/how2_s3d_val.lst video_processor: ShardedVideoProcessor vfeat_dir: data/feat/feat_how2_s3d_shard_small text_processor: ShardedTextProcessor tfeat_dir: data/feat/feat_how2_s3d_shard_small/raw_caption_dedup.bert-base-uncased. aligner: FixedLenAligner可见离线预处理的目标就是把“原始视频文件 原始字幕”转换成vfeat_dir视频特征分片与tfeat_dir文本 token 分片两组可直接随机访问的 numpy 分片文件。二、S3D 视频特征提取模型准备与 PathBuilder 路径跟踪2.1 预训练模型放置视频特征提取使用预训练 S3D 模型HowTo100M 上的 S3D 预训练权重需要把两个文件放到指定位置pretrained_models/s3d_dict.npypretrained_models/s3d_howto100m.pth2.2 PathBuilder视频 id 到特征路径的自动映射文档强调实现了一个PathBuilder来自动维护“视频 id → 源视频路径 → 特征输出路径”的映射依赖conda install -c anaconda pandas视频解码则需要pip install ffmpeg-python。查看 scripts/video_feature_extractor/pathbuilder.py 可以看到其核心逻辑若feature_dir/meta_plan.json已存在则直接加载该 JSON 作为计划支持断点续跑否则遍历video_dirs以逗号分隔的目录列表把每个视频文件或子目录分片中的文件的文件名去扩展名作为video_id建立video_id → 视频路径字典为每个视频 id 生成feature_dir/{video_id}.npy若启用shards参数则按idx % shards分发到子目录将{video_path: [...], feature_path: [...]}写入meta_plan.json之后训练/提取脚本直接复用该计划。PathBuilder还支持split参数如0/10把全部视频按 chunk 切分到不同机器配合文档“建议在多台机器上并行提取”的做法实现水平扩展。2.3 extract.py特征提取器与解码配置scripts/video_feature_extractor/extract.py 内置了多种 CNN 类型的解码配置typefpssizecentercrop输出特征维度2d1224否20483d24112是2048s3d30224是512vmz24112是512vae2256是1024LongTensor其中s3d对应 fps30、224×224、中心裁剪、输出 512 维video_embedding见extract.py中对batch_features[video_embedding]的取用。其他可调参数还包括--batch_size默认 64特征前向的批大小--half_precision默认 0置 1 时将特征保存为float16显著节省磁盘并加速训练文档推荐默认开启--l2_normalize默认 1特征做 L2 归一化--num_decoding_thread默认 4视频解码的并行线程数--hflip默认 0是否随机水平翻转增强。2.4 一键脚本 s3d.shHowto100M 的完整提取命令封装在 scripts/video_feature_extractor/how2/s3d.shpython scripts/video_feature_extractor/extract.py \ --vdir path_to_video_folder \ --fdir data/feat/feat_how2_s3d \ --types3d --num_decoding_thread4 \ --batch_size 32 --half_precision 1运行前替换path_to_video_folder为已下载的 Howto100M 视频目录输出特征将写入data/feat/feat_how2_s3d/每个视频一个.npy文件。解码侧由 videoreader.py 配合RandomSequenceSampler完成采样预处理resize、crop由 preprocessing.py 负责。三、Howto100M 预处理的三处关键差异文档明确指出MMPT 的预处理与既有论文相比有三处不同这三点直接影响自监督信号的质量3.1 使用 raw_caption.json 而非 caption.jsonHowto100M 官方发布了两份字幕caption.json已人工去除停用词raw_caption.json是原始字幕。MMPT 选用raw_caption.json目的是让文本侧保持“纯自监督”状态——不做人工清洗让模型自己学习停用词等语言结构避免监督信号被人工干预污染。3.2 去除为实时可读性设计的部分重复文本Howto100M 的字幕片段存在大量因“实时滚动字幕可读性”而引入的部分重复相邻片段文字互相包含/重叠。这些重复会破坏文本与视频片段的对齐监督因此需要专门的去重处理器。实现位于 mmpt/processors/dedupprocessor.py 的CaptionDedupProcessor其_dedup逻辑见 dedupprocessor.py#L119-L207逐条扫描相邻片段并分情况处理当前文本是上一片段的子集texts[-1].endswith(text)→ 并入上一片段只扩展结束时间当前文本是上一片段的超集text.startswith(texts[-1])→ 用当前文本替换并合并时间区间部分重叠 → 以 0.5 概率随机选择“重叠部分并入前一片段尾部”或“前一片段尾部并入当前片段开头”并调用random_merge保持start/end/text三元组的一致性。去重后每个片段仍满足end start且文本非空代码中有断言校验。该处理器还内置了统计能力save_stat/print_stat对前 4096 个视频统计t_clip_len、clip_tps、video_tps等指标用于评估去重效果注释中的示例统计显示去重后clip_tps从约 2.49 下降到约 0.88字幕冗余度显著降低。3.3 用 ShardedTensor 分片替代 h5py训练时需要按 video_id 随机访问特征MMPT 没有采用常用的 h5py而是自研了 mmpt/utils/shardedtensor.py 中的ShardedTensorfrom_list(xs)把多个变长数组如不同长度的视频特征序列沿 axis0 拼接成单一data数组并用starts记录每个样本的起止偏移__getitem__(i)通过data[starts[i]:starts[i1]]以 O(1) 完成随机访问save将_starts.npy与_data.npy两个 numpy 文件落盘load支持mmap_mode可内存映射按需加载。相比 h5py这种“连续内存 偏移表”的格式加载更快内存连续、无文件句柄开销文档中的评价是“比 h5py 更快”。四、视频侧三步走提取 → 划分 → 分片4.1 提取视频特征编辑并运行s3d.sh见上文默认以 fp16 存储特征以节省空间并加速训练。文档建议在多台机器上并行执行配合PathBuilder的split参数切分视频列表。4.2 划分 train/val 视频 id 列表将可用的视频 id 拆分为两个清单文件data/how2/how2_s3d_train.lstdata/how2/how2_s3d_val.lst每行一个视频 id不带扩展名这两个文件在训练配置 projects/task/how2.yaml 中对应train_path与val_path。4.3 打包为 ShardedTensor运行 scripts/video_feature_extractor/shard_feature.py其Shard类按 train/val 两个列表读取 video_id以shard_size4096为步长把每个 split 切成若干 shardtrain_0, train_1, ...对每个 shard逐个np.load对应vfeat_dir/{video_id}.npy再ShardedTensor.from_list拼接并save到target_dir/{split}_{shard_idx}同时把每个 shard 内的 video_id 清单 pickle 成{split}_meta.pkl供训练时按 meta 索引加载。默认输出目录为data/feat/feat_how2_s3d_shard_small与 projects/task/how2.yaml 中vfeat_dir完全对应。注意Shard.__call__中tfeat_dir参数当前仅用于展示文本分片由下一节的 pretokenization 脚本负责生成。五、文本侧去重 → BERT 预分词 → 分片5.1 清洗与去重执行命令python -m mmpt.processors.dedupprocessor该模块的__main__见 dedupprocessor.py#L210-L236完成三步若data/how2/raw_caption.pkl不存在先把data/how2/raw_caption.json中的每条字幕json.dumps后序列化为 pickle构造CaptionDedupProcessor并对全部视频执行去重内部用 tqdm 显示进度finalize输出data/how2/raw_caption_dedup.pkl——这正是后续预分词脚本的输入。如需单条视频调试可在__main__注释的 demo 中调用deduper.single(HfIeQ9pzL5U)对比去重前后的片段列表。5.2 预分词并分片把去重后的data/how2/raw_caption_dedup.pkl分词成 sharded numpy 数组python scripts/text_token_extractor/pretokenization.py scripts/text_token_extractor/configs/bert-base-uncased.yaml配置 scripts/text_token_extractor/configs/bert-base-uncased.yaml 只有四个字段dataset: bert_name: bert-base-uncased caption_pkl_path: data/how2/raw_caption_dedup.pkl use_fast: true target_dir: data/feat/feat_how2_s3d_shard_smallpretokenization.py 的处理流程分两阶段tokenize 阶段用PKLJSONStrTextProcessor读取 pkl 中的字幕DataLoader(num_workers16)并行调用 HuggingFaceAutoTokenizerbert-base-uncased、use_fastTrue即 Rust 加速分词器逐条转成input_ids输出data/how2/raw_caption_dedup.bert-base-uncased.pkl若已存在则跳过sharding 阶段先读取{split}_meta.pkl拿到视频 id 到 shard 的映射再按 shard 调用numpify——为每个片段生成[start, end]时间戳数组float32和长度max_cap_len32的定长 token 数组int32不足补 -1分别以ShardedTensor保存为.startends与.caps_ids后缀文件。文件名前缀由raw_caption_dedup.bert-base-uncased.拼接而成正好匹配 projects/task/how2.yaml 中的tfeat_dir: data/feat/feat_how2_s3d_shard_small/raw_caption_dedup.bert-base-uncased.。此后训练时文本处理器通过ShardedTensor.load(mmap_mode)按需读取而不再逐条分词。六、Youcook、MSRVTT 等下游数据集即时分词的轻量方案对于端到端任务如视频-文本检索、视频问答MMPT 使用与 Howto100M 同源的 Youcook2 与 MSRVTT 版本源自 Howto100M 与 MILNCE 项目配套发布的数据。接入方式与 Howto100M 的第一阶段类似——同样走 S3D 特征提取——但文本不再离线预分词而是直接从 meta 数据读取文本、训练时即时分词on-the-fly tokenization。这一点在 mmpt/processors/processor.py 的TextProcessor中体现得很清楚它持有AutoTokenizer在__call__中实时把文本字符串转成input_ids类注释明确警告“on-the-fly tokenization 对 how2 这种超大数据集太慢因此主要用于端任务”。下游数据集的完整配置可直接查看 projects/task/youcook.yaml、projects/task/vtt.yaml以及对应的检索版youcook_videoclip.yaml、vtt_videoclip.yaml、零样本测试版test_youcook_zs.yaml等。数据按约定下载到data/youcook、data/msrvtt目录训练/验证时由各个MetaProcessor读取。七、小结一份可直接照搬的预处理路线图MMPT 的数据准备思路可以浓缩为以下路线图适用于任何“大规模视频-文本”预训练数据的接入视频下载原始视频 → 放置 S3D 预训练权重pretrained_models/s3d_dict.npy、s3d_howto100m.pth→ 按需修改并运行s3d.sh提取 512 维 fp16 特征 → 生成{split}_train/val.lst→ 运行shard_feature.py打成ShardedTensor分片文本以raw_caption.json为原始输入 →python -m mmpt.processors.dedupprocessor去除片段重复 → 配置bert-base-uncased.yaml后运行pretokenization.py完成 BERT 预分词与.startends/.caps_ids分片下游任务复用同一套视频特征文本走TextProcessor即时分词用 projects/task 下的 yaml 配置即可衔接训练。通过“离线预分词 ShardedTensor 分片”组合Howto100M 这种百万级规模数据集在训练期可以做到接近零解码开销的随机访问而去重与raw_caption的选择则为视频-文本对齐提供了更纯净的自监督信号。这套管线同样构成了 Kosmos-2 中 MMPT 框架的数据底座理解了它也就掌握了复用该框架接入任意视频数据集的关键。【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考