橘智橘智
匀速小子
预计阅读时间:1分钟34秒

分类比赛如何获取公榜数据分布?

测榜入门技能

0
0

本文参考Kaggle的notebook:如何获取分类比赛的公榜数据分布?


这里主要说明一下核心代码的核心思路,在原文中是在第6个代码块。


import numpy as np
def cal_dist(score_list):
    err_list_all=[]
    for i in range(8):
        err_list=[]
        for j in range(8):
            if i==0 and j==0:
                err=0
            else:
                err=200*abs(i-j)/(i+j)
            err_list.append(err)
        err_list_all.append(err_list)
    err_all=np.array(err_list_all).T
    return np.linalg.inv(err_all)@np.array(score_list).reshape(-1,1)

我们就以比赛中的场景来说明吧。比赛是个8分类(或者说回归)任务,需要预测的是用户未来7天登录某款游戏的天数,TARGET可以是0到7的任意一个整数.比赛的评估指标是SMAPE:


def smape(y_true,y_pred):
    return 200*np.mean(np.abs(y_true-y_pred) / ( np.abs(y_true)+np.abs(y_pred) ) )

我们通过8次测榜得到了8个分数,那么如何知道每个类别在测试集中的占比呢?(这里的测榜是全预测为0-7中的某个数得到的分数)

online_score_list=[177.37,135.31,103.35,81.86,67.22,57.16,51.17,49.54]

根据小学知识可以知道,在大多数情况下,8个未知数需要有8个方程才能够解出来,所以我们现在需要找8个方程。


下面直接解读代码吧。我们可以知道的是一个样本TARGET为i,pred为j时候的损失SMAPE,由于这是一个8分类任务,所以可以有8*8=64种情况,这就是err_all这个矩阵。


SMAPE这种评估指标很特殊,它的y_true和y_pred交换一下,损失是一样的,所以矩阵是个对称矩阵,但是为了严谨,作者还是进行了矩阵转置的操作。


我们需要求的是每个类别在测试集的占比,占比求和是等于1的,我们假设这个占比矩阵为矩阵A,这是一个1行8列的矩阵。之前所说的64种情况就是8*8的矩阵,矩阵的第j列就是真实标签为i但是预测为j的损失,也是矩阵B.


那么矩阵A乘矩阵B表达的实际含义就是样本在A的占比情况下全部预测为某个类别的损失,也就是最终我们通过测榜得到的矩阵C.


A*B=C,那么怎么通过B和C求矩阵A呢?这就很简单了,A=A*B*B^{-1}=C*B^{-1},这就是最后一行代码的原因,函数最后返回的就是公榜的概率分布。不过由于数值计算存在一些不可避免的误差,所以最终求出的值也会存在误差,但是无伤大雅。





评论