获得低 ROC AUC 分数但准确率高
Getting a low ROC AUC score but a high accuracy
在 scikit-learn
的 flight delay dataset.
版本上使用 LogisticRegression
class
我使用 pandas
来 select 某些列:
df = df[["MONTH", "DAY_OF_MONTH", "DAY_OF_WEEK", "ORIGIN", "DEST", "CRS_DEP_TIME", "ARR_DEL15"]]
我填写NaN
值0:
df = df.fillna({'ARR_DEL15': 0})
确保分类列标记有 'category' 数据类型:
df["ORIGIN"] = df["ORIGIN"].astype('category')
df["DEST"] = df["DEST"].astype('category')
然后从pandas
调用get_dummies()
:
df = pd.get_dummies(df)
现在我训练和测试我的数据集:
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
test_set, train_set = train_test_split(df, test_size=0.2, random_state=42)
train_set_x = train_set.drop('ARR_DEL15', axis=1)
train_set_y = train_set["ARR_DEL15"]
test_set_x = test_set.drop('ARR_DEL15', axis=1)
test_set_y = test_set["ARR_DEL15"]
lr.fit(train_set_x, train_set_y)
调用 score
方法后,我得到大约 0.867。但是,当我调用 roc_auc_score
方法时,我得到的数字要低得多,约为 0.583
probabilities = lr.predict_proba(test_set_x)
roc_auc_score(test_set_y, probabilities[:, 1])
为什么 ROC AUC 比 score
方法提供的值低很多?
首先,说 0.583 的 AUC 比 0.867 的分数*“低”就像比较苹果和橙子一样。
[* 我假设您的 score 是平均准确度,但这对于本次讨论并不重要 - 原则上它可以是任何其他内容]
至少根据我的经验,大多数 ML 从业者认为 AUC 分数衡量的东西与它实际所做的不同:常见(不幸的)用途就像任何其他越高越好的指标,例如准确性,这自然会导致像您自己表达的那样的难题。
事实是,粗略地说,AUC 衡量的是二进制 class 运算符 在所有可能的决策阈值 .
上取平均值的性能
二进制class化中的(决策) 是我们决定 将样本标记为 1 的值(回想一下概率 classifiers 实际上 return [0, 1] 中的值 p
,通常被解释为概率 - 在 scikit-learn 中它是 predict_proba
returns) .
现在,这个阈值,在像 scikit-learn predict
which return labels (1/0
) 这样的方法中,是 set to 0.5 by default,但这不是唯一的可能性,在某些情况下(例如数据不平衡)甚至可能不合需要。
带回家的要点是:
- 当您要求
score
(在幕后 uses predict
,即 标签 而不是概率)时,您还隐含地将此阈值设置为0.5
- 当你要求 AUC 时(相比之下,它使用概率 return 和
predict_proba
),不涉及阈值,你得到(类似的)准确度 在所有可能的阈值中取平均值
根据这些说明,您的特定示例提供了一个非常有趣的案例:
I get a good-enough accuracy ~ 87% with my model; should I care that, according to an AUC of 0.58, my classifier does only slightly better than mere random guessing?
只要数据中的 class 表示 合理平衡,现在的答案应该很明显:不,你不应该关心;对于所有实际情况,您关心的是部署有特定阈值的 classifier,以及此 classifier 在纯 理论和抽象 情况下的作用当对所有可能的阈值进行平均时,从业者应该不会感兴趣(它确实会引起 研究人员 提出新算法的兴趣,但我认为这不是你的情况)。
(对于不平衡的数据,参数改变;这里的准确率几乎没有用,你应该考虑准确率、召回率和混淆矩阵)。
出于这个原因,AUC 开始在文献中受到严重批评(不要误读 - ROC 曲线 本身的分析非常有用且有用); Wikipedia entry 和其中提供的参考资料强烈推荐阅读:
Thus, the practical value of the AUC measure has been called into question, raising the possibility that the AUC may actually introduce more uncertainty into machine learning classification accuracy comparisons than resolution.
[...]
One recent explanation of the problem with ROC AUC is that reducing the ROC Curve to a single number ignores the fact that it is about the tradeoffs between the different systems or performance points plotted and not the performance of an individual system
强调我的 - 另见 On the dangers of AUC...
我不知道 AIR_DEL15
到底是什么,你用它作为标签(它不在原始数据中)。我的 猜测 是它是一个不平衡的特征,即 0 比 1 多得多;在这种情况下,准确性作为指标没有意义,您应该改用精度、召回率和混淆矩阵 - 另请参阅 this thread).
举个极端的例子,如果你 87% 的标签是 0,你可以通过简单地(天真地)将所有样本分类为 0 来获得 87% 的准确率 "classifier";在这种情况下,您的 AUC 也会很低(非常接近 0.5,就像您的情况一样)。
关于 AUC 到底是什么的更一般的(在我看来也是非常需要的)讨论,请参阅我的其他答案。
在 scikit-learn
的 flight delay dataset.
LogisticRegression
class
我使用 pandas
来 select 某些列:
df = df[["MONTH", "DAY_OF_MONTH", "DAY_OF_WEEK", "ORIGIN", "DEST", "CRS_DEP_TIME", "ARR_DEL15"]]
我填写NaN
值0:
df = df.fillna({'ARR_DEL15': 0})
确保分类列标记有 'category' 数据类型:
df["ORIGIN"] = df["ORIGIN"].astype('category')
df["DEST"] = df["DEST"].astype('category')
然后从pandas
调用get_dummies()
:
df = pd.get_dummies(df)
现在我训练和测试我的数据集:
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
test_set, train_set = train_test_split(df, test_size=0.2, random_state=42)
train_set_x = train_set.drop('ARR_DEL15', axis=1)
train_set_y = train_set["ARR_DEL15"]
test_set_x = test_set.drop('ARR_DEL15', axis=1)
test_set_y = test_set["ARR_DEL15"]
lr.fit(train_set_x, train_set_y)
调用 score
方法后,我得到大约 0.867。但是,当我调用 roc_auc_score
方法时,我得到的数字要低得多,约为 0.583
probabilities = lr.predict_proba(test_set_x)
roc_auc_score(test_set_y, probabilities[:, 1])
为什么 ROC AUC 比 score
方法提供的值低很多?
首先,说 0.583 的 AUC 比 0.867 的分数*“低”就像比较苹果和橙子一样。
[* 我假设您的 score 是平均准确度,但这对于本次讨论并不重要 - 原则上它可以是任何其他内容]
至少根据我的经验,大多数 ML 从业者认为 AUC 分数衡量的东西与它实际所做的不同:常见(不幸的)用途就像任何其他越高越好的指标,例如准确性,这自然会导致像您自己表达的那样的难题。
事实是,粗略地说,AUC 衡量的是二进制 class 运算符 在所有可能的决策阈值 .
上取平均值的性能二进制class化中的(决策)p
,通常被解释为概率 - 在 scikit-learn 中它是 predict_proba
returns) .
现在,这个阈值,在像 scikit-learn predict
which return labels (1/0
) 这样的方法中,是 set to 0.5 by default,但这不是唯一的可能性,在某些情况下(例如数据不平衡)甚至可能不合需要。
带回家的要点是:
- 当您要求
score
(在幕后 usespredict
,即 标签 而不是概率)时,您还隐含地将此阈值设置为0.5 - 当你要求 AUC 时(相比之下,它使用概率 return 和
predict_proba
),不涉及阈值,你得到(类似的)准确度 在所有可能的阈值中取平均值
根据这些说明,您的特定示例提供了一个非常有趣的案例:
I get a good-enough accuracy ~ 87% with my model; should I care that, according to an AUC of 0.58, my classifier does only slightly better than mere random guessing?
只要数据中的 class 表示 合理平衡,现在的答案应该很明显:不,你不应该关心;对于所有实际情况,您关心的是部署有特定阈值的 classifier,以及此 classifier 在纯 理论和抽象 情况下的作用当对所有可能的阈值进行平均时,从业者应该不会感兴趣(它确实会引起 研究人员 提出新算法的兴趣,但我认为这不是你的情况)。
(对于不平衡的数据,参数改变;这里的准确率几乎没有用,你应该考虑准确率、召回率和混淆矩阵)。
出于这个原因,AUC 开始在文献中受到严重批评(不要误读 - ROC 曲线 本身的分析非常有用且有用); Wikipedia entry 和其中提供的参考资料强烈推荐阅读:
Thus, the practical value of the AUC measure has been called into question, raising the possibility that the AUC may actually introduce more uncertainty into machine learning classification accuracy comparisons than resolution.
[...]
One recent explanation of the problem with ROC AUC is that reducing the ROC Curve to a single number ignores the fact that it is about the tradeoffs between the different systems or performance points plotted and not the performance of an individual system
强调我的 - 另见 On the dangers of AUC...
我不知道 AIR_DEL15
到底是什么,你用它作为标签(它不在原始数据中)。我的 猜测 是它是一个不平衡的特征,即 0 比 1 多得多;在这种情况下,准确性作为指标没有意义,您应该改用精度、召回率和混淆矩阵 - 另请参阅 this thread).
举个极端的例子,如果你 87% 的标签是 0,你可以通过简单地(天真地)将所有样本分类为 0 来获得 87% 的准确率 "classifier";在这种情况下,您的 AUC 也会很低(非常接近 0.5,就像您的情况一样)。
关于 AUC 到底是什么的更一般的(在我看来也是非常需要的)讨论,请参阅我的其他答案。