sklearn(十)多标签问题如何获取label,设置固定阈值,还是选择topn作为最终预测结果?

背景:nlp模型,基于bert预训练模型做的fine-tuning,用来多文本的多标签任务,一个文本会有多个标签。

预习知识:

1.分类层后面添加sigmod函数:

经过sigmod+互信息输出的结果是伯努利分布:p(y1|x)  p(y2|x)

softmax输出的结果是多项分布 p(y1,y2…|x)

对于贰分两类问题:

softmax输出的两个值,相加为1。比如(0.3,0.7)表示是的概率为0.7,否的概率为0.3

对于sigmod来说,也得到2个值,不过没有可加性,两个值均为0到1的某个数,对于一个值p来说,1-p是它对应的另外一个概率。比如(0.4,0.8),sigmod认为输出第一位的概率为0.4,第一位不为1的概率为0.6,输出为第二位的概率为0.8,不为第二位的概率为0.2.

分类问题:类别之间是互斥的。

多标签问题:类别之间不要求互斥,是否属于当前类别,跟别的类别没有关系。

多分类用softmax:归一化指数函数

因为多分类最终只能属于一个类别,所以要将分类层的输出用softmax得出每个类的相对概率。

多标签用sigmod:

一个样本可能属于多个类别,只能得出样本是不是某个类别的概率,跟它是不是其它类别没关系。

1.多标签模型的损失函数介绍:

1. BCELoss

该类主要用来创建衡量目标和输出之间的二进制交叉熵的标准。用法如下:
torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')

参数:

  • weight,表示对loss中每个元素的加权权值;
  • reduction, 指定输出的格式,包括'none','mean','sum';
  • 其它两个参数一般不推荐使用;

形状:

  • input,(N, *);
  • target,(N, *);
  • output,标量,当reduction为'none'时,为(N, *)。

计算

当reduction参数为'none',即对计算结果不进行处理时,loss可以表示为,

其中,

这里N为batch size。如果reduction参数不为'none'时,

这里需要注意的是target的值必须为0或1。

 

 

 

2. BCEWithLogitsLoss

这个loss类将sigmoid操作和与BCELoss集合到了一个类。
用法如下:
torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='mean', pos_weight=None)

参数:

  • weight (Tensor),针对每个loss元素的加权权值;
  • reduction (string), 指定输出的格式,包括'none','mean','sum';
  • pos_weight (Tensor),正样例的权重,必须为长度为类别数量的向量,主要可用来处理类别不均衡情形。
  • 其它两个参数一般不推荐使用;

形状:

  • input,(N, *);
  • target,(N, *);
  • output,标量,当reduction为'none'时,为(N, *)。

计算过程与BCELoss类似,除了增加一个sigmoid层,

3. binary_cross_entropy_with_logits

该函数主要度量目标和输出之间的二进制交叉熵。与第2节的类功能基本相同。
用法如下:
torch.nn.functional.binary_cross_entropy_with_logits(input, target, weight=None, size_average=None, reduce=None, reduction='mean', pos_weight=None)
其参数与BCEWithLogitsLoss基本相同。

2.如何确定模型的预测结果

先看一个模型预测的结果,有三个label:

[0.8806893229484558, 0.03691115230321884, 0.03341011703014374]

这个list的索引就是对应的标签label,是第0个标签的概率0.8806893229484558,同理以此类推。是否为某一个标签的概率不完全一致,这个概率跟各个标签样本比例有关系,样本占比大的标签,是这个标签的阈值大一些。曾经简单统计过训练样本的占比跟测试集预测得分的均值情况,二者走势大致一致。至于凸起点,通过观察测试样本,这些标签类别较为容易识别,或者说这个标签跟其他标签相比,有自己独特的属性,可区别于其他标签,所以这些标签虽然训练样本占比小,但是他们的预测得分为真平均值较高。

在计算模型准确率时,需要输入如下形式,也就是说需要将0.88这种概率转为0或者1,那么怎么划分,是一个关键问题,常见的有按照阈值划分、取topn划分。接下来思考思考这两个方式的合理性。

predicted_labels = [[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[1,0,1,0,1]]
true_labels      = [[1,1,0,0,1],[1,0,0,1,1],[1,0,0,0,1],[1,1,1,0,1],[1,0,0,0,1],[1,0,0,0,1]]

1.阈值问题:

这个阈值没有实际意义,添加它,为了调整准招率。

2.topn的问题:

这个n为变量,top没有实际意义,有它,为了调整准招率的阈值

3.如何评估多标签模型

用于多标签,多类别分类的最流行的准确性矩阵是:

  • 海明得分
  • 汉明损失
  • 子集精度

以上三个指标的计算代码:

def hamming_score(y_true, y_pred, normalize=True, sample_weight=None):
    '''
    Compute the Hamming score (a.k.a. label-based accuracy) for the multi-label case

    '''
    acc_list = []
    for i in range(y_true.shape[0]):
        set_true = set( np.where(y_true[i])[0] )
        set_pred = set( np.where(y_pred[i])[0] )
        #print('\nset_true: {0}'.format(set_true))
        #print('set_pred: {0}'.format(set_pred))
        tmp_a = None
        if len(set_true) == 0 and len(set_pred) == 0:
            tmp_a = 1
        else:
            tmp_a = len(set_true.intersection(set_pred))/\
                    float( len(set_true.union(set_pred)) )
        #print('tmp_a: {0}'.format(tmp_a))
        acc_list.append(tmp_a)

    return  { 'hamming_score' : np.mean(acc_list) , 
              'subset_accuracy' : sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None), 
              'hamming_loss' : sklearn.metrics.hamming_loss(y_true, y_pred)}

4.使用多标签损失函数BECwithlogistloss可能会遇见的问题:

1.RuntimeError: Found dtype Long but expected Float

说明此时需要float型数据,但识别到long型数据,此时需要对入参和出参做一下类型转换
关键的两行代码:

output=output.to(torch.float32)
target=target.to(torch.float32)

例子:

output =net(input)
target = variable(t.arange(0,10))

#the point
output=output.to(torch.float32)
target=target.to(torch.float32)

criterion = nn.MSELoss()
loss = criterion(output,target)

net.zero_grad()
print("反向传播之前conv1.bias的梯度")
print(net.conv1.bias.grad)
loss.backward()          #此处疑难杂症  先跳过
print("反向传播之后conv1.bias的梯度")
print(net.conv1.bias.grad)

参考:

1.损失函数:https://www.jianshu.com/p/0062d04a2782

 

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值