model.eval()

pytorch中model.eval()会对哪些函数有影响?

pytorch中model.eval()会对哪些函数有影响?

答:将BN和dropout这些训练和测试时行为不同的层切换到test mode。

Dropout训练和推理时的差异

众所周知,dropout是训练的时候将某层的神经元输出以 $p$(如10%)的概率随机置为零,以减缓过拟合。那么测试时呢?

为了保证测试时每次推理的一致性,肯定是不能再随机让神经失活了,那什么都不做,让所有神经元都按正常输出值原样输出可以嘛?

从训练和测试时的输出值尺度一致性来看,答案显然是否定的。设每个神经元原始输出的绝对值均值为 $x$ ,则该层训练时dropout后每个神经元输出的绝对值均值为 $(1-p)x$ ,如果测试时简单地让所有神经元都按正常输出值原样输出,则输出的绝对值均值为 $x$ ,导致训练和测试的不一致。

因此,带dropout的层,测试时的行为是让所有神经元都输出,但输出值要从原始的 $x$ 变成 $(1-p)x$ 。

当然,也可以在训练的时候就除以$(1-p)$,这样训练时dropout后每个神经元输出的绝对值均值就是$x$,测试的时候直接简单地做恒等映射输出就行,速度更快。

torch官方使用的是这种实现:

BatchNorm测试时统计量怎么来

Batch Normalization训练时,使用的均值和方差统计量是从同batch数据的同一特征维度统计而来。

而测试时,为了保证每个测试点的预测输出不受batch内其他数据影响,肯定得采用固定的统计量,这个统计量从何而来呢?

直观的想法是再过一遍整个训练集,在整个训练集上估计均值和方差,但在数据多的时候,每次在测试之前都要过一遍整个训练集超级费时:

因此,我们需要一个近似的在训练时估计全局统计量分布的办法。这个统计量要满足两个要求:

  1. 尽量反映整个训练集的分布;
  2. 尽量使用模型训练结束或者即将结束时的权重来计算,以便和测试时行为一致。

考虑到这两个要求,是不是想起了SGD里的momentum?采用训练时指数滑动平均的方式就可以得到测试时用的统计量,参考torch的官方文档:

model.eval()影响大模型吗

我们已经厘清了model.eval()对dropout层和batch norm层的影响,那么model.eval()影响大模型吗这个问题就等价于:大模型用batch norm和dropout吗?

首先,大模型用的都是layer norm, batch norm显然是不存在的。那么大模型开dropout吗?

先明确一下dropout的位置,大多数transformer的实现(尤其是类gpt的decoder模型中)只在self-attention的softmax概率之后使用dropout,相应的失活概率$p$ 超参数attention_dropout。

而在LLaMA、Mistral这些常见的开源大模型中,attention_dropout都被设为0,也就是实际上不使用dropout,model.eval()对这些不开dropout的大模型实际上没有影响