更新:
2020/09/02:新增一篇写的很好的关于视频监控异常检测的学报http://jst.tsinghuajournals.com/CN/rhhtml/20200609.htmjst.tsinghuajournals.com
一. 介绍
异常检测(Anomaly detection)是目前时序数据分析最成熟的应用之一,定义是从正常的时间序列中识别不正常的事件或行为的过程。有效的异常检测被广泛用于现实世界的很多领域,例如量化交易,网络安全检测、自动驾驶汽车和大型工业设备的日常维护。以在轨航天器为例,由于航天器昂贵且系统复杂,未能检测到危险可能会导致严重甚至无法弥补的损害。异常随时可能发展为严重故障,因此准确及时的异常检测可以提醒航天工程师今早采取措施。
1.1 判断异常的方法异常类型:异常检测:
- 直接检测:针对点异常,直接定位离群点
- 间接检测:上下文或集合异常先转化成点异常,然后再求解
时间跨度: ARIMA, MA, 回归模型,指数光滑等
序列跨度:许多传感器应用程序产生的时间序列通常彼此紧密相关。例如,在一个传感器上的鸟叫通常也会被附近的传感器记录下来。在这种情况下,经常可以使用一个序列来预测另一个序列。与此类预期预测的偏差可以报告为异常值。隐式马尔科夫链HMM等
1.2 ARIMA类算法详解:预处理
a) 对于纯随机序列,也称为白噪声序列,序列的各项之间没有任何的关系, 序列在进行完全无序的随机波动, 可以终止对该序列的分析。
b) 对于平稳非白噪声序列, 它的均值和方差是常数。ARMA 模型是最常用的平稳序列拟合模型。
c) 对于非平稳序列, 由于它的方差和均值不稳定, 处理方法一般是将其转化成平稳序列。 可以使用ARIMA 模型进行分析。预处理流程建模
a) AR 自回归模型:描述当前值与历史值之间的关系, 用变量自身的历史时间数据对自身进行预测。自回归模型必须满足平稳性的要求。
公式定义:
自回归模型的限制:
1.自回归模型是使用自身的数据进行预测的
2.必须具有平稳性
3.必须具有相关性,如果相关性小于 0.5 , 则不宜使用
4.自回归模型只适用于预测与自身前期相关的预测。
b) MA(移动平均模型):•移动平均模型关注的是自回归模型中的误差项的累加
•移动平均法能有效地消除预测中的随机波动。
c) ARIMA(p,d,q)差分自回归移动平均模型(Autoregressive Integrated Moving Average Model ,简称ARIMA)
自回归和移动平均的结合。
AR 是自回归, p 是自回归项, MA 是移动平均, q 为移动平均项, d 为时间序列称为平稳时 所做的差分次数。
原理: 将非平稳时间序列转换成平稳时间序列, 然后将因变量仅对它的滞后值(p阶)以及随机误差项的现值和滞后值进行回顾所建立的模型。实例:使用ARIMA 模型对某餐厅的销售数据进行预测
#coding=gbk
#使用ARIMA 模型对非平稳时间序列记性建模操作
#差分运算具有强大的确定性的信息提取能力, 许多非平稳的序列差分后显示出平稳序列的性质, 这是称这个非平稳序列为差分平稳序列。
#对差分平稳序列可以还是要ARMA 模型进行拟合, ARIMA 模型的实质就是差分预算与 ARMA 模型的结合。
#导入数据
import pandas as pd
filename = r'D:\datasets\arima_data.xls'
data = pd.read_excel(filename, index_col = u'日期')
#画出时序图
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #定义使其正常显示中文字体黑体
plt.rcParams['axes.unicode_minus'] = False #用来正常显示表示负号
# data.plot()
# plt.show()
#画出自相关性图
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# plot_acf(data)
# plt.show()
#平稳性检测
from statsmodels.tsa.stattools import adfuller
print('原始序列的检验结果为:',adfuller(data[u'销量']))
#原始序列的检验结果为: (1.8137710150945268, 0.9983759421514264, 10, 26, {'1%': -3.7112123008648155,
# '10%': -2.6300945562130176, '5%': -2.981246804733728}, 299.46989866024177)
#返回值依次为:adf, pvalue p值, usedlag, nobs, critical values临界值 , icbest, regresults, resstore
#adf 分别大于3中不同检验水平的3个临界值,单位检测统计量对应的p 值显著大于 0.05 , 说明序列可以判定为 非平稳序列
#对数据进行差分后得到 自相关图和 偏相关图
D_data = data.diff().dropna()
D_data.columns = [u'销量差分']
D_data.plot() #画出差分后的时序图
# plt.show()
plot_acf(D_data) #画出自相关图
# plt.show()
plot_pacf(D_data) #画出偏相关图
# plt.show()
print(u'差分序列的ADF 检验结果为: ', adfuller(D_data[u'销量差分'])) #平稳性检验
#差分序列的ADF 检验结果为: (-3.1560562366723537, 0.022673435440048798, 0, 35, {'1%': -3.6327426647230316,
# '10%': -2.6130173469387756, '5%': -2.9485102040816327}, 287.5909090780334)
#一阶差分后的序列的时序图在均值附近比较平稳的波动, 自相关性有很强的短期相关性, 单位根检验 p值小于 0.05 ,所以说一阶差分后的序列是平稳序列
#对一阶差分后的序列做白噪声检验
from statsmodels.stats.diagnostic import acorr_ljungbox
print(u'差分序列的白噪声检验结果:',acorr_ljungbox(D_data, lags= 1)) #返回统计量和 p 值
# 差分序列的白噪声检验结果: (array([11.30402222]), array([0.00077339])) p值为第二项, 远小于 0.05
#对模型进行定阶
from statsmodels.tsa.arima_model import ARIMA
pmax = int(len(D_data) / 10) #一般阶数不超过 length /10
qmax = int(len(D_data) / 10)
bic_matrix = []
for p in range(pmax +1):
temp= []
for q in range(qmax+1):
try:
temp.append(ARIMA(data, (p, 1, q)).fit().bic)
except:
temp.append(None)
bic_matrix.append(temp)
bic_matrix = pd.DataFrame(bic_matrix) #将其转换成Dataframe 数据结构
p,q = bic_matrix.stack().idxmin() #先使用stack 展平, 然后使用 idxmin 找出最小值的位置
print(u'BIC 最小的p值 和 q 值:%s,%s' %(p,q)) # BIC 最小的p值 和 q 值:0,1
#所以可以建立ARIMA 模型,ARIMA(0,1,1)
model = ARIMA(data, (p,1,q)).fit()
model.summary2() #生成一份模型报告
model.forecast(5) #为未来5天进行预测,返回预测结果、标准误差和置信区间
利用模型向前预测的时期越长, 预测的误差就会越大,这是时间预测的典型特点
二. 时间序列的特征工程
首先,连续特征我们可以直接使用,离散特征使用one-hot编码进行转换。然后可以根据不同的思路去做特征工程:常见的时间序列特征构造思路
2.1 特征工程
a) 统计特征max、min、interval
avg、median
variance、偏度、峰度
峰度(Kurtosis mesure)是一种用来衡量一列数据(单变量)离群度的特征量。第一步是计算均值μ和标准差σ,
并将数据标准化为0均值和单位1的方差: _ =( _ − )/ 然后计算Zi四次幂的平均值,得到峰度如下:K( _1… _ )=(∑2_( =1)^ 〖 _ 〗^4 )/同比、环比
重复值
b) 拟合特征移动平均算法
带权重的移动平均算法
1/2/3次指数移动平均算法
SVD算法
线性拟合
自回归:AR/MA/ARMA/ARIMA/卡尔曼滤波器
c) 时域特征自相关,偏相关系数
差分
赫斯特指数
趋势、周期
噪声
d) 频域特征小波分析特征(大象流/老鼠流):小波变换系数、变换波峰数、变换均值
傅里叶变换偏度、峰度、方差、系数等
2.2 特征选择的方法
a)相关度(筛除无关特征)
相关度(Correlation)挑选的方法的基本的思想是:通常离群点是那些违反了正常数据依赖关系下模型的点,而无关的特征是不能用来单独建模的,反而会影响模型准确性。因此,我们首先可以通过回归模型利用其他特征来预测某一个特征,如果均方根误差RMSE很大,说明这个特征和其他特征相关度非常低,应该被剔除。
方法:将所有的特征标准化,然后分别利用其他的特征来预测第k(k=1…N)个特征,得到均方根误差RMSE_k = √(E((θ ̂-θ)^2 ))如果RMSE_k 大于1,则预测误差大于特征的方差,此时这个第k特征应当剔除。我们也可以用这种方法,通过给予权重来衡量特征的重要性。通常,第 k特征的权重为max{ 0,1-RMSE_k}。
b)PCA 主成分分析:(筛除多重共线性特征)
去除平均值->计算协方差矩阵->计算协方差矩阵的特征值和特征向量->将特征值从大到小排序->保留最大的N个特征值以及它们的特征向量
三. 异常检测算法
3.1 经典算法:
3.1.1 基于统计(假设高斯分布):
a) 针对单变量数据:
a).1 集中不等式:集中不等式是数学中的一类不等式,描述了一个随机变量是否集中在某个取值附近马尔可夫不等式: 给出了一个实值随机变量取值大于等于某个特定数值的概率的上限。设X是一个随机变量,a>0为正实数,那么以下不等式成立:比切雪夫不等式:马尔可夫不等式给出了随机变量处于区间 [a,+inf] 概率的上限估计。切比雪夫不等式则给出了随机变量集中在距离其数学期望值距离不超过a的区间上之概率的上限估计:
a).2 统计置信度检验:3-sigma: (μ−3σ,μ+3σ)区间内的概率为99.74。所以可以认为,当数据分布区间超过这个区间时,即可认为是异常数据。n-sigma异常检测准则t检验,f检验,卡方检验:检验一个正态分布的总体的均值是否在满足H0假设的值之内
b) 针对多变量数据:
b).1 马氏距离:用来计算样本X与中心点μ的距离,也可以用来做异常分值,计算方式:
马氏距离最强大的地方是引入了数据之间的相关性(协方差矩阵)。 而且马氏距离不需要任何参数,这对无监督学习来说无疑是一件很好的方法。通常一个简单的最近邻算法加上马氏距离就可以秒杀很多复杂的检测模型。
(马氏距离+ KNN)DaiDongyang/knngithub.com
3.1.2 基于相似度量:
a) 基于距离:KNN:
输入数据集D,参数k,n->对于每个点计算它的k邻近距离->按照距离降序排序->前N个点认为是离群点
b) 基于密度:LOF(Local Outlier Factor):局部离群因子检测方法,该算法会给数据集中的每个点计算一个离群因子
通过判断LOF是否接近于1来判定是否是离群因子。若LOF远大于1,则认为是离群因子,接近于1,则是正常点。LOF离群因子分布图
(LOF计算方法):刘腾飞:机器学习-异常检测算法(二):Local Outlier Factorzhuanlan.zhihu.com
KDE 核密度估计:所谓核密度估计,就是采用平滑的峰值函数(“核”)来拟合观察到的数据点,从而对真实的概率分布曲线进行模拟:
核密度函数的原理也比较简单,“核”是一个函数,用来提供权重。例如高斯函数 (Gaussian) 就是一个常用的核函数,如果某一个数在观察中出现了,我们可以认为这个数的概率密度很大,和这个数比较近的数的概率密度也会比较大,而那些离这个数远的数的概率密度会比较小。
(KDE计算方法)非参数估计:核密度估计KDE_皮皮blog-CSDN博客_python kdeblog.csdn.net
c) 基于聚类:K-means,GMM
缺点:聚类参数难界定,导致检测效果偏差;聚类训练开销较大
d) 基于树:孤立森林(Isolation Forest)
基于集成学习(Ensemble),适用于连续数据的异常检测,通过多颗iTree形成森林来判定是否有异常点;这种方法很有效,但是并不总是有用的,比如说数据的分布不是沿着特征轴,而是随意分布,或者流型分布,就需要选择别的方式了。iTree伪代码IF模型结构示意图
f) 基于谱(线性模型):通过与正常谱型进行残差对比,发现异常
简单的线性模型就是相关性分析。利用一些自变量来预测因变量。比较重要的一个应用就是时序数据或者空间轨迹数据。我们可以利用上一个值或者上几个值来预测当前值,将预测值和实际值的误差作为优化对象,这样就建立了一个正常数据的模型,背离这个模型的就被当作异常值,预测值和实际值的误差也可以作为异常分值来提供One-class SVM 矩阵分解法:
(无监督,解决极度不平衡数据)
严格地讲,OneClassSVM不是一种异常点检测方法,而是一种奇异值检测方法,因为它的训练集不应该掺杂异常点(训练集只有一类),否则的话,可能在训练时影响边界的选取。 但在数据维度很高,或者对相关数据分布没有任何假设的情况下,OneClassSVM也可以作为一种很好的outlier detection方法。Replicator Neural Networks and Deep Autoencoders:
基于神经网络(需要构造必要特征)适用于连续数据的异常检测,并通过寻找神经网络的重构误差来区分正常点和异常点。
接着,我们可以通过训练样本库中人工标注的数据得到多种有监督模型,比如
逻辑回归/线性回归/决策树/RF/BGDT
四、变量处理方法
(非数值型变量:categorical,text,mixed data)
极值分析和统计算法依赖于统计量化,例如均值或者标准差,对于非数值型变量,这些统计量化将不再有意义;但通过一些改变我们就能将上面介绍的模型拓展为适用于非数值型变量的模型。
4.1 统计概率模型:
唯一的区别就是变量不再默认服从特定分布(如高斯),而需要单独定义概率分布(按比例),并按乘积方式与数 值变量组合以创建单个多元分布。
4.2 线性模型:
1.One-hot码二进制转换,一个值对应一个种类,但容易维度爆炸,且无法体现不同类别的不同权重。可以通过将每列除以其标准偏差(deviation)来进行归一化。
2.潜在语义分析(Latent Semantic Analysis)
4.3 基于相似度量模型:
a) 基于距离:
1.基于非数值属性的统计频率计算相似度,比如稀有属性的匹配比常规属性的匹配权重要高。
2.基于数据的统计邻域计算相似度,比如文本变量中“红色”和“橙色”比“红色”和“蓝色”更相近,但要求人为区分属性值之间的语义关系。
b) 基于密度:基于密度的方法可以自然地扩展到离散数据,因为通常数值属性也将离散化以创建频率曲线。
(邻域相似度计算方法)
五、几种深度学习的思路
5.1 基于Transformer掩码重建的时序数据异常检测算法(pyTorch)
有关Transformer的基础知识可以参考我的另一篇学习笔记VoidOc:PyTorch框架学习笔记(二) —— Transformerzhuanlan.zhihu.com
5.1.1 如何重建?
对于大部分重建的时间步而言,模型事实上是从整段时间序列中取一段长度来重建下一步(LSTM信息传播的步数是有限的)。重建序列是将一步步的预测拼接而成一段完整的序列,如图 3(a)所示。也就是说,这一过程是单向的,仅有重建时间步之前的数据影响了重建的这一时间步。图3(a)
而 Transformer 与传统的基于 RNN 的模型不同。一次性读取整段时序数据。在 NLP 任务中,模型可以从一个单词的左右文字学习这个单词的作用。因此设想了一种新的数据输入输出的方式,即图 3(b)。获取一段完整序列并分割成小序列时,不是重建这一段小序列的最后一节数据,而是预测这一段小序列的中间一节数据。这样就可以使用重建数据的左右两边的信息来重建。图3(b)
5.1.2 模型结构?
受 Mask Language Modelling 启发,有人提出Mask Time Series Modeling ,一种基于时序数据的重建。 模型结构如下:掩码时序建模
对于输入序列X = [ 1, 2,…, ],选择其中将要重建的时间步如 4用[mask]标志代替,从 接 下 来 的 模 型 中 屏 蔽 掉。经 过 一 层 position encoding 进入如上的 Transformer encoder 得到编码后的序列 encoded sequence 也就是上文提到的memory(但与一般的 memory 不同,此时的 memory不含要重建的 4).再经过一个简单的 decoder 之后获取序列。损失函数定义为被屏蔽的 4预测值与真实值之间。换言之, mask time series modeling 是从被 mask 的时间步两边的数据或者说上下文数据重建时间步。这充分利用了 Transformer 无向性的特点。同时,综合利用上下文信息,也可提高重建的精度。
5.1.3 异常检测效果
时序数据异常检测数据集的标注需要昂贵的专家成本,尤其是详细标注了异常发生的开始和结束时刻的数据集。这类数据集规模通常较小,因此检验算法效果存在一定偶然性。
基于重建误差的异常检测,要求模型在输入正常数据时重建误差较小,输入异常数据时重建误差较大;下面我们可以看一下孟恒宇同学在他的论文里对不同工况的存储数据集进行重建效果的对比:四个工况子集上传感器的数据的Transformer重建结果对比,绿色为预测波形
可以看出优化后的数据比未优化的数据更平稳波动更小,而异常数据比跟正常数据多了一小段激剧上下波动的异常。不同工况下LSTM与Transformer的绝对误差对比
上表为四个子集上的重建结果的绝对误差对比。可以看到 Transformer 方法在有异常的数据集上重建的绝对误差更大,这 说 明 面 对 异 常 发 生 时Transformer 的表现更鲁棒。优化工况的周期性更明显,本文方法效果显著提高。不同工况下LSTM与Transformer的训练耗时对比
可以看出,由于 Transformer 放弃了 LSTM 的序列式推进,其 self-attention 模块完全可以并行,因此用时普遍较少,最多可以节约 80.7%的时间,同时异常检测 F1 score 达到0.78。
5.1.4 补充
需要强调一下Multi-head 机制在这个时序数据任务中几乎没有发挥作用,可能是因为数据维度过少,只有 25 或 55维,而一般的 NLP 任务的词一般会嵌入 512 维度的词向量空间。
引用:
1. 《基于Transformer重建的时序数据异常检测与关系提取》—— 孟恒宇
2. 时间序列模式(ARIMA)---Python实现
3. 基于时间序列的异常检测算法小结基于时间序列的异常检测算法小结_人工智能_Jasminexjf的博客-CSDN博客blog.csdn.net
4. 《Outlier Analysis》 —— Charu C.Aggarwal
声明:
所有文章都为本人的学习笔记,非商用,
目的只求在工作学习过程中通过记录,梳理清楚自己的知识体系。
文章或涉及多方引用,如有纰漏忘记列举,请多指正与包涵。