内容简介:点击上方“AI公园”,关注公众号作者:George Seif编译:ronghuaiyang
点击上方“AI公园”,关注公众号
作者:George Seif
编译:ronghuaiyang
不是所有的数据都是完美的。实际上,如果你拿到一个真实的完全均衡的数据集的话,那你真的是走了狗屎运了。大部分的时候,你的数据都会有某种程度上的不均衡,也就是说你的数据集中每个类别的数量会不一样。
我们为什么想要数据是均衡的?
在我们开始花时间做深度学习项目之前,非常重要的一点是需要理解为什么我们要做这个事情,确保我们的投入是值得的。当我们真正关心的是少数的类别的时候,类别均衡技术就是真正的必须的了。
比如说,我们想预测基于当前的市场情况,房子的属性,自己的预算,是否应该买房子。在这种情况下,如果我们买了,那么这是个正确的决定是非常重要的,因为这个是很大的一笔投资。同时,如果你的模型说不要买,而事实上需要买的话,这也没什么大不了的。你错过了这个,总是有其他的房子可以买的。但是如果买错了的话,那就是个大事了。
在上面的情况中,我们当然需要我们的少数“买”的类别要特别的准确,而“不买”的类别则无关紧要。但是在实际情况中,由于买的情况比不买的情况要少得多,我们的模型预测会偏向“不买”的类别,而“买”的类别的准确率则可能会很差。这就需要数据均衡了,我们可以让“买”类别的权重变大,来让“买”类别的预测更加准确。
但是如果我们对少数类别不关心怎么办呢?例如,我要做一个图像的分类,而你的类别的分布看起来是这样的:
第一眼看上去似乎数据均衡是有好处的。但是也许我们对那些少数的类别并不关心。也许我们的目的就是得到最高的准确率。在这种情况下,做数据均衡并没什么意义,因为大多数的准确率来自于包含了大量样本的类别中。第二,交叉熵的损失即使是在不均衡的数据的时候,也是趋向于得到最高的准确率。总的来说,我们的少数类别并没有对准确率有多少贡献,所以说,数据均衡并不需要。
综上所述,当我们遇到需要均衡数据的时候,有两个方法可以帮助我们办到:
权值均衡
权值均衡是在训练样本的时候,在计算loss的时候,通过权值来均衡数据的分布。正常情况下,每个类别在损失函数中的权值是1.0。但是有时候,当某些类别特别重要的时候,我们需要给该类别的训练样本更大权值。参考我们的买房的例子,由于“买”的类别的准确率非常的重要,训练样本中的这个类别应该对损失函数有更大的影响。
可以直接给对应的类别的样本的loss乘上一个因子来设定权值。在Keras中,我们可以这样:
import keras class_weight = {"buy": 0.75, "don't buy": 0.25} model.fit(X_train, Y_train, epochs=10, batch_size=32, class_weight=class_weight)
我们创建了一个字典,其中,“买”类别为75%,表示了占据了75%的loss,因为比“不买”的类别更加的重要,“不买”的类别设置成了25%。当然,这两个数字可以修改,直到找到最佳的设置为止。我们可以使用这种方法来均衡不同的类别,当类别之间的样本数量差别很大的时候。我们可以使用权值均衡的方式来使我们的所有的类别对loss的贡献是相同的,而不用取费力的收集少数类别的样本了。
另一个可以用来做训练样本的权值均衡的是Focal loss。如下所示,主要思想是这样:在数据集中,很自然的有些样本是很容易分类的,而有些是比较难分类的。在训练过程中,这些容易分类的样本的准确率可以达到99%,而那些难分类的样本的准确率则很差。问题就在于,那些容易分类的样本仍然在贡献着loss,那我们为什么要给所有的样本同样的权值?
这正是Focal loss要解决的问题。focal loss减小了正确分类的样本的权值,而不是给所有的样本同样的权值。这和给与训练样本更多的难分类样本时一样的效果。在实际中,当我们有数据不均衡的情况时,我们的多数的类别很快的会训练的很好,分类准确率很高,因为我们有更多的数据。但是,为了确保我们在少数类别上也能有很好的准确率,我们使用focal loss,给与少数类别的样本更高的权值。focal loss使用Keras是很容易实现的:
import keras from keras import backend as K import tensorflow as tf # Define our custom loss function def focal_loss(y_true, y_pred): gamma = 2.0, alpha = 0.25 pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred)) pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred)) return -K.sum(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1))-K.sum((1-alpha) * K.pow( pt_0, gamma) * K.log(1. - pt_0)) # Compile our model adam = Adam(lr=0.0001) model.compile(loss=[focal_loss], metrics=["accuracy"], optimizer=adam)
过采样和欠采样
选择合适的类别的权重有时候比较复杂。做一个简单的频率倒数可能有时候效果也不好。Focal loss有点用,但是仍然会对所有的正确分类的样本都做权值的下降。另外一个数据均衡的方法就是直接的采样。下面的图给出了一个大概的说明.
在图像的两边,蓝色的类别比橘黄色的类别的样本多得多。这种情况下,我们在预处理时,有两种选择。
欠采样意思是从多数的类别中只采样其中的一部分的样本,选择和少数类别同样多的样本。这种采样保持了该类别原来的数据分布。这很容易,我们只需要少用点样本就可以让数据变得均衡。
过采样的意思是我们复制少数类别中的样本,使得数量和多数样本一样多。复制操作需要保持少数样本的原有的数据分布。我们不需要获取更多的数据就可以让数据集变得均衡。采样的方法是一个很好的类别均衡的方法,如果你发现类别权值很难做而且效果不好的时候,可以试试!
本文可以任意转载,转载时请注明作者及原文地址。
请长按或扫描二维码关注我们
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 深度学习实战 图像数据集预处理总结
- 深度学习中超大规模数据集的处理
- 深度学习与人类语言处理-语音识别(part1)
- 深度学习实战 mnist数据集预处理技术分析
- 深度学习实战 cifar数据集预处理技术分析
- spring5 源码深度解析— IOC 之 循环依赖处理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。