【问题标题】:How to build a lift chart (a.k.a gains chart) in Python?如何在 Python 中构建提升图(又名增益图)?
【发布时间】:2017-07-30 16:02:27
【问题描述】:

我刚刚使用 scikit-learn 创建了一个模型,该模型估计了客户对某些提议做出响应的可能性。现在我正在尝试评估我的模型。为此,我想绘制提升图。我理解提升的概念,但我很难理解如何在 python 中实际实现它。

【问题讨论】:

    标签: python machine-learning modeling evaluation


    【解决方案1】:

    您可以使用scikit-plot 包来完成繁重的工作。

    skplt.metrics.plot_cumulative_gain(y_test, predicted_probas)
    

    示例

    # The usual train-test split mumbo-jumbo
    from sklearn.datasets import load_breast_cancer
    from sklearn.model_selection import train_test_split
    from sklearn.naive_bayes import GaussianNB
    
    X, y = load_breast_cancer(return_X_y=True)
    X_train, X_test, y_train, y_test = train_test_split(X, y, 
    test_size=0.33)
    nb = GaussianNB()
    nb.fit(X_train, y_train)
    predicted_probas = nb.predict_proba(X_test)
    
    # The magic happens here
    import matplotlib.pyplot as plt
    import scikitplot as skplt
    skplt.metrics.plot_cumulative_gain(y_test, predicted_probas)
    plt.show()
    

    这应该会产生这样的情节:

    【讨论】:

      【解决方案2】:

      提升/累积收益图表不是评估模型的好方法(因为它不能用于模型之间的比较),而是在资源有限的情况下评估结果的一种方法。要么是因为对每个结果采取行动都需要成本(在营销场景中),要么你想忽略一定数量的有保证的选民,而只对那些处于观望状态的选民采取行动。如果您的模型非常好,并且对所有结果都具有很高的分类准确度,那么您不会从按置信度排序结果中获得太多提升。

      import sklearn.metrics
      import pandas as pd
      
      def calc_cumulative_gains(df: pd.DataFrame, actual_col: str, predicted_col:str, probability_col:str):
      
          df.sort_values(by=probability_col, ascending=False, inplace=True)
      
          subset = df[df[predicted_col] == True]
      
          rows = []
          for group in np.array_split(subset, 10):
              score = sklearn.metrics.accuracy_score(group[actual_col].tolist(),
                                                         group[predicted_col].tolist(),
                                                         normalize=False)
      
              rows.append({'NumCases': len(group), 'NumCorrectPredictions': score})
      
          lift = pd.DataFrame(rows)
      
          #Cumulative Gains Calculation
          lift['RunningCorrect'] = lift['NumCorrectPredictions'].cumsum()
          lift['PercentCorrect'] = lift.apply(
              lambda x: (100 / lift['NumCorrectPredictions'].sum()) * x['RunningCorrect'], axis=1)
          lift['CumulativeCorrectBestCase'] = lift['NumCases'].cumsum()
          lift['PercentCorrectBestCase'] = lift['CumulativeCorrectBestCase'].apply(
              lambda x: 100 if (100 / lift['NumCorrectPredictions'].sum()) * x > 100 else (100 / lift[
                  'NumCorrectPredictions'].sum()) * x)
          lift['AvgCase'] = lift['NumCorrectPredictions'].sum() / len(lift)
          lift['CumulativeAvgCase'] = lift['AvgCase'].cumsum()
          lift['PercentAvgCase'] = lift['CumulativeAvgCase'].apply(
              lambda x: (100 / lift['NumCorrectPredictions'].sum()) * x)
      
          #Lift Chart
          lift['NormalisedPercentAvg'] = 1
          lift['NormalisedPercentWithModel'] = lift['PercentCorrect'] / lift['PercentAvgCase']
      
          return lift
      

      要绘制累积收益图表,您可以使用下面的代码。

          import matplotlib.pyplot as plt
          def plot_cumulative_gains(lift: pd.DataFrame):
              fig, ax = plt.subplots()
              fig.canvas.draw()
          
              handles = []
              handles.append(ax.plot(lift['PercentCorrect'], 'r-', label='Percent Correct Predictions'))
              handles.append(ax.plot(lift['PercentCorrectBestCase'], 'g-', label='Best Case (for current model)'))
              handles.append(ax.plot(lift['PercentAvgCase'], 'b-', label='Average Case (for current model)'))
              ax.set_xlabel('Total Population (%)')
              ax.set_ylabel('Number of Respondents (%)')
          
              ax.set_xlim([0, 9])
              ax.set_ylim([10, 100])
          
              labels = [int((label+1)*10) for label in [float(item.get_text()) for item in ax.get_xticklabels()]]
          
              ax.set_xticklabels(labels)
          
              fig.legend(handles, labels=[h[0].get_label() for h in handles])
              fig.show()
      

      并可视化提升:

          def plot_lift_chart(lift: pd.DataFrame):
              plt.figure()
              plt.plot(lift['NormalisedPercentAvg'], 'r-', label='Normalised \'response rate\' with no model')
              plt.plot(lift['NormalisedPercentWithModel'], 'g-', label='Normalised \'response rate\' with using model')
              plt.legend()
              plt.show()
      

      结果如下:

      我发现这些网站可供参考:

      编辑:

      我发现 MS 链接的描述有些误导,但 Paul Te Braak 链接信息量很大。回复评论;

      对于上面的累积增益图表,所有计算均基于该特定模型的准确性。正如 Paul Te Braak 链接所指出的,我的模型的预测准确率如何达到 100%(图表中的红线)?最好的情况(绿线)是我们可以多快达到与红线在整个人口过程中达到的相同精度(例如,我们的最佳累积收益情景)。蓝色是如果我们只是随机选择总体中每个样本的分类。因此,累积收益和提升图表纯粹用于了解该模型(并且仅该模型)在我不打算与整个人群互动的情况下如何给我带来更大的影响。 p>

      我使用累积收益图表的一个场景是针对欺诈案例,我想知道有多少应用程序我们基本上可以忽略或优先考虑(因为我知道模型可以尽可能地预测它们)对于前 X百分。在这种情况下,对于“平均模型”,我改为从真正的无序数据集中选择分类(以显示现有应用程序是如何处理的,以及如何使用模型来确定应用程序类型的优先级)。

      因此,为了比较模型,只需坚持 ROC/AUC,一旦您对所选模型感到满意,就可以使用累积收益/提升图查看它对数据的响应情况。

      【讨论】:

      • 你为什么说不能用累积收益图表来比较不同的模型呢?在您提供的微软资源中,它说:“您可以将多个模型添加到提升图,只要模型都具有相同的可预测属性”。我想您可以使用 AUC(曲线下面积)将不同的曲线与 ROC 或 P-R 曲线进行比较,还是我错了?
      • @Tanguy,见上文,我在答案中添加了一些细节。
      • 即使在阅读了您的 cmets 和您指出的文章中的那些之后,我仍同意 @Tanguy 的观点,即使用升力曲线下的面积似乎是一种有效的比较方式,至少对于异常而言检测用例。您从 Paul Te Braak 链接到的文章比任何内容都更令人困惑,并且通过将 Y 轴命名为“准确度”而实际上是“灵敏度”,从而产生了一个不存在的问题。
      【解决方案3】:

      您也可以使用kds 包。

      对于累积收益图:

      # pip install kds
      import kds
      kds.metrics.plot_cumulative_gain(y_test, y_prob)
      

      示例

      # REPRODUCABLE EXAMPLE
      # Load Dataset and train-test split
      from sklearn.datasets import load_iris
      from sklearn.model_selection import train_test_split
      from sklearn import tree
      
      X, y = load_iris(return_X_y=True)
      X_train, X_test, y_train, y_test = train_test_split(X, y, 
      test_size=0.33,random_state=3)
      clf = tree.DecisionTreeClassifier(max_depth=1,random_state=3)
      clf = clf.fit(X_train, y_train)
      y_prob = clf.predict_proba(X_test)
      
      
      # CUMMULATIVE GAIN PLOT
      import kds
      kds.metrics.plot_cumulative_gain(y_test, y_prob[:,1])
      

      向导曲线将为模型提供最佳曲线。

      免责声明:我是这个包的作者

      【讨论】:

      • 嗨,Prateek,也许说你是这个包的开发者;)恭喜你有这么好的东西——我刚刚下载并立即喜欢它,干得好! :)
      • 谢谢你的建议,我会补充的。很高兴你喜欢这个包。
      猜你喜欢
      • 1970-01-01
      • 2023-02-03
      • 2015-02-08
      • 1970-01-01
      • 1970-01-01
      • 2020-09-26
      • 2015-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多