VishnuSas21/fraud-detection-system
GitHub: VishnuSas21/fraud-detection-system
结合 SQL 规则引擎与 XGBoost 机器学习模型,通过混合决策架构实现金融交易欺诈检测的数据科学项目。
Stars: 0 | Forks: 0
# 欺诈检测系统 — SQL 规则引擎 + XGBoost ML 模型
一个基于 50,000 笔合成交易记录、具备生产级设计理念的欺诈检测系统。
结合了**基于 SQL 的规则引擎**与 **XGBoost 机器学习模型**,旨在展示
真实的反欺诈团队如何将规则与 ML 结合使用 —— 它们并非互相替代,而是作为多层防线协同工作。
## 项目结构
```
fraud-detection-system/
├── sql/
│ ├── 01_exploratory_analysis.sql
│ ├── 02_velocity_bin_geo.sql
│ ├── 03_ato_merchant_structuring.sql
│ └── 04_hybrid_decision_engine.sql
├── python/
│ └── fraud_detection_xgboost.ipynb
├── data/
│ └── fraud_db_setup.sql
├── docs/
│ └── project_findings.md
└── README.md
```
## 业务问题
金融平台每年因欺诈损失数十亿资金。目前存在两种失败模式:
- **漏报欺诈** → 直接财务损失、拒付、监管处罚
- **误拦合法客户** → 收入损失、客户流失、客服成本增加
本项目构建了一个旨在将这两种损失降至最低的系统 —— 以高精准度捕捉欺诈,
同时将误报率控制在运营团队可接受的范围内。
## 数据集
- **50,000 笔交易**,涵盖 5,000 名客户和 200 家商户
- **782 起欺诈案例** —— 1.56% 的欺诈率(符合真实的信用卡欺诈水平)
- **包含的欺诈模式:** ATO、BIN 攻击、地理速度、分层洗钱、CNP 欺诈
- **特征:** 金额、交易类型、商户类别、KYC 状态、登录失败次数、
账户年龄、设备 ID、地理位置、风险细分
使用 `data/fraud_db_setup.sql` 生成 —— 可在 MySQL 中完全复现。
## 第 1 部分 — SQL 规则引擎
由四个循序渐进的模块组成,每个模块针对特定的欺诈模式。
### 模块
| 文件 | 涵盖的欺诈模式 | 关键 SQL 技术 |
|---|---|---|
| 01_exploratory_analysis | 按细分、KYC、账户年龄划分的基线欺诈率 | GROUP BY、条件聚合、CASE WHEN |
| 02_velocity_bin_geo | 每日速度、滚动 1 小时速度、BIN 攻击、地理速度 | Self JOIN、INTERVAL 窗口、CTE、LAG()、TIMESTAMPDIFF |
| 03_ato_merchant_structuring | 账户接管、商户拒付风险、AML 分层 | 多信号 AND 逻辑、JOIN、阈值临近检测 |
| 04_hybrid_decision_engine | 风险评分引擎 + 最终决策引擎 | 加权 CASE WHEN、硬性规则、4 级 CTE 链 |
### 风险评分引擎
每笔交易都会根据 10 项欺诈信号获得一个加权风险评分。
权重最初由领域知识设定,随后通过 XGBoost 特征重要性进行验证。
| 信号 | 权重 | 依据 |
|---|---|---|
| 登录失败次数 > 2 | 35 | 最强 ATO 预测因子 —— XGBoost 重要性占比 60.5% |
| 金额 > $800 | 10 | 高价值 = 高损失敞口 |
| KYC 未验证 | 9 | 未验证身份 = 风险升高 |
| 高风险细分 | 9 | 在 v1 中权重偏低 —— ML 纠正了这一点 |
| 加密货币/博彩商户 | 8 | 欺诈率为 2.67%,而电商为 1.38% |
| 境外交易 | 6 | 在 v1 中权重偏高 —— ML 纠正了这一点 |
| 金额 > 用户平均值的 3 倍 | 5 | 行为激增信号 |
| 账户年龄 < 30 天 | 5 | 新账户风险 |
| 非营业时间(凌晨 2 点至 5 点) | 5 | 行为异常 |
| CNP 交易 | 5 | 上下文信号 —— 单独使用时信号较弱 |
### 混合决策引擎
针对高置信度单一信号使用硬性规则。
针对较弱信号的组合使用软评分。
```
Strong single signal → HARD BLOCK (no score needed)
Weak signals combined → Score ≥ 25 → REVIEW
Score < 25 → APPROVE
```
**硬性拦截条件:**
- failed_logins > 5
- failed_logins > 2 且 kyc_verified = 0
- failed_logins > 2 且 amount > $800
- risk_segment = High 且 kyc_verified = 0 且 merchant = Crypto/Gaming
**为什么 failed_logins 被排除在软评分之外:**
它已经是 4 项硬性规则中 3 项的触发条件 —— 如果将其包含在软评分中,
会导致对该信号进行重复计算。这两层机制保持了清晰的隔离。
### 决策引擎结果
| 决策 | 交易数 | 欺诈数 | 欺诈率 | FP Rate |
|---|---|---|---|---|
| BLOCK | 285 | 112 | 39.3% | 60.7% |
| REVIEW | 3,146 | 87 | 2.77% | 97.2% |
| APPROVE | 46,569 | 583 | 1.25% | 0% |
**整体召回率:25.4%** —— 解释详见局限性部分。
## 第 2 部分 — XGBoost ML 模型
### 为什么在规则之外还需要 ML?
规则引擎擅长捕捉已知的欺诈模式。而 ML 能够捕捉未知模式。
更重要的是 —— ML 会告诉你哪些信号才是真正重要的,而不是你主观假设重要的。
### Notebook 结构
| 步骤 | 功能说明 |
|---|---|
| Step 1 | 从 MySQL 加载 50,000 笔交易 |
| Step 2 | 特征工程 v1 —— 二元标志基线 |
| Step 3 | 训练 XGBoost 模型 v1 |
| Step 4 | 评估模型 v1 —— 揭示二元标志过于粗糙 |
| Step 5 | 特征工程 v2 —— 原始连续值 |
| Step 6 | 评估模型 v2 —— 相比 v1 有显著提升 |
| Step 7 | XGBoost 特征重要性分析 |
| Step 8 | 将重要性分数映射到 SQL 权重 v1 |
| Step 9 | 按比例进行 ML 验证的 SQL 权重 v2 |
| Step 10 | 阈值分析 —— 精准度/召回率的权衡 |
| Step 11 | 信号覆盖度分析 —— 为何召回率存在上限 |
| Step 12 | 混合决策引擎 —— 硬性规则 + 软评分 |
| Step 13 | 最终三方对比 V1 vs V2 vs V3 |
### 模型性能
| 指标 | 模型 V1 (二元标志) | 模型 V2 (原始 + 工程化) |
|---|---|---|
| AUC-ROC | 0.71 | 0.9999* |
| AUC-PR | 0.15 | 0.9956* |
| 捕捉到的欺诈 | 41.7% | 98.1%* |
| False Positives | 969 | 8* |
*近乎完美的得分反映了合成数据泄露 —— 欺诈标签正是基于训练中使用的相同特征生成的。详见局限性部分。
### XGBoost 特征重要性 — SQL 权重验证
| 特征 | ML 重要性 | 旧版 SQL 权重 | 新版 SQL 权重 | 变化 |
|---|---|---|---|---|
| failed_logins | 60.5% | 30 | 35 | ↑ 确认为最强信号 |
| amount | 11.3% | 25 | 10 | ↓ 原先权重过高 |
| kyc_verified | 8.2% | 20 | 9 | ↓ 权重下调 |
| flag_high_risk_seg | 7.8% | 10 | 9 | ↑ 原先权重过低 |
| flag_risky_merchant | 6.2% | 15 | 8 | ↓ 权重下调 |
| is_foreign | 3.1% | 20 | 6 | ↓ 严重高估 |
| daily_velocity | 0.0% | 20 | 0 | ❌ 完全移除 |
### 阈值分析
系统评估表明,没有任何单一阈值能够解决精准度与召回率的权衡问题:
| 阈值 | 精准度 | 召回率 | F1 | FP Rate |
|---|---|---|---|---|
| 35 | 17.6% | 20.6% | 0.190 | 82.4% |
| 50 | 25.9% | 8.7% | 0.130 | 74.1% |
| 65 | 80.0% | 1.5% | 0.030 | 20.0% |
在阈值为 35 时 F1 表现最佳 —— 但召回率依然只有 20.6%。
这直接促成了采用混合架构的决策。
## 决策引擎演进
| 版本 | 架构 | BLOCK 精准度 | BLOCK FP Rate | BLOCK 数量 | 召回率 |
|---|---|---|---|---|---|
| V1 | 领域权重,阈值 60 | 7.75% | 92.25% | 3,344 | 33.2% |
| V2 | ML 验证权重,阈值 65 | 25.86% | 74.14% | 263 | 25.4% |
| V3 | 混合硬性规则 + 软评分 | 39.30% | 60.70% | 285 | 25.4% |
**V1 → V2:** ML 权重将 BLOCK 数量减少了 92%(3,344 → 263),同时精准度提升了 3.3 倍
**V2 → V3:** 硬性规则将 BLOCK 精准度提升至 39.3% —— 几乎每 2 次拦截中就有 1 次是真正的欺诈
## 关键发现
**1. 登录失败次数主导了所有其他信号**
failed_logins 的 XGBoost 重要性占比达 60.5%,其预测能力是次优特征的 5 倍。
任何 failed_logins > 2 且伴随一项次要信号的交易,都足以触发硬性拦截。
**2. 境外交易信号权重过高**
is_foreign 在 80% 的交易中都会触发 —— 范围太广,无法有效区分。
3.1% 的 ML 重要性证实它只能作为辅助信号。
在评分引擎中的权重从 20 分降至 6 分。
**3. 混合架构优于纯评分机制**
将高置信度单一信号(硬性规则)与弱信号组合(软评分)分离,
在不改变召回率的情况下,将 BLOCK 精准度从 25.86% 提升至 39.30%。
**4. 规则与 ML 相互验证**
领域专业知识设定了初始权重。ML 纠正了三个权重过高
和一个权重过低的信号。单独采用任何一种方法都无法发现这一点。
**5. REVIEW 分组在生产环境中应使用阶梯式认证**
REVIEW 中 97% 的误报率对于人工审核来说是不可接受的。
解决方案:自动化 OTP 或 3DS —— 客户可在几秒钟内自助验证通过,
运营团队根本无需介入,误报成本降至接近零。
## 局限性
**合成数据天花板 —— 召回率上限为 25%**
有 583 起欺诈案例得分较低,因为数据生成器将它们标记为由单一孤立信号触发。
评分引擎要求多个信号同时触发,因此单信号欺诈案例在任何阈值下都会漏网。
在生产环境中,这种限制是不存在的 —— 真实的欺诈者会同时触发多个信号。
一次 ATO 攻击会同时表现出登录失败、且是新设备、且存在地理差异,
且发生在异常时间。该架构已具备生产级应用能力;
当前的瓶颈在于合成数据,而非引擎的设计。
**近乎完美的 ML 指标表明存在数据泄露**
欺诈标签是确定性基于训练中使用的相同特征生成的。
XGBoost 逆向推导了这些标签生成规则,而不是学习通用的欺诈模式。
真实世界的欺诈模型在生产数据上的 AUC-ROC 通常为 0.75–0.90。
## 如何运行
**前置条件:**
- MySQL 8.0+
- Python 3.9+
- Jupyter Notebook
**第 1 步 — 设置数据库:**
```
-- In MySQL Workbench or mysql CLI
source data/fraud_db_setup.sql
```
**第 2 步 — 按顺序运行 SQL 模块:**
```
USE fraud_db;
source sql/01_exploratory_analysis.sql
source sql/02_velocity_bin_geo.sql
source sql/03_ato_merchant_structuring.sql
source sql/04_hybrid_decision_engine.sql
```
**第 3 步 — 运行 Notebook:**
```
pip install pandas numpy scikit-learn xgboost==2.1.1 mysql-connector-python matplotlib
jupyter notebook
```
打开 `python/fraud_detection_xgboost.ipynb` 并运行所有单元格。
在运行之前,请更新数据库连接单元格中的 MySQL 密码。
## 展示的技能
| 技能 | 应用位置 |
|---|---|
| 高级 SQL —— CTE、窗口函数、自连接 | 所有 SQL 模块 |
| 欺诈领域知识 —— ATO、BIN 攻击、地理速度、分层洗钱 | sql/02、sql/03 |
| 特征工程 —— 原始值与二元标志对比 | Notebook 步骤 2 和 5 |
| 类别不平衡处理 —— XGBoost 中的 scale_pos_weight | Notebook 步骤 3 |
| 阈值优化 —— 准度/召回率权衡 | Notebook 步骤 10 |
| 信号覆盖度分析 —— 为何召回率存在上限 | Notebook 步骤 11 |
| ML 与规则结合 —— 特征重要性 → SQL 权重更新 | Notebook 步骤 7–9 |
| 混合架构 —— 硬性规则 + 软评分 | sql/04、Notebook 步骤 12 |
| 生产级思维 —— 通过率、阶梯式认证建议 | Notebook 步骤 12 |
| 客观评估 —— 正视合成数据的局限性 | 局限性部分 |
## 作者
**Vishnu Saseendran**
高级主管 —— 支付表现与风险调查
拥有 6 年以上欺诈检测、交易监控和支付风险领域的经验
[LinkedIn](https://linkedin.com/in/vishnu-saseendran-522798148) | [GitHub](https://github.com/VishnuSas21)
标签:Apex, NoSQL, SQL规则引擎, XGBoost, 代码示例, 多线程, 数据分析, 机器学习, 欺诈检测, 逆向工具, 金融风控