土法炼钢兴趣小组的算法知识备份

【金融科技工程】反欺诈:设备指纹、关系图谱、行为序列、黑产对抗

文章导航

分类入口
architecturefintech
标签入口
#fraud#anti-fraud#graph#gnn#xgboost#pagerank#device-fingerprint#account-takeover

目录

风控引擎(Risk Engine,见上一篇)解决了”把规则、特征、模型编排成一条毫秒级决策流”的工程问题,它是承载反欺诈策略的基础设施。但真正决定一个支付平台每年能否少损失十亿人民币的,不是决策流,而是策略本身——也就是这一篇的主题:反欺诈(Anti-Fraud)

反欺诈的对手不是随机事件,而是有组织、有学习能力、有经济动机的黑产。他们会研究平台的规则、测试模型的边界、批量注册账号、租用真实设备、雇佣”卡农”和”跑分”人员、甚至反向训练生成对抗样本。这让反欺诈成为所有金融系统里唯一一个持续存在”红蓝对抗”的方向:风控工程师上线一条规则,黑产三天内就能绕过;你把逻辑回归换成 XGBoost,黑产就开始拆分金额、切换设备、模拟行为序列。

本文的读者画像是:支付、借贷、交易所、出行、电商平台的风控策略工程师 / 反欺诈算法工程师 / 安全后端。我们不重复第 19 篇的”决策流实现”,而是聚焦:

一个常被忽视的视角:反欺诈的”成功”不是零欺诈,而是在可接受的误伤率下把欺诈率压到业务可承受的水平。零欺诈在商业上既不可行(成本会压垮业务),也不必要(保险、回补、追偿机制可以覆盖残余损失)。真正的目标是让欺诈成本高于收益,让黑产自己离开你的平台——这是一场永远在进行中的经济博弈。


一、欺诈类型分类:攻防的起点

所有反欺诈系统的第一步,都是把”欺诈”拆成可工程化的子类。不同类型的欺诈,数据在哪里、特征是什么、模型用什么损失函数、拦截在哪个节点,几乎完全不同。行业里比较稳定的划分如下。

1.1 账户盗用(Account Takeover,ATO)

定义:账号本身是真实用户的,但操作者是攻击者。常见入口是撞库(Credential Stuffing)、钓鱼(Phishing)、SIM 卡劫持(SIM Swap)、木马窃取 Cookie/Token。

特征信号

拦截点:登录、敏感操作前置(加验证码 / 人脸 / 二次确认),而不是交易末端——交易发生时往往钱已经出去了。

1.2 新账户欺诈(New Account Fraud,NAF)

定义:用伪造身份他人身份注册的新账户,从第一天起就是为欺诈准备的。典型场景:薅羊毛、套现、养号、贷款欺诈、电诈”收款码”账户。

特征信号

难点:新账户没有历史行为,传统 RFM(Recency / Frequency / Monetary,见 1.8)特征全部缺失,只能依赖设备、环境、关系图。这也是为什么头部平台在开户环节的风控投入往往比交易环节还大——一个被养起来的黑账户,损失远远不止单笔交易

1.3 盗卡、伪卡、无卡支付(CNP)欺诈

定义:攻击者持有泄露的卡号+CVV+有效期,在无卡环境(Card-Not-Present)下完成交易。CNP 欺诈是国际卡组织欺诈损失的最大头,根据 Nilson Report 公开数据,CNP 在全球卡欺诈损失中长期占比超过 60%。

特征信号

拦截点:商户侧风控 + 发卡行侧风控 + 卡组织的网络令牌化(Network Tokenization)协同,典型产品如 Stripe Radar、Visa Advanced Authorization。

1.4 刷单、套现、薅羊毛

定义:利用平台的营销规则漏洞牟利,本质是”把补贴变成现金”。严格说这类不总是法律意义上的欺诈,但对平台来说损失是实打实的。

特征信号:收款方高度集中、商品价格异常、退款率极高、IP / 设备 / 收货地址共享、时间聚集性强。图算法在这里效果极好——因为团伙必然共享某些节点

1.5 电信网络诈骗(Social Engineering)

定义:账户和操作都是真实用户本人,但他是被骗了。冒充公检法、冒充客服、杀猪盘、刷单返利、虚假投资。

这是最难拦截的一类,因为所有”技术信号”都是绿的:是用户自己登录、自己点击、自己输入密码、自己转账。拦截必须依赖场景语义

2022 年起,中国人民银行与公安部联合推动全国反诈大数据平台,与各商业银行、支付机构打通实时预警接口;银行侧常见做法是:命中高风险特征后,强制”冷静期”、延迟到账、人工外呼核实。

1.6 洗钱(Anti-Money Laundering,AML)

洗钱虽然也是”用金融系统干坏事”,但它的目标是把黑钱变白而不是把别人的钱变自己的。监测逻辑、报送义务、国际标准(FATF)都完全不同,放到下一篇 《反洗钱与 KYC》 专门讨论。

1.7 欺诈生命周期

下面这张图总结了大多数欺诈案件的生命周期——它也是反欺诈平台最外层的业务闭环

stateDiagram-v2
    [*] --> 侦测: 实时规则/模型触发
    侦测 --> 拦截: 高置信度直接拒绝
    侦测 --> 挑战: 中置信度加验
    挑战 --> 通过: 验证成功
    挑战 --> 拦截: 验证失败
    拦截 --> 调查: 进入人工案件
    调查 --> 封控: 账户/设备/卡/商户多维度冻结
    封控 --> 司法: 报送反诈平台/起诉
    封控 --> 申诉: 用户申述
    申诉 --> 解封: 误伤恢复
    申诉 --> 封控: 维持处置
    司法 --> [*]
    解封 --> [*]

1.8 RFM 与特征骨架

RFM 是反欺诈最古老也最稳定的特征骨架:

真实系统会把 RFM 扩展成多维度多时间窗的矩阵:(用户 × 设备 × IP × 商户) × (1min / 5min / 1h / 1d / 7d / 30d) × (登录 / 支付 / 退款 / 绑卡),轻松达到几千维。


二、特征工程:反欺诈的真正护城河

业内有一句被反复引用的话:“特征决定上限,模型决定下限”。反欺诈尤其如此——换模型带来的提升通常是几个百分点的 AUC,而一个好的设备指纹可能直接让某类团伙失效

2.1 设备指纹(Device Fingerprinting)

设备指纹的目标:即使用户卸载重装、清除 Cookie、切换账号,也能认出这是同一台设备

信号层 采集内容 稳定性 黑产伪造难度
OS / 硬件 IMEI、Android ID、IDFV、CPU 型号、传感器校准偏差 高(需真机改机)
应用层 SDK 生成的 DeviceID、安装列表、字体列表 中(改机工具可伪造)
浏览器 Canvas / WebGL 指纹、UA、时区、字体、WebRTC 泄漏 IP
网络 公网 IP、ASN、TCP/IP 指纹、TLS JA3 低(切 IP 即可)
行为 触屏压力、陀螺仪、打字节奏、滑动轨迹 较高 高(需要模拟真人)

工程要点

  1. 设备 ID 必须服务端生成,客户端只提交原始信号。否则黑产直接伪造 ID。
  2. 相似度 / 聚类而不是严格相等。同一台真机也会因系统升级、App 重装发生漂移。业内常用 SimHash、MinHash 处理”一堆弱特征聚合成一个稳定 ID”。
  3. 设备指纹与账号的关系必须是历史累积图:账号 A 在哪些设备上活跃、设备 D 被哪些账号使用过。这张图是团伙识别的基础。

国内主流方案:同盾、顶象、数美、腾讯天御;海外:ThreatMetrix(LexisNexis)、Iovation、Fingerprint.com。

2.2 行为序列(Behavior Sequence)

把用户的一次会话抽象成 (event_type, timestamp, context) 的序列,例如:

[login_pwd(09:01), home_view(09:01), coupon_list(09:02),
 search("iPhone", 09:03), item_view(sku=123, 09:04),
 add_cart(09:05), checkout(09:06), pay_wechat(09:06, ¥6999)]

好的序列模型能识别:“这个 9 秒完成的支付链路,和正常用户 89 秒的中位耗时差距过大”。常用技术:

2.3 IP 归属、Wi-Fi、LBS 与生物特征

2.4 关系特征(Graph-based Aggregations)

在上图之前,很多”关系信号”其实可以用一跳聚合就拿到巨大收益,成本远低于真正的 GNN:

工程上这些特征一般用 HBase 或 Redis 的反向索引 + Sorted Set 实现:

Key: dev:<device_id>:users_30d   -> ZSET(user_id, ts)
Key: ip:<ip>:register_1h         -> ZSET(user_id, ts)
Key: acct:<acct_id>:payers_7d    -> ZSET(payer_id, ts)

每次事件到来时,用 ZADD + ZREMRANGEBYSCORE 维护滑窗,读取时 ZCARD 取基数。单次读取 < 1ms。真正需要更多跳、更复杂拓扑时,再进图库。

2.5 特征分层存储

反欺诈的特征体系通常按时效性分三层(接续第 19 篇的特征平台):

示例 存储 计算方式
实时(秒级) 近 1 分钟登录次数、本次会话事件数 Redis / 内存表 流式 Flink + 滑窗
近线(分钟级) 过去 1 小时交易金额、过去 10 分钟绑卡次数 Redis / HBase Flink / Spark Streaming
离线(T+1) 过去 30 天关联设备数、过去 90 天退款率 HBase / ClickHouse / Hive 每日批处理

口径统一是这里最大的工程陷阱:同一个字段 amount_sum_30d,实时链路用 Flink 滑窗、离线链路用 Hive 日切,两者逻辑稍有差异,就会造成线下训练特征和线上推理特征不一致(Training-Serving Skew)——模型精度直线下跌。业内做法:

  1. 特征定义中心化:一份 YAML / Protobuf 定义特征元数据(名称、窗口、聚合函数、回溯范围),实时和离线链路都从同一份定义生成代码
  2. 离线回放实时:用 Flink 的 Batch 模式或 Kappa 架构,让”训练用的历史特征”也由实时管道生成
  3. 影子对比:每天抽样 N 条线上请求,同时跑离线特征管道,比较差异率,超阈值报警

2.6 数据存储示例

下面是一个简化的用户实体特征表 DDL,反映分层思想:

CREATE TABLE user_risk_feature (
    user_id          BIGINT PRIMARY KEY,
    -- 静态 / 离线
    reg_ts           TIMESTAMP,
    real_name_status TINYINT,
    kyc_level        TINYINT,
    -- 近线(分钟级)
    login_cnt_1h     INT,
    pay_amt_1h       DECIMAL(20,4),
    new_device_1h    TINYINT,
    -- 图特征(T+1 回写)
    assoc_device_30d INT,
    assoc_ip_30d     INT,
    comm_size        INT,
    comm_black_ratio DECIMAL(6,4),
    pr_score         DECIMAL(10,8),
    -- 元数据
    update_ts        TIMESTAMP,
    INDEX idx_update_ts (update_ts)
) ENGINE=InnoDB;

实际生产中会拆成多张表或走 HBase / 特征仓(Feast、阿里 FeatureStore)。


三、模型演进:从规则到图神经网络

3.1 规则:永远不会消失

规则有三个不可替代的优势:可解释、上线快、容易回滚。反欺诈里的规则典型形态:

IF amount > 50000 AND device_is_new AND login_city != usual_city
THEN challenge_face

大厂的反欺诈系统里,规则命中的拦截量通常仍然占 30% 以上。规则负责”兜底”和”响应新型欺诈”——模型训练周期是天,规则上线是分钟。

3.2 逻辑回归(Logistic Regression)

第一代统计模型。优点:系数可直接解读为 log-odds,监管友好;缺点:必须大量手工做特征交叉。至今信贷评分卡仍以 LR + WOE / IV 为主(见第 22 篇)。

3.3 GBDT:XGBoost / LightGBM / CatBoost

过去十年反欺诈的主力。优点:

大多数支付公司的线上欺诈评分模型仍然是 LightGBM——不是因为 DNN 不好,而是因为它的成本 / 效果比最高。一个典型的生产参数组合(1 亿样本、千维特征、欺诈率 0.3%):

params = {
    "objective": "binary",
    "metric": "auc",
    "num_leaves": 127,
    "max_depth": -1,
    "learning_rate": 0.03,
    "min_child_samples": 100,
    "feature_fraction": 0.8,
    "bagging_fraction": 0.8,
    "bagging_freq": 5,
    "lambda_l2": 1.0,
    "scale_pos_weight": 300,   # ≈ neg/pos
    "n_estimators": 2000,
    "early_stopping_round": 50,
}

调参经验:num_leaves 过大直接过拟合;min_child_samples 是欺诈场景最关键的正则——小样本叶子容易把某几个黑样本当规律。

3.4 DNN 与行为序列模型

DNN 的价值主要在高维稀疏特征(userid、itemid、deviceid 的 embedding)和序列建模。蚂蚁、美团、滴滴的风控算法团队都公开分享过用 Transformer 对用户行为序列建模的工作。

3.5 图神经网络(GNN)

团伙欺诈的本质是:多个”看起来正常”的节点,在图结构上呈现异常聚集。单点特征再多也抓不到这种关系,GNN 的输入就是图。

主流算法:

以 GraphSAGE 为例,单层聚合公式:

\[h_v^{(k)} = \sigma\left(W^{(k)} \cdot \text{CONCAT}\bigl(h_v^{(k-1)},\ \text{AGG}\bigl(\{h_u^{(k-1)} : u \in \mathcal{N}(v)\}\bigr)\bigr)\right)\]

其中 AGG 可以是 mean / max / LSTM。真实风控图通常 2 跳即可,3 跳后邻居爆炸且语义稀释(“朋友的朋友的朋友”对你几乎没有信息)。

GNN 在风控落地的最大挑战不是效果,而是训练 / 推理的工程复杂度

3.6 多模态与 LLM 风控

2024–2026 年的新方向:把文本(聊天记录、工单、客诉)、图像(商品图、身份证 OCR)、图结构一起喂给模型。LLM 在电诈场景特别有用——它能理解”冒充领导要求转账”的语义。但目前 LLM 主要用于辅助(可疑案件辅助调查、生成人工审核提示词),而不是在线拦截主模型:延迟、幻觉、对抗性都是障碍。

3.7 演进全景

graph LR
    R[规则] --> LR[逻辑回归]
    LR --> GBDT[XGBoost / LightGBM]
    GBDT --> DNN[DNN / 序列模型]
    DNN --> GNN[图神经网络]
    GNN --> MM[多模态 / LLM 辅助]
    R -.始终存在.-> MM

四、类别不平衡:反欺诈最头疼的数据问题

欺诈样本通常占比 0.01% – 1%。直接训练的模型会倾向全部预测为”正常”,AUC 看着很高、但 Recall 惨不忍睹。

4.1 数据层面

4.2 损失函数层面

4.3 评估层面

AUC 在极度不平衡时会虚高。生产上更看:

一个实战经验是:不要只看单点指标,要看整条 PR 曲线。模型 A 在 Top 1% 精度高,模型 B 在 Top 5% 召回高——选哪个取决于业务愿意付出多少误伤换召回。

4.4 阈值决策

大多数欺诈模型输出 [0, 1] 的概率,但线上要不要拦截是阈值决策。生产上不会单阈值”一刀切”,而是按场景分阈值

场景 阈值策略
登录 较低阈值,加验证码成本小
小额支付 中等阈值,避免过度骚扰
大额提现 较高阈值但加多重复核
新开户 极低阈值,宁可加验

阈值需要定期重校准:样本分布漂移(Distribution Shift)会让同一分数对应的真实欺诈率发生变化。


五、图风控:什么时候上图?怎么上?

5.1 图的节点与边

节点类型 典型属性
用户(User) 注册时间、实名状态、等级
设备(Device) 设备指纹、机型、首次出现时间
IP / Wi-Fi 归属、ASN、是否代理
银行卡 / 账户 BIN、开户行、是否一类户
商户(Merchant) MCC、注册地、风险等级
收货地址 经纬度、历史退款率
边类型 语义 方向
注册 User → Device 单向
登录 User → Device / IP 多对多,带时间戳
绑定 User → Card 多对多
交易 User → Merchant / User → User 有向,带金额
共设备 Device ↔︎ User 派生边,聚类用

5.2 算法地图

5.3 实时图更新

离线图分析 T+1 出团伙名单是远远不够的——等名单生成时,钱已经被洗完了。真正的挑战是实时图:交易发生时,新的边要在毫秒内出现在图里,且子图查询必须在 SLA 内完成。

工业界常见方案:

方案 代表 特点
图数据库 Nebula Graph(开源,中国)、TigerGraph(商业,美国)、JanusGraph 支持 Cypher/GSQL,实时写入 + 多跳查询
流式图计算 Flink + Gelly、蚂蚁 GeaBase、阿里 AGL(AntGraphLearning) 图算法增量更新
自研 + Embedding 缓存 支付宝、字节 离线算 embedding,在线查向量 + 轻量聚合

蚂蚁 AGL 公开过一个思路:离线把每个用户节点训练成一个 128 维 embedding,在线决策时只取本人 + 直接邻居 embedding,用轻量模型融合——把”图推理”降维成”向量查询 + MLP”,延迟可控。

5.4 一个真实团伙识别 Pipeline

下面是一个大厂常见的离线团伙识别 pipeline(T+1):

flowchart LR
    A[原始事件<br/>登录/注册/交易] --> B[构图 ETL<br/>Spark/Flink]
    B --> C[图存储<br/>Nebula/HBase]
    C --> D[社区发现<br/>LPA/Louvain]
    D --> E[社区特征<br/>规模/稠密度/黑率]
    E --> F{阈值过滤}
    F -- 高风险社区 --> G[人工标注]
    F -- 灰色社区 --> H[在线模型特征]
    G --> I[团伙黑名单]
    I --> J[实时风控拦截]
    H --> J

工程注意:

5.5 图查询的毫秒化

一个典型的 Nebula Graph 查询(找用户 2 跳内的共设备用户):

GO 2 STEPS FROM "u:123456" OVER login_on REVERSELY \
  YIELD login_on._dst AS device \
  | GO 1 STEPS FROM $-.device OVER login_on \
    YIELD login_on._dst AS related_user \
  | GROUP BY $-.related_user \
    YIELD $-.related_user AS uid, COUNT(*) AS co_count \
  | ORDER BY $-.co_count DESC \
  | LIMIT 100;

生产中这样的 2 跳查询在千万级图规模下,P99 通常能压到 30–80ms。


六、实时决策:特征 + 模型推理 + 响应

反欺诈的端到端 SLA 通常是:支付场景 100 – 300ms登录场景 50 – 100ms提现 500ms – 1s(因为可以异步)。

6.1 推理加速

6.2 决策动作

决策结果不是二元的”过/不过”,而是多级响应

  1. 放行:低风险
  2. 加验:短信 OTP、人脸、安全问题
  3. 限额:当日限 5000、单笔限 1000
  4. 延迟:T+1 到账(反诈常用)
  5. 拦截:直接拒绝
  6. 冷处理:放行但打”观察”标签,后续重点核查

不同动作的成本 / 效果曲线完全不同。生产上我们经常画一张 “challenge rate vs fraud recall” 图,决策层按业务风险偏好选工作点。

6.3 请求链路时序

一次 300ms 预算下的典型支付风控链路切分:

sequenceDiagram
    autonumber
    participant C as 客户端
    participant G as 网关
    participant R as 风控引擎
    participant F as 特征平台
    participant M as 模型服务
    participant GR as 图服务
    C->>G: 支付请求
    G->>R: 调用风控 (budget 300ms)
    par 特征并发取
        R->>F: 实时特征 MGET
        R->>GR: 图特征 (2 跳)
        R->>F: 离线特征
    end
    F-->>R: 特征向量 (15ms)
    GR-->>R: 图特征 (40ms)
    R->>R: 规则命中判断 (2ms)
    R->>M: 模型推理 (ONNX)
    M-->>R: 欺诈分数 (20ms)
    R->>R: 决策合成 (5ms)
    R-->>G: 决策结果
    G-->>C: 响应

典型耗时预算:网关 + 风控入口 10ms + 特征 / 图并发 40ms + 模型 20ms + 决策 5ms + 回包 10ms ≈ 85ms P50,P99 控制在 200–300ms。


七、对抗性:黑产是怎么打穿你的模型的

7.1 黑产工具链

7.2 对抗学习

黑产对模型的攻击在学术上叫对抗样本攻击

防守方的手段:

7.3 一个典型案例

2023 年某出行平台报告过一次”车费套现”团伙事件:黑产用虚构行程的方式,把信用支付的额度转成现金(乘客和司机是同一团伙)。第一版模型靠交易金额、路线规律抓到了一批;黑产快速调整为”短途 + 合理路线 + 真实司机跑空车”;第二版接入设备 + 支付卡 + 收款账户的关系图,通过 LPA 社区发现找到共享节点簇——有效拦截率恢复。这个案例说明:当单点特征被绕过时,图关系往往是最后一道防线

7.4 对抗攻防的认知框架

把反欺诈的对抗想象成一个重复博弈更贴近现实:

维度 攻方 守方
目标 最大化欺诈收益(金额 × 成功率 ÷ 成本) 最大化单位拦截成本下的真欺诈召回
信息 只能看到”通过 / 不通过”,不知道为什么 有全量样本、标签、行为日志
节奏 按天调整参数 策略按分钟、模型按周
不对称 可选择高价值场景集中攻击 必须覆盖所有场景

这种不对称意味着守方必须做”全链路纵深”:单点风控必然被攻破,多层(注册 → 登录 → 绑卡 → 支付 → 提现)独立风控 + 事后追溯机制才是完整防御。


八、可解释性:不是做给工程师看的

反欺诈模型的可解释性有两个受众:

  1. 内部:策略同学 / 案件审核员需要知道”为什么拦”,以便调参、核案、反馈
  2. 外部:监管 / 用户申诉。欧盟 GDPR 第 22 条明确规定,纯自动化决策对个人有”重大影响”时,用户有权获得解释

8.1 SHAP(SHapley Additive exPlanations)

基于合作博弈论的 Shapley 值,给出每个特征对单样本预测的边际贡献。工业界对 GBDT 模型有 TreeSHAP,O(TLD²) 非常快。典型输出:

拒绝交易 ¥5,800(欺诈分 0.92)
贡献最高的 5 个特征:
  device_age_days=0       +0.31
  ip_asn_is_idc=1         +0.22
  hist_amt_max_30d=120    +0.14
  recv_acct_blacklist=1   +0.13
  behave_seq_novelty=0.88 +0.09

8.2 反事实解释(Counterfactual)

回答”要改变什么,模型就会放行”。例如:“如果交易金额降到 3000 以下,且使用了历史设备,模型会判为低风险”。比 SHAP 更贴近用户直觉,但计算成本更高。

8.3 误伤与申诉

所有自动化风控系统都有误伤率。工程上必须做到:

8.4 解释的粒度

给不同角色的解释必须有不同粒度:

角色 解释形式 示例
普通用户 自然语言摘要 + 所需动作 “本次交易存在风险,请完成人脸验证后重试”
客服 / 审核员 关键特征 + 分数 + 历史记录 “设备首次出现、IP 归属异地、社区黑率 0.35”
风控策略 全特征 SHAP + 规则命中 完整归因报告
监管 / 法务 决策链路 + 依据 + 合规引用 模型版本、训练数据范围、使用目的

混淆不同受众的解释既会伤害用户体验(看不懂),又会泄露风控逻辑(被黑产反利用)。


九、行业案例

9.1 支付宝:图风控 + AGL

蚂蚁集团长期构建了业内最大规模的金融图之一,节点覆盖用户、设备、账户、商户、商品。技术栈公开资料:

业务上覆盖反套现、反洗钱、反欺诈、反骗贷。

9.2 美团:多场景风控

美团的反欺诈挑战在于业务极度多样(外卖、到店、打车、酒店、金融),每个场景欺诈模式不同。其公开技术博客提到的实践:

9.3 PayPal / Stripe Radar

9.4 央行反诈大数据平台

中国人民银行与公安部联合建设的全国反电信网络诈骗中心 / 金融侦查大数据平台,在 2022 年后实现与主要商业银行、支付机构、三大运营商的数据联动:

对支付机构而言,合规接入反诈平台是强制性的,这部分逻辑通常放在风控引擎的最前置”合规前置过滤”层。

9.5 案例小结

跨这四个案例可以看到共性设计

要素 支付宝 美团 Stripe Radar 反诈平台
主力模型 GBDT + GNN 场景化 GBDT Ensemble + 网络效应 规则 + 名单
图能力 自研图库 + AGL JanusGraph / 自研 跨商户隐式关联 多方数据融合
拦截手段 加验/限额/拦截 阶梯处置 3DS 挑战 / 拒付 延迟/冷静期/止付
合规接入 反诈 + 人行 反诈 + 监管 PSD2 / SCA 强制

一句话总结:没有”最好的”反欺诈架构,只有”最适合你业务和合规要求”的架构


十、代码示例:NetworkX + LightGBM 简化实现

下面用一个极简示例串起”图特征 + 模型评分”两个最核心的模块,重点看工程结构。生产环境不会用 NetworkX(单机、内存图),但示例逻辑与分布式图库一致。

10.1 构图与团伙识别(LPA + PageRank)

import networkx as nx
import pandas as pd
from networkx.algorithms.community import label_propagation_communities

# 交易记录:user_id, device_id, ip, card_id, amount, ts, label(0/1)
tx = pd.read_parquet("tx_sample.parquet")

G = nx.Graph()
for _, r in tx.iterrows():
    u = f"u:{r.user_id}"
    d = f"d:{r.device_id}"
    p = f"p:{r.ip}"
    c = f"c:{r.card_id}"
    # 共设备、共 IP、共卡作为无向边
    G.add_edge(u, d, weight=1.0)
    G.add_edge(u, p, weight=0.5)
    G.add_edge(u, c, weight=1.5)

# 1) 社区发现:找团伙候选
communities = list(label_propagation_communities(G))
comm_map = {}
for cid, comm in enumerate(communities):
    for n in comm:
        comm_map[n] = cid

# 2) PageRank 传播已知黑样本的风险
black_users = set(f"u:{u}" for u in tx.loc[tx.label == 1, "user_id"].unique())
personalization = {n: (1.0 if n in black_users else 0.0) for n in G.nodes()}
pr = nx.pagerank(G, alpha=0.85, personalization=personalization)

# 3) 图特征回写到用户维度
def graph_features(user_id):
    n = f"u:{user_id}"
    if n not in G:
        return {"comm_size": 0, "pr_score": 0.0,
                "comm_black_ratio": 0.0, "degree": 0}
    cid = comm_map.get(n, -1)
    comm = communities[cid] if cid >= 0 else set()
    user_nodes = [x for x in comm if x.startswith("u:")]
    black_cnt = sum(1 for x in user_nodes if x in black_users)
    return {
        "comm_size": len(comm),
        "pr_score": pr.get(n, 0.0),
        "comm_black_ratio": black_cnt / max(len(user_nodes), 1),
        "degree": G.degree(n),
    }

10.2 LightGBM 欺诈评分

import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, precision_score

feat = tx.copy()
gf = feat["user_id"].apply(graph_features).apply(pd.Series)
feat = pd.concat([feat, gf], axis=1)

cols = [
    "amount", "hour_of_day", "is_new_device",
    "hist_amt_30d", "hist_cnt_30d",
    "comm_size", "pr_score", "comm_black_ratio", "degree",
]
X, y = feat[cols], feat["label"]

X_tr, X_te, y_tr, y_te = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42)

# 类别不平衡:scale_pos_weight = neg / pos
spw = (y_tr == 0).sum() / max((y_tr == 1).sum(), 1)

model = lgb.LGBMClassifier(
    n_estimators=400, learning_rate=0.05,
    num_leaves=63, min_child_samples=50,
    scale_pos_weight=spw, objective="binary",
)
model.fit(X_tr, y_tr, eval_set=[(X_te, y_te)],
          callbacks=[lgb.early_stopping(30)])

p = model.predict_proba(X_te)[:, 1]
print("AUC:", roc_auc_score(y_te, p))

# TopK 精确率:按分数取 Top 1%
k = max(int(len(p) * 0.01), 1)
top_idx = p.argsort()[-k:]
print(f"Precision@Top1%: {y_te.iloc[top_idx].mean():.3f}")

10.3 SHAP 归因

import shap

explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_te.iloc[:5])
shap.summary_plot(shap_values, X_te.iloc[:5], show=False)

工程上,线上推理环节不用 Python 计算 SHAP(太慢),而是把特征 SHAP 值预计算 / 近似或者用更快的 TreeSHAP C++ 版本。

10.4 实时评分服务(简化)

生产上模型服务通常用 C++/Go 重写或 ONNX Runtime 部署。这里给一个 FastAPI + ONNX 的最小示例:

import onnxruntime as ort
import numpy as np
from fastapi import FastAPI
from pydantic import BaseModel

sess = ort.InferenceSession("fraud_lgbm.onnx",
                            providers=["CPUExecutionProvider"])
app = FastAPI()

class Req(BaseModel):
    features: list[float]

@app.post("/score")
def score(req: Req):
    x = np.array([req.features], dtype=np.float32)
    p = sess.run(None, {"input": x})[0][0][1]
    action = "pass"
    if p > 0.9:
        action = "reject"
    elif p > 0.6:
        action = "challenge"
    return {"score": float(p), "action": action}

真实线上:uvicorn 前挂 4–8 个 worker,单实例约 5–10k QPS;特征与评分拆成两个微服务;ONNX 模型经 onnxruntime-tools 量化后,Int8 推理进一步提速 2–3 倍。

10.5 一条规则的演化

最后看一条规则从”粗糙版”到”工程版”的演化,具体展示反欺诈工程的真实工作形态:

# V1(2 行代码,误伤率极高)
if amount > 50000 and new_device:
    reject()

# V2(加入历史基线)
if amount > max(50000, 3 * user.hist_amt_p95_90d) and new_device:
    challenge_face()

# V3(加入图 / 社区信号)
if (amount > max(50000, 3 * user.hist_amt_p95_90d)
    and new_device
    and (user.comm_black_ratio > 0.2 or recv_acct.in_black_comm)):
    reject(reason="HIGH_AMT_NEW_DEV_BLACK_COMM")
elif amount > max(50000, 3 * user.hist_amt_p95_90d) and new_device:
    challenge_face()

# V4(拆出配置,运营可调)
rule = load_rule("R_HIGH_AMT_NEW_DEV")
if rule.match(ctx):
    action = rule.decide(ctx)   # 支持 A/B 切流
    audit_log(rule.id, action, ctx)

V4 才是生产形态:规则与代码分离、可配置、可灰度、可审计。这一套往往比模型本身更决定系统的长期可维护性。


十一、风控闭环:发现 → 拦截 → 调查 → 封控 → 司法

这张图是所有成熟反欺诈团队的运营闭环,和业务团队、风控运营、客服、法务、监管都打通。

flowchart TB
    A[在线决策<br/>规则+模型] --> B{风险等级}
    B -- 低 --> C[放行]
    B -- 中 --> D[加验/延迟]
    B -- 高 --> E[拦截+打标]
    D --> F[案件队列]
    E --> F
    F --> G[人工审核]
    G -- 确认 --> H[多维度封控<br/>账户/设备/卡/商户]
    G -- 误伤 --> I[恢复+反馈样本]
    H --> J{是否涉刑}
    J -- 是 --> K[报送反诈平台/移交公安]
    J -- 否 --> L[平台处置]
    I --> M[模型重训练]
    K --> N[司法追偿]
    L --> M
    N --> M

几个工程要点:

  1. 封控是多维度的:封一个账号没用,黑产五分钟换号;必须同时封设备、卡、收款账户、收货地址
  2. 样本回流必须自动化:审核员每一次”确认欺诈 / 确认误伤”点击,都应该落入样本库
  3. 处置和沟通必须分级:银行冻结和支付平台限额,监管处置口径完全不同
  4. 报送时效:反诈平台对部分高危案件要求分钟级报送

十二、工程坑点

  1. 标签延迟:欺诈标签往往 T+7、T+30 才确认(用户举报、对账)。训练集需要延迟回填,否则刚上线的模型 AUC 虚高。
  2. 标签污染:被拦截的交易永远看不到”如果放行会不会真是欺诈”——这是选择偏差(Selection Bias)。需要保留一小部分不拦截对照组(Holdout)才能估算真实 PR 曲线。
  3. 特征穿越:训练时用了”将来才能知道”的特征(如”未来 7 天退款数”),导致线下 AUC=0.99、线上崩盘。这是反欺诈最常见事故。
  4. 模型老化:黑产迭代快,模型通常 1–3 个月衰减显著。必须有自动监控 + 定期重训机制。监控信号:每日 PSI(Population Stability Index)、特征分布漂移、模型分数分布漂移、拦截率波动。
  5. 图爆炸:某些超级节点(公共 Wi-Fi 的 IP、运营商 NAT)会连接上百万用户。必须节点权重归一化超级节点隔离,否则整张图都变成一个社区。
  6. 实时和一致性:实时特征和离线特征在同一个字段的口径上必须一致(如”最近 30 天金额”——实时是滑窗,离线是日切)。不一致会导致训练-线上偏差,模型精度下降。
  7. 压测:风控是高 QPS 系统,压测必须覆盖黑产洪水场景——短时间内 10 万次可疑请求时,特征取数、图查询会不会直接打爆 Redis / 图库?
  8. 双写与降级:规则、模型、特征必须各自可独立降级。模型服务挂了,规则仍应能拦高危动作;特征链路慢了,模型应能降级为”兜底规则 + 限额”。禁止把所有风控都堆在一个单点链路里。
  9. 冷启动与新业务:新上线的场景没有历史欺诈样本,迁移学习(从老场景)+ 激进阈值 + 强监控是标准打法。不要因为”没样本”就裸奔。
  10. 灰度发布:新模型 / 新规则必须走影子 + 小流量灰度,观察若干天拦截率、误伤率、申诉率。一刀切全量上线是事故高发区。
  11. 数据权限:特征仓里混合了用户敏感信息、第三方数据源、模型分数,必须做字段级权限 + 审计日志,防止内鬼泄漏或做被”逆向利用”。
  12. 时间戳陷阱:所有特征窗口必须基于事件时间(Event Time)而不是处理时间(Processing Time),否则回放历史时会引入系统性偏差。

十三、选型与落地清单

起步期(团队 <5 人,GMV 百亿以下)

成长期(GMV 千亿级 / 支付机构)

成熟期(头部支付 / 银行 / 交易所)

13.1 上线前的自检清单

无论处于哪个阶段,一个反欺诈系统在上线 / 升级前都应回答以下问题:


十四、隐私与伦理

反欺诈系统会收集、处理大量个人敏感信息,必须把合规作为工程约束而不是装饰。

14.1 误伤的真实代价

工程师讨论”拦截率”时常常忽略一个事实:误伤不是数字上的 -1,而是一个真实用户的困境。一个被错误冻结账户的用户可能:

这意味着反欺诈系统必须把误伤作为一等公民指标:

指标 含义 目标
False Positive Rate 误伤率 尽量低,但不为零
申诉响应时长 P95 用户申诉到首次响应 < 2h
解封时长 P95 从申诉到账户恢复 < 24h
误伤回流率 确认误伤样本进入训练集比例 100%

14.2 跨平台数据共享的边界

反欺诈天生有”多方数据越多效果越好”的诱惑——PayPal / Stripe 的护城河之一就是跨商户数据。但在中国 PIPL 与欧盟 GDPR 下,跨平台共享用户数据需要单独授权 + 最小必要,不能用”反欺诈”作为模糊借口无限扩张数据收集。

合规做法:


十五、参考资料


上一篇《实时风控引擎:规则、特征、模型、决策流、Flink/Spark》

下一篇《反洗钱与 KYC:客户尽调、交易监测、STR/SAR、FATF》

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-22 · architecture / fintech

【金融科技工程】金融科技工程全景:从支付到交易所的系统分类与读图

金融科技(FinTech)不是普通后端加一张账户表。钱的原子性、监管的硬边界、一个小数点的代价,把这个领域推进到工程强度最高的那一档。本文是【金融科技工程】25 篇的总目录与阅读地图:先交代为什么它比一般业务系统更难,再给出对账体、支付体、交易体、风控合规体四维分类,把后续 24 篇挂到骨架上,最后给出一份绿地项目的落地顺序建议。

2026-04-22 · architecture / fintech

【金融科技工程】复式记账工程化:科目、分录、余额、对账

把 500 年历史的复式记账翻译成工程师可以落地的数据模型、SQL 表结构与余额计算策略,覆盖充值、下单、退款、分润、红包、多币种与冲销的真实场景,并对比 TigerBeetle、beancount、Ledger CLI、Square LedgerDB、Stripe Ledger 等开源与工业实现。


By .