多标签分类中存在类别不平衡的问题,想要尝试用focalloss损失函数,但是网上很少有多标签分类的损失函数设计,终于在kaggle上别人做的keras下的focalloss中举例了多标签问题:
Focalloss for Keras 代码和例子如下:

Focal loss主要思想是这样:在数据集中,很自然的有些样本是很容易分类的,而有些是比较难分类的。在训练过程中,这些容易分类的样本的准确率可以达到99%,而那些难分类的样本的准确率则很差。问题就在于,那些容易分类的样本仍然在贡献着loss,那我们为什么要给所有的样本同样的权值?
这正是Focal loss要解决的问题。focal loss减小了正确分类的样本的权值,而不是给所有的样本同样的权值。这和给与训练样本更多的难分类样本时一样的效果。在实际中,当我们有数据不均衡的情况时,我们的多数的类别很快的会训练的很好,分类准确率很高,因为我们有更多的数据。但是,为了确保我们在少数类别上也能有很好的准确率,我们使用focal loss,给与少数类别的样本更高的权值。focal loss使用Keras是很容易实现的:

from keras import backend as K
import tensorflow as tf

def KerasFocalLoss(target, input):
    
    gamma = 2.
    input = tf.cast(input, tf.float32)
    
    max_val = K.clip(-input, 0, 1)
    loss = input - input * target + max_val + K.log(K.exp(-max_val) + K.exp(-input - max_val))
    invprobs = tf.log_sigmoid(-input * (target * 2.0 - 1.0))
    loss = K.exp(invprobs * gamma) * loss
    
    return K.mean(K.sum(loss, axis=1))

# 这个例子就是多标签的情况
Y_true = np.array([[0, 1, 0, 1, 0], [1, 0, 1, 0, 1]])
Y_pred = np.array([[0.1, 0.2, 0.3, 0.4, 0.5], [0.6, 0.7, 0.8, 0.9, 1]], dtype=np.float32)
print(K.eval(KerasFocalLoss(Y_true, Y_pred)))

当然文章里面还拓展了一下pytorch的focalloss设计,这里不搬运了。

这个代码里面没有加入alpha权重,我想实现一下:

数据挖掘中的多标签分类问题 多标签分类focal loss_权值


数据挖掘中的多标签分类问题 多标签分类focal loss_数据挖掘中的多标签分类问题_02


使用FL可以改善单个类别中正负样本的不平衡,提高难挖掘样本的分类精度,计算每个类别的权重W。使阳性病例数越多的疾病,权重越小,以平衡各类别之间的数据倾斜程度。因此,使用W和FL的乘积作为最终的损失函数,可以同时解决单类正负样本不平衡和多类数据偏斜的问题

#多标签版本
from tensorflow.keras import backend as K
import tensorflow as tf
import numpy as np

def KerasFocalLoss(target, input, Num):#Num为样本数量
    
    gamma = 2.
    input = tf.cast(input, tf.float32)
    
    max_val = K.clip(-input, 0, 1)
    loss = input - input * target + max_val + K.log(K.exp(-max_val) + K.exp(-input - max_val))
    invprobs = tf.compat.v1.log_sigmoid(-input * (target * 2.0 - 1.0))
    loss = K.exp(invprobs * gamma) * loss
    W = 1/np.log(Num)
    W = tf.cast(W, tf.float32)
    we_loss = tf.compat.v1.matmul(loss, W)
    
    return K.mean(K.sum(we_loss, axis=1))