You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多个体时间序列数据异常值检测建模方法及代码示例求助

多用户时间序列异常检测建模方案

核心思路

你的数据属于多实体时间序列异常检测场景,每个用户的序列长度、时间区间差异大,建模时要兼顾:

  • 单用户内部的时序规律(比如用户自身的数值波动模式)
  • 用户间的共性特征(比如不同用户的异常值共性表现)
    训练时可选择两种路径:一是将每个时间步转化为带时序特征的独立样本,用传统分类模型;二是用序列模型直接捕捉用户的连续行为模式。

步骤拆解

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:09:50