• (完美解决)为什么在train/val/test数据集上用train模式效果都很好,但是在eval模式下全部很差


    背景

    这个东西,其实是一个玄学。我已经第二次遇到这个问题了。

    第一次遇到的时候就很头疼,那次我不知道是怎么地莫名奇妙的解决了。这次又来一次,没有办法莫名奇妙了。只能思考如何解决。

    我这次背景是:模型主体使用了CNN架构,出现这个问题。啥问题呢?在train数据集上,使用train模式的时候准确率很高,然后用eval模式在val数据集上测试,发现效果特别差。

    第一反应是什么?过拟合对不对!所以我用eval模式在train数据集上测试,发现效果特别差!!!

    结论:不是过拟合,就是eval模式和train模式的问题。所以进一步验证,在train模式下,val/test数据集上测试效果都不错。

    解决思路

    我的情况是这样的,我不算是自己设计的网络,而是官方的网络,然后我只是对层数进行删减,框架是保留的。所以网上说的,1. 不要同时使用dropout和batchnormalization 在我这里不适用,毕竟是官方网络架构,本身没有问题。我这个网络架构,他是在卷积层后面,平均池化,然后dropout,然后线性层分类。其他地方没有使用dropout,大家可以对照下自己的网络结构,也按照这个思路设计,从而有一个参考。

    由于是官方网络,2. 不同地方调用了同一个batchnormalization 对我也不适用,因为官方网络不会有这个错误。不过,话说,这个调用同一个,会有这么大影响嘛?我真没试过。

    也有人说,3. 输入数据没有归一化 ,如果是这个问题,那为什么train模式下对train/val/test效果都可以呢?

    终极办法

    要明白,train和eval只有一个区别,那就是dropout和batch normalization在train/eval模式下工作方式不一样。所以,上面两个解决思路也的确是围绕这个在展开。

    在train模式下好,eval模式下差,我们可以理解为:train模式下,最后一层得到的那一堆向量好,eval得到的那一堆向量差,从而逐步往前推。

    batch normalization的一个好处就是使用过后,数据会服从均为0,方差为1的正态分布,比较稳定,从而使得模型比较好训练。

    因此,一个简单的对比就是,你在你的模型训练了好几轮,觉得效果不错了之后,停下来,选择几个训练集数据,比如5个,分别在train模式和eval模式下,打印他们输入,中间层以及结尾的结果,这个你自己看着办即可。

    至于打印什么结果,当然不是那些tensor,没有看得懂,而是打印他们的均值和方差。

    x.mean()
    x.var()
    
    • 1
    • 2
    #数据1
    1.4886/29791.4102#输入
    0.0249/0.6548  0.0215/0.3354#中间某层
    前面是eval模式的mean/var,后面是train模式
    0.4258/13.0988 0.1238/12.9480#中间某层
    
    #数据2
    0.6043/751.1927 
    0.0119/0.0104 0.0333/0.3308 
    0.4165/7.9723 0.2913/14.2297
    #数据3
    1.7033/34862.4297
    0.0267/0.7132 0.0223/0.3357
    0.4337/11.9446 0.1300/12.6917
    #数据4
    0.3590/40.7517 
    0.0099/0.0007 0.0708/0.3518
    0.4294/8.2139 0.4683/15.1485
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    不管怎么说吧,首先引人注目的就是,我的4个数据,输入的均值和方差都特别不一样,尤其是方差,3万多的方差,吓死。之前没有打印,说句实话我还不知道。

    然后就是中间层1:我们发现,train模式下,其很稳定。均值大概就在0.02/0.03的样子,只有数据4有点反常,0.07。然后方差,他们都稳定在0.3的样子。

    反观eval模式下,中间层1抖来抖去的。

    中间层2,eval模式下,均值倒是很稳定,但是方差不稳定。train模式下,均值有点抖动,但是方差稳定。

    总的来说,我们的数据输入方差很大,然后train模式和eval模式各层结果差别显著。

    结论

    前者数据输入我们可以处理,train模式和eval模式差别很大我们只能干看着,没有办法处理哈哈。

    结论:

    我们将数据进行预处理,进行归一化,前面我们不是否定了归一化嘛?又屈服了?对的哈哈。我们实打实地看到了,输入方差贼大。

    我当时没有归一化,因为我怕归一化会损失我地输入数据的一些细节。因为我的输入并不是真实世界的图片,里面的一些数字是有含义的,我怕归一化之后破坏了。

    怎么归一化?可以对图片的各个channel进行z-标准化,也就是batch normalization那样。

    成功了,同时发现,归一化之后训练得很快!!!之前要3个epoch收敛,现在1个epoch就差不多收敛了。牛逼。


    完结撒花

  • 相关阅读:
    部署k8s集群-docker
    图解LeetCode——1235. 规划兼职工作(难度:困难)
    Verilog编程中数据对齐问题_内插滤波器
    智慧导览|智能导游系统|AR景区导览系统|景区电子导览
    Go 语言控制台输入&生成随机数
    JCF之List集合实现——Vector
    ai语音机器人工作的原理流程电销机器人部署
    深度学习_2_数据处理
    Springcloud之OAuth2
    node微信小程序登录实现登录
  • 原文地址:https://blog.csdn.net/qq_43391414/article/details/125991435