2026/2/23 19:47:35
网站建设
项目流程
北京电商网站开发价格,做网站横幅的图片,高青网站建设,网站建设用图片1. 精度异常表现
Adam#xff08;Adaptive Moment Estimation#xff09;是深度学习中最常用的自适应学习率优化器之一#xff0c;用来更新网络模型训练参数。在NPU上调试apply_adam算子时遇到了一些微小的精度差异#xff0c;有一个用例精度正确率只有99.9931%#xff0c…1. 精度异常表现AdamAdaptive Moment Estimation是深度学习中最常用的自适应学习率优化器之一用来更新网络模型训练参数。在NPU上调试apply_adam算子时遇到了一些微小的精度差异有一个用例精度正确率只有99.9931%数据类型为fp32报错索引位置和与标杆的误差如下可以看到误差为0.000x, 来到了小数点的后四位。似乎这是计算过程中引入的必不可少的误差报错位置分布毫无规律但严谨考虑该算子为优化器算子我们还是要再细究一下这个问题以避免模型训练累积误差。2. 观察和猜想apply_adam 的计算公式如下2.1 猜想1可以看到公式中有addsubsqrtdivmul 5类指令。这几个指令中最可能出问题的就是sqrt了从计算的复杂度考虑。于是笔者尝试用牛顿迭代法手动实现了sqrt的计算公式如下式中n为需要求取的值x_k为每次迭代结果值初始值设置为x_0n/2。通常迭代5~6次就能满足fp64的精度保守起见笔者迭代了10次来验证精度是否由此处引起。不幸地是依然存在同样的精度问题。2.2 猜想2就在笔者准备放弃尝试承认这是硬件计算误差带来的问题时突然瞥见最后一个公式w使用了下面的计算逻辑Muls(outCastLocal[expAvgOffset_], outCastLocal[expAvgOffset_], stepSize_, dataCount); PipeBarrierPIPE_V(); Div(inCastLocal[varOffset_], outCastLocal[expAvgOffset_], inCastLocal[varOffset_], dataCount);我们通过下面这个公式来进行讲解在原本要计算的逻辑过程中应该先计算a tensor1/tensor2再计算value * a即先除后乘。然而在实际实现中写成了数学上“等价”的形式a value * tensor1然后计算a/tensor2先乘后除。在浮点数计算中由于精度限制运算顺序的改变可能导致不同的舍入误差二者在实际实现中并不完全等价也就有可能引入误差。而验证的方法非常简单直接将第1行和第3行代码行交换一下位置变成先除后乘Div(inCastLocal[varOffset_], outCastLocal[expAvgOffset_], inCastLocal[varOffset_], dataCount); PipeBarrierPIPE_V(); Muls(inCastLocal[varOffset_], inCastLocal[varOffset_], stepSize_, dataCount);再重新经过验证果然精度100%通过。3. 根因浮点运算中本应先除后乘但实际实现被写成了先乘后除。虽然数学上等价但在浮点运算中由于中间结果的舍入误差累积不同导致最终结果出现精度偏差。4. 解决方法调整w参数计算过程中l*m/(√vε)中的错误计算顺序先计算am/(√vε)再计算l*a与实际计算顺序保持一致避免浮点计算误差。5. 启发如果我们止步于99.9931%时不再细究就可能遇到在模型集群训练时模型loss跑飞的问题。小小的乘法顺序不同可能会导致几天的模型白白训练。浮点数数值敏感是个需要长时间投入研究的课题当出现了精度的细微差距时开发者也要敏感起来。可能你的计算逻辑看上去是等价的但是遇到问题时还是要看看CPU或者你的参考标杆是怎么处理的。