优化深度学习训练技术
Lingvanex 专注于机器翻译,并提供创新解决方案,帮助用户和企业有效克服语言障碍。我们的机器翻译技术确保不同语言间通信的准确性、速度和便利性,为个人和公司提供高质量的翻译服务。
本文深入探讨了几种旨在提高训练效率和有效性的先进技术。我们将讨论有助于模型参数逐步调整的方法,这可以带来更稳定的学习过程。通过微调模型权重的更新方式和时间,这些技术旨在增强收敛性并最终产生更好的结果。此外,本文还将涵盖学习率管理策略,学习率在决定模型学习速度方面起着关键作用。了解如何随时间调整这些学习率可以显著影响训练动态,并产生更快、更准确的模型。
最后,我们将探讨检查点管理的重要性,它通过平均多次训练会话的权重来更好地利用已训练模型。这有助于减轻过拟合的影响,并确保模型保留其训练过程中学到的最佳特征。
指数移动平均
在 Transformer 模型的默认配置文件中,参数 moving_average_decay 未设置。将 moving_average_decay 参数设置为接近 1 的值(根据 TensorFlow 文档)后,下一步是计算模型权重的指数移动平均。根据文档,将 moving_average_decay 应用于模型权重可以显著改善模型结果。moving_average_decay 算法如下:
- 在每个训练步骤中,计算并应用梯度后,初始化 MovingAverage 类;
- 初始化 MovingAverage 后,调用更新模型权重的函数;
- 模型权重按以下方式更新:
- 计算 衰减 系数:decay = 1 - min(0.9999, (1.0 + training_step) / (10.0 + training_step))
- 对每个模型权重应用以下算法:shadow_weight = previous_weight - (previous_weight - current_weight) * decay (在第一个训练步骤,previous_weight = current_weight)
- 每个训练步骤后的平滑权重存储在 MovingAverage 类 中;训练权重替换为平滑权重仅在保存模型检查点时发生。
简化调用序列
- def call() 类 Trainer 模块 training.py
- def init() 类 MovingAverage 模块 training.py
- def _update_moving_average() 类 Trainer 模块 training.py
- def update() 类 MovingAverage 模块 training.py
学习率衰减机制
学习率衰减 机制使用在 NoamDecay 和 ScheduleWrapper 类中初始化的变量。在每个训练步骤后,ScheduleWrapper 类中发生以下转换:- 使用 tf.math.maximum 函数计算 step 变量 → tf.maximum(step - step_start, 0) = 1;
- 通过整数除法 → step //= step_duration = 1 // 1 = 1,将 step 变量调整为 step_duration 值;
- 将上一步调整后的 step 变量传递给 NoamDecay 类。
在 NoamDecay 类中发生以下转换:
- 计算 step 变量 → step = step + 1 = 2;
- 中间值 a:使用 tf.math.pow 函数将 model_dim 值提升到 -0.5 次方,这等效于一除以 model_dim 的平方根 → 1 / sqrt(4) = 0.5;
- 中间值 b:使用 tf.pow 函数 将上述获得的 step 值提升到 -0.5 次方,这等效于一除以 step 的平方根 → 1 / sqrt(2) = 0.7071;
- 中间值 c:使用 tf.pow 函数,将 warmup_steps 值 提升到 -1.5 次方并乘以 step 值 → (1 / 8000^1.5) * 2 = 0.000001397 * 2 = 0.000002795;
- 使用 tf.math.minimum 函数,确定两个中间值 b 和 c 的最小值 → min(b, c) → 0.000002795;
- 将得到的最小值乘以中间值 a 和 scale → 0.0000027951 * 0.5 * 2 = 0.000002795;
- 中间转换的完整周期如下所示 (scale * tf.pow(model_dim, -0.5) * tf.minimum(tf.pow(step, -0.5), step * tf.pow(warmup_steps, -1.5)));
- 上面获得的值 0.000002795 返回到 ScheduleWrapper 类。
在 ScheduleWrapper 类 中,定义了系数的最终值:learning rate = tf.maximum(learning_rate, minimum_learning_rate) → learning rate = max(0.000002795, 0.0001) = 0.000002795 = 0.0001。这是输出到训练日志的值:Step = 1; Learning rate = 0.000100; Loss = 3.386743。
使用上述算法,我们将绘制一个模型维度为 768 且训练器配置文件中指定参数 学习率 = 2 的优化器 学习率 值变化图。
现在,我们将绘制一个模型维度为 768 且训练器配置文件中指定参数 学习率 = 6 的优化器 学习率 值变化图。
从图中我们可以得出结论,随着 warmup_steps 值减小,优化器 学习率 迅速增加,而随着配置文件中 学习率 增加,可以实现更高的优化器 学习率 值,这有助于在大模型维度下实现更快的学习。
您还可以使用 start_decay_steps 参数影响 学习率 的变化,即我们可以指定训练开始后多少步应用 warmup_steps 机制和后续衰减。
下图显示,当 start_decay_steps = 10,000 时,模型在前 1 万步以固定的 学习率 值(等于最小值)进行训练,在 1 万步之后,带有衰减的 warmup_steps 机制开始工作。
decay_step_duration 参数可用于增加 warmup_steps 机制的持续时间并减慢衰减率。
简化调用序列
- def call() 类 ScheduleWrapper 模块 schedules/lr_schedules.py
- def call() 类 NoamDecay 模块 schedules/lr_schedules.py
- def call() 类 ScheduleWrapper 模块 schedules/lr_schedules.py
检查点平均机制
检查点是模型在某个训练步骤的状态。训练模型的检查点存储训练期间更改的模型权重、每个层的优化器变量(在某个训练步骤的优化器状态)和计算图。一个简单网络的计算图示例如图 6 所示——计算图。优化器以红色突出显示,常规变量为蓝色,优化器槽变量为橙色。其他节点以黑色突出显示。槽变量是优化器状态的一部分,但为特定变量创建。例如,上面的“m”边对应于 Adam 优化器为每个变量跟踪的动量。训练结束时,模型目录中的 最后检查点 被读取并恢复,数量等于 average_last_checkpoints 参数。
根据训练模型的架构,所有模型层的权重都初始化为零。
接下来在循环中,对于每个恢复的检查点,读取权重;每个层的权重除以 average_last_checkpoints 参数中指定的检查点数量,并将结果值通过 variable.assign_add(value / num_checkpoints) 函数添加到上面初始化的权重中(embeddings 层仅与 embeddings 层求和,依此类推)。
我们示例模型中小层的平均机制,平均最后两个检查点。