Normalized Gini Coefficient

在github看到一个开源项目,deepFM,即https://github.com/ChenglongChen/tensorflow-DeepFM

代码中使用了Normalized Gini Coefficient评价指标。

这篇博客系统介绍了Normalized Gini Coefficient指标。https://blog.csdn.net/u010665216/article/details/78528261

我对文中一些公式和代码做一些补充说明。

1 基尼系数

文中

Gini

这里对公式做一下推导:

由基尼系数定义可知

G = \frac{S_{A}}{S_{A} + S_{B}}

由定积分与极限公式

基尼系数计算时将横纵坐标标准化为0到1

先以计算0到1区间y = x的面积为例。

这里可以知道实际对y的累加计算是,即

计算y = x的面积就是,将0到1分为n段,每段宽为1/n,高为yi,yi = i / n,因此用1/n乘以对y的累计求和来近似积分。

所以基尼系数可以如下计算:

这里除以\sum y_{i}是因为基尼系数横纵坐标要标准化为0到1。这里gini(x)积分就是B的面积。但是这里我有一个疑问,分子0到1的x的积分为什么不直接用1/2代替。

2 Normalized Gini Coefficient

文中的两个图,用第一个图橙色面积除以第二个图橙色面积,就是 Normalized Gini Coefficient。

 

但是找到的一些开源实现,却如下:

def gini(actual, pred):
    assert (len(actual) == len(pred))
    all = np.asarray(np.c_[actual, pred, np.arange(len(actual))], dtype=np.float) 
    all = all[np.lexsort((all[:, 2], -1 * all[:, 1]))]
    totalLosses = all[:, 0].sum() 
    giniSum = all[:, 0].cumsum().sum() / totalLosses  
    giniSum -= (len(actual) + 1) / 2.
    return giniSum / len(actual)


def gini_norm(actual, pred):
    return gini(actual, pred) / gini(actual, actual)

可以发现,代码中对预测样本是从大到小排序,而文中是从小到大排序。

实际上,Normalized Gini Coefficient还有一(几)种理解方式,即从大到小排列时,下面第一个图橙色面积除以第二个橙色面积:

附上从大到小排列时公式,这里A是橙色加蓝色面积,B是蓝色面积

上述两个方法从小到大排列和从大到小排列,有什么区别吗,我认为几乎没有区别。

验证如下:

import numpy as np


def gini(actual, pred):
    assert (len(actual) == len(pred))
    # np.c_是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等。
    all = np.asarray(np.c_[actual, pred, np.arange(len(actual))], dtype=np.float)  
    all = all[np.lexsort((all[:, 2], -1 * all[:, 1]))]
    totalLosses = all[:, 0].sum()  # 6.0  正样本个数
    giniSum = all[:, 0].cumsum().sum() / totalLosses  

    giniSum -= (len(actual) + 1) / 2.
    return giniSum / len(actual)


def gini1(actual, pred):
    assert (len(actual) == len(pred))
    # np.c_是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等。
    all = np.asarray(np.c_[actual, pred, np.arange(len(actual))], dtype=np.float)  
    all = all[np.lexsort((all[:, 2], all[:, 1]))]
    totalLosses = all[:, 0].sum()  # 6.0  正样本个数
    giniSum = all[:, 0].cumsum().sum() / totalLosses 

    giniSum = (len(actual) + 1) / 2. - giniSum
    return giniSum / len(actual)


def gini_norm(actual, pred):  
    return gini(actual, pred) / gini(actual, actual)


def gini_norm1(actual, pred):  
    return gini1(actual, pred) / gini1(actual, actual)


# 针对main代码的注释
if __name__ == '__main__':
    predictions = [0.9, 0.3, 0.8, 0.75, 0.65, 0.6, 0.78, 0.7, 0.05, 0.4, 0.4, 0.05, 0.5, 0.1, 0.1]
    actual = [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    print(gini_norm(actual, predictions))  # 0.6296296296296299  
    print(gini_norm1(actual, predictions))  # 0.6296296296296295  

 

3 参考文献&延伸阅读

https://www.kaggle.com/c/porto-seguro-safe-driver-prediction/overview/evaluation

https://blog.csdn.net/u010665216/article/details/78528261

https://www.kaggle.com/batzner/gini-coefficient-an-intuitive-explanation

https://www.kaggle.com/cppttz/gini-coefficient-an-explanation-with-math/

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忧郁的常凯申

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值