将连续模型概率得分转换为分类评级
Converting Continuous Model Probability Score to a Categorical Rating
我有一个经过训练的标准 xgboost 分类模型,现在可以预测概率分数。但是,为了使用户界面更简单,我想将此分数转换为 5 星评级方案。 IE。离散化分数。
推导此量化阈值的智能方法是什么,以便高评分代表具有高置信度的高概率得分?
例如,我正在考虑生成置信区间以及预测并将高置信度高分分组为 5 星。高置信度低分作为 1 星。高置信度中高分如 4 星等。
你可以使用Pandas.cut()
方法:
In [62]: np.random.seed(0)
In [63]: a = np.random.rand(10)
In [64]: a
Out[64]: array([0.5488135 , 0.71518937, 0.60276338, 0.54488318, 0.4236548 , 0.64589411, 0.43758721, 0.891773 , 0.96366276, 0.38344152])
In [65]: pd.cut(a, bins=np.linspace(0, 1, 6), labels=[1,2,3,4,5])
Out[65]:
[3, 4, 4, 3, 3, 4, 3, 5, 5, 2]
Categories (5, int64): [1 < 2 < 3 < 4 < 5]
更新: .
演示:
In [117]: a
Out[117]: array([0.6 , 0.8 , 0.85, 0.9 , 0.95, 0.97])
In [118]: pd.cut(a, bins=np.linspace(a.min(), a.max(), 6),
labels=[1,2,3,4,5], include_lowest=True)
Out[118]:
[1, 3, 4, 5, 5, 5]
Categories (5, int64): [1 < 2 < 3 < 4 < 5]
假设一个class化问题:either 1's or 0's
计算 ROC 曲线的 AUC 时,您按模型预测对 "events" 进行排序。所以在顶部,您很可能会有很多 1,并且在排序列表中越往下,0 就越多。
现在假设您尝试确定分数的阈值 "5"
。
您可以计算您愿意承受的数据中 0 的相对百分比。
给出以下 table:
item A score
1 1 0.99
2 1 0.92
3 0 0.89
4 1 0.88
5 1 0.74
6 0 0.66
7 0 0.64
8 0 0.59
9 1 0.55
如果我希望 "user score" "5"
的误报率为 0%,我会确定“5”的阈值高于 0.89
如果我可以容忍 10% 的误报,我会确定阈值高于 0.66
。
您可以对每个阈值执行相同的操作。
在我看来,这是一个 100% 的商业决策,选择这些阈值的最明智的方法是根据您对用户的了解。
如果用户期望 "5"
是对 class(生死攸关的情况)的完美预测,则误报率为 0%。
我为此研究了多种解决方案并制作了 V0 解决方案的原型。解决方案的主要要求如下:
随着评级水平的提高(5 星优于 1 星),误报数必须减少。
用户不必手动定义得分概率的阈值,阈值是自动导出的。
阈值源自某些更高级别的业务需求。
阈值源自标记数据,并可在发现新信息时重新导出。
考虑的其他解决方案:
- 基于置信区间的评级。例如,您可能有 0.9 的高预测分数但低置信度(即大置信区间)和 0.9 的高预测分数但高置信度(即小区间)。我怀疑我们可能希望后者成为 5 星候选人,而前者可能是 4*?
- 识别ROC曲线的凸凹度以识别最大值点
- 利用约登指数确定最佳点
最终解决方案 - 使用一组给定的业务需求(一组与每个星级相关联的 FPR)对 ROC 曲线进行采样,然后转换为阈值。
注意:这可行,但假设精度曲线有些单调,但情况可能并非总是如此。我通过将问题表述为优化问题来改进解决方案,其中评级阈值是自由度,objective 函数是每个评级桶之间转换率的线性度。我相信您可以尝试不同的 objective 函数,但就我的目的而言,效果非常好。
参考文献:
- http://www.medicalbiostatistics.com/roccurve.pdf
- http://www.bigdatarepublic.nl/regression-prediction-intervals-with-xgboost/
原型解决方案:
import numpy as np
import pandas as pd
# The probas and fpr/tpr/thresholds come from the roc curve.
probas_ = xgb_model_copy.fit(features.values[train], label.values[train]).predict_proba(features.values[test])
# Compute ROC curve and area the curve
fpr, tpr, thresholds = roc_curve(label.values[test], probas_[:, 1])
fpr_req = [0.01, 0.3, 0.5,0.9]
def find_nearest(array,value):
idx = (np.abs(array-value)).argmin()
return idx
fpr_indexes = [find_nearest(fpr, fpr_req_val) for fpr_req_val in fpr_req]
star_rating_thresholds = thresholds[fpr_indexes]
star_rating_thresholds = np.append(np.append([1],star_rating_thresholds),[0])
candidate_ratings = pd.cut(probas_,
star_rating_thresholds[::-1], labels=[5,4,3,2,1],right=False,include_lowest=True)
star_rating_thresolds
array([1. , 0.5073538 , 0.50184137, 0.5011086 , 0.4984425 ,
0. ])
candidate_ratings
[5, 5, 5, 5, 5, ..., 2, 2, 2, 2, 1]
Length: 564
Categories (5, int64): [5 < 4 < 3 < 2 < 1]
我有一个经过训练的标准 xgboost 分类模型,现在可以预测概率分数。但是,为了使用户界面更简单,我想将此分数转换为 5 星评级方案。 IE。离散化分数。
推导此量化阈值的智能方法是什么,以便高评分代表具有高置信度的高概率得分?
例如,我正在考虑生成置信区间以及预测并将高置信度高分分组为 5 星。高置信度低分作为 1 星。高置信度中高分如 4 星等。
你可以使用Pandas.cut()
方法:
In [62]: np.random.seed(0)
In [63]: a = np.random.rand(10)
In [64]: a
Out[64]: array([0.5488135 , 0.71518937, 0.60276338, 0.54488318, 0.4236548 , 0.64589411, 0.43758721, 0.891773 , 0.96366276, 0.38344152])
In [65]: pd.cut(a, bins=np.linspace(0, 1, 6), labels=[1,2,3,4,5])
Out[65]:
[3, 4, 4, 3, 3, 4, 3, 5, 5, 2]
Categories (5, int64): [1 < 2 < 3 < 4 < 5]
更新:
演示:
In [117]: a
Out[117]: array([0.6 , 0.8 , 0.85, 0.9 , 0.95, 0.97])
In [118]: pd.cut(a, bins=np.linspace(a.min(), a.max(), 6),
labels=[1,2,3,4,5], include_lowest=True)
Out[118]:
[1, 3, 4, 5, 5, 5]
Categories (5, int64): [1 < 2 < 3 < 4 < 5]
假设一个class化问题:either 1's or 0's
计算 ROC 曲线的 AUC 时,您按模型预测对 "events" 进行排序。所以在顶部,您很可能会有很多 1,并且在排序列表中越往下,0 就越多。
现在假设您尝试确定分数的阈值 "5"
。
您可以计算您愿意承受的数据中 0 的相对百分比。
给出以下 table:
item A score
1 1 0.99
2 1 0.92
3 0 0.89
4 1 0.88
5 1 0.74
6 0 0.66
7 0 0.64
8 0 0.59
9 1 0.55
如果我希望 "user score" "5"
的误报率为 0%,我会确定“5”的阈值高于 0.89
如果我可以容忍 10% 的误报,我会确定阈值高于 0.66
。
您可以对每个阈值执行相同的操作。
在我看来,这是一个 100% 的商业决策,选择这些阈值的最明智的方法是根据您对用户的了解。
如果用户期望 "5"
是对 class(生死攸关的情况)的完美预测,则误报率为 0%。
我为此研究了多种解决方案并制作了 V0 解决方案的原型。解决方案的主要要求如下:
随着评级水平的提高(5 星优于 1 星),误报数必须减少。
用户不必手动定义得分概率的阈值,阈值是自动导出的。
阈值源自某些更高级别的业务需求。
阈值源自标记数据,并可在发现新信息时重新导出。
考虑的其他解决方案:
- 基于置信区间的评级。例如,您可能有 0.9 的高预测分数但低置信度(即大置信区间)和 0.9 的高预测分数但高置信度(即小区间)。我怀疑我们可能希望后者成为 5 星候选人,而前者可能是 4*?
- 识别ROC曲线的凸凹度以识别最大值点
- 利用约登指数确定最佳点
最终解决方案 - 使用一组给定的业务需求(一组与每个星级相关联的 FPR)对 ROC 曲线进行采样,然后转换为阈值。 注意:这可行,但假设精度曲线有些单调,但情况可能并非总是如此。我通过将问题表述为优化问题来改进解决方案,其中评级阈值是自由度,objective 函数是每个评级桶之间转换率的线性度。我相信您可以尝试不同的 objective 函数,但就我的目的而言,效果非常好。
参考文献:
- http://www.medicalbiostatistics.com/roccurve.pdf
- http://www.bigdatarepublic.nl/regression-prediction-intervals-with-xgboost/
原型解决方案:
import numpy as np
import pandas as pd
# The probas and fpr/tpr/thresholds come from the roc curve.
probas_ = xgb_model_copy.fit(features.values[train], label.values[train]).predict_proba(features.values[test])
# Compute ROC curve and area the curve
fpr, tpr, thresholds = roc_curve(label.values[test], probas_[:, 1])
fpr_req = [0.01, 0.3, 0.5,0.9]
def find_nearest(array,value):
idx = (np.abs(array-value)).argmin()
return idx
fpr_indexes = [find_nearest(fpr, fpr_req_val) for fpr_req_val in fpr_req]
star_rating_thresholds = thresholds[fpr_indexes]
star_rating_thresholds = np.append(np.append([1],star_rating_thresholds),[0])
candidate_ratings = pd.cut(probas_,
star_rating_thresholds[::-1], labels=[5,4,3,2,1],right=False,include_lowest=True)
star_rating_thresolds
array([1. , 0.5073538 , 0.50184137, 0.5011086 , 0.4984425 ,
0. ])
candidate_ratings
[5, 5, 5, 5, 5, ..., 2, 2, 2, 2, 1]
Length: 564
Categories (5, int64): [5 < 4 < 3 < 2 < 1]