机器学习 - 模型评估(TPR、FPR、K1、ROC、AUC、KS、GAIN、LIFT、GINI、KSI)

以下内容多为个人理解,如有不当之处,欢迎指正!

1. 混淆矩阵

一个二分类模型,是对现实情况的一种预测。如病例(阴性/阳性、有病/没病)、邮件(垃圾邮件/非垃圾邮件)等。以病例为例,对于一个患者,存在着有病/没病两种结果。对于医生的诊断,也存在着有病/没病两种结果。将医生的诊断结果与患者的实际情况对比,则得出四种结果:

  • 诊断为有病,实际上确实有病,称为真阳性(TP) 
  • 诊断为有病,实际上却没病,称为伪阳性(FP)
  • 诊断为没病,实际上确实没病,称为真阴性(TN) 
  • 诊断为没病,实际上却有病,称为伪阴性(FN)

将上面的四种结果,可以绘制成一个2x2的混淆矩阵

真实值 总数
p n
预测输出 p' 真阳性(TP) 伪阳性(FP) P'
n' 伪阴性(FN) 真阴性(TN) N'
总数 P N

需要注意的是,混淆矩阵是对医生的诊断结果(阳性/阴性)以及医生诊断结果的结果(正确/错误)的一种描述,患者的实际患病情况是对医生诊断结果的一种评估。切勿将患者的患病情况与医生的诊断结果的评估混为一谈。即,混淆矩阵是用来评估模型的,而与样本“无关”。

在某一次集体的病例检测的过程中,我们希望尽可能多、尽可能准确的检测出患者所以,针对这种情况,我们提出以下指标:

1. 准确度(acc, Accuracy):正确诊断为阴性和正确诊断为阳性的占所有样本的比例。

\small ACC = \frac{TP + TN}{P + N}

如前所述,我们希望尽可能多、尽可能准确的检测出患者。那么检测出非患者则没有什么意义,因此,准确度并不能很好的反映出我们的目标,或者说并不能衡量出我们预测模型的好坏。甚至如果我们检测出非患者的准确度非常高,反而会影响我们对“尽可能多、尽可能准确的检测出患者”的模型进行评估。

2. 查全率(召回率,Recall)尽可能多反应的是我们希望能够把全部的阳性患者都检测出来。对于医学诊断而言,遗漏下来的患者,可能不能够得到及时的治疗,或者存在更大的隐患(如传染病);或者在图像分类中我们期望尽可能多的把用户期望的类别展现给用户,如用户希望识别小猫的图片,我们可以将图库中更多关于猫的图片展示给用户。那么,查全率表示的就是正确检测为阳性(TP)占全部阳性的概率。其中,全部阳性包括正确检测为阳性(TP),和错误检测为阴性(FN)之和。

\small Recall = \frac{TP}{TP + FN}

3. 查准率(精准率,Precision)尽可能准确反应的是每一个被诊断为阳性的病例都是正确的。类似抢打靶子,枪枪命中,避免子弹的浪费。那么,查准率表示的就是正确检测为阳性(TP)占全部检测为阳性的比例。其中,全部检测

  • 11
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
这些指标函数的代码可以在不同的编程语言中实现,下面是Python中的代码示例: 1. TPR (True Positive Rate) 和 FPR (False Positive Rate): ```python from sklearn.metrics import confusion_matrix def tpr_fpr(y_true, y_pred): tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel() tpr = tp / (tp + fn) fpr = fp / (fp + tn) return tpr, fpr ``` 2. K1 (Kappa): ```python from sklearn.metrics import cohen_kappa_score def kappa(y_true, y_pred): return cohen_kappa_score(y_true, y_pred) ``` 3. ROC (Receiver Operating Characteristic) 和 AUC (Area Under the Curve): ```python from sklearn.metrics import roc_curve, auc def roc_auc(y_true, y_pred_prob): fpr, tpr, thresholds = roc_curve(y_true, y_pred_prob) roc_auc = auc(fpr, tpr) return roc_auc ``` 4. KS (Kolmogorov-Smirnov): ```python from scipy.stats import ks_2samp def ks(y_true, y_pred_prob): tpr_fpr_df = pd.DataFrame({'y_true': y_true, 'y_pred_prob': y_pred_prob}) p0 = tpr_fpr_df[tpr_fpr_df.y_true == 0].y_pred_prob p1 = tpr_fpr_df[tpr_fpr_df.y_true == 1].y_pred_prob ks_statistic, p_value = ks_2samp(p0, p1) return ks_statistic ``` 5. GAIN: ```python import numpy as np def gain(y_true, y_pred_prob, n_bins=10): df = pd.DataFrame({'y_true': y_true, 'y_pred_prob': y_pred_prob}) df['y_true'] = df['y_true'].astype(int) df['n'] = 1 df['decile'] = pd.qcut(df['y_pred_prob'], n_bins) grouped = df.groupby('decile', as_index=False) agg_df = grouped.agg({'y_true': np.sum, 'n': np.sum}) agg_df['pct_total'] = agg_df['n'] / agg_df['n'].sum() agg_df['pct_pos'] = agg_df['y_true'] / agg_df['y_true'].sum() agg_df['cum_pct_total'] = agg_df['pct_total'].cumsum() agg_df['cum_pct_pos'] = agg_df['pct_pos'].cumsum() agg_df['cum_pct_neg'] = agg_df['cum_pct_total'] - agg_df['cum_pct_pos'] agg_df['lift'] = agg_df['cum_pct_pos'] / agg_df['pct_total'].mean() agg_df['gain'] = agg_df['cum_pct_pos'] / agg_df['cum_pct_pos'].max() return agg_df[['decile', 'pct_total', 'pct_pos', 'cum_pct_pos', 'cum_pct_neg', 'lift', 'gain']] ``` 6. LIFT: ```python import numpy as np def lift(y_true, y_pred_prob, n_bins=10): df = pd.DataFrame({'y_true': y_true, 'y_pred_prob': y_pred_prob}) df['y_true'] = df['y_true'].astype(int) df['n'] = 1 df['decile'] = pd.qcut(df['y_pred_prob'], n_bins) grouped = df.groupby('decile', as_index=False) agg_df = grouped.agg({'y_true': np.sum, 'n': np.sum}) agg_df['pct_total'] = agg_df['n'] / agg_df['n'].sum() agg_df['pct_pos'] = agg_df['y_true'] / agg_df['y_true'].sum() agg_df['cum_pct_total'] = agg_df['pct_total'].cumsum() agg_df['cum_pct_pos'] = agg_df['pct_pos'].cumsum() base_pos_rate = agg_df.y_true.sum() / len(df) lift_series = agg_df.cum_pct_pos / (agg_df.cum_pct_total * base_pos_rate) return lift_series ``` 7. GINI: ```python from sklearn.metrics import roc_curve def gini(y_true, y_pred_prob): fpr, tpr, thresholds = roc_curve(y_true, y_pred_prob) auc_score = auc(fpr, tpr) gini_coefficient = 2 * auc_score - 1 return gini_coefficient ``` 8. KSI: ```python from scipy.stats import norm def ksi(y_true_train, y_pred_prob_train, y_true_test, y_pred_prob_test): mu_train, std_train = norm.fit(y_pred_prob_train) mu_test, std_test = norm.fit(y_pred_prob_test) cdf_train_train = norm.cdf(y_pred_prob_train, loc=mu_train, scale=std_train) cdf_train_test = norm.cdf(y_pred_prob_test, loc=mu_train, scale=std_train) cdf_test_test = norm.cdf(y_pred_prob_test, loc=mu_test, scale=std_test) ksi_train = np.abs((cdf_train_train - cdf_train_test).mean()) ksi_test = np.abs((cdf_test_test - cdf_train_test).mean()) return ksi_train, ksi_test ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值