HumanML3D 完整数据集下载这件事,说难不难,说简单也绝对不简单。我在第一次接触它的时候,以为跟平时下 MNIST、COCO 那种一键打包的数据集一样,找到官网点个按钮就行,结果折腾了整整一个周末才把目录结构理顺。原因很直接:HumanML3D 本身不提供"原始数据"的下载,它是一套建立在 AMASS 和 HumanAct12 之上的派生数据集,真正的动捕原始文件(几十 GB)需要单独去源站点申请许可,而 HumanML3D 官方仓库里放的是一堆预处理脚本,负责把那些原始动捕文件加工成统一的 263 维动作向量。换句话说,你要下载的不是"一个数据集",而是一条完整的加工流水线。
这篇内容写给三类人:正在做文本驱动人体动作生成、想复现 Text2Motion 那一系工作的研究者;需要一份清洁动作数据去训练下游模型(比如动作识别、动作预测、虚拟人驱动)的工程同学;以及单纯想找一份带英文描述的动作数据集做多模态实验的人。我会把目录怎么摆、脚本怎么跑、下完之后怎么确认没下错、以及我在预处理阶段踩过的那几个坑,一条条摊开讲清楚。全程以我实际复现时用的路径为准,你的版本如果略有差异,以仓库当次提交的 README 为准。
1. HumanML3D 的定位:它其实是一条数据加工流水线
1.1 AMASS、HumanAct12 与 HumanML3D 的三角关系
先把这三者的关系捋顺,不然后面下载清单根本列不出来。AMASS 是一个"动捕数据集合集",它把 CMU、KIT、BioMotionLab、Eyes Japan 等一大批来源各异的动捕数据,统一转换成 SMPL 人体参数的形式保存,每个序列一个.npz文件,里面存的是姿态参数、全局位移、体型参数、性别标签和原始帧率。它的体量非常大,覆盖了几百个受试者、几十小时的动作,但它是"无标注"的——只有动作,没有一句话告诉你这段动作在干什么。
HumanAct12 则是另一条线,动作类别明确(走、跳、挥手这类共 12 类),规模小得多,约一千多条序列,但它自带类别标签,适合做分类类任务。HumanML3D 做的事情是把这两者合并:从 AMASS 中筛出具有明确动作语义、且质量过关的序列,把 HumanAct12 也纳进来,统一降采样到 20 FPS,统一到同一套 22 关节骨架,修掉脚底打滑,然后雇人给每一段动作写三条英文描述。
最终产物就是那个耳熟能详的数字组合:约 14,616 段动作序列、44,970 条文本描述。所以你在下载清单里看到的不是"HumanML3D 数据包"这一个东西,而是 AMASS(原始素材)+ 仓库脚本(加工机器)+ 少量额外资源(词向量、SMPL 模型文件)这三块。
1.2 加工完成后,目录里到底躺着什么
我第一次跑完预处理,看到HumanML3D/下面冒出来四五个文件夹,当时是有点懵的。这几个目录各管一件事,理解清楚了后面用起来会非常顺手:
| 目录/文件 | 内容 | 用途 |
|---|---|---|
new_joints/ | 每条动作一个.npy,形状约(帧数, 22, 3) | 关节三维位置,可视化、算物理指标时用 |
new_joint_vecs/ | 每条动作一个.npy,形状(帧数, 263) | 训练主用的统一动作表示 |
texts/ | 每条动作一个.txt,内含多条英文描述 | 文本侧监督信号 |
Mean.npy/Std.npy | 263 维的均值与标准差 | 训练前归一化,必须和向量配套 |
train.txt/val.txt/test.txt/all.txt | 划分索引列表 | 控制数据划分,不要自己另起炉灶 |
这里有个细节很多人会忽略:new_joints和new_joint_vecs是同一批动作的两种表达,文件名一一对应。如果你只保留了new_joint_vecs而删掉了new_joints,大部分训练代码能跑,但一旦你想做可视化或者计算脚部接触相关的物理指标,就得重新跑一遍预处理。我现在的习惯是两份都留着,反正加起来也不大。
另外Mean.npy和Std.npy是跟着你这次预处理结果一起生成的,不是固定常量。如果你换了数据子集重新生成,归一化参数也会变,用旧的去归一化新数据,训练出来的损失曲线会非常诡异。
1.3 263 维不是"原始数据",而是一种精心设计的紧凑表示
标题里写"完整数据集下载",但我必须提醒一句:你拿到手的 HumanML3D 向量已经是高度加工过的表示,不是原始动捕的关节欧拉角。所以讨论"下没下完整"的时候,标准不是"文件有没有缺失",而是"这些向量能不能被官方评估器正确还原"。
263 这个数字不是随便凑的,它由五段拼成,我按顺序给你拆开:
- 第 0 到 3 维(共 4 维):根节点的旋转速度(用 yaw 角的正余弦表示,避免角度跳变)加上根节点在水平面内的线速度(x、z 两个方向)。
- 第 4 维(共 1 维):根节点的高度。因为动作的绝对高度对语义有影响,比如蹲和跳。
- 第 5 到 130 维(21 个非根关节 × 6 维):每个关节的局部旋转,用 6D 连续旋转表示,也就是把旋转矩阵的前两列拉平。之所以不用四元数或欧拉角,是因为网络训练时 6D 表示连续且没有奇异性。
- 第 131 到 196 维(22 个关节 × 3 维):关节相对于根节点的局部位置。
- 第 197 到 262 维(22 个关节 × 3 维):关节的线速度。
理解了这套切片,你才知道为什么很多论文里说"直接操作 263 维向量做编辑或者插值",因为它们本质上是速度加位置加旋转的混合编码,物理意义清楚但耦合度不低。
2. 动手之前:许可申请、磁盘账和环境的真实门槛
2.1 两个必须单独申请的许可,别指望能找到"现成链接"
这是整个流程里最容易劝退人的一步。AMASS 的原始数据受学术许可保护,你需要到它的官方站点注册账号、填写研究用途说明、同意使用协议,通过之后才会拿到下载入口。SMPL 的人体模型文件同理,需要去另一套站点单独申请,两个账号体系不通用——我见过不少人拿着 AMASS 的账号去登 SMPL 的站点,然后卡在那里怀疑人生。
几个实际操作上的经验:
- 申请时用的邮箱尽量用机构邮箱,个人免费邮箱有时候收不到确认信,或者被投进垃圾箱。我第一次用个人邮箱,等了半天没动静,翻垃圾箱才找到,隔了太久链接已经过期,只能重新申请。
- 研究用途描述写具体一点,比如"用于文本驱动人体动作生成方法的训练与评测",比"学术研究"这种四个字回复得快。
- 审核不是秒批,快的话几小时,慢的话一两天。这段时间别干等,可以先把仓库克隆下来、把 conda 环境配好、把 SMPL 那边的申请也一并提交。
- 下载时不要写脚本并发几十个连接去拉,被风控拦了之后重新走流程更麻烦。我一般是用浏览器或单线程命令行工具,分几天慢慢下。
2.2 磁盘、内存和时间,这三个数字要先算清楚
我在自己的机器上做过一次统计,给个参考区间:AMASS 的压缩包加起来在几十 GB 量级,解压之后会明显膨胀,各子数据集的文件数量非常可观。如果你还要保留解压前的压缩包做备份,磁盘占用会再翻一层。
我的建议是:预留 100 GB 以上的可用空间再开工。空间紧张的话,可以只解压你真正需要的那几个子集,但要注意——筛选子集这件事本身就意味着你得到的 HumanML3D 规模会和官方论文里的数字对不上,做对比实验时容易被人质疑,所以我个人还是倾向全下。
内存方面,预处理过程需要把参数字列加载进内存做姿态解算,单进程峰值占几个 GB 很正常。16 GB 内存的机器能跑通,但会比较吃力;32 GB 会舒服很多。时间上,从原始 AMASS 到最终向量,几个小时是常态,取决于你机器的单核性能和磁盘 IO。我第一次用的是机械硬盘,光读文件就花掉了大半时间,后来换到固态盘,整体耗时肉眼可见地缩短。
2.3 环境依赖:版本选对了,能省掉一半的报错
预处理脚本对环境的敏感度不算高,但有几个坑是高频复现的。我的做法是老老实实建一个独立 conda 环境,不要和现有的训练环境混用。
Python 版本建议落在 3.7 到 3.9 这个区间,太新的版本有些老依赖会装不上或者行为不一致。核心依赖大概是这几类:
- 数值计算:
numpy、scipy、pandas - 进度与可视化:
tqdm、matplotlib - 自然语言处理:
spacy(分词用,需要额外下载对应语言的模型)和gensim(读词向量) - 深度学习框架:预处理阶段其实用不着 GPU,CPU 版即可,主要是后面跑评估模型时才需要
- 人体模型解析:仓库会用到 SMPL 参数解析相关的库,具体装哪个看 README 里列的文件名
另外记得装ffmpeg并确保在 PATH 里,否则可视化脚本导出视频那一步会直接失败,而失败信息往往只有一行"找不到可执行文件",容易让人以为是脚本逻辑有问题。
3. 预处理管线:从原始动捕到统一向量的每一步
3.1 amass_data 的目录层级必须和脚本预期严格对齐
这一步是整个流程里最"机械"但也最容易出错的地方。脚本扫描数据靠的是目录结构,不是文件内容,所以层级错了它不会报错,只会静默地一条都不处理。
标准的结构大致是这样:顶层目录下按原始子数据集名分文件夹,再往下是受试者编号文件夹,再下面是形如xxx_poses.npz的序列文件。很多人踩的坑是解压时多套了一层目录——比如解压出来是amass_data/CMU/CMU/...或者amass_data/amass_extracted/CMU/...,脚本自然扫不到。我现在的做法是解压完先跑一条 find 命令,随手看几个路径长什么样,确认没有多余的中间层,再去跑预处理。
还有个细节:不同来源的压缩包解压后命名风格不完全一致,有的带后缀有的不带。如果你从多个渠道拼凑数据,最好先统一检查一遍文件名是否都是_poses.npz结尾,混进去几个_stageii.npz之类的文件,脚本可能直接崩在解析环节。
3.2 骨架对齐与 20 FPS 重采样背后的取舍
AMASS 里的数据来源五花八门,原始帧率高高低低,有 60 FPS 的也有 120 FPS 的,全局朝向和坐标系也各有各的习惯。HumanML3D 把它们统一到 20 FPS,这个选择是有取舍的。
选 20 FPS 的原因是:文本描述标注的动作本身是粗粒度的语义("一个人向前走然后转身"),不需要保留高帧率下的细微抖动;帧率降低直接带来数据量和计算量下降,训练时的序列长度也更容易塞进显存。代价是快速动作(比如跳跃落地那几帧)会有一定程度的细节丢失。我做过对比,把一个快速旋转动作从 20 FPS 恢复到更高帧率插值,确实能看到明显的运动模糊感,但对于文本到动作这个任务来说,影响可以接受。
骨架方面,HumanML3D 只保留 22 个关节,把手指关节去掉了。这个决策也很务实:AMASS 里很多序列的手部姿态本身就不可靠,有的甚至没捕捉到手指,保留下来只会给模型引入噪声。同时,22 关节的表示和 SMPL 的主体骨架完全一致,后面想还原成 mesh 渲染也不会缺关节。
3.3 脚底打滑修复:一个不起眼但决定质量的关键步骤
如果让我挑一个"最容易被忽略、但影响最大"的处理环节,就是这一步。原始动捕数据经过重定向和拟合之后,经常出现脚明明踩在地上却在滑动的现象,也就是常说的脚滑。肉眼看视频的时候可能只是一点点不自然,但换算成 263 维向量里的关节速度分量,就变成了持续的、本不该存在的速度信号。模型学下去,生成的动作会出现"原地漂移"这种非常典型的失败模式。
HumanML3D 的处理思路是用启发式方法检测脚部接触:根据脚部关节相对地面的高度设定阈值,判断哪些帧属于接触帧;对接触帧施加约束,让脚的位置保持稳定,再反向修正相关联的上游关节。这个方法不复杂,但非常有效。我自己在小数据集上做过消融,不做这步的模型在 FID 上明显更差,生成视频里脚滑的帧数肉眼可见地变多。
所以我在下载和预处理时,从不跳过这一步。有些人为了省时间,直接拿预处理的中间产物去训练,结果调了两周模型效果上不去,最后发现问题出在数据质量上。
3.4 文本标注与词向量的准备
动作向量准备好之后,文本侧还得配齐。texts/目录下每条动作对应一个文本文件,里面是若干条用分隔符隔开的英文描述,同一段动作的不同描述之间用分隔符切分。读取的时候注意分隔符的处理,末尾可能带一个空字段,直接按分隔符 split 会多出一个空字符串,写数据加载器时记得过滤掉,否则你的 token 序列里会混进一堆空样本,损失函数看着正常但收敛会很怪。
词向量方面,官方方案用的是 GloVe 系列的大词表文件,需要单独下载。这个文件不小,下载完之后按仓库要求放到指定路径。我建议下完立刻算一遍文件的 MD5 或者至少确认文件大小对得上,因为大文件断点续传失败是常有的事,一个被截断的文件加载时不报错,但查表会缺一大批词,最后表现为"模型好像学了但效果就是差一截"。
4. 怎么确认自己真的下完整了:四层校验法
4.1 数量核对:先看文件数,再看总数
预处理跑完之后,第一件事是数文件。new_joint_vecs和new_joints两个目录下的文件数量必须完全一致,如果有差异,说明某个环节中途失败或者保存时出错,这种不一致在训练时通常会表现为随机报"找不到对应文件"。
接着核对总数。官方规模是约 14,616 段动作,如果你的数量差得比较远,比如只有几千,那大概率是 AMASS 只解压了一部分子集。差个几十条属于正常波动,因为筛选规则在不同版本间可能有微调。
然后是划分文件的行数。官方划分大致是 11,320 训练、1,178 验证、2,118 测试。把这三个数字加起来,应该等于你all.txt的行数。我在一次复现中发现测试集行数对但训练集少了十几行,追查下来是某条序列因为帧数太短被过滤掉了,而划分文件是仓库里预先固定的,这种不一致会导致训练时数据加载器在某个 epoch 突然报错。
4.2 用官方评估器做一次端到端自检
光数文件只能证明"数据在",证明不了"数据对"。最靠谱的自检方式是直接跑一次官方评估流程:加载官方提供的评估模型检查点,在你的数据上算一遍指标。
这一步的意义在于,它会把动作向量反解成正向运动学结果,再和文本编码器的输出对齐。如果数据格式、归一化参数、文本文件有任何一个环节错位,算出来的指标会明显偏离论文报告值。我一般会记下这次自检的数值作为基线,以后每次改动数据管线,都拿同一套流程跑一遍,数值漂了就说明改坏了。
4.3 可视化:用眼睛做最后一道防线
数字和指标都正常,仍然有可能出问题,比如左右手搞反、整体朝向翻转、动作被裁掉一截。这些问题在指标上不一定明显,但一眼就能看出来。
我的习惯是随机抽五到十条动作,分别来自 AMASS 源和 HumanAct12 源,渲染成骨骼动画看一遍。重点看三件事:动作是否完整(有没有突然断掉)、脚是否踩地(有没有明显滑行)、朝向是否合理(有没有面朝地或者倒立)。这一步花不了十分钟,但能提前发现很多后期要花几天才能定位的诡异问题。
4.4 检查 Mean 和 Std 是否被正确加载
这个坑很隐蔽。Mean.npy和Std.npy是训练时归一化用的,很多开源代码在加载时会做一个维度校验,维度不匹配才报错;如果维度恰好匹配但内容来自另一次预处理,就不会报错。我曾经因为换了数据子集却没换这两个文件,训练损失前几个 epoch 看着正常,之后突然发散,排查了两天才找到原因。
现在我的做法是:预处理完成后,把这两个文件和数据目录一起打包存档,并在文件名里标注生成日期。训练时不从别的项目里复制这两个文件,一律用同一批次的。
5. 预处理阶段那些真实发生过的报错
5.1 SMPL 模型文件找不到:报错信息往往指向错误的方向
最常见的报错是某个.pkl模型文件找不到。表面看是路径问题,实际上有几种不同的成因。一种是文件确实没下载,这好办;另一种是下载了但文件名不同,不同来源的模型文件命名习惯不一样;还有一种是模型文件版本不匹配,加载时不报错,但在做姿态解算时结果明显偏差。
我的排查顺序是:先确认文件存在,再确认文件名和脚本里写死的字符串完全一致(包括大小写),最后核对一次解算结果是否合理。如果前两步都对但结果不对,基本可以判定是版本问题,老老实实按 README 指定的来源重新下载。
5.2 内存不够、进程被系统杀掉:不要靠调大内存解决
预处理到中途进程突然消失,终端只留下一行 Killed,这是内存耗尽的典型表现。我遇到过一次,定位到是某个序列的帧数特别长,加载后一次性展开成大量中间数组。
处理方式不是去加内存条,而是控制并发和分批处理。仓库脚本通常支持指定处理范围,你可以按子数据集分批跑,跑完一批再跑下一批,最后合并。另外把不必要的中间变量及时释放,也能把峰值压下来。
5.3 路径、pickle 与 numpy 版本导致的静默错误
有一类问题特别恶心:脚本不报错,跑完了,但结果不对。我遇到的一次是 numpy 版本较新,对某些旧格式的数组反序列化行为有变化,导致读取出来的姿态参数被 reshape 成了错误的形状,后面的解算虽然能跑通,但输出的关节位置整体错乱。
这类问题的特征是"能跑但不对",唯一的解法是对照法:拿一小段数据,用一个确定可用的旧环境跑一遍,再用你的新环境跑一遍,对比输出的数值差异。如果数值不一致,就是环境问题,不用怀疑数据本身。
5.4 AMASS 子集没下全,脚本却一声不吭
这个坑我必须要单独拿出来说。脚本通常是按存在的文件去处理的,缺了某个子集它就少处理一部分,不会报警。等你训练时发现数据量不对,已经过去很久了。
我的建议是:在预处理前,先把 AMASS 官方给出的子数据集清单列出来,逐项确认本地有没有对应的目录。这一步花五分钟,能避免后面几天的困惑。我在第二次复现时做了个核对表,把子集名、预期文件数、实际文件数三列并排,一眼就能看出缺了什么。
6. 数据到手之后:向量切片、文本编码与评估对齐
6.1 把 263 维当成一张地图来用
前面拆过 263 维的构成,这里说几个实际使用中的注意点。
根节点的旋转速度用正余弦表示,这意味着你如果想改朝向,不能直接改角度,要先在正余弦空间里插值再转回去。很多人做动作编辑时直接对这一段做线性插值,结果朝向上出现不自然的抖动,原因就是没有处理周期性。
水平线速度这一段和根节点的水平位置高度相关,如果你打算在水平方向上做平移编辑,改速度比改位置更自然,因为模型学到的主要是速度分布的统计特性。
关节速度那 66 维是最后一段,也是最容易被忽略的一段。有些开源实现在做损失计算时只用了前两段,把速度段丢掉了,结果生成的动作在时序上显得迟滞、不连贯。我的经验是,速度相关的损失权重给得小一点但不要给零,对动作的流畅度有肉眼可见的提升。
6.2 文本侧:GloVe、句子编码器该怎么选
官方管线用的是 GloVe 词向量加上一个固定的文本编码器。这个方案的优点是复现性强,大家用的都一样,指标可比;缺点是语义表达能力有限,尤其是面对长句和复杂修饰的时候。
| 方案 | 优点 | 代价 | 适用场景 |
|---|---|---|---|
| GloVe 词向量 | 官方一致,指标可比 | 语义粒度粗 | 复现论文、做基线 |
| 预训练句子编码器 | 语义表达强 | 需要额外权重,推理开销大 | 追求生成质量、做应用 |
| 多模态对比模型 | 图文对齐好 | 权重大、显存吃紧 | 追求 SOTA 效果 |
我自己的做法是基线用 GloVe 跑通,确认数据管线没问题;追求效果时换成对比学习类的文本编码器,同时把动作侧的特征也做投影,两边维度对齐后再算损失。
6.3 评估指标与官方评估模型必须配套使用
HumanML3D 常用的几个指标是:检索准确率(R-Precision)、特征分布距离(FID)、多模态距离(MM-Dist)、生成多样性(Diversity)以及同一文本多次生成之间的差异度(MultiModality)。
这里的关键点是,这些指标都依赖官方提供的那个评估模型。你不能自己随便换一个动作编码器去算,算出来的数值和论文没有可比性,审稿人第一个就会问。所以在你下载数据的同时,记得把官方评估模型的权重也一并下好,和数据集放在同一个版本管理体系里。
另外,评估用的划分必须严格使用test.txt,不要自己重新随机切。我见过有人为了"更公平"自己重新切了一份测试集,结果指标比论文高出一截,这种结果没有人会认可。
7. 我自己的操作时序与几条实在建议
把整个流程按我现在的习惯串一遍:先去两个站点提许可申请,同时把仓库克隆下来、conda 环境建好、依赖装齐;许可下来之后分批下载原始数据,下完检查每个子集的文件数;解压、整理目录层级,用 find 命令抽查几处路径;下载词向量和模型文件,核对大小;跑预处理,按子集分批,中途观察内存;跑完之后数文件、对划分、跑官方评估做自检;抽几条动作可视化确认;最后把向量、文本、归一化参数、划分文件打包存档,标注日期。
最后分享三个我觉得最省时间的细节。第一个是别跳过可视化,它花十分钟能省你两天。第二个是把磁盘类型当回事,同样一份预处理,机械盘和固态盘的耗时差的不是一点半点,有条件就把数据放在固态盘上跑。第三个是给数据目录起个带日期的名字,我吃过一次亏:两份不同批次的 HumanML3D 放在同一台机器上,训练脚本里路径写成相对路径,结果加载到了另一份的归一化参数,排查了很久才发现。现在我的目录名一律是humanml3d_2024xxxx这种格式,再也没出过这类问题。