为啥说:训练用BF16,推理用FP16

FP16、BF16 是张量里每一个数字的存储格式(数据类型)

张量可以理解成一大堆数字组成的矩阵/向量,里面最小单元就是单个数字,FP16/BF16规定:这个数字在内存、权重文件里占多少字节、怎么存小数。

1. 先搞懂基础参照物:FP32(普通32位浮点数)

电脑平时存小数默认用FP32,占4个字节,分三段:

  1. 正负符号位
  2. 指数(控制数字能多大/多小)
  3. 尾数(控制数字精准程度)

大模型原始训练时,所有权重数字本来都是FP32,但4字节一个数,权重文件会巨大,显存扛不住,于是搞出两种压缩到2字节(16位)的方案:FP16、BF16。

两者都只占2字节,区别只是指数和尾数的位数分配不一样

2. FP16(Float16,标准16位浮点)

分配规则:1位符号 + 5位指数 + 10位尾数

  • 优点:尾数10位,精度更高,算乘法、推理速度更快,老显卡加速友好;
  • 缺点:只有5位指数,能表示的数字范围很小。
    遇到模型里差距很大的权重数值、训练时的梯度,很容易超出范围直接变成0(下溢),训练容易崩。

举个生活化例子:

好比一把尺子,刻度分得特别细(尾数多=精度高),但尺子总长很短(指数少=范围小)。小数能算得很准,但数字稍微一大一小就超出去读不出来。

3. BF16 = BFP16(Brain Float16,谷歌搞出来的)

分配规则:1位符号 + 8位指数 + 7位尾数

  • 优点:8位指数,和FP32的指数长度一模一样,能承载的数字范围和完整版FP32完全一致。训练时梯度、权重大小波动再大,也不会溢出失效;
  • 缺点:尾数只剩7位,精度比FP16低一点点,微小数值会丢失一点细节,但大模型训练完全感知不到损失。

生活化例子:

尺子总长和完整4字节尺子一样长(指数8位),但刻度稍微粗一点(尾数少),范围足够用,牺牲一点点精细度换稳定。

4. 它们是不是张量的基本单元数据类型?

是的,完全正确。

  1. 张量 = 一堆数字的集合(权重矩阵、输入向量、中间计算结果全是张量)
  2. 张量的最小组成单位:单个数值
  3. FP16/BF16 就是规定「张量里每一个数字用哪种16位格式保存」

举个直观对比:

  • 同样100万个权重数字:
    FP32:每个4字节,总占用400MB
    FP16/BF16:每个2字节,总占用200MB,直接减半显存/硬盘占用

5. 使用场景

  1. 训练、微调模型(QLoRA/全量微调)一律用 BF16
    训练时会产生梯度(极大、极小数),BF16表示数值范围广,不怕数值溢出,训练稳定,现在所有大模型预训练标配。
  2. 单纯本地推理、显卡老旧(比如老10系NVIDIA卡)优先 FP16
    FP16表示的数据范围小,计算速度更快,更省算力。

6、手动转换 两种格式

一、先分清 概念:「训练计算精度」「权重文件存储精度」「推理运行精度」

1. QLoRA/全量微调阶段:为什么强制用BF16做计算?

训练时会产生梯度(极小/极大的数值):

  • BF16指数位8位,和FP32范围一模一样,梯度不会溢出、训练稳定;
  • FP16只有5位指数,梯度极易变成0/无穷,训练直接崩掉。
    这里说的「用BF16」,指整个训练过程的运算统一走BF16浮点计算
2. 训练完保存的权重文件默认是什么格式?

两种情况:

  1. 普通LoRA(非QLoRA) :全程基座BF16训练,保存出来的基座权重、LoRA适配器都是 BF16文件
  2. QLoRA 4bit训练 :显存里基座是4bit NF4压缩存储,计算时临时反量化BF16;保存只会存两件东西:4bit基座模型 + BF16格式LoRA小权重,不会直接存完整BF16基座
3. 关键:BF16权重文件 ≠ 推理必须跑BF16

权重文件只是静态存储数字 ,BF16和FP16都是16位浮点数,底层框架(PyTorch/Transformers/vLLM)自带类型强制转换算子,一行代码手动转,不是自动变。

二、两条落地路线:微调完怎么得到FP16推理模型

路线1:LoRA微调(原生BF16权重)转FP16推理
步骤
  1. 用BF16跑完微调,保存.safetensors权重(文件里数值是BF16编码);
  2. 推理加载时,手动执行类型转换:
python 复制代码
# 加载BF16模型
model = AutoModelForCausalLM.from_pretrained("./your_bf16_model")
# 全局强制转FP16,所有权重数值重新编码为FP16格式
model = model.to(torch.float16)
# 此时显存里运行是FP16加速,你也可以重新保存一份FP16权重文件
model.save_pretrained("./fp16_infer_model")
原理大白话

BF16、FP16本质都是记录同一个小数,只是二进制拆分「指数/尾数」规则不同。

框架会把BF16数字先翻译成标准FP32中间值,再重新编码成FP16二进制,存在显存里用于推理;

  • 优点:老10系显卡跑FP16算子速度更快;
  • 代价:极个别超大/极小权重数值会丢失一点精度(推理无梯度,轻微损失肉眼看不出)。
路线2:QLoRA 4bit微调 → 合并LoRA → 导出FP16完整模型(最常用部署流程)

QLoRA训练完不会有完整BF16基座,必须先合并权重才能导出FP16:

  1. 加载4bit量化基座 + BF16 LoRA适配器;
  2. 执行model.merge_and_unload():框架自动把4bit权重反量化还原成BF16完整基座,再叠加LoRA参数;
  3. 此时内存里是完整BF16大模型,手动转FP16后保存,得到纯FP16权重文件用于部署;
  4. 以后推理直接加载这份FP16文件,全程FP16运算加速。

三、必须手动操作

  1. 训练保存的文件固定是BF16/4bit,不会自动变成FP16
  2. 「推理优先FP16」不是让原BF16文件自己变形,是两种操作二选一:
    • 加载BF16权重,运行时实时转FP16计算(不改动原文件);
    • 转换后另存一份独立FP16权重文件,专门给老显卡推理用;
  3. 反过来也成立:FP16权重推理,加载时转BF16运行,完全可逆。
相关推荐
KaMeidebaby1 小时前
卡梅德生物技术快报|蛋白 N 端测序在重组贻贝融合蛋白表征中的应用,解决原核表达序列偏移工艺难题
前端·人工智能·物联网·算法·百度
TMT星球1 小时前
从像素复刻到行动控制:具身世界模型的底层逻辑探索
人工智能·深度学习·机器学习
ccimao63161 小时前
散户做财报整理、研报阅读、复盘记录,各类AI工具适配环节梳理
大数据·人工智能
派叔1 小时前
老字号营销服务商技术解构:三类方案的架构逻辑与选型评估
大数据·人工智能·搜索引擎·架构·产品运营·流量运营
Byron__2 小时前
AI学习_06_短期记忆与长期记忆
人工智能·python·学习
万悉科技2 小时前
实战:如何通过GEO原生内容结构化,让LLM稳定推荐你的品牌网站
大数据·人工智能·重构
董厂长2 小时前
从 Claude Code 放弃 RAG 说起:实际项目中如何合理创建知识库
人工智能·llm
元岳数字人小元2 小时前
如何依托数字人源码做好私有化部署选型
人工智能·开源·人机交互·交互
Turbo正则2 小时前
群论在AI中的应用概述
人工智能·算法·抽象代数