混合精度训练(mixed-precision training)
/ mikst-pruh-SIZH-un TRAY-ning /
混合精度训练,是指把绝大多数数字运算改用「精度更低」的数字来做——每个数字的有效位数更少——以求更快、更省内存,同时把少数关键环节仍保留在全精度,免得准确度崩掉。想象一个木匠:粗活儿他量到「最近的厘米」就动手,图个快;可一到真正要紧的榫接,他就换上毫米刻度的尺子。能将就的地方粗着来,要紧的地方再精细。
计算机用固定数目的「比特」来存数;比特越多,能表示的值越精确,但占的内存越多、算得越慢。传统上训练从头到尾都用 32 比特的数字。混合精度则把大头的活儿改用 16 比特的数字(叫 FP16 或 BF16 的格式)来做,加速器芯片啃它们大约能快上一倍,占的内存也只有一半。危险在于:极小的数字可能被舍入成零,把学习给弄坏;所以模型会保留一份 32 比特的参数「主副本」,并用「损失缩放」之类的招数,护住那些娇贵的更新。
为什么这很重要:这是现代训练里最廉价的大收益之一——往往能近乎把速度翻倍、内存减半,而最终质量几乎不受损,正因如此它如今成了标准做法。诚实的提醒是:它并非白来的魔法。粗手粗脚地用,会让训练变得不稳,或悄悄损伤准确度,而且并非每个运算都受得住低精度。它是工程师要去调校的一桩谨慎权衡,而不是你按下去就能忘掉的开关。
某一层的矩阵乘法用快速的 16 比特运算来跑,但权重更新的累计账本,则保留在一份 32 比特的主副本里。那些在 16 比特下会被舍入成零的微小梯度,在 32 比特副本里得以存活,于是模型还能继续学。
能将就的地方用快算,需要让小数存活的地方留一份精确的主副本。
训练中的低精度(16 比特数字、保持动态)与部署用的量化(常是 8 比特乃至更低、固定不变)不是一回事。训练需要足够的精度去学到微小的更新;而一个练好的模型,事后往往能被压得狠得多。