zoukankan      html  css  js  c++  java
  • 转载,gini系数代码对应的公式

    引言

    大家在机器学习中经常会看到基尼系数的词汇,有时候在做比赛的时候,有些赛题的Scoring Metric就是基尼系数。我们去Google或者Baidu,得到的都是些不甚满意的经济学相关的解释。那么在机器学习、数据挖掘领域,基尼系数在实际的应用场景中又该如何解释以及如何实现呢?
    基尼系数的经济学解释

    首先,我们先看一张从Wiki上找来的经典图片:
    Gini
    基尼系数是一个分布不平衡程度的度量。它被定义成大小在0到1之间的比值:分子是均匀分布直线与洛伦兹曲线之间的面积,分母是均匀分布直线下方的面积。它是由意大利统计学家Corrado Gini提出并于1912年发表论文:”Variability and Mutability”。
    基尼系数的计算

    首先我们直接构造赛题结果:真实数据与预测数据

    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]

    1
    2

    参考Wiki上关于财富基尼系数计算公式的定义:
    In some cases, this equation can be applied to calculate the Gini coefficient without direct reference to the Lorenz curve. For example, (taking y to mean the income or wealth of a person or household): For a population uniform on the values yi, i = 1 to n, indexed in non-decreasing order (yi ≤ yi+1):
    G=1n(n+1−2∑ni=1(n+1−i)yi∑ni=1yi)(1)

    上面的话我通俗翻译下:在某些情况下,我们能够不直接参考洛伦兹曲线来计算出基尼系数。比如,(假设y代表某人或某个家庭的财富值):序列yi是非递减序列。那么序列yi就代表着从穷人到富人的排列顺序。因此基尼系数的公式就是:
    G=1n(n+1−2∑ni=1(n+1−i)yi∑ni=1yi)(1)

    那么这个公式我在这里将它拆分解释下:

    n代表y的个数
    ∑ni=1yi

    代表总财富值
    ∑ni=1(n+1−i)yi

    代表财富值的累计求和

    1.数据转换

    在这里我们并没有穷人到富人的数据序列,我们可以将预测值从小到大排列。

    # Sort the actual values by the predictions
    data = zip(actual, predictions)
    sorted_data = sorted(data, key=lambda d: d[1])
    sorted_actual = [d[0] for d in sorted_data]
    print('Sorted Actual Values', sorted_actual)

    1
    2
    3
    4
    5

    [out] Sorted Actual Values [0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1]

    1

    2.累计求和

    在这里我们对排序后的真实值累计求和:

    # Sum up the actual values
    cumulative_actual = np.cumsum(sorted_actual)
    cumulative_index = np.arange(1, len(cumulative_actual)+1)

    plt.plot(cumulative_index, cumulative_actual)
    plt.xlabel('Cumulative Number of Predictions')
    plt.ylabel('Cumulative Actual Values')
    plt.show()

    1
    2
    3
    4
    5
    6
    7
    8

    cum_sum
    上图显示的折线就与我们从wiki上找来的图片中的洛伦兹曲线相对应。
    3.Normalization

    接下来我们将数据Normalization到0,1之间。并画出45度线。

    cumulative_actual_shares = cumulative_actual / sum(actual)
    cumulative_index_shares = cumulative_index / len(predictions)

    # Add (0, 0) to the plot
    x_values = [0] + list(cumulative_index_shares)
    y_values = [0] + list(cumulative_actual_shares)

    # Display the 45° line stacked on top of the y values
    diagonal = [x - y for (x, y) in zip(x_values, y_values)]

    plt.stackplot(x_values, y_values, diagonal)
    plt.xlabel('Cumulative Share of Predictions')
    plt.ylabel('Cumulative Share of Actual Values')
    plt.show()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    normalization
    4.计算橙色区域面积

    我们使用线性代数库scipy,求得橙色区域面积:

    fy = scipy.interpolate.interp1d(x_values, y_values)
    blue_area, _ = scipy.integrate.quad(fy, 0, 1, points=x_values)
    orange_area = 0.5 - blue_area
    print('Orange Area: %.3f' % orange_area)

    1
    2
    3
    4

    [out] Orange Area: 0.189

    1

    5.最大可能的基尼系数

    前面我们是按照预测值对真实值排序,得到一个基尼系数;现在我们按照真实值给真实值排序,得到最大可能的基尼系数:

    cumulative_actual_shares_perfect = np.cumsum(sorted(actual)) / sum(actual)
    y_values_perfect = [0] + list(cumulative_actual_shares_perfect)

    # Display the 45° line stacked on top of the y values
    diagonal = [x - y for (x, y) in zip(x_values, y_values_perfect)]

    plt.stackplot(x_values, y_values_perfect, diagonal)
    plt.xlabel('Cumulative Share of Predictions')
    plt.ylabel('Cumulative Share of Actual Values')
    plt.show()

    # Integrate the the curve function
    fy = scipy.interpolate.interp1d(x_values, y_values_perfect)
    blue_area, _ = scipy.integrate.quad(fy, 0, 1, points=x_values)
    orange_area = 0.5 - blue_area
    print('Orange Area: %.3f' % orange_area)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    maxgini

    [out] Orange Area: 0.300

    1

    数据挖掘中的Scoring Metric的实现

    在这里我们封装好基尼系数的函数,可用来作为比赛中的打分函数。

    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_normalized(actual, pred):
    return gini(actual, pred) / gini(actual, actual)


    gini_predictions = gini(actual, predictions)
    gini_max = gini(actual, actual)
    ngini= gini_normalized(actual, predictions)
    print('Gini: %.3f, Max. Gini: %.3f, Normalized Gini: %.3f' % (gini_predictions, gini_max, ngini))

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    [out] Gini: 0.189, Max. Gini: 0.300, Normalized Gini: 0.630

    1

    总结

    关于Gini系数的pdf文章,请戳:传送门
    ---------------------
    作者:OraYang
    来源:CSDN
    原文:https://blog.csdn.net/u010665216/article/details/78528261
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    发明专利授权容易吗?
    No module named 'PyQt5.QtWebEngineWidgets' 解决方法
    Python可视化界面编程入门
    Python用户界面编程PyQt5的四种的布局方式
    cmd进入任何一个文件夹的步骤?
    cmd如何进入和退出Python编程环境?
    《C++ Primer Plus》16.3 标准模板库 学习笔记
    《C++ Primer Plus》16.2 智能指针模板类
    《C++ Primer Plus》16.1 string类 学习笔记
    Python错误和异常 学习笔记
  • 原文地址:https://www.cnblogs.com/Rvin/p/11127876.html
Copyright © 2011-2022 走看看