Pytorch的nn.CrossEntropyLoss()的weight使用场景:
现实工程中,经常出现以下情况:
label标注的0-3四类,0类的比重过大,1类其次,2,3类都很少,怎么使用loss的weight来减轻样本不平衡问题?weight参数该如何设置?
此时,
比如设置loss weight代码,(0.1、 0.8、 1、 1 )四个类别的比例是我自己设置的)
weight=torch.from_numpy(np.array([0.1, 0.8, 1.0, 1.0])).float()
criterion = nn.CrossEntropyLoss(weight=weight).to(device)
如何设置weight才能提升分类的性能。
一般情况下,假 n u m m a x num_{max} nummax 表示数量最多类别的样本个数, n u m m i n num_{min} nummin表示数量最少类别的样本个数,当 n u m m a x n u m m i n ≤ 10 \frac{num_{max}}{num_{min}}\leq10 numminnummax≤10的时候,是不需要考虑样本不平衡问题的。
当它们的比值大于(或者远远)10的时候是要考虑样本不平衡问题,为什么要考虑样本不平衡问题呢?接下来我们来解释一下:
假设有三类,标签类别为0, 1, 2,所对应的样本数量为100000,100, 10。
此时就有一个问题,在网络学习的过程中,假设预测出来的标签都是0(100000个样本),它的准确率为 100000 100110 ≈ 0.9989 \frac{100000}{100110}\approx0.9989 100110100000≈0.9989 ,将近100%,所以模型就会朝着拟合标签0的方向更新,导致对标签0的样本过拟合,对其它两个类别的样本欠拟合,泛化能力很差。
那 nn.CrossEntropyLoss()的weight如何解决样本不平衡问题的。
当类别中的样本数量不均衡的时候,
对于训练图像数量较少的类,你给它更多的权重,这样如果网络在预测这些类的标签时出错,就会受到更多的惩罚。
对于具有大量图像的类,您可以赋予它较小的权重。那我们如何选择weight的值呢?
一般有两种方式(建议第二种):
第一种,用样本数的倒数当做权重。即 1 C l a s s S i z e \frac{1}{ClassSize} ClassSize1 。
用上述的三分类表示就是, w e i g h t = [ 1 100000 , 1 100 , 1 10 ] weight=[\frac{1}{100000}, \frac{1}{100}, \frac{1}{10}] weight=[1000001,1001,101] 。之前测试过几次,这种方式会造成分类准确率下降。
第二种,Max(Numberof occurrences in most common class) / (Number of occurrences in rare classes)。即用类别中最大样本数量除以当前类别样本的数量,作为权重系数。
用上述的三分类表示就是, w e i g h t = [ 100000 100000 , 100000 100 , 100000 10 ] = [ 1.0 , 1000 , 10000 ] weight=[\frac{100000}{100000}, \frac{100000}{100}, \frac{100000}{10}]=[1.0, 1000, 10000] weight=[100000100000,100100000,10100000]=[1.0,1000,10000]。
代码表示如下:
weights = [1.0, 1000, 10000]
class_weights = torch.FloatTensor(weights).to(device)
criterion = nn.CrossEntropyLoss(weight=class_weights)