# Summary
Area Under the [[ROC]] Curve
**AUC = 0.75** 意味着:
- 随机选择一个有病的患者(如张三)
- 随机选择一个没病的患者(如钱七)
- 模型给有病患者的预测分数 > 没病患者分数的概率是75%
**AUC的核心价值**:
1. **不受类别不平衡影响**:即使正负样本比例悬殊也能正确评估
2. **考虑所有可能的阈值**:不需要预先设定决策阈值
3. **直观的概率解释**:正样本得分高于负样本的概率
4. **适合排序任务**:不仅关心分类对错,还关心排序质量
**实际应用建议**:
- AUC < 0.6:模型基本无用
- AUC 0.6-0.7:有一定效果,但需改进
- AUC 0.7-0.8:效果不错
- AUC 0.8-0.9:效果很好
- AUC > 0.9:效果优秀(但要注意是否过拟合)
# Cues
# Notes
我来用几个实际例子详细介绍AUC(Area Under the ROC Curve)。
## 什么是AUC?
AUC是**ROC曲线下的面积**,用于评估二分类模型的性能。取值范围是[0,1],越接近1表示模型越好。
## 实例1:医院诊断系统
### 场景设定
医院开发了一个AI系统,根据血液检查结果预测患者是否患有糖尿病。
```python
# 10个患者的真实情况和AI预测
patients = [
# (姓名, AI预测概率, 真实情况)
("张三", 0.95, 1), # 1表示有病
("李四", 0.85, 1),
("王五", 0.75, 0), # 0表示没病
("赵六", 0.65, 1),
("钱七", 0.55, 0),
("孙八", 0.45, 0),
("周九", 0.35, 0),
("吴十", 0.25, 1),
("郑一", 0.15, 0),
("陈二", 0.05, 0),
]
```
### 计算AUC的过程
#### 步骤1:按预测概率排序
```python
# 按AI预测概率从高到低排序
sorted_patients = [
("张三", 0.95, 1), # ✓ 预测高,确实有病
("李四", 0.85, 1), # ✓ 预测高,确实有病
("王五", 0.75, 0), # ✗ 预测高,但没病(假阳性)
("赵六", 0.65, 1), # ✓ 预测较高,确实有病
("钱七", 0.55, 0), # ✓ 预测中等,确实没病
("孙八", 0.45, 0), # ✓ 预测较低,确实没病
("周九", 0.35, 0), # ✓ 预测较低,确实没病
("吴十", 0.25, 1), # ✗ 预测低,但有病(假阴性)
("郑一", 0.15, 0), # ✓ 预测低,确实没病
("陈二", 0.05, 0), # ✓ 预测低,确实没病
]
```
#### 步骤2:计算不同阈值下的TPR和FPR
```python
# 如果我们设置不同的阈值
thresholds = [1.0, 0.95, 0.85, 0.75, 0.65, 0.55, 0.45, 0.35, 0.25, 0.15, 0.05, 0]
# 阈值=0.5时的混淆矩阵
"""
预测概率 >= 0.5 → 预测为有病
预测概率 < 0.5 → 预测为没病
结果:
- 真阳性(TP): 张三、李四、赵六 = 3
- 假阳性(FP): 王五、钱七 = 2
- 真阴性(TN): 孙八、周九、郑一、陈二 = 4
- 假阴性(FN): 吴十 = 1
TPR = TP/(TP+FN) = 3/4 = 0.75
FPR = FP/(FP+TN) = 2/6 = 0.33
"""
```
#### 步骤3:绘制ROC曲线
```python
import matplotlib.pyplot as plt
# ROC曲线上的点
fpr = [0, 0.17, 0.33, 0.33, 0.5, 0.67, 0.83, 1.0]
tpr = [0, 0.5, 0.5, 0.75, 0.75, 0.75, 0.75, 1.0]
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, 'b-', linewidth=2, label='ROC曲线')
plt.plot([0, 1], [0, 1], 'k--', label='随机猜测')
plt.fill_between(fpr, tpr, alpha=0.3)
plt.xlabel('假阳性率 (FPR)')
plt.ylabel('真阳性率 (TPR)')
plt.title('糖尿病诊断系统的ROC曲线')
plt.legend()
plt.grid(True, alpha=0.3)
```
### AUC的直观理解
**AUC = 0.75** 意味着:
- 随机选择一个有病的患者(如张三)
- 随机选择一个没病的患者(如钱七)
- 模型给有病患者的预测分数 > 没病患者分数的概率是75%
## 实例2:银行信用卡欺诈检测
### 场景
银行需要识别信用卡交易是否为欺诈。
```python
# 交易数据示例
transactions = pd.DataFrame({
'transaction_id': range(1000),
'amount': [100, 5000, 50, 10000, ...], # 交易金额
'time': ['凌晨3点', '下午2点', ...], # 交易时间
'location': ['异地', '本地', ...], # 交易地点
'fraud_score': [0.92, 0.15, 0.78, ...], # AI预测的欺诈概率
'is_fraud': [1, 0, 1, 0, ...] # 实际是否欺诈
})
```
### 不同AUC值的实际含义
```python
# AUC = 0.5(随机猜测)
"""
银行场景:AI系统完全没用,和抛硬币一样
后果:大量欺诈交易被放过,正常交易被误拦
"""
# AUC = 0.7(一般)
"""
银行场景:能识别出一些明显的欺诈模式
- 凌晨大额异地交易 → 高概率欺诈
- 白天小额本地交易 → 低概率欺诈
后果:减少了一些损失,但仍有改进空间
"""
# AUC = 0.9(优秀)
"""
银行场景:能准确识别复杂的欺诈模式
- 考虑用户历史行为
- 识别异常消费模式
- 检测设备异常
后果:显著减少欺诈损失,用户体验良好
"""
# AUC = 0.99(极好)
"""
银行场景:几乎能识别所有欺诈
后果:欺诈损失降到最低,很少误报
"""
```
## 实例3:电商推荐系统
### 场景
电商平台预测用户是否会购买推荐的商品。
```python
# 用户-商品推荐数据
recommendations = [
# (用户, 商品, 预测购买概率, 实际是否购买)
("用户A", "iPhone", 0.88, 1), # 高收入用户看了多次
("用户B", "充电线", 0.72, 1), # 刚买了手机
("用户C", "冰箱", 0.68, 0), # 上个月刚买过
("用户D", "零食", 0.61, 1), # 经常买零食
("用户E", "奢侈品包", 0.45, 0), # 收入不匹配
# ... 更多数据
]
```
### AUC在业务中的应用
```python
# 计算不同推荐策略的AUC
strategies = {
"随机推荐": 0.50, # 完全随机
"基于浏览历史": 0.65, # 看过就推荐
"协同过滤": 0.75, # 相似用户买过
"深度学习模型": 0.85, # 综合多种特征
}
# 业务影响
for strategy, auc in strategies.items():
if auc == 0.50:
print(f"{strategy}: 转化率≈2%,收入低")
elif auc == 0.65:
print(f"{strategy}: 转化率≈5%,有一定效果")
elif auc == 0.75:
print(f"{strategy}: 转化率≈10%,效果不错")
elif auc == 0.85:
print(f"{strategy}: 转化率≈20%,效果显著")
```
## 实例4:简历筛选系统
### 场景
HR系统自动筛选简历,预测候选人是否适合某职位。
```python
# 候选人数据
candidates = pd.DataFrame({
'name': ['小明', '小红', '小刚', ...],
'education': ['985硕士', '普通本科', '211本科', ...],
'experience_years': [5, 2, 8, ...],
'skill_match': [0.9, 0.6, 0.8, ...],
'ai_score': [0.92, 0.45, 0.78, ...], # AI综合评分
'hired': [1, 0, 1, ...] # 最终是否录用
})
```
### AUC的实际意义
```python
# 假设AUC = 0.8
"""
这意味着:
- 如果随机选一个最终被录用的候选人(小明)
- 再随机选一个没被录用的候选人(小红)
- AI给小明的分数 > 小红的概率是80%
实际效果:
- HR可以优先面试高分候选人
- 节省80%的筛选时间
- 减少错过优秀人才的概率
"""
```
## 为什么AUC比准确率更好?
### 实例:疾病筛查
```python
# 罕见疾病:1000人中只有10人患病
total = 1000
sick = 10
healthy = 990
# 模型A:全部预测为健康
model_A_accuracy = 990/1000 = 0.99 # 99%准确率!
model_A_auc = 0.5 # 但AUC只有0.5(随机水平)
# 模型B:能识别出8个病人,但误报了50个
model_B_accuracy = (8 + 940)/1000 = 0.948 # 94.8%准确率
model_B_auc = 0.85 # AUC达到0.85
# 结论:模型B虽然准确率低,但AUC高,实际更有用
```
## AUC的计算代码
```python
from sklearn.metrics import roc_auc_score, roc_curve
import numpy as np
# 实际计算AUC
def calculate_auc_manually(y_true, y_scores):
"""
手动计算AUC,帮助理解原理
"""
# 获取正负样本
positives = [(score, 1) for score, label in zip(y_scores, y_true) if label == 1]
negatives = [(score, 0) for score, label in zip(y_scores, y_true) if label == 0]
# 计算每对正负样本的比较结果
total_pairs = len(positives) * len(negatives)
correct_pairs = 0
for pos_score, _ in positives:
for neg_score, _ in negatives:
if pos_score > neg_score:
correct_pairs += 1
elif pos_score == neg_score:
correct_pairs += 0.5
auc = correct_pairs / total_pairs
return auc
# 使用sklearn计算
y_true = [1, 1, 0, 1, 0, 0, 0, 1, 0, 0]
y_scores = [0.95, 0.85, 0.75, 0.65, 0.55, 0.45, 0.35, 0.25, 0.15, 0.05]
auc = roc_auc_score(y_true, y_scores)
print(f"AUC = {auc:.3f}")
```
## 总结