Time Series Anomaly Detection for E-Commerce Monitoring
Skill-Time-Series-Anomaly-Detection · 03-时间序列
experimentforecastingfraud_detection其他
实现难度⭐⭐☆☆☆
业务优先级⭐⭐☆☆☆
业务视角
适用角色供应链负责人 / 采购负责人 · 运营负责人 · 财务负责人
适用平台Amazon FBA · 海外仓 · 多市场多仓
什么情况下用大促前备货总是不是多了就是少了;新品上线第一个月断货,再补又积压;年底预算不知道各月目标怎么定
成功是什么样的提前 4-8 周准确预判各 SKU 需求峰值,库存积压减少 30%,断货率降低 50%
业务痛点
1. 解决的问题
母婴出海电商的关键指标(GMV、订单量、转化率、退货率)时刻波动。
2. 核心算法逻辑
核心问题:母婴出海电商的关键指标(GMV、订单量、转化率、退货率)时刻波动。如何区分"正常波动"和"真实异常"?异常检测的本质是:建立正常行为的概率模型,将低概率事件标记为异常。
3. 业务应用场景
业务问题:Momcozy 的日订单量通常在500-800单之间波动。某天订单量突然降到200单——是系统Bug、支付通道故障、还是正常的市场波动?
检测流程: 1. 数据预处理:取过去90天日订单量 2. STL分解:分离趋势、季节性(周内模式)、残差 3. 残差异常检测:残差超过3倍标准差标记为异常 4. 上下文校验:检查当天是否为节假日、是否有已知促销活动 5. 多指标交叉验证:同时检查转化率、客单价是否同步异常
预期产出: - 异常检测:订单量残差 = -4.2σ → 标记为异常 - 根因定位:转化率正常,但支付成功率从98%降到72% → 支付通道故障 - 告警延迟:<30分钟(实时检测)
4. 输入数据要求
请查看原始代码模板获取输入规格。
5. 输出结果
请查看原始代码模板获取输出规格。
6. 业务价值 / ROI
- 数据要求:只需要单变量时序数据
- 技术门槛:低,STL和Isolation Forest都有现成实现
- 主要挑战:调参(阈值设定)和减少误报
- 刚需监控能力:任何数据驱动业务都需要异常检测
- 实施成本低:现成算法,1周内可上线
- 高杠杆:30分钟发现故障 vs 4小时发现,差异巨大
7. 代码模板
代码块数量:1 · 路径:未检测到
"""
Time Series Anomaly Detection — 时序异常检测
用于电商关键指标的监控与告警
支持:STL分解、Isolation Forest、Prophet区间检测
"""
import numpy as np
import pandas as pd
from sklearn.ensemble import IsolationForest
from statsmodels.tsa.seasonal import STL
import warnings
warnings.filterwarnings('ignore')
# ==================== 统计方法:STL + Z-Score ====================
class STLAnomalyDetector:
"""基于STL分解的异常检测器"""
def __init__(self, period=7, threshold=3.0):
"""
Args:
period: 季节性周期(7=周,30=月)
threshold: Z-Score阈值
"""
self.period = period
self.threshold = threshold
self.stl = None
def fit(self, series):
"""拟合STL模型"""
self.series = series
self.stl = STL(series, period=self.period, robust=True).fit()
self.residual_mean = self.stl.resid.mean()
self.residual_std = self.stl.resid.std()
return self
def predict(self, series=None):
"""预测异常"""
if series is None:
resid = self.stl.resid
else:
# 对新数据,用趋势+季节性作为基线,计算残差
# 简化:假设新数据的趋势/季节性与训练期最后一段相同
last_trend = self.stl.trend.iloc[-self.period:].mean()
last_seasonal = self.stl.seasonal.iloc[-self.period:].values[:len(series)]
resid = series - last_trend - last_seasonal[:len(series)]
z_scores = (resid - self.residual_mean) / (self.residual_std + 1e-8)
anomalies = np.abs(z_scores) > self.threshold
return {
'is_anomaly': anomalies,
'z_scores': z_scores,
'residuals': resid,
'trend': self.stl.trend if series is None else None,
'seasonal': self.stl.seasonal if series is None else None
}
8. 论文来源
未自动抽取;请查看原始 Skill 卡片。