踩坑日记:pytorch模型训练train模式和eval模式结果相差甚远?

如我在文中对相关术语和概念的描述错误或不准确,欢迎评论区指正!谢谢~


参考博文:
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↑)

如果对你的问题有帮助点赞支持哟,谢谢~

你可能感兴趣的:(pytorch,深度学习,transformer)