神经网络/模型训练Debug
深度模型的Debug与一般程序的Debug有很大的不同. 一般程序的Debug通常可以通过简单地打断点调试出来. 而深度模型通常会出现程序的所有模块都可以正常跑通, 但就是模型效果与正常情况相去甚远, 这种Debug就非常的困难.
尤其对于大模型来说, 一处"笔误"可能也会导致很大的问题.
因此, 这里总结常见的Bug以及Debug经验.
常见Bug
1. 某一部分参数梯度总为0
可能是程序里存在"笔误", 有一部分的参量并没有加入模型中进行运算
2. Loss不下降
(未完待续)
Debug经验
1. 检查激活函数的输入值
使用Relu系的激活函数时, 如果输入激活函数前的数值异常大, 那么可能导致之后的结果出现问题.
使用Sigmoid时, 如果输入激活函数前的数值远远超出了其激活范围(即[-1,1]), 也可能导致训练出现严重问题.
2. 检查梯度
- 检查梯度是否消失
- 检查梯度是否爆炸
具体方法:直接输出各个参数的梯度
def _print_grad(self, model):
'''Print the grad of each layer'''
for name, parms in model.named_parameters():
print('-->name:', name, '-->grad_requirs:',parms.requires_grad, ' -->grad_value:',parms.grad)
先输出该层参数是否存在梯度, 再输出梯度值. 这个函数应该放在梯度反向传播计算之后, 即loss.backward()之后.
3. 消融实验
如果一个深度模型中有多个模块, 可以使用消融实验的方法对每个模块进行测试.
这样可以先定位出问题出在哪个模块里, 即缩小bug的范围.
如果每个模块都有问题, 那么则应该去检查数据输入以及训练部分是否存在问题.
⭐️ 我觉得这各方法非常重要, 因为他能帮助定位bug的范围. 其实debug最大的难点就在于确定bug的位置.
4. 使用最短的时间
如果问题不是训练本身的精度不够等问题, 可以适当调整batch size的大小来加快训练.
这样可以提高debug效率.
5. 静下心来
遇到bug首先要静下心来想问题可能出现的地方, 然后一步步去排查.
最好是能将问题以及排查结果进行记录, 这样可以更好地分析问题所在.
切忌还没有想好问题就一遍遍地跑训练, 其实这样做是非常浪费时间的.
在很多次尝试后, 都没能够将bug排除也是很有可能遇到的事情, 这时候会非常烦躁, 不利于问题的分析. 建议先去完成其他的任务, 在冷静下来后再继续进行debug(本人亲测有效, 有时甚至第二天一开始就干掉了bug).
ps: 之后我会随着学习的深入, 不断进行更新~