处理不平衡数据
我们在进行机器学习和深度学习的时候,常常会遇到样本不均衡的问题,解决样本不均衡的问题常常有以下几种方法,达到平衡数据集:
- 过采样少数类
- 降采样多数类
- 合成新的少数类
- 调整类权重(误判成本)
这篇文章就讲如何通过修改交叉熵loss调整类权重
交叉熵误差
交叉熵公式如下
E=-\sum_{k}t_{k}log&space;y_{k}" title="E=-\sum_{k}t_{k}log y_{k}
这里,log表示以e为底数的自然对数。y_k是神经网络的输出,t_k是正确的标签。并且,t_k中只有正确的标签的索引为1,其他均为0(one-hot表示)。用mnist数据举例,如果是3,那么标签是[0,0,0,1,0,0,0,0,0,0],除了第4个值为1,其他全为0。
因此,上公式实际上只计算对应正确的标签的输出的自然对数,交叉熵误差的值是由正确的标签所对应的输出结果决定的。
在tensorflow里面,是用
tf.nn.softmax_cross_entropy_with_logits(logits=prediction,labels=y)
来计算交叉熵的。predicttion就是神经网络最后一层的输出,y就是实际的标签。
带权重的交叉熵loss
那么现在我们修改交叉熵loss的权重,要增加少数类的分错的权重,就是在交叉熵的公式里面对应的少数类乘上一个系数:
E = -\sum_{k}\alpha \cdot t_{k} \cdot \log y_{k} \left(
\begin{pmatrix}
\alpha = n (n > 1) \text{ if } k = i \
\alpha = 1 \text{ if } k \neq i
\end{pmatrix}
\right)
假设k类里面,第i类是少数类,为了加大分错第类的成本,在交叉熵上给第i类乘以一个大于1的系数,这样如果分错第i类的话,交叉熵loss就会增加。
下面,就用一个二分类的例子的代码来说明一下,以下是用tensorflow来举例。
在硬盘故障预测里面,由于损坏的硬盘数量远远小于健康硬盘的数量,样本极其不均衡,所以通过修稿交叉熵的loss视图体改算法的准确率。
假设健康硬盘样本的标签为[1,0],损坏硬盘样本的标签为[0,1],即在标签中第一个索引为1的是健康硬盘的样本,第二个索引为1的是损坏的样本。
假设在网络中,最后一层输出的结果是prediction,我们要先对prediction做一个softmax,求取输出属于某一类的概率:
yprediction = tf.nn.softmax(prediction)
然后给实际标签乘上一个系数,健康的样本保持系数1不变,损坏样本乘上系数10,这样健康样本的标签就变为[1,0],损坏样本的标签就变为[0,10],再计算交叉熵loss:
coe = tf.constant([1.0,10.0])
y_coe = y*coe
loss = -tf.reduce_mean(y_coe*tf.log(yprediction))
这样就达到了修改交叉熵loss增大分错损坏样本的成本的目的。这时候公式就变为:
E = -\sum_{k}\alpha \cdot t_{k} \cdot \log y_{k} \left(
\begin{pmatrix}
\alpha = 1 \text{ if } k = \text{healthDisk} \
\alpha = 10 \text{ if } k = \text{failureDisk}
\end{pmatrix}
\right)
tensorflow官方的权重交叉熵
tf.nn.weighted_cross_entropy_with_logits(labels,logits, pos_weight, name=None)
参考文献
https://blog.csdn.net/mao_xiao_feng/article/details/53382790
https://www.svds.com/learning-imbalanced-classes/
http://scikitlearn.org/stable/modules/generated/sklearn.utils.class_weight.compute_class_weight.html
深度学习入门-基于python的与实现 by 斋藤康毅