时间序列异常检测分析

异常检测是数据分析中的一个重要环节,它涉及到识别那些与数据集整体行为显著偏离的数据点。在训练模型之前进行异常检测尤为有用,例如在欺诈检测、垃圾邮件过滤、CPU使用异常检测以及服务器使用异常检测等领域都有应用。

时间序列数据的特点

时间序列数据是指与时间戳相关联的数据观测值,这些数据是按顺序排列的,因此在训练过程中不能打乱数据顺序。时间序列数据中的观测值具有自相关性,即观测值与其之前的观测值高度相关。由于这些限制,时间序列数据需要特殊处理。

时间序列异常检测

在时间序列数据中检测异常时,不能使用传统的异常检测算法,如IQR、Isolation Forest、COPOD等。需要采用特别的方法来处理时间序列异常检测任务。

首先,检查数据是否是平稳的。如果不是平稳的,需要将数据转换为平稳的。然后,对预处理后的数据拟合一个时间序列模型。接着,为数据中的每个观测值找到平方误差,并确定误差的阈值。如果误差超过了这个阈值,可以将该观测值标记为异常。

之所以采用这种方法,是因为时间序列数据是严格顺序的,并且容易受到自相关的影响。时间序列模型会使用数据来训练并找到数据的一般行为,并尝试预测数据。如果一个观测值是正常的,预测值会尽可能接近实际值;如果一个观测值是异常的,预测值会尽可能远离实际值。因此,通过检查预测的误差,可以在数据中找到异常。

单变量与多变量时间序列数据

单变量时间序列数据只包含一个特征(或列)和一个与之相关的时间戳列。多变量时间序列数据包含多个特征和一个与之相关的时间戳列。本文将讨论单变量时间序列异常检测

将使用Kaggle上的“Air Passengers”数据集作为例子。该数据集包含了每个月登机的乘客数量,包含两个列:月份和乘客数量。

import pandas as pd data = pd.read_csv('AirPassengers.csv') data = data.set_index('Month') print(data)

首先,使用增广迪基-富勒(ADF)测试来检查数据是否平稳。测试结果将显示数据是否平稳。ADF测试返回的统计数据中包含p值,p值用于确定数据是否平稳。如果p值小于0.05,则数据是平稳的;如果p值大于0.05,则数据是非平稳的。0.05被称为显著性水平,对应于95%的置信度。也可以尝试不同的显著性水平来测试平稳性。

test_stationarity(data, 'Passengers') # 输出:非平稳

测试结果显示数据是非平稳的,这意味着数据没有恒定的均值、方差和自相关性。为了将数据转换为平稳的,可以对数据进行差分处理。

def differencing(data, column, order):   differenced_data = data[column].diff(order)   differenced_data.fillna(differenced_data.mean(), inplace=True)   return differenced_data preprocessed_data = differencing(data, 'Passengers', 1)

上述代码将对数据进行差分处理,使数据变得平稳。现在可以使用ADF测试来检查差分后的数据是否平稳。

test_stationarity(preprocessed_data, series=True) # 输出:平稳

经过差分处理后,数据变得平稳。现在可以使用这些数据来训练时间序列模型。

在这里,将使用ARMA(自回归移动平均)模型来预测数据。ARMA模型有两个参数,分别是p和q。p用于AR(自回归),q用于MA(移动平均)。自回归使用数据的滞后值来建模数据,而移动平均使用之前的预测误差来建模数据。

自回归使用数据的滞后值作为特征,提供的数据作为目标,并使用最小二乘法(或线性回归)来建模数据之间的关系。如前所述,使用这个模型来建模严格顺序的并且具有自相关的时间序列数据。不能直接使用最小二乘法或线性回归,因为残差的自相关会导致虚假的预测。这就是为什么使用专门为时间序列数据构建的特殊模型。

为了找到模型的最佳阶数(p, q),需要选择能够降低模型AIC的阶数(p, q)。可以使用以下代码来找到它。

max_p, max_q = 5, 5 # ...(省略部分代码) min_aic, min_order, results_df = find_best_order_for_model( preprocessed_data, ARMA, "ARMA" ) print(min_aic, min_order) # 输出:1341.1035677173795, (4, 4)

上述代码如何工作?需要提供p和q的最大值来探索。上述代码将为不同的p和q值拟合模型,并记录每个模型的AIC。在这里,使用了多线程来加速代码执行。完成最佳阶数的寻找后,可以使用最小AIC值来拟合ARMA模型。

def find_anomalies(squared_errors):   threshold = np.mean(squared_errors) + np.std(squared_errors)   predictions = (squared_errors >= threshold).astype(int)   return predictions, threshold arma = ARMA(preprocessed_data, order=min_order) arma_fit = arma.fit() squared_errors = arma_fit.resid ** 2 predictions, threshold = find_anomalies(squared_errors) # 阈值 = 1428.0094261298002

使用(4, 4)阶来拟合模型。拟合结果的resid属性将包含每个观测值和预测的残差。使用以下公式来找到平方误差的阈值,超过该阈值的数据被认为是异常的。

data['predictions'] = predictions print(data)
  • 确定数据是否平稳。
  • 如果数据不平稳,使用差分将其转换为平稳数据。
  • 找到ARMA模型的最佳阶数。
  • 拟合ARMA模型并找到平方误差。
  • 使用平方误差找到阈值。
  • 超过阈值的误差被认为是异常数据。
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485