2. 金融欺诈交易检测模型

任务目标

基于信用卡交易数据训练异常检测模型,识别欺诈交易。核心挑战是类别极度不平衡(欺诈样本通常占比<1%),因此需要调整决策阈值来平衡召回率与精确率,而非简单使用默认0.5阈值。

环境与依赖

需要 pandas、numpy、scikit-learn。数据集使用公开的 creditcard.csv(约28万条,31列,其中Class列1为欺诈,0为正常)。若本地无该文件,可从Kaggle下载后置于脚本同目录。

完整实现

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import precision_recall_curve, precision_score, recall_score, f1_score

# 1. 加载数据(若文件不存在则提示)
df = pd.read_csv('creditcard.csv')
print(f"数据形状: {df.shape}, 欺诈占比: {df['Class'].mean():.4f}")

# 2. 特征与标签(Time与Amount需标准化,其余PCA特征已标准化)
X = df.drop('Class', axis=1)
y = df['Class']
X[['Time', 'Amount']] = (X[['Time', 'Amount']] - X[['Time', 'Amount']].mean()) / X[['Time', 'Amount']].std()

# 3. 划分训练/测试集(分层抽样保持类别比例)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)

# 4. 训练随机森林(n_estimators=100,class_weight='balanced'处理不平衡)
model = RandomForestClassifier(n_estimators=100, class_weight='balanced', random_state=42, n_jobs=-1)
model.fit(X_train, y_train)

# 5. 预测概率(取正类概率)
y_scores = model.predict_proba(X_test)[:, 1]

# 6. 计算精确率-召回率曲线,寻找最优阈值
precisions, recalls, thresholds = precision_recall_curve(y_test, y_scores)

# 7. 选择F1分数最高的阈值
f1_scores = 2 * (precisions[:-1] * recalls[:-1]) / (precisions[:-1] + recalls[:-1] + 1e-9)
best_idx = np.argmax(f1_scores)
best_threshold = thresholds[best_idx]
print(f"最优阈值: {best_threshold:.4f}")

# 8. 用最优阈值预测并评估
y_pred_optimal = (y_scores >= best_threshold).astype(int)
print(f"最优阈值下 - 精确率: {precision_score(y_test, y_pred_optimal):.4f}, "
      f"召回率: {recall_score(y_test, y_pred_optimal):.4f}, "
      f"F1: {f1_score(y_test, y_pred_optimal):.4f}")

# 9. 对比默认阈值0.5
y_pred_default = (y_scores >= 0.5).astype(int)
print(f"默认阈值0.5 - 精确率: {precision_score(y_test, y_pred_default):.4f}, "
      f"召回率: {recall_score(y_test, y_pred_default):.4f}, "
      f"F1: {f1_score(y_test, y_pred_default):.4f}")

运行方式

将上述代码保存为 fraud_detection.py,与 creditcard.csv 置于同一目录,执行:

python fraud_detection.py

验证方法与判定标准

运行后观察输出:

  • 数据形状应为 (284807, 31),欺诈占比约 0.0017。
  • 最优阈值通常远低于0.5(约0.1~0.3),且该阈值下的召回率显著高于默认阈值0.5下的召回率。
  • 判定通过条件:最优阈值下的F1分数高于默认阈值下的F1分数,且召回率提升幅度明显(通常从0.6左右提升至0.8以上),同时精确率下降幅度可接受。
阈值调整对精确率/召回率的影响(示意) 分数 阈值 0.0 0.1 0.2 0.3 0.5 0.0 0.5 1.0 精确率 召回率 F1 最优阈值≈0.15 默认0.5 低阈值区 高召回 低精确 高阈值区 高精确 低召回

上图示意了阈值调整的核心权衡:降低阈值可捕获更多欺诈(召回率上升),但会误伤更多正常交易(精确率下降);提高阈值则相反。F1曲线最高点对应最优平衡阈值,通常远低于默认的0.5。

常见问题

  • 数据未找到:确认 creditcard.csv 在当前目录,或修改代码中的文件路径。
  • 训练耗时较长:随机森林100棵树在28万样本上约需1~2分钟,可先减少 n_estimators 至30验证流程。
  • 阈值选择标准:若业务更关注召回(如银行风控),可手动选择召回率≥0.9时的最高精确率阈值;若更关注精确(减少人工审核量),则选择精确率≥0.9时的最高召回率阈值。本案例以F1最大为默认标准。