使用混合精度 mixed precision 给 Keras 加速

通过设置全局策略为mixed_float16并配合LossScaleOptimizer,可以在支持的GPU上加速Keras模型的训练。混合精度计算利用float16提高速度,同时保持float32的数值稳定性。在实验中,模型训练速度提升约1.25倍,减少了计算时间。需要注意的是,可能会遇到损失值溢出导致的inf或nan,这通常在训练后期会改善。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可以使用混合精度 mixed precision 给 Keras 加速,3个操作步骤如下:

  1. 使用算力在 7.0以上的GPU,比如 NVIDIA 的 RTX 3090 等。
  2. 在建立模型之前,设置 global_policy 为 mixed_float16。代码如下。
policy = tf.keras.mixed_precision.Policy('mixed_float16')
tf.keras.mixed_precision.set_global_policy(policy)
# 另一种写法是只用下面这一行语句。但是为了验证 policy.compute_dtype,必须使用上面2行语句。
# tf.keras.mixed_precision.set_global_policy("mixed_float16")

# 上面设置好 global_policy 之后,可以用下面2行验证数据类型。
print(f'Compute dtype: {policy.compute_dtype}')
print(f'Variable dtype: {policy.variable_dtype}')
# 变量的数据类型保持为 float32,以保证数字的稳定性 numeric stability。
  1. 对优化器使用 LossScaleOptimizer 。 代码如下 2 行。
opt_adam = keras.optimizers.Adam(learning_rate=lr, beta_1=0.9, beta_2=0.999)                
opt_mixed_precision = keras.mixed_precision.LossScaleOptimizer(opt_adam)
# 后续编译模型时要使用 opt_mixed_precision,即 model.compile(optimizer=opt_mixed_precision ……

混合精度的原理,简单来说,就是在计算时从 float32 格式改为使用 float16 格式,从而加快计算速度(而保存的数据本身依然是使用 float32 格式)。
此外,为了不丢失过大或过小的损失值,避免损失值溢出,还需要使用 LossScaleOptimizer 对损失值进行动态缩小和放大,使得损失值能够用 float16 格式进行计算。
对混合精度的详细介绍,可以参看官方文档 https://keras.io/api/mixed_precision 和 https://tensorflow.google.cn/guide/mixed_precision

最后注意2点:

  1. 不同的模型和硬件配置,加速程度也会不一样。我在一次模型试验中,看到了 1.25倍的加速,相当于5天的计算量,在使用混合精度后,4天可以算完。并且这里使用的 Keras 版本是 2.4版,即 TensorFlow 2.4 。
  2. 损失值在计算过程中会出现个别 inf 或 nan 的情况,这是因为某些 epoch 中损失值过大引起的,在模型经过若干 epochs 优化后,损失值会逐渐变小。
### 混合精度训练的概述 混合精度训练是一种通过结合低精度(如 `float16` 或 FP16)和高精度(如 `float32` 或 FP32)数据类型来加速深度学习模型训练的技术。这种方法可以显著减少内存占用并提高计算效率,同时保持模型收敛性和准确性[^1]。 #### PyTorch 中的混合精度训练实现 在 PyTorch 中,可以通过 `torch.cuda.amp` 提供的功能轻松实现混合精度训练。核心组件包括 `autocast` 和 `GradScaler`: - **`autocast`**: 自动选择合适的精度执行操作。 - **`GradScaler`**: 处理梯度缩放问题,防止数值下溢。 以下是基于 PyTorch 的混合精度训练代码示例: ```python import torch from torch.cuda.amp import GradScaler, autocast # 初始化模型、优化器和 GradScaler model = MyModel().cuda() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) scaler = GradScaler() for epoch in range(num_epochs): for data, label in data_loader: data, label = data.cuda(), label.cuda() optimizer.zero_grad() # 启用自动混合精度上下文管理器 with autocast(): output = model(data) loss = loss_fn(output, label) # 使用 scaler 缩放损失以稳定梯度更新 scaler.scale(loss).backward() scaler.step(optimizer) scaler.update() ``` 上述代码展示了如何利用 `autocast` 上下文管理和 `GradScaler` 实现高效的混合精度训练[^2]。 #### TensorFlow 中的混合精度训练实现 TensorFlow 支持通过 Keras API 轻松启用混合精度训练。主要依赖于 `tf.keras.mixed_precision.Policy` 和策略设置。以下是一个简单的例子: ```python import tensorflow as tf # 设置混合精度策略 policy = tf.keras.mixed_precision.Policy('mixed_float16') tf.keras.mixed_precision.set_global_policy(policy) # 构建模型 model = tf.keras.Sequential([ tf.keras.layers.InputLayer(input_shape=(224, 224, 3)), tf.keras.layers.Conv2D(32, kernel_size=3), tf.keras.layers.Flatten(), tf.keras.layers.Dense(10, activation='softmax'), ]) # 编译模型 optimizer = tf.keras.optimizers.Adam() loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) model.compile(optimizer=optimizer, loss=loss_fn, metrics=['accuracy']) # 训练模型 dataset = ... # 数据集定义 model.fit(dataset, epochs=num_epochs) ``` 此代码片段说明了如何配置 TensorFlow 进行混合精度训练,从而提升 GPU 性能[^4]。 #### 半精度浮点数的作用 半精度浮点数 (`float16`) 是混合精度训练的核心之一。相比传统的单精度浮点数 (`float32`),它具有更少的有效位数和指数范围,因此存储需求更低且运算更快。然而,在某些情况下可能会引入数值不稳定性,这正是为什么需要使用梯度缩放技术的原因。 ### §相关问题§ 1. 如何评估混合精度训练对模型性能的影响? 2. 在哪些硬件平台上推荐优先采用混合精度训练? 3. 如果遇到数值不稳定的情况,有哪些解决方案? 4. PyTorch 和 TensorFlow混合精度实现方式有何异同? 5. 是否可以在推理阶段应用类似的混合精度技术?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值