我刚刚使用scikit-learn创建了一个模型,该模型估计客户对某项优惠做出响应的概率。现在我想评估我的模型。为此,我想绘制提升图。我理解提升的概念,但我在Python中实际实现它时遇到了困难。
回答:
提升/累积收益图并不是评估模型的好方法(因为它不能用于模型之间的比较),而是评估结果的一种方式,特别是在资源有限的情况下。无论是因为每个结果的行动成本(在市场营销场景中),还是因为你想忽略一定数量的确定选民,只对那些犹豫不决的人采取行动。当你的模型非常好,并且对所有结果都有很高的分类准确性时,通过按置信度排序结果,你不会获得太多的提升。
import sklearn.metricsimport pandas as pddef 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()
结果看起来像这样:
我发现这些网站对参考很有用:
- https://learn.microsoft.com/en-us/sql/analysis-services/data-mining/lift-chart-analysis-services-data-mining
- https://paultebraak.wordpress.com/2013/10/31/understanding-the-lift-chart/
- http://www2.cs.uregina.ca/~dbd/cs831/notes/lift_chart/lift_chart.html
编辑:
我发现微软链接的描述有些误导,但Paul Te Braak的链接非常有信息量。为了回答评论;
对于上面的累积收益图,所有的计算都是基于该特定模型的准确性。正如Paul Te Braak链接所指出的,我的模型的预测准确性如何达到100%(图表中的红线)?最佳情况(绿线)是我们能多快达到红线在整个总体中实现的相同准确性(例如,我们的最佳累积收益情景)。蓝色是如果我们只是随机选择总体中每个样本的分类。所以累积收益和提升图完全是用来理解该模型(仅该模型)在不与整个总体互动的情况下如何给我带来更多影响的工具。
我使用累积收益图的一个场景是欺诈案例,我想要知道我们可以忽略或优先处理多少申请(因为我知道模型对它们的预测尽可能准确)对于前X百分比。在这种情况下,对于“平均模型”,我反而从真实的无序数据集中选择分类(以显示现有申请是如何被处理的,以及如何使用模型,我们可以优先处理某些类型的申请)。
因此,对于比较模型,只需使用ROC/AUC,一旦你对选择的模型满意,就使用累积收益/提升图来查看它对数据的反应。