多个体时间序列数据异常值检测建模方法及代码示例求助
多用户时间序列异常检测建模方案
核心思路
你的数据属于多实体时间序列异常检测场景,每个用户的序列长度、时间区间差异大,建模时要兼顾:
- 单用户内部的时序规律(比如用户自身的数值波动模式)
- 用户间的共性特征(比如不同用户的异常值共性表现)
训练时可选择两种路径:一是将每个时间步转化为带时序特征的独立样本,用传统分类模型;二是用序列模型直接捕捉用户的连续行为模式。
步骤拆解
1. 数据预处理
- 按
x1(用户ID)分组,确保每个用户的序列按x2(datetime)升序排列 - 生成关键特征:
- 滞后特征:
x3的前1/2/3步值(捕捉短期波动) - 滚动统计量:近n步的均值、方差、极值(捕捉用户的正常波动范围)
- 时间特征:星期几、月份、是否工作日(如果数据粒度到天/小时)
- 滞后特征:
- 处理缺失值:滞后/滚动特征会导致序列开头出现缺失,可直接删除这些行,或对极短序列用简单插值填充
2. 模型选择
方案一:传统机器学习(推荐标签充足时使用)
把每个时间步作为独立样本,用户ID可作为类别特征输入,用XGBoost、Random Forest这类对类别特征友好的模型。优势是训练快、易解释,适合序列较短的用户。
方案二:深度学习序列模型(适合长序列用户)
用LSTM、Transformer捕捉序列依赖关系,以用户的连续时间窗口为输入,输出每个时间步的异常概率。优势是能更好捕捉复杂的时序模式,但对短序列效果差,训练成本高。
Python代码示例
传统XGBoost实现
import pandas as pd import numpy as np from xgboost import XGBClassifier from sklearn.metrics import precision_recall_fscore_support # 加载并预处理数据 df = pd.read_csv('your_dataset.csv') df['x2'] = pd.to_datetime(df['x2']) df = df.sort_values(['x1', 'x2']) # 生成时序特征 df['lag1'] = df.groupby('x1')['x3'].shift(1) df['lag2'] = df.groupby('x1')['x3'].shift(2) df['roll_mean_3'] = df.groupby('x1')['x3'].rolling(3).mean().droplevel(0) df['roll_std_3'] = df.groupby('x1')['x3'].rolling(3).std().droplevel(0) df['day_of_week'] = df['x2'].dt.dayofweek # 移除缺失值 df = df.dropna().reset_index(drop=True) # 拆分训练/测试用户 all_users = df['x1'].unique() train_users = all_users[:800] test_users = all_users[800:] train_df = df[df['x1'].isin(train_users)] test_df = df[df['x1'].isin(test_users)] # 准备特征与标签 X_train = train_df.drop(['x1', 'x2', 'x4'], axis=1) y_train = train_df['x4'] X_test = test_df.drop(['x1', 'x2', 'x4'], axis=1) y_test = test_df['x4'] # 训练模型(处理类别不平衡) model = XGBClassifier( scale_pos_weight=len(y_train[y_train==0])/len(y_train[y_train==1]), use_label_encoder=False, eval_metric='logloss' ) model.fit(X_train, y_train) # 评估 y_pred = model.predict(X_test) precision, recall, f1, _ = precision_recall_fscore_support(y_test, y_pred, average='binary') print(f"Precision: {precision:.2f}, Recall: {recall:.2f}, F1-Score: {f1:.2f}")
LSTM序列模型实现
import tensorflow as tf from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, LSTM, Dense, Dropout from sklearn.metrics import precision_recall_fscore_support WINDOW_SIZE = 5 # 序列窗口大小 # 生成序列样本的函数 def build_sequences(user_data, window_size): X, y = [], [] for i in range(window_size, len(user_data)): # 取窗口内的特征 seq_features = user_data[['x3', 'lag1', 'roll_mean_3', 'day_of_week']].iloc[i-window_size:i].values X.append(seq_features) y.append(user_data['x4'].iloc[i]) return np.array(X), np.array(y) # 准备训练序列 X_train_seq, y_train_seq = [], [] for user in train_users: user_df = train_df[train_df['x1'] == user] if len(user_df) >= WINDOW_SIZE: x, y = build_sequences(user_df, WINDOW_SIZE) X_train_seq.append(x) y_train_seq.append(y) X_train_seq = np.concatenate(X_train_seq) y_train_seq = tf.keras.utils.to_categorical(np.concatenate(y_train_seq), num_classes=2) # 构建LSTM模型 input_layer = Input(shape=(WINDOW_SIZE, X_train_seq.shape[2])) lstm_out = LSTM(64, return_sequences=False)(input_layer) dropout_out = Dropout(0.2)(lstm_out) output_layer = Dense(2, activation='softmax')(dropout_out) model = Model(inputs=input_layer, outputs=output_layer) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) # 训练(处理类别不平衡) model.fit( X_train_seq, y_train_seq, epochs=10, batch_size=32, class_weight={0:1, 1:10} # 异常值权重设为10 ) # 测试集预测 X_test_seq, y_test_seq = [], [] for user in test_users: user_df = test_df[test_df['x1'] == user] if len(user_df) >= WINDOW_SIZE: x, y = build_sequences(user_df, WINDOW_SIZE) X_test_seq.append(x) y_test_seq.append(y) X_test_seq = np.concatenate(X_test_seq) y_test_seq = np.concatenate(y_test_seq) y_pred_prob = model.predict(X_test_seq) y_pred = np.argmax(y_pred_prob, axis=1) precision, recall, f1, _ = precision_recall_fscore_support(y_test_seq, y_pred, average='binary') print(f"Precision: {precision:.2f}, Recall: {recall:.2f}, F1-Score: {f1:.2f}")
关键注意点
- 类别不平衡处理:异常值(x4=1)通常占比低,必须设置类别权重,避免模型偏向正常样本
- 短序列用户处理:对于序列长度小于窗口大小的用户,建议用统计方法(比如3σ原则)单独检测,或在预处理时过滤/合并
- 特征工程优化:可根据业务场景添加更多特征,比如用户的历史均值、数值突变幅度等
内容的提问来源于stack exchange,提问作者JHoon
相关产品推荐
相关产品推荐

