#时间预测算法_【时间序列】时序预测竞赛之异常检测算法综述

本文将介绍在时间序列预测相关问题中常见的异常检测算法,可以很大程度上帮助改善最终预测效果。

异常分类

时间序列的异常检测问题通常表示为相对于某些标准信号或常见信号的离群点。虽然有很多的异常类型,但是我们只关注业务角度中最重要的类型,比如意外的峰值、下降、趋势变化以及等级转换(level shifts)。

常见的异常有如下几种:

  • 革新性异常:innovational outlier (IO),造成离群点干扰不仅作用于X(T),而且影响T时刻以后序列的所有观察值。

  • 附加性异常:additive outlier (AO),造成这种离群点的干扰,只影响该干扰发生的那一个时刻T上的序列值,而不影响该时刻以后的序列值。

  • 水平移位异常:level shift (LS),造成这种离群点的干扰是在某一时刻T,系统的结构发生了变化,并持续影响T时刻以后的所有行为,在数列上往往表现出T时刻前后的序列均值发生水平位移。

  • 暂时变更异常temporary change (TC):造成这种离群点的干扰是在T时刻干扰发生时具有一定初始效应,以后随时间根据衰减因子的大小呈指数衰减。

上面的解释可能不太容易理解,我们结合图片来看一下:

d9b3ae9eb1a9ed3516f7b4fcfbae8fa2.png

通常,异常检测算法应该将每个时间点标记为异常/非异常,或者预测某个点的信号,并衡量这个点的真实值与预测值的差值是否足够大,从而将其视为异常。使用后面的方法,你将能够得到一个可视化的置信区间,这有助于理解为什么会出现异常并进行验证。

常见异常检测方法

从分类看,当前发展阶段的时序异常检测算法和模型可以分为一下几类:

75236b431f21e7c409f533658c1bf632.png

  • 统计模型:优点是复杂度低,计算速度快,泛化能力强悍。因为没有训练过程,即使没有前期的数据积累,也可以快速的投入生产使用。缺点是准确率一般。但是这个其实是看场景的,并且也有简单的方法来提高业务层面的准确率。这个后面会提到。

  • 机器学习模型:鲁棒性较好,准确率较高。需要训练模型,泛化能力一般。

  • 深度学习模型:普遍需要喂大量的数据,计算复杂度高。整体看,准确性高,尤其是近段时间,强化学习的引入,进一步巩固其准确性方面的领先优势。

3-Sigma

3-Sigma原则又称为拉依达准则,该准则定义如下:假设一组检测数据只含有随机误差,对原始数据进行计算处理得到标准差,然后按一定的概率确定一个区间,认为误差超过这个区间的就属于异常值。

d4401c3e8ca7ac776959c58c00118547.png

使用3-Sigma的前提是数据服从正态分布,满足这个条件之后,在3-Sigma范围(μ–3σ,μ+3σ)内99.73%的为正常数据,其中σ代表标准差,μ代表均值,x=μ为图形的对称轴。下面是3-Sigma的Python实现:

import numpy as npdef three_sigma(df_col):    '''    df_col:DataFrame数据的某一列    '''    rule = (df_col.mean() - 3 * df_col.std() > df_col) | (df_col.mean() + 3 * df_col.std() < df_col)    index = np.arange(df_col.shape[0])[rule]    out_range = df_col.iloc[index]    return out_range

对于异常值检测出来的结果,有多种处理方式,如果是时间序列中的值,那么我们可以认为这个时刻的操作属于异常的;如果是将异常值检测用于数据预处理阶段,处理方法有以下四种:

  • 删除带有异常值的数据;

  • 将异常值视为缺失值,交给缺失值处理方法来处理;

  • 用平均值进行修正;

  • 当然我们也可以选择不处理。

Grubbs测试

Grubbs’Test为一种假设检验的方法,常被用来检验服从正太分布的单变量数据集(univariate data set)Y 中的单个异常值。若有异常值,则其必为数据集中的最大值或最小值。原假设与备择假设如下:

  • H0: 数据集中没有异常值

  • H1: 数据集中有一个异常值

使用Grubbs测试需要总体是正态分布的。算法流程:

  1. 样本从小到大排序

  2. 求样本的mean和dev

  3. 计算min/max与mean的差距,更大的那个为可疑值

  4. 求可疑值的z-score (standard score),如果大于Grubbs临界值,那么就是outlier

Grubbs临界值可以查表得到,它由两个值决定:检出水平α(越严格越小),样本数量n,排除outlier,对剩余序列循环做 1-4 步骤。由于这里需要的是异常判定,只需要判断tail_avg是否outlier即可。

from outliers import smirnov_grubbs as grubbsprint(grubbs.test([8, 9, 10, 1, 9], alpha=0.05))print(grubbs.min_test_outliers([8, 9, 10, 1, 9], alpha=0.05))print(grubbs.max_test_outliers([8, 9, 10, 1, 9], alpha=0.05))print(grubbs.max_test_indices([8, 9, 10, 50, 9], alpha=0.05))

S-ESD与S-H-ESD

鉴于时间序列数据具有周期性(seasonal)、趋势性(trend),异常检测时不能作为孤立的样本点处理;故而Twitter的工程师提出了S- ESD (Seasonal ESD)与S-H-ESD (Seasonal Hybrid ESD)算法,将ESD扩展到时间序列数据。

STL分解

STL (Seasonal-Trend decomposition procedure based on Loess) 为时序分解中一种常见的算法,基于LOESS将某时刻的数据Yv分解为趋势分量(trend component)、季节性分量(seasonal component)和残差(remainder component):

edd4661514727556f19c05072c7adf83.png

8feea4beb57ff0f549db39cf9f4ed546.png

由上到下依次为:原始时间序列和使用 STL 分解得到的季节变化部分、趋势变化部分以及残差部分。

STL分为内循环(inner loop)与外循环(outer loop),其中内循环主要做了趋势拟合与周期分量的计算。假定T(k)v、Sv(k)为内循环中第k-1次pass结束时的趋势分量、周期分量,初始时T(k)v=0;并有以下参数:

  • n(i)内层循环数

  • n(o)外层循环数

  • n(p)为一个周期的样本数

  • n(s)为Step 2中LOESS平滑参数

  • n(l)为Step 3中LOESS平滑参数

  • n(t)为Step 6中LOESS平滑参数

每个周期相同位置的样本点组成一个子序列(subseries),容易知道这样的子序列共有共有n(p)个,我们称其为cycle-subseries。

Python的statsmodels实现了一个简单版的时序分解,通过加权滑动平均提取趋势分量,然后对cycle-subseries每个时间点数据求平均组成周期分量:

使用示例:

import numpy as npimport pandas as pdfrom statsmodels.tsa.seasonal import seasonal_decomposeimport matplotlib.pyplot as plt# Generate some datanp.random.seed(0)n = 1500dates = np.array('2019-01-01', dtype=np.datetime64) + np.arange(n)data = 12 * np.sin(2 * np.pi * np.arange(n) / 365) + np.random.normal(12, 2, 1500)df = pd.DataFrame({'data': data}, index=dates)# Reproduce the example in OPseasonal_decompose(df, model='additive', period=1).plot()plt.show()

S-ESD

STL将时间序列数据分解为趋势分量、周期分量和余项分量。想当然的解法——将ESD运用于STL分解后的余项分量中,即可得到时间序列上的异常点。但是,我们会发现在余项分量中存在着部分假异常点(spurious anomalies)。如下图所示:

d7de1e85d012e6a41e91e8d29f654dac.png

在红色矩形方框中,向下突起点被误报为异常点。为了解决这种假阳性降低准确率的问题,S-ESD算法用中位数(median)替换掉趋势分量;

使用示例:

import numpy as npimport sesdts = np.random.random(100)# Introduce artificial anomaliests[14] = 9ts[83] = 10outliers_indices = sesd.seasonal_esd(ts, periodicity=20, hybrid=True, max_anomalies=2)for idx in outliers_indices:    print(f'Anomaly index: {idx}, anomaly value: {ts[idx]}')

移动平均/加权移动平均/指数加权移动平均

移动平均 moving average

给定一个时间序列和窗口长度N,moving average等于当前data point之前N个点(包括当前点)的平均值。不停地移动这个窗口,就得到移动平均曲线。

累加移动平均 cumulative moving average

设{xi:i≥1}是观察到的数据序列。累积移动平均线是所有数据的未加权平均值。如果若干天的值是x1,…,xi,那么:

267bd701a1e34739e8969389c35eb38a.png

加权移动平均 weighted moving average

加权移动平均值是先前w个数据的加权平均值

26765e3c671178905fa5141470736585.png

指数加权移动平均 exponential weighted moving average

指数移动与移动平均有些不同:

  • 并没有时间窗口,用的是从时间序列第一个data point到当前data point之间的所有点。

  • 每个data point的权重不同,离当前时间点越近的点的权重越大,历史时间点的权重随着离当前时间点的距离呈指数衰减,从当前data point往前的data point,权重依次为

045c0678c71d4225dfd971a2108cb503.png

该算法可以检测一个异常较短时间后发生另外一个异常的情况,异常持续一段时间后可能被判定为正常。

ARIMA 模型

自回归移动平均模型(ARIMA)是一种设计上非常简单的方法,但其效果足够强大,可以预测信号并发现其中的异常。该方法的思路是从过去的几个数据点来生成下一个数据点的预测,在过程中添加一些随机变量(通常是添加白噪声)。以此类推,预测得到的数据点可以用来生成新的预测。很明显:它会使得后续预测信号数据更平滑。使用这种方法最困难的部分是选择差异数量、自回归数量和预测误差系数。另一个障碍是信号经过差分后应该是固定的。也就是说,这意味着信号不应该依赖于时间,这是一个比较显著的限制。

45fb14367508697472840a4406c83d1c.png

异常检测是利用离群点来建立一个经过调整的信号模型,然后利用t-统计量来检验该模型是否比原模型能更好的拟合数据。

8ec0deb52518ee8abbfb94df50594438.png

在这种情况下,你可以找到适合信号的 ARIMA 模型,它可以检测出所有类型的异常。

神经网络

与CART方法一样,神经网络有两种应用方式:监督学习和无监督学习。我们处理的数据是时间序列,所以最适合的神经网络类型是 LSTM。如果构建得当,这种循环神经网络将可以建模实现时间序列中最复杂的依赖关系,包括高级的季节性依赖关系。如果存在多个时间序列相互耦合,该方法也非常有用。该领域还在研究中,可以参考这里,构建时序模型需要大量的工作。构建成功完成后,就可能在精确度方面取得优异的成绩。

32b680b8875dac6b6864b76820a436b1.png

往期精彩回顾

适合初学者入门人工智能的路线及资料下载

机器学习及深度学习笔记等资料打印

机器学习在线手册

深度学习笔记专辑

《统计学习方法》的代码复现专辑

AI基础下载

机器学习的数学基础专辑

获取本站知识星球优惠券,复制链接直接打开:

https://t.zsxq.com/qFiUFMV

本站qq群704220115。

加入微信群请扫码:

2d101a5bdbf97748abf19efafa264cad.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291712.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

监测利器cacti服务安装

1、Cacti原理及概述1Cacti是一款使用PHP语言开发的性能与流量监测工具。监测的对象可以是linux也可以是windows也可以是路由器交换机等网络设备主要基于SNMPsimple network managerprotocol简单网络管理协议来搜集cpu占用内存使用运行进程数磁盘空间网卡流量等各种网络数据。2实…

linux c之解决array subscript is not integer和AF_NET not undeclared

1、array subscript is not integer 我一开始写的代码是这样的写的 buf[strlen[buf] - 1] \0; 很明显写错了&#xff0c;以后不要再犯这样的错误了&#xff0c;切记 buf[strlen(buf) - 1] \0; 2、AF_NET not undeclared 这是我写的代码 inet.pton(AF_NET, buf 6, &add…

C#中的类型转换

前几篇文章中经常说到强制类型转换&#xff0c;就是可以将派生类对象强制转换为基类对象的做法或者通过as运算符进行的转换。今天我们就来一起简单了解复习下在C#中都有哪些类型的转换。要理解转换很容易&#xff0c;日常的开发编码过程中&#xff0c;由于变量类型的不同我们可…

Excel 用于批量把单元格设置为文本格式保存的数字的宏

首先把所有的数字录入&#xff08;或者导出为&#xff09;井号数字的格式&#xff0c;比如“#3333333323424234234234”&#xff0c;然后运行下面的宏&#xff1a; Sub Num2Text()If Not TypeOf Application.Selection Is Range ThenMsgBox "You must select cells!"…

ACM题解系列之一:刘汝佳:《算法竞赛入门经典》(第2版)

题是书中的题&#xff0c;解法参照了书中的解法&#xff0c;不少解法都做了简化和改进。 做程序&#xff0c;就要努力做到自己的程序是最好的&#xff01; 第3章例题 POJ1488 UVA272 UVALive5381 TEX Quote【输入输出】 POJ2538 ZOJ1884 UVA10082 WERTYU【输入输出】 HDU1318 P…

linux之快速过滤文本的关键字以及快速过滤目录下的关键字

1、快速过过滤文本的关键字 cat file | grep 关键字 比如Android日志文件很长&#xff0c;需要过滤Exception,就可以用这个办法&#xff0c;如下图 2、快速过滤目录下的关键字 grep -r 关键字 比如我们在linux上看目录下哪些关键字段&#xff0c;好像开发工具里面的 find usag…

hadoop使用

2019独角兽企业重金招聘Python工程师标准>>> 框架简介 Hadoop使用主/从&#xff08;Master/Slave&#xff09;架构&#xff0c;主要角色有NameNode&#xff0c;DataNode&#xff0c;secondary NameNode&#xff0c;JobTracker&#xff0c;TaskTracker组成。 其中Nam…

bigint hive java类型_详解Apache Hudi如何配置各种类型分区

1. 引入Apache Hudi支持多种分区方式数据集&#xff0c;如多级分区、单分区、时间日期分区、无分区数据集等&#xff0c;用户可根据实际需求选择合适的分区方式&#xff0c;下面来详细了解Hudi如何配置何种类型分区。2. 分区处理为说明Hudi对不同分区类型的处理&#xff0c;假定…

C#中的命名空间和程序集

前言今天这篇文章和大家一起学习下C#语言下的命名空间和程序集。在日常的编码工作中&#xff0c;我们对命名空间和程序集都不会很陌生。在创建项目文件时&#xff0c;IDE自动会为我们创建好一个大的命名空间和程序集。大多数业务代码都是在解决方案下各自的命令空间里进行编码的…

C/C++预处理宏的总结

1.定义顺序的无关性 #define PI 3.14 #define TWO_PI 2*PI 这两句谁前谁后无所谓&#xff0c;因为预处理器不断迭代来实现宏替换&#xff0c;直到源文件中没有宏了才停止。 2. 宏变量变成字符串 #define str(x) #x 例子&#xff1a;str (teststring) > "teststrin…

基于jQuery的ajax系列之用FormData实现页面无刷新上传

接着上一篇ajax系列之用jQuery的ajax方法向服务器发出get和post请求写&#xff0c;这篇主要写如何利用ajax和FormData实现页面无刷新的文件上传效果&#xff0c;主要用到了jQuery的ajax()方法和XMLHttpRequest Level 2的FormData接口。关于FormData&#xff0c;大家可以看MDN文…

linux网络编程之用多线程实现客户端到服务端的通信(基于udp)

1、开启一个线程接受数据,主线程发送数据的代码 #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <netinet/in.h> #include <errno.h> #include <sys/time.h&g…

Apache FTPClient操作文件上传下载及公共类

我们在项目中可能需要使用ftp进行文件的上传、下载、获取服务器目录信息等相关操作&#xff0c;我们可以使用apache的FTPClient进行相关的操作&#xff0c;下面把相关公共方法与大家交流分享&#xff0c;每个方法前都有详细的注释进行讲解&#xff0c;不过在进行ftp测试的时候&…

abd shell关闭所有程序_在后台服务器上运行程序

之前总结过screen的用法&#xff0c;但还可以用nohup命令。nohup工具&#xff1a;Linux系统中有提供一个很好的不挂断地运行命令——nohup。我们使用nohup能很简单的控制使用&#xff0c;在此就简单的介绍一下nohup工具。nohup 命令nohup就是不挂起的意思( no hang up)。用途&a…

优秀的JavaScript模块是怎样炼成的

引言&#xff1a;如今的JavaScript已经是Web上最流行的语言&#xff0c;没有之一。从Github上的语言排行榜https://github.com/languages上即可看出&#xff0c;也是如今最为活跃的开源社区。随着Node的加入&#xff0c;JavaScript开枝散叶进入服务器领域&#xff0c;为这个语言…

解锁JDK 12的奇妙之旅:新特性详解

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 解锁JDK 12的奇妙之旅&#xff1a;新特性详解 前言switch表达式拓展NumberFormat对复杂数字的格式化字符串支持transform、indent操作新增方法Files.mismatch(Path, Path)Teeing Collector支持unicode…

.NET6之MiniAPI(十四):跨域CORS(上)

为了说明跨请求&#xff0c;创建了两个项目&#xff0c;一个mini api&#xff0c;端口是5001&#xff0c;另一个razor page项目&#xff0c;端口是5280。5280项目会在页面用ajax的方式来请求5001&#xff0c;形成跨域请求&#xff0c;由于是本地测试&#xff0c;host都是localh…

Linux文件锁学习-flock, lockf, fcntl

参考 linux中fcntl()、lockf、flock的区别 这三个函数的作用都是给文件加锁&#xff0c;那它们有什么区别呢&#xff1f; 首先flock和fcntl是系统调用&#xff0c;而lockf是库函数。lockf实际上是fcntl的封装&#xff0c;所以lockf和fcntl的底层实现是一样的&#xff0c;对文件…

linux网络编程之sockaddr_in和in_addr区别

1、struct in_addr struct in_addr就是32位IP地址。 struct in_addr { union {struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;struct { u_short s_w1,s_w2; } S_un_w;u_long S_addr;} S_un;#define s_addr S_un.S_addr }; 2、sockaddr_in struct sockaddr_in …

入驻

新手登录~