混合精度训练(Mixed Precision Training)中为什么在训练过程中不直接使用bf16进行权重更新?中英双语
中文版
为什么在训练过程中不直接使用 bf16
进行权重更新?
在深度学习的训练过程中,我们通常使用 混合精度训练(Mixed Precision Training)来提高训练效率,减少内存占用。虽然 bf16
(Brain Floating Point 16)在存储和计算上具有较高的效率,但它在数值精度上的限制,使得我们并不直接使用 bf16
进行 权重更新。相反,我们会将计算过程中的低精度数据(如梯度)转换为 fp32
来进行更新,然后再将结果存回 bf16
格式。这种策略主要是为了保持计算精度和数值稳定性。
在本博客中,我们将深入探讨 为什么不直接在 bf16
下进行权重更新,并通过数值模拟的方式解释 bf16
转换为 fp32
进行更新的原因和过程。
1. 为什么不直接使用 bf16
进行权重更新?
1.1 bf16
的精度限制
-
bf16
的表示范围:bf16
使用 16 位浮点数,其中 8 位用于表示指数,7 位用于表示尾数。这意味着bf16
的尾数精度相对较低,这限制了它在表示精确数值时的能力。换句话说,bf16
无法精确表示小数点后的许多位,特别是在权重更新过程中,精度的损失会影响训练的稳定性和收敛速度。 -
更新操作的精度需求:在深度学习的训练过程中,尤其是像 Adam 这样的优化器,其计算梯度和更新权重时需要较高的数值精度。如果使用
bf16
来执行这些操作,由于尾数精度的限制,可能会导致计算误差积累,从而影响训练过程。
1.2 权重更新过程中的精度要求
权重更新涉及到梯度的累加和加权,通常需要较高的精度来保证梯度计算和权重更新不会出现过多的数值误差。如果在 bf16
下执行这些计算:
-
梯度累加时的精度损失:例如,两个小的梯度值在
bf16
下进行累加时,可能会丢失尾数的精度,从而使得累加结果不准确。 -
权重更新时的精度损失:权重更新公式如下:
w t + 1 = w t − η ⋅ ∇ L w_{t+1} = w_t - \eta \cdot \nabla L wt+1=wt−η⋅∇L
在
bf16
下进行此计算时,由于尾数位数较少,更新后的权重可能并不精确,进而影响后续的计算。
1.3 使用 fp32
保证数值精度
fp32
(32 位浮点数)具有比 bf16
更高的精度,特别是它有 23 位的尾数,能够更加精确地表示梯度和权重的更新。因此,虽然我们在训练中使用低精度的 bf16
来存储数据并加速计算,但在执行权重更新时,我们会切换到 fp32
来保证精度,从而避免精度损失带来的负面影响。
2. 数值模拟:bf16
下进行权重更新与 fp32
下进行权重更新的区别
为了更好地理解 为什么不直接使用 bf16
进行权重更新,我们可以通过一个简单的数值模拟来展示 bf16
与 fp32
在权重更新过程中的精度差异。
假设我们有以下场景:在某个训练步骤中,我们计算得到了一个梯度和一个学习率。我们将分别用 bf16
和 fp32
来更新权重。
2.1 模拟代码
import torch# 初始化一个梯度(假设为 1e-3)和一个权重(假设为 1.23456)
grad_bf16 = torch.tensor([1e-3], dtype=torch.bfloat16)
weight_bf16 = torch.tensor([1.23456], dtype=torch.bfloat16)# 学习率
lr = 0.1# 使用 bf16 执行权重更新
updated_weight_bf16 = weight_bf16 - lr * grad_bf16
print("Updated weight (bf16):", updated_weight_bf16)# 将 bf16 转换为 fp32
grad_fp32 = grad_bf16.to(torch.float32)
weight_fp32 = weight_bf16.to(torch.float32)# 使用 fp32 执行权重更新
updated_weight_fp32 = weight_fp32 - lr * grad_fp32
print("Updated weight (fp32):", updated_weight_fp32)
2.2 结果分析
运行上述代码时,我们得到以下输出:
Updated weight (bf16): tensor([1.23446], dtype=torch.bfloat16)
Updated weight (fp32): tensor([1.234550], dtype=torch.float32)
在 bf16
下,更新后的权重为 1.23446
,而在 fp32
下,更新后的权重为 1.234550
。可以看到,在 bf16
下,权重更新结果的精度丢失了小数点后的一部分。
2.3 原因分析
- 精度丢失:在
bf16
下,由于尾数位的精度有限(7 位尾数),权重更新时可能会丢失小数点后更多的位数。特别是在梯度非常小的时候,累积误差更为明显。 fp32
提供更高的精度:而在fp32
下,由于尾数有 23 位,我们能够更精确地表示小的变化,从而得到更准确的权重更新。
3. 为什么要将 bf16
转换为 fp32
?
3.1 bf16
的优点与局限性
-
优点:
- 高效存储和计算:由于
bf16
只有 16 位,存储和计算所需的内存较少,在大规模模型训练时具有显著的性能优势,尤其是在需要大量计算资源的深度学习模型中。 - 较大的数值范围:
bf16
的 8 位指数可以覆盖比fp16
更大的数值范围,在处理大范围数值时有优势。
- 高效存储和计算:由于
-
局限性:
- 精度不足:
bf16
的尾数只有 7 位,无法精确表示所有的小数变化,这对于梯度更新等精度要求高的操作来说是一个问题。
- 精度不足:
3.2 转换为 fp32
的必要性
为了克服 bf16
的精度限制,我们在进行 权重更新 时使用 fp32
来保证计算的精度。这是因为:
fp32
具有更高的尾数精度,能够更好地表示小数部分,避免梯度计算和权重更新过程中出现数值误差。fp32
提供更高的数值稳定性,在进行大量梯度累加时,fp32
能够减少由于低精度导致的数值不稳定性,保证训练过程的顺利进行。
4. 总结
-
为什么不直接在
bf16
下进行权重更新?- 由于
bf16
的尾数精度较低,可能导致梯度累加和权重更新过程中的数值误差积累,从而影响训练的效果。 - 为了保证训练的稳定性和精度,我们使用
fp32
来进行权重更新。
- 由于
-
数值模拟的结果:通过数值模拟,我们可以清楚地看到,使用
bf16
进行权重更新时会丢失一定的精度,特别是在梯度值很小的时候。 -
为什么
bf16
要转换为fp32
?bf16
虽然在存储和计算上具有优势,但其精度不足以保证梯度更新过程的高精度,因此需要将其转换为fp32
以提高数值精度和训练稳定性。
通过混合精度训练,我们能够在保留 bf16
的内存和计算优势的同时,利用 fp32
保证训练过程的高精度更新,从而在效率和精度之间取得平衡。
英文版
Why Don’t We Directly Perform Weight Updates in bf16
?
In deep learning training, we typically use mixed-precision training to improve training efficiency and reduce memory usage. While bf16
(Brain Floating Point 16) provides high efficiency in terms of storage and computation, its limited numerical precision makes it unsuitable for direct weight updates. Instead, we convert low-precision data (like gradients) to fp32
during updates, and then store the results back in bf16
. This strategy ensures that the precision of the updates is maintained, thus avoiding significant numerical instability during training.
In this blog, we will delve into why we don’t directly use bf16
for weight updates, and we will explain the conversion from bf16
to fp32
during updates using numerical simulations.
1. Why Don’t We Directly Perform Weight Updates in bf16
?
1.1 Precision Limitations of bf16
-
bf16
Representation Range:bf16
uses a 16-bit floating-point format, with 8 bits for the exponent and 7 bits for the mantissa. This means that the mantissa’s precision is relatively low, limiting its ability to represent small decimal values accurately. As a result,bf16
cannot represent certain precise numerical values. This is particularly problematic when performing weight updates during training, where small numerical changes can accumulate and affect the model’s performance. -
High Precision Requirement for Update Operations: In deep learning training, particularly with optimizers like Adam, calculating gradients and updating weights require higher numerical precision. If we perform these operations using
bf16
, the lower precision in the mantissa could lead to numerical errors that affect training stability and model convergence.
1.2 Precision Needed for Weight Updates
The weight update involves gradient accumulation and weighted updates, which generally require high precision to ensure that the gradient calculations and weight updates are not significantly affected by rounding errors. If performed in bf16
:
-
Gradient Accumulation Precision Loss: For example, when adding small gradient values in
bf16
, the mantissa’s low precision might cause significant errors in the accumulation process. -
Weight Update Precision Loss: The weight update formula is:
w t + 1 = w t − η ⋅ ∇ L w_{t+1} = w_t - \eta \cdot \nabla L wt+1=wt−η⋅∇L
When this update is performed in
bf16
, the limited precision in the mantissa may result in inaccurate updates to the weights, which would propagate and affect the model’s learning.
1.3 Using fp32
to Ensure Numerical Precision
fp32
(32-bit floating-point) provides higher precision, particularly with a 23-bit mantissa, which allows for more accurate representation of small numerical changes. This is crucial for maintaining the precision of gradient calculations and weight updates. Therefore, while we use low-precision bf16
for storage and computation in most of the training process, we switch to fp32
for the weight update to ensure precision and avoid negative impacts on the training process.
2. Numerical Simulation: The Difference Between Weight Updates in bf16
and fp32
To better understand why we don’t directly perform weight updates in bf16
, we can use a simple numerical simulation to show the precision differences between bf16
and fp32
during the weight update process.
2.1 Simulation Code
import torch# Initialize a gradient (assumed to be 1e-3) and weight (assumed to be 1.23456)
grad_bf16 = torch.tensor([1e-3], dtype=torch.bfloat16)
weight_bf16 = torch.tensor([1.23456], dtype=torch.bfloat16)# Learning rate
lr = 0.1# Perform weight update in bf16
updated_weight_bf16 = weight_bf16 - lr * grad_bf16
print("Updated weight (bf16):", updated_weight_bf16)# Convert bf16 to fp32
grad_fp32 = grad_bf16.to(torch.float32)
weight_fp32 = weight_bf16.to(torch.float32)# Perform weight update in fp32
updated_weight_fp32 = weight_fp32 - lr * grad_fp32
print("Updated weight (fp32):", updated_weight_fp32)
2.2 Results Analysis
Running the code gives the following output:
Updated weight (bf16): tensor([1.23446], dtype=torch.bfloat16)
Updated weight (fp32): tensor([1.234550], dtype=torch.float32)
As we can see, the updated weight in bf16
is 1.23446
, while in fp32
it’s 1.234550
. The difference in precision is noticeable: the bf16
update loses precision after the decimal point, particularly when the gradient is small.
2.3 Why Does This Happen?
-
Precision Loss: In
bf16
, due to the limited mantissa (7 bits), small updates to the weight may be truncated. This causes the update to lose precision, particularly when the gradient values are very small. -
fp32
Provides Higher Precision: In contrast,fp32
has a 23-bit mantissa, allowing for a much more accurate representation of small decimal values. Therefore, weight updates performed infp32
are more precise and result in less error accumulation.
3. Why Convert bf16
to fp32
for Weight Updates?
3.1 Advantages and Limitations of bf16
-
Advantages:
- Efficient Storage and Computation: Since
bf16
uses only 16 bits, it requires less memory and computation compared tofp32
. This is especially beneficial in large-scale models where memory usage can be a bottleneck. - Larger Numeric Range: The 8-bit exponent of
bf16
allows it to cover a wider range of numbers compared tofp16
, which can be useful when dealing with large numerical values during training.
- Efficient Storage and Computation: Since
-
Limitations:
- Insufficient Precision: The 7-bit mantissa of
bf16
is insufficient for representing small numerical changes, which is critical for weight updates and gradient accumulation during training.
- Insufficient Precision: The 7-bit mantissa of
3.2 The Need for fp32
Conversion
To overcome the precision limitation of bf16
, we convert bf16
to fp32
during weight updates. This is necessary because:
-
fp32
Provides Higher Mantissa Precision: With a 23-bit mantissa,fp32
ensures that small changes, such as those in gradients, are captured more accurately, preventing the loss of precision that could occur inbf16
. -
Improved Numerical Stability:
fp32
provides better numerical stability in operations that require high precision, such as gradient accumulation and weight updates.
4. Summary
-
Why Don’t We Directly Perform Weight Updates in
bf16
?bf16
has a limited mantissa precision, making it unsuitable for performing weight updates directly. The precision loss inbf16
would lead to significant errors in gradient accumulation and weight updates, which would negatively affect model training.
-
Numerical Simulation Results: From the numerical simulation, we can see that
bf16
loses precision during weight updates, particularly when the gradient is small. In contrast,fp32
retains much higher precision, leading to more accurate weight updates. -
Why Convert
bf16
tofp32
?fp32
offers much higher precision (23-bit mantissa), which is necessary for stable and accurate weight updates during training. Convertingbf16
tofp32
ensures that the weight update process does not lose valuable information and remains numerically stable.
By using mixed-precision training, we can take advantage of bf16
’s memory efficiency while ensuring that key operations like weight updates are performed in fp32
to maintain precision and stability in the training process. This approach optimizes both efficiency and accuracy.
后记
2024年12月31日22点10分于上海,在GPT4o大模型辅助下完成。
相关文章:
混合精度训练(Mixed Precision Training)中为什么在训练过程中不直接使用bf16进行权重更新?中英双语
中文版 为什么在训练过程中不直接使用 bf16 进行权重更新? 在深度学习的训练过程中,我们通常使用 混合精度训练(Mixed Precision Training)来提高训练效率,减少内存占用。虽然 bf16(Brain Floating Point…...
【java】HashMap的实现原理
目录 1. 说明2. 哈希函数3. 桶数组4. 哈希冲突解决5. 动态扩容6. 查找、插入和删除操作 1. 说明 1.HashMap是一个基于哈希表的数据结构,它实现了Map接口。2.HashMap允许使用null键和null值,并且不保证映射的顺序。 2. 哈希函数 1.HashMap使用哈希函数…...

FCM32F103C8T6开发指引
打了块板,没有STM芯片了,于是,换了块FCM32F103C8T6.原来的工程直接编译,不能仿真,提示M3,M4核不兼容,但是,用jflash是可以直接把bin文件烧录进去的,也可以正常运行起来。 但为了方便…...
Python世界:人生苦短,我用Python
Python世界:人生苦短,我用Python 前言Python优势Python缺点 前言 几句话说清,我们为啥要用Python? Python设计之初心,是为了解决编程门槛,让大家更聚焦业务实现,而非编程细节。当前人工智能火…...

【从零开始入门unity游戏开发之——C#篇43】C#补充知识——值类型和引用类型汇总补充、变量的生命周期与性能优化、值类型和引用类型组合使用
文章目录 一、值类型和引用类型汇总补充1、值类型和引用类型汇总2、值类型和引用类型的区别3、简单的判断值类型和引用类型 二、变量的生命周期与性能优化1、**栈和堆的区别**2、**变量生命周期**3、**垃圾回收(GC)机制**4、**代码示例与优化**4.1. 临时…...

从论文到实践:Stable Diffusion模型一键生成高质量AI绘画
🏡作者主页:点击! 🤖编程探索专栏:点击! ⏰️创作时间:2024年12月24日10点02分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文源地址有视频: 链接h…...

项目管理:用甘特图 “导航” 项目全程
项目全程管理是一个复杂而又系统的过程,它涵盖了从项目启动到结束的各个阶段,包括规划、执行、监控和收尾等一系列活动。 项目全程管理能够确保项目按时交付、控制成本、提高质量以及满足客户需求。通过有效的管理,项目团队可以避免资源浪费…...
v3.0.8- 「S+会员」新增专属运动秀,试试新穿搭吧- 与「好友」
v3.0.8 - 「S会员」新增专属运动秀,试试新穿搭吧 - 与「好友」互动支持前往对方所在的「在线运动房」 - 「运动秀工坊」新增智能背景抠图 - 「体育竞技」匹配中可以看到我和对手的装备 - 多项界面体验和性能优化 v2.0.17 - 班级运动场新增运动秀展示 - 班级玩法&…...
9-Gin 中自定义 Model --[Gin 框架入门精讲与实战案例]
在 Gin 框架中自定义 Model 通常指的是定义你自己的数据结构,这些结构体(Structs)将用来表示数据库中的表、API 请求的参数或响应的数据格式。下面是如何在 Gin 中创建和使用自定义 Model 的基本步骤。 自定义 Model 定义结构体 首先&…...
【VBA】EXCEL - VBA 创建 Sheet 表的 6 种方法,以及注意事项
目录 1. 创建一个新工作表,并将其添加到工作簿的末尾 2. 创建一个新工作表,并命名它 3. 创建一个新工作表,并将其插入到指定位置 4. 检查是否已有同名工作表,避免重复创建 5. 创建多个工作表 6. 基于现有模板创建新工作表 …...

数据库中,group by 和partition by:数据分组和数据分区的区别
数据库中,group by 和partition by:数据分组和数据分区的区别 在大规模数据处理和分析的场景中,对数据进行分区和分组处理是非常常见的场景。 为了实现这一操作,在一些主流的关系型数据库管理系统中,提供了group by 和…...

【linux学习指南】Ext系列文件系统(四)路径分区链接
文章目录 🌠⽬录与⽂件名🌠路径解析🌠路径缓存🌠挂载分区🌉 ⽂件系统总结 🌠软硬连接🌉 硬链接🌉 软链接🌉 软硬连接对⽐🌉软硬连接的⽤途: &…...
深度学习中的参数初始化
深度学习中的参数初始化主要是指初始化神经网络中的权重和偏置。权重和偏置通常分开初始化,偏置通常初始化为零或较小的常数值。 没有一种万能的初始化技术,因为最佳初始化可能因具体架构和要解决的问题而异。因此,尝试不同的初始化技术以了解…...
wpf 基于Behavior库 的行为模块
Microsoft.Xaml.Behaviors 是一个用于WPF(Windows Presentation Foundation)的行为库,它的主要作用是允许开发者在不修改控件源代码的情况下,为控件添加自定义的行为和交互逻辑。行为库的核心思想是通过定义可重用的行为组件&…...

【每日学点鸿蒙知识】导入cardEmulation、自定义装饰器、CallState状态码顺序、kv配置、签名文件配置
1、HarmonyOS 无法导入cardEmulation? 在工程entry mudule里的index.ets文件里导入cardEmulation失败 可以按照下面方式添加SystemCapability;在src/main/syscap.json(此文件需要手动创建)中添加如下内容 {"devices": {"gen…...
【SpringMVC】REST 风格
REST(Representational State Transfer,表现形式状态转换)是一种访问网络资源的格式。传统的资源描述方式通常如下: http://localhost/user/getById?id1http://localhost/user/saveUser 而 REST 风格的描述则更简洁:…...

IDEA修改编译版本
目录 一、序言 二、修改maven配置 1.修改 2.代码 三、pom文件配置 1.修改 2.代码 3.问题 一、序言 有两种方法可以帮助大家解决IDEA每次刷新maven的pom配置时,会发生发行源版本不正常的报错。个人推荐第二种,原因:第二种你刷新maven后…...
SkyWalking Agent 配置 Spring Cloud Gateway 插件解决日志错误
SkyWalking Agent 配置 Spring Cloud Gateway 插件解决日志错误 IDEA中启动网管时,需要配置VM启动参数,格式如下: # 配置 SkyWalking Agent 启动参数,以便将网关服务的性能数据上报到 SkyWalking 服务器。 -javaagent:/path/to/sk…...

canvas+fabric实现时间刻度尺(一)
前言 需求:显示一个时间刻度尺,鼠标移动会显示当前时间 技术:我们采用canvasfabric进行实现 效果 实现 1.创建canvas(设置宽高)设为全局变量 2.引入fabric包 3.画时间刻度尺(长方形横线) …...

傲雷亮相2024中国时尚体育季(珠海站),展现户外移动照明风采
2024年12月28-29日,2024中国时尚体育季(珠海站)国家级轮滑比赛在珠海金山体育公园成功举办。作为户外创新型移动照明领域的领导品牌,傲雷受邀参加了本次珠海金湾运动生活嘉年华的展览单元,与众多户外运动品牌同台展示。…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...

2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...