XGBoost、LSTM、Transformer 在时序异常检测中的原理与选型
背景
在构建基于机器学习的异常流量识别系统时,常见的模型选择包括 XGBoost、LSTM 和 Transformer。三者的适用场景、资源要求和数据预处理方式差异显著。本文从原理出发,结合实际工程约束,给出清晰的选型依据和预处理方案。
一、三种模型的原理
1.1 XGBoost
XGBoost 是**梯度提升决策树(GBDT)**的高效实现。核心思想是用多棵决策树迭代拟合"残差"------每棵新树专注于修正前一棵树的错误。
特征向量 [f1, f2, f3, ...]
↓
Tree 1 → Tree 2 → ... → Tree N
↓
预测输出(如 bot 概率)
关键特性:
- 每一行样本是独立的,不感知时间顺序
- 时序信息需要人工计算成特征(如请求数标准差、峰谷比)后再传入
- 对特征量纲不敏感,无需归一化
适合场景: 特征工程完善、样本量有限(千级即可)、需要可解释性、资源受限的环境。
1.2 LSTM(Long Short-Term Memory)
LSTM 是 RNN(循环神经网络)的改进版,专为序列数据设计。其核心是三个"门"控制信息的保留与遗忘:
| 门 | 作用 |
|---|---|
| 遗忘门(Forget Gate) | 决定上一时刻的记忆保留多少 |
| 输入门(Input Gate) | 决定当前输入写入多少到记忆 |
| 输出门(Output Gate) | 决定输出记忆的哪部分 |
在时序异常检测中,LSTM 以同一个 IP 在连续时间窗口的特征序列作为输入:
IP 1.2.3.4 在过去 24 小时,每小时一个特征向量:
[t-23的特征] → [t-22的特征] → ... → [t的特征]
↕ hidden state 在时间步之间传递
↓
bot 概率
能捕捉 XGBoost 捕捉不到的模式:
- "白天休眠、夜间爆发"的节律型 bot
- "先伪装正常行为、再突然攻击"的潜伏型 bot
- 请求速率的趋势变化(加速 / 减速模式)
适合场景: 有足够长的每 IP 历史序列(几天到几周)、训练集 10 万+ 样本、有 GPU 资源。
1.3 Transformer
Transformer 放弃了递归结构,改用自注意力机制(Self-Attention),让每个时间步直接与所有其他时间步计算相关性权重:
t-23 ←→ t-22 ←→ ... ←→ t
(所有时间步两两计算注意力分数,并行处理)
相比 LSTM 的优势:
- 训练可完全并行,速度更快
- 能捕捉任意距离的时间依赖,不存在 RNN 的梯度消失问题
- 数据量充足时精度更高
代价:
- 数据需求更大(百万级样本)
- GPU 是必选项
- 模型可解释性极低
二、三种模型的横向对比
| 维度 | XGBoost | LSTM | Transformer |
|---|---|---|---|
| 输入形式 | 一行特征向量 | IP 的时序特征序列 | IP 的时序特征序列 |
| 时间感知 | 否(人工特征工程) | 是 | 是 |
| 训练数据量 | 1000+ 样本 | 10 万+ 序列样本 | 100 万+ |
| 硬件要求 | 2 核 CPU,1GB 内存 | GPU 强烈推荐 | GPU 必选 |
| 训练时间 | 分钟级 | 小时级 | 天级 |
| 推理延迟 | 毫秒级 | 毫秒~秒级 | 毫秒~秒级 |
| 可解释性 | 高(feature importance) | 低 | 极低 |
| 部署复杂度 | 极低(单模型文件) | 中(需 PyTorch/TF) | 高 |
三、数据预处理要求
3.1 归一化 / 标准化
XGBoost 不需要,神经网络必须做。
原因:决策树按"大于/小于某个值"分裂,不在乎量纲;而梯度下降对特征量纲极为敏感,量级差距大会导致收敛极慢甚至发散。
典型特征的量纲差异举例:
| 特征 | 典型范围 | 是否需要缩放 |
|---|---|---|
req_count |
3 ~ 100000 | 是 |
avg_body_bytes |
100 ~ 500000 | 是 |
avg_req_time_ms |
1 ~ 5000 | 是 |
uri_diversity |
0 ~ 1 | 可选(统一处理) |
error_ratio |
0 ~ 1 | 可选(统一处理) |
推荐使用 Z-score 标准化:
python
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
# 推理时:X_test_scaled = scaler.transform(X_test)
相比 Min-Max 归一化,Z-score 对离群点(极端攻击 IP)更鲁棒。
注意 :scaler 必须只在训练集上
fit,推理时用同一个 scalertransform,不能对测试集重新 fit。
3.2 Embedding
Embedding 将离散/类别变量映射为可学习的稠密向量。连续数值特征归一化后直接输入即可,不需要 Embedding。
| 特征类型 | 示例 | 处理方式 |
|---|---|---|
| 连续数值 | req_rate、uri_diversity | 标准化后直接输入 |
| 类别变量 | cluster_name、ASN 编号 | Embedding(维度约 4-16) |
| 周期性时间 | 小时(0-23)、星期(0-6) | 正弦/余弦编码,或 Embedding |
周期性时间特征推荐正弦/余弦编码,保留周期性连续性:
python
hour = 14 # 下午2点
hour_sin = math.sin(2 * math.pi * hour / 24)
hour_cos = math.cos(2 * math.pi * hour / 24)
3.3 Positional Encoding(Transformer 专有)
Transformer 的自注意力机制是无序的,需要额外注入位置信息。LSTM 天然按序处理,不需要。
标准正弦位置编码:
python
PE(pos, 2i) = sin(pos / 10000^(2i / d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i / d_model))
将位置编码与输入特征向量相加后送入 Transformer。
3.4 序列数据的组织方式
LSTM 和 Transformer 需要将数据从"一行=一个样本 "重组为"N行=一个样本":
python
# XGBoost:直接从 features 表取一行
# LSTM/Transformer:取同一 IP 的历史序列
def build_sequence(ip, window_size=3600, seq_len=24):
rows = db.query("""
SELECT req_rate, uri_diversity, same_subnet_count, ...
FROM features
WHERE ip = ? AND window_size = ?
ORDER BY window_ts DESC
LIMIT ?
""", ip, window_size, seq_len)
return np.array(rows) # shape: [seq_len, num_features]
如果按小时窗口取 24 个时间步、24 个特征,则每个 IP 的输入张量形状为 [24, 24]。
四、预处理操作汇总
| 操作 | XGBoost | LSTM | Transformer |
|---|---|---|---|
| 标准化 / 归一化 | 不需要 | 必须 | 必须 |
| 数值 Embedding | 不需要 | 不需要 | 不需要 |
| 类别 Embedding | 不需要 | 按需 | 按需 |
| Positional Encoding | 不需要 | 不需要 | 必须 |
| 数据重组为序列 | 不需要 | 必须 | 必须 |
五、选型建议
第一阶段(冷启动):首选 XGBoost
- 1000 个标注样本即可训练
- 2 核 CPU 分钟级完成训练
- 特征工程覆盖多时间尺度(通过 Rollup 计算 std、峰谷比等),已隐式编码时序信息
- 可解释性强,调试方便
升级到 LSTM 的时机:
- XGBoost 运行 3-6 个月后,发现某类 bot 反复漏判
- 已积累 10 万+ 标注样本
- 有独立 GPU 机器可用
features表中已有足够长的每 IP 历史序列
升级到 Transformer 的时机:
- LSTM 精度瓶颈明显
- 数据量达到百万级
- 有多卡 GPU 训练资源
关键认知: 多窗口特征工程(1分/5分/1时/1天 Rollup)+ XGBoost 能覆盖绝大多数 bot 检测场景,引入深度学习的收益边际递减,工程复杂度却大幅上升。优先把特征做扎实,而非过早引入复杂模型。