如我在文中对相关术语和概念的描述错误或不准确,欢迎评论区指正!谢谢~
参考博文:
Pytorch 查看模型参数_happyday_d的博客-CSDN博客_pytorch查看模型参数
https://www.jb51.net/article/189288.htm
最近在利用pytorch进行transformer模型训练的时候发现,明明训练的时候loss已经降到非常低、在调试模式下结果也十分理想,在测试集上生成的结果却非常离谱,无论是分类结果还是回归结果都不符合预期,以下通过整个调试过程阐述产生这种现象可能的原因,希望能够帮到你:
【本文运行环境:ubuntu16.04 + vscode 语言:python】
1、排查训练的模型加载是否有问题:
最直观的方式是将加载进来的模型权重参数打印出来看一看,正常情况下只要模型路径正确且模型确实成功加载了,在两种模式下的权重参数应该没有区别。
for parameters in net.parameters():
print(parameters)
2、模型调参和反复训练尝试:
在这一项尝试中发现有两种途径能让问题得到一定程度的解决:
- 在低loss以后依然持续训练(显然这个方法有点呆,也不符合训练需求)
- 增加transformer模型中多头注意力机制的头数(类似CNN中的多通道,本质上是增加了编解码层的参数)
多次实验后发现这两种途径在该问题虽然有一定的缓解作用,但是并不可靠。
3、train模式和eval模式的核心区别:
eval模式和train模式不同之处在于Batch Normalization和Dropout。Dropout比较简单,在train时会丢弃一部分连接,在eval时则不会。Batch Normalization,在train时不仅使用了当前batch的均值和方差,也使用了历史batch统计上的均值和方差,并做一个加权平均(momentum参数)。在test时,由于此时batchsize不一定一致,因此不再使用当前batch的均值和方差,仅使用历史训练时的统计值。
经过查阅,train和eval模式有以下区别:
- eval模式时屏蔽了网络的Batch Normalization层和Dropout层的作用
- train模式包含 Batch Normalization层和Dropout层 的作用
由于自己使用的网络结构中并没有使用batch Normaization而是采用layer Normalization,因此排除了BN导致差异的可能性。
结合2中的现象总结,其实此时训练的网络虽然看似loss很低,但其实是欠拟合的,网络的神经元本身就还不足以表征所有的深层次特征,因此使用dropout和不使用dropout会产生很大的区别,
建议的方案是:
- 降低dropout的比率(dropout↓ /
dropout) - 同时增加多头注意力机制的头数(head↑)
如果对你的问题有帮助点赞支持哟,谢谢~