行为基线基础:正常行为建模思想
老实说,当初我刚接触异常检测时也犯过“见啥都觉得异常”的毛病。后来带我的老哥说了句话我一直记着:不知道什么正常,就别谈什么异常。这句话点醒了。行为基线,说白了就是给系统的“正常画个像”,然后让异常自己跳出来。
为什么非要先建基线?
你想想看,每个系统都有自己的脾气——访问量有高低峰,API调用有节假日效应,数据库连接数有昼夜规律。你要是拿一把死尺子去量,准出事。所以基线是从历史数据里长出来的活标准。它的核心思想就八个字:多数正常,少数异常。
我在一个电商监控项目里就吃过亏:硬件指标明明没变,报警却一天响几百次。后来发现——我拿的是全局均值当基线,但业务流量晚上8点翻三倍。那不是异常,那是正常规律。嗯,这坑我栽过,后面会细说。
正常行为建模的两个方向
建模方法归根结底两类:统计基线 和 时序基线。我建议你先把这两条路捋清楚,后面写算法才不会跑偏。
| 对比维度 | 统计基线 | 时序基线 |
|---|---|---|
| 核心理念 | 用概率分布描述整体 | 用时间模式描述变化 |
| 典型指标 | 均值、标准差、Z-score | 周期分量、趋势、残差 |
| 适用场景 | 指标稳定、无强周期 | 有日/W/季规律 |
| 建模方式 | 历史数据 → 统计量 | 历史序列 → 分解/预测 |
| 检测能力 | 发现离群点 | 发现模式偏离 |
| 缺点 | 忽略时间关联 | 对突变反应慢 |
核心原则:统计基线更“静”,时序基线更“动”。大部分复杂系统需要两者配合,我习惯先跑个时序分解看看趋势,再在残差上做统计检测。
统计基线:拿概率说话
这是最直观的做法。假设正常行为落在某个概率范围内,比如正态分布 ±3σ 内算正常。你只需要收集一段时间的历史数据,算均值和标准差就搞定了。
举个例子:某API每秒请求数,历史均值为200,标准差为15。那么Z-score = (当前值 - 200) / 15。 |Z| > 3,我就报异常。简单粗暴,但管用。
import numpy as np
# 假设历史数据
history = [205, 198, 210, 202, 195, 208, 200, ...]
mean = np.mean(history) # 约200
std = np.std(history) # 约15
# 实时检测
current = 240
z = (current - mean) / std # z ≈ 2.67
if abs(z) > 3:
print("异常:请求量激增")
else:
print("正常")
看起来很美好对吧?但小心两个坑:
- 数据本身就不服从正态分布——别硬套,我是吃过亏的。碰到长尾分布(比如文件大小),建议换成中位数+四分位距(IQR)。
- 统计基线无视时间顺序。你凌晨3点请求量20算异常吗?如果在深夜时段的历史分布里,20可能是正常。但你把全天数据混一起,20就变成离群点了。所以…
我曾经犯的错:拿24小时的总统计量去检测所有时段,结果白天报警少、夜里乱报警。后来老老实实加了个“时段分桶”,每小时的基线独立算。效果立刻好了。
时序基线:让规律自己说话
时序基线想解决的问题正是统计基线忽略的:时间关联。你的请求量、连接数、CPU使用率,今天8点的值和昨天8点的值高度相关,但和今天凌晨2点的值关系不大。
常见做法:
- 移动平均法:取过去N个点的滑动窗口均值作为期望值,残差 = 当前值 - 移动平均。残差超阈值就报警。
- 周期分解法(STL):把时间序列拆成趋势 + 季节 + 残差。残差异常就报。
- 预测类模型:如ARIMA、Holt-Winters。用历史拟合模型,预测下一个值,实际值和预测值的差 > 阈值则异常。
我记得在做一个IoT设备流量监控时,设备每周有固定固件升级流量脉冲。用统计基线怎么也调不平报警,换成时序分解后把“每周脉冲”当作季节分量抽掉,剩下的残差才真正代表异常。那感觉,就像把噪音滤掉了一样的清爽。
实践建议:如果业务有明显周期(比如工作日/周末),先对数据按周期分桶再建基线。分桶比高级模型更容易解释,出问题排查也快。
什么时候该用哪种?
我个人的经验法则:
- 指标波动平稳(如系统资源利用率)→ 统计基线足够。
- 指标有明显周期且周期稳定(如Web日活)→ 时序基线优先。
- 指标既平稳又有周期(如数据库QPS,白天高夜里低)→ 先分时段,每个时段内做统计基线。这是性价比最高的方案。
如果你刚起步,我强烈建议从分段统计基线开始:按小时、星期几分桶,每个桶内算均值+标准差。代码简单,效果好,排查问题也直观。等业务复杂了再叠加时序模型不迟。
建基线的实用检查清单
最后分享一份我每次上线前都会过一遍的清单:
- 数据是否干净? 去掉历史中的异常值再算基线,否则基线自己就是歪的。
- 时间规律是否考虑了? 周期、趋势、节假日,一个都不能少。
- 阈值是否可解释? 别用黑盒调参,Z=3还是IQR×1.5,必须能对业务讲清楚。
- 基线是否持续更新? 场景会漂移,建议每周/每月重新拟合一次。
再说句掏心窝的话:很多时候失败不是因为算法不够先进,而是基线构建阶段就把业务理解丢了。多和运维、业务聊聊天,比多看几篇管用。