分类比赛如何获取公榜数据分布?
测榜入门技能
本文参考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},这就是最后一行代码的原因,函数最后返回的就是公榜的概率分布。不过由于数值计算存在一些不可避免的误差,所以最终求出的值也会存在误差,但是无伤大雅。
评论
目录