ziadharmanani/Financial-Fraud-Detection
GitHub: ziadharmanani/Financial-Fraud-Detection
一个基于 IEEE-CIS 数据集的金融欺诈检测机器学习流水线,涵盖特征工程、树模型训练、阈值优化和 SHAP 可解释性分析。
Stars: 0 | Forks: 0
# 金融欺诈检测:特征工程与分类 Pipeline
本项目构建了一个机器学习 Pipeline,用于在 IEEE-CIS 欺诈检测数据集上检测欺诈性金融交易。该数据集具有高维度(434个特征)、类别严重不平衡(约3.5%为欺诈)的特点,并混合了数值型、类别型以及 339 个匿名支付网络特征(V1-V339)。其目标是尽可能多地正确标记出欺诈交易,同时将误报率保持在可控范围内。
**数据集:** [Kaggle 上的 IEEE-CIS 欺诈检测](https://www.kaggle.com/c/ieee-fraud-detection/data)
**目标变量:** `isFraud`(0 = 合法,1 = 欺诈)
**类别不平衡:** 约 96.5% 合法,约 3.5% 欺诈
**引用:** IEEE Computational Intelligence Society 和 Vesta Corporation. (2019). *IEEE-CIS Fraud Detection*. Kaggle. https://kaggle.com/competitions/ieee-fraud-detection
## 项目结构
```
Financial-Fraud-Detection/
├── notebooks/
│ ├── 01_Transaction_EDA.ipynb - Exploratory data analysis
│ └── 02_Preprocessing.ipynb - Feature engineering, preprocessing, and modeling
├── data/ - Raw CSVs (not tracked in Git)
├── pyproject.toml - Python dependencies
└── README.md
```
## 方法论
### 1. 探索性数据分析
EDA 笔记本(`01_Transaction_EDA.ipynb`)涵盖了所有主要的特征组:交易金额、时间模式、D 列、电子邮件域名、卡片特征、地址字段、身份列以及匿名的 V 列。影响建模 Pipeline 的主要发现如下:
- `TransactionAmt` 的偏度为 14.37,在建模前需要进行对数转换。
- D 列(D1-D15)会随着时间的推移发生漂移,因为它们计算的是距离过去事件的天数。通过归一化步骤可以纠正这一点。
- D9 由于缺失率高达 87% 且在量级上与其他 D 列存在根本性差异,因此被完全排除。
- V 列(V1-V339)都存在一定程度的缺失。使用哨兵值填充代替中位数插补,以便模型能够区分“缺失”与零。
- card1、card2、card5、addr1 和 addr2 拥有数千个唯一值。使用频率编码以避免独热编码导致的维度爆炸。
### 2. 特征工程
所有的特征工程均在训练集上完成,并在不产生数据泄露的情况下应用于测试集。
- **时间特征:** 使用确认的参考日期 2017-12-01,将 `TransactionDT` 解码为 `Hour`(小时)、`Weekday`(星期几)和 `Day`(天数)。
- **D 列归一化:** 通过减去当前交易日(`TransactionDT / 86400 - D_col`),将每个 D 列转换为固定的日历参考基准,从而消除时间漂移。
- **电子邮件域名分组:** 将原始域名映射为 Google、Yahoo 或 Microsoft。出现次数少于 500 次的域名被合并为“other”。缺失值则单独作为“missing”类别处理。
- **频率编码:** 将 card1、card2、card5、addr1 和 addr2 替换为它们在训练集中的频率计数。一张出现 50,000 次的卡可能是老客户;而仅出现 3 次的卡则十分可疑。
- **对数转换:** 使用 `np.log1p` 对 `TransactionAmt` 进行对数转换,以降低偏度。
### 3. 预处理
- 缺失值超过 50% 的列将被删除(V 列单独处理)。
- V 列使用 `min_value - 1`(哨兵值填充)进行填充,使得缺失状态对基于树的模型依然可见。
- 数值列使用中位数进行插补;类别列使用众数进行插补。
- 类别列进行标签编码。避免使用 `get_dummies` 以防止高基数特征引发维度爆炸。
- V 列使用 MinMaxScaler 进行缩放,并通过 PCA 从 339 维降维至 30 个主成分。
### 4. 建模
训练并比较了三个模型:
| 模型 | 关键设置 |
|---|---|
| Decision Tree | `criterion='entropy'`, `max_depth=12`, `min_samples_leaf=50`, `class_weight='balanced'` |
| Random Forest | `n_estimators=100`, `class_weight='balanced'`, `n_jobs=-1` |
| XGBoost | `n_estimators=300`, `learning_rate=0.05`, `max_depth=6`, `scale_pos_weight` 自动设置 |
所有模型均使用 `class_weight='balanced'`(或 XGBoost 中的等效参数 `scale_pos_weight`)来处理严重的类别不平衡问题,而无需进行过采样。
## 结果
Decision Tree 和 Random Forest 的阈值设定为 0.4(原始值)。XGBoost 使用根据尤登 J 统计量推导出的最优阈值。完整的交叉验证和业务成本分析包含在 `02_Preprocessing.ipynb` 中。
| 模型 | ROC-AUC | Precision (欺诈) | Recall (欺诈) | F1 (欺诈) |
|---|---|---|---|---|
| Decision Tree | ~0.88 | 0.12 | 0.82 | 0.21 |
| Random Forest | ~0.97 | 0.92 | 0.54 | 0.68 |
| XGBoost | ~0.98+ | 详见 notebook | 详见 notebook | 详见 notebook |
**关键权衡:** Decision Tree 能捕获更多的欺诈行为(高 Recall),但也会标记大量合法交易(低 Precision)。Random Forest 则更为保守。XGBoost 通常在其尤登优化阈值下能取得更好的平衡。
**阈值合理性说明:** 为每个模型计算尤登 J 统计量(`J = TPR - FPR`),以找到能使敏感度加特异度最大化的阈值。这取代了手动选择的 0.4。
**SHAP 分析:** 对 XGBoost 模型使用 SHAP(SHapley Additive exPlanations)来解释个体和全局层面的特征重要性。
**交叉验证:** 使用 5 折分层交叉验证(ROC-AUC 评分)来验证结果并非是特定训练集/测试集划分的偶然产物。
## 业务背景
在欺诈检测中,两类模型错误的成本截然不同:
- **False Negative(漏报欺诈):** 银行将承担退款费用。这是代价更高的错误。
- **False Positive(误报):** 合法交易被阻止或标记以供审查。这会给客户带来不便。
本项目中的建模决策(类别加权、阈值调整、优先考虑 Recall)反映了这种不对称性。笔记本中包含了使用 illustrative values(每次漏报欺诈损失 $200,每次误报成本 $5)进行的成本分析。
## 环境配置
### 依赖要求
Python 3.10 或更高版本。依赖项由 [uv](https://docs.astral.sh/uv/) 管理。
```
pip install uv
uv sync
```
或者直接使用 pip 安装:
```
pip install -r requirements.txt
```
### 数据
从 [Kaggle](https://www.kaggle.com/c/ieee-fraud-detection/data) 下载数据集,并将这四个 CSV 文件放置在项目根目录的 `data/` 文件夹中:
```
data/
├── train_transaction.csv
├── train_identity.csv
├── test_transaction.csv
└── test_identity.csv
```
### 运行 notebooks
```
jupyter notebook
```
首先打开 `01_Transaction_EDA.ipynb` 查看完整的 EDA 演示,然后打开 `02_Preprocessing.ipynb` 查看建模 Pipeline。
## 局限性与未来工作
- V 列已完全匿名化,因此无法确认其在现实世界中的实际含义。PCA 表示会损失一部分可解释性。
- Decision Tree 和 Random Forest 的超参数是手动选择的。完整的 GridSearchCV 过程可能会改进这两个模型。
- 成本分析使用了 illustrative numbers。实际部署将需要经过校准的退款率和审查成本。
- 生产环境中需要实时评分 Pipeline(例如带有序列化模型的 FastAPI endpoint)。
- 在早期的迭代中曾尝试过 SMOTE 过采样,但最终被 `class_weight='balanced'` 取代,从而避免了创建合成数据。
标签:Apex, Kaggle, NoSQL, Python, SHAP, Vesta, XGBoost, 交易安全, 代码示例, 决策树分类器, 反欺诈系统, 异常检测, 探索性数据分析, 支付安全, 数据分析, 数据预处理, 无后门, 机器学习, 模型可解释性, 欺诈检测, 特征工程, 类别不平衡, 网络安全, 逆向工具, 金融风控, 阈值优化, 隐私保护, 高维数据