第四章:基于MLP的异常交易检测

各位同学好,今天我们聊聊多层感知机(MLP)在反洗钱场景里的实战应用。说实话,MLP这个模型在深度学习里算是“老前辈”了,但你别小看它——在异常交易检测这种结构化数据任务上,它依然能打。

4.1 为什么是MLP?

你可能会问:现在Transformer、GNN这么火,为什么还要用MLP?

我个人习惯是:先上简单的,再上复杂的。MLP有三个天然优势:

  • 训练速度快:相比图神经网络,MLP的训练时间能少一个数量级
  • 可解释性强:每个特征对输出的贡献,通过权重可以直观分析
  • 数据要求低:不需要构建复杂的图结构,表格数据直接喂进去就行

我在项目中遇到过一家中小银行,他们的交易数据量不大,每天也就几十万笔。用GNN反而过拟合严重,换成MLP后效果立竿见影。说白了,杀鸡不用牛刀。

4.2 MLP模型设计要点

设计MLP时,我一般遵循“三看”原则:看数据量、看特征维度、看业务复杂度。

4.2.1 网络结构设计

对于反洗钱场景,我推荐这样的基础结构:

输入层(特征维度) → 隐藏层1(128节点,ReLU) → Dropout(0.3) 
→ 隐藏层2(64节点,ReLU) → Dropout(0.3) 
→ 隐藏层3(32节点,ReLU) → 输出层(1节点,Sigmoid)

嗯,这里要注意:隐藏层不是越多越好。我曾经试过堆到8层,结果训练集准确率99%,测试集直接崩到60%。过拟合的典型症状。

4.2.2 激活函数选择

层位置 推荐激活函数 原因
隐藏层 ReLU / LeakyReLU 缓解梯度消失,计算快
输出层 Sigmoid 输出0-1概率,符合二分类

为什么不用Tanh?我在实践中发现,Tanh在反洗钱这种稀疏特征场景下,容易让梯度卡在饱和区。ReLU虽然简单,但够用。

4.3 训练与评估

训练MLP就像调一杯鸡尾酒——配方重要,手法更重要。

4.3.1 损失函数与优化器

  • 损失函数:Binary Cross-Entropy(二分类交叉熵)
  • 优化器:Adam,学习率设为0.001
  • Batch Size:256或512,看显存大小

这里有个坑:反洗钱数据极度不平衡。正常交易可能占99.9%,异常只有0.1%。直接用BCE Loss,模型会学成“全部预测为正常”。

避坑指南:我曾经因为没处理样本不平衡,模型准确率99.8%但召回率只有2%。后来加了正样本权重,把异常类的loss权重设为正常类的100倍,召回率才拉到70%以上。

4.3.2 评估指标

别只看准确率。在反洗钱场景,我重点关注:

  • 召回率(Recall):抓到了多少真正的异常交易
  • 精确率(Precision):抓到的里面有多少是真的异常
  • F1-Score:两者的调和平均
  • AUC-ROC:模型区分正负样本的能力

你想想看,如果模型漏掉一笔洗钱交易,可能造成几百万的损失。所以召回率往往比精确率更重要。

4.4 实战案例:信用卡套现检测

下面我拿一个真实项目来拆解。某支付公司想检测信用卡套现行为,数据包含:交易金额、交易时间、商户类型、地理位置、历史交易频率等20个特征。

4.4.1 数据预处理

# 标准化连续特征
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)

# 处理类别特征(商户类型等)
# 我用的是Label Encoding + Embedding层
# 但简单场景下One-Hot也够用

记得我当时踩过一个坑:金额特征分布极右偏,直接标准化效果很差。后来做了log变换,模型收敛速度快了一倍。

4.4.2 模型训练代码

import torch
import torch.nn as nn

class AML_MLP(nn.Module):
    def __init__(self, input_dim):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(input_dim, 128),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(64, 32),
            nn.ReLU(),
            nn.Linear(32, 1),
            nn.Sigmoid()
        )
    
    def forward(self, x):
        return self.net(x)

# 训练循环(简化版)
model = AML_MLP(input_dim=20)
criterion = nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for epoch in range(50):
    outputs = model(X_train_tensor)
    loss = criterion(outputs, y_train_tensor)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

4.4.3 结果分析

训练完成后,我们在测试集上得到:

指标 数值
召回率 0.87
精确率 0.72
F1-Score 0.79
AUC-ROC 0.94

召回率87%意味着每100笔套现交易,我们能抓到87笔。剩下的13笔,嗯,需要配合规则引擎做二次过滤。

4.5 知识体系总览

下面这张图,是我梳理的本章核心逻辑:

MLP异常交易检测知识体系 交易特征输入(20维) 隐藏层1: 128 → ReLU → Dropout(0.3) 隐藏层2: 64 → ReLU → Dropout(0.3) 隐藏层3: 32 → ReLU 输出: Sigmoid → 异常概率 关键设计点: • 层数不宜超过4层 • Dropout防过拟合 • 正样本加权处理 • 评估看召回率

核心要点回顾:MLP在反洗钱场景中,关键在于处理好样本不平衡、选择合适的网络深度、以及用召回率而非准确率来评估模型。记住:抓不到异常比误报更可怕。

个人小建议:如果你刚开始做反洗钱模型,先用MLP跑通基线。等业务方认可了,再考虑上更复杂的模型。这样沟通成本最低,效果也最可控。

专注资料整理