今天我们介绍一下使用python做时间序列数据分析和预测中异常值检测的方法,常用的异常值检测方法有以下几种:

  • 3sigma: 基于正太分布,当数据值超过±3个标准差(3sigma)时为异常值。
  • z-score : z标准分数,它测量数据值到平均值的距离,当数据与平均值相差2个标准差时z-score为2,如果将z-score为3作为异常值判断标准时,便相当于3sigma。
  • 箱体法(box): 它基于数据的四分位值来判断异常值。
  • 多维度异常值判断法,通过数据特征的多个维度综合判断数据是否为异常值。

注:3sigma,z-score,箱体法(box)都是从数据值本身的单一维度去分析和判断异常值,从而有一定的局限性, 然而多维度异常值判断法更注重从数据特征的各个维度去分析和判断异常值,显然多维度异常值判断法更为科学和精准。

导入时间序列数据

我们的数据来自于某商业零售门店的每日客流量数据,客流量数据直接关系到门店销售业绩,所以有必要对客流量数据进行分析。

数据中的 y 列代表了客流量,这里数据的时间范围为2020.1至2023.1 ,接下来我们查看数据的趋势图。

plt.figure(figsize=(10,4),dpi=100)
plt.plot(df)
plt.title("客流量趋势")
plt.show()

下面我们查看客流量数据的热力图分布:

calplot.calplot(df.y,suptitle='客流量分布',cmap='YlGn');

从热力图的颜色深浅变化,我们也能发现客流量逐年在减少,这可能和疫情持续有关。

3sigma

依据正太分布异常值分布在3个标准差以外的位置,如下图所示:

下面我们来计算数据的±3个标准以外的位置,落在这两个位置内的数据点即为异常值:

# 3sigma
def three_sigma(df):mean=df.y.mean()std=df.y.std()upper_limit=mean+3*stdlower_limit=mean-3*stddf['anomaly']=df.y.apply(lambda x: 1 if (x>upper_limit )or (x<lower_limit) else 0)return df
df1 = three_sigma(df.copy())
df1[df1.anomaly==1]

fig, ax = plt.subplots(figsize=(10,4))
a = df1.loc[df1['anomaly'] == 1, ['y']] #anomaly
ax.plot(df.index, df['y'], color='blue', label='正常值')
ax.scatter(a.index,a['y'], color='red', label='异常值')
plt.title(f'3sigma')
plt.xlabel('date')
plt.ylabel('y')
plt.legend()
plt.show();

z-score

z-score测量数据值到平均值的距离,异常值的判断依据为给定的距离阈值,一般情况下阈值可以设置在大于2个标准差的任意位置(依据业务和经验来确定阈值)。如果将z-score为3作为异常值判定的阈值时,便相当于3sigma。

# Z-Score
def z_score(df,threshold):mean=df.y.mean()std=df.y.std()df['z_score']=df.y.apply(lambda x:abs(x-mean)/std)df['anomaly']=df.z_score.apply(lambda x: 1 if x>threshold else 0)return df#设置阈值为2或3,当阈值为3时便相当于3sigma
threshold=2
df2 = z_score(df.copy(),threshold)
df2[df2.anomaly==1]

fig, ax = plt.subplots(figsize=(10,4))
a = df2.loc[df2['anomaly'] == 1, ['y']]
ax.plot(df.index, df['y'], color='blue', label='正常值')
ax.scatter(a.index,a['y'], color='red', label='异常值')
plt.title(f'Z-score, {threshold=}')
plt.xlabel('date')
plt.ylabel('y')
plt.legend()
plt.show();

箱体法(box)

箱体法(box)基于数据的四分位值来判断异常值。异常值>Q3+1.5*IQR 或者 异常值<Q1-1.5*IQR

def box_plot(df):q1=np.nanpercentile(df.y,25)q3=np.nanpercentile(df.y,75)iqr=q3-q1lower_limit=q1-1.5*iqrupper_limit=q3+1.5*iqrdf['anomaly']=df.y.apply(lambda x: 1 if x<lower_limit or x>upper_limit  else 0)return df
df3 = box_plot(df.copy())
df3[df3.anomaly==1]

fig, ax = plt.subplots(figsize=(10,4))
a = df3.loc[df3['anomaly'] == 1, ['y']]
ax.plot(df.index, df['y'], color='blue', label='正常值')
ax.scatter(a.index,a['y'], color='red', label='异常值')
plt.title(f'Box-plot')
plt.xlabel('date')
plt.ylabel('y')
plt.legend()
plt.show();

多维度异常检测法PyOD

异常检测算法工具库(PyOD) 可以从数据的多个特征维度来检测异常值,所以我们可以将时间序列数据的日期特征分解成多个和时间相关的其它特征,同时我们还需要设置一个异常值比例,一般情况下我们设置异常值比例在5%以下。这里我们使用的是Pycaret的异常值检测模型,该模型是对PyOD进行了再次包装,使之调用更为简单,感兴趣的朋友可以去查看Pycaret和PyOD的相关文档。这里我们首先将日期字段进行分解,从原始的日期字段中我们可以拆分出年,月,日,星期,季度等和时间相关的特征:

from pycaret.anomaly import AnomalyExperiment
# 分解日期特征
def create_features(df):        df['year'] = df.index.year #年 df['month'] = df.index.month #月df['dayofmonth'] = df.index.day #日df['dayofweek'] = df.index.dayofweek #星期df['quarter'] = df.index.quarter #季度df['weekend'] = df.dayofweek.apply(lambda x: 1 if x > 5 else 0) #是否周末df['dayofyear'] = df.index.dayofyear   #年中第几天df['weekofyear'] = df.index.weekofyear #年中第几月df['is_month_start']=df.index.is_month_startdf['is_month_end']=df.index.is_month_endreturn df
#创建特征
df4 = create_features(df.copy())
df4

接下来我们使用Pycaret的anomaly模型对新数据集进行建模和预测,同时我们仍然需要设置一个异常值比例的阈值fraction:

#异常值算法:'knn','cluster','iforest','svm'等。
alg='knn'#异常值算法
fraction=0.02 #异常值比例 0.02,0.03,0.04,0.05
#创建异常值模型
exp = AnomalyExperiment()
r = exp.setup(df4.copy(), session_id = 123,verbose=False)
model = exp.create_model(alg, fraction=fraction,verbose=False)
model_results = exp.assign_model(model,verbose=False)
#获取检测结果
df5 = pd.merge(df.reset_index(),model_results[['Anomaly']],left_index=True, right_index=True)
df5.set_index('date',inplace=True)fig, ax = plt.subplots(figsize=(10,4))
a = df5.loc[df5['Anomaly'] == 1, ['y']]
ax.plot(df5.index, df5['y'], color='blue', label='正常值')
ax.scatter(a.index,a['y'], color='red', label='异常值')
plt.title(f'Pycaret.anomaly {fraction=}')
plt.xlabel('date')
plt.ylabel('y')
plt.legend()
plt.show();

这里我们还有多种异常值算法可以选择,有兴趣的朋友可以自己去尝试不同的异常值算法:

总结

今天我们介绍几种常用的异常值检测方法,其中3sigma,z-score,箱体法(box)都是从数据值本身的单一维度去分析和判断异常值,从而有一定的局限性, 而多维度异常值判断法更注重从数据特征的各个维度去分析和判断异常值,显然多维度异常值判断法更为科学和精准。

参考资料

Pycaret 文档

PyOD文档

基于Python的时间序列异常值检测相关推荐

  1. Python实现基于3σ原则的异常值检测

    异常值是指样本中的个别值明显偏离其余的观测值.异常值的存在会对数据分析.建模产生干扰,因此需要对数据集进行异常值检测并进行异常值删除或修正,以便后续更好地进行数据分析和挖掘.对于异常值检测,有描述性统 ...

  2. 离群点、异常点检测及Python实现(正态分布3∂,Z-score 异常值检测,基于MAD的Z-score 异常值检测,杠杆值点、DFFITS值、SR学生化残差、cook距离和covratio值)

    有一些准则可以检测离群点,如:正态分布3∂,Z-score 异常值检测,基于MAD的Z-score 异常值检测 以上部分详情与代码请参考:https://blog.csdn.net/weixin_35 ...

  3. 基于Python长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析等领域中的应用实践技术

    查看原文>>>基于Python长时间序列遥感数据处理及在全球变化.物候提取.植被变绿与固碳分析.生物量估算与趋势分析等领域中的应用实践 目录 专题一.长时序遥感产品在全球变化/植被变 ...

  4. 用于时间序列异常值检测的全栈机器学习系统

    在本文中,我想介绍一个开源项目,用于构建机器学习管道以检测时间序列数据中的异常值.本文将简要介绍三种常见的异常值以及相应的检测策略.然后将提供基于两个支持的 API 的示例代码:用于开发时间序列异常值 ...

  5. 双向LSTM在时间序列异常值检测的应用

    双向LSTM在时间序列异常值检测的应用 参考文章: (1)双向LSTM在时间序列异常值检测的应用 (2)https://www.cnblogs.com/zakured1/p/10287304.html ...

  6. 基于Python+OpenCV车道线检测(直道和弯道)

    基于Python+OpenCV车道线检测(直道和弯道) 基于Python+OpenCV车道线检测(直道和弯道)

  7. 管道无损检测python_基于PYTHON的多通道漏磁检测系统设计

    基于 PYTHON 的多通道漏磁检测系统设计 * 李广凯 , 周庆祥 , 肖君武 [摘 要] 针对钢管漏磁检测中存在单通道探头检测效率低,缺陷定量困难,仪 器不便携带等难题,根据漏磁检测原理设计了一套 ...

  8. 基于Python长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析

    植被是陆地生态系统中最重要的组分之一,也是对气候变化最敏感的组分,其在全球变化过程中起着重要作用,能够指示自然环境中的大气.水.土壤等成分的变化,其年际和季节性变化可以作为地球气候变化的重要指标.此外 ...

  9. 基于 Python 长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析等领域中的应用

    植被是陆地生态系统中最重要的组分之一,也是对气候变化最敏感的组分,其在全球变化过程中起着重要作用,能够指示自然环境中的大气.水.土壤等成分的变化,其年际和季节性变化可以作为地球气候变化的重要指标.此外 ...

最新文章

  1. Go: 分布式学习利器(3) -- Go的数据类型和运算符
  2. 4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍
  3. Virtual Lab. For Probability and Statistics
  4. 移动端事件 、zepto移动端事件
  5. Intel汇编语言程序设计学习-第五章 过程-上
  6. MongoDB 权限
  7. 11gOCP 1z0-052 :2013-09-11 MGR_ROLE role........................................................A66
  8. LeetCode 6061. 买钢笔和铅笔的方案数
  9. python的作用域分别有几种_python 作用域知识点整理
  10. inventor中齿条怎么画_渐开线齿轮是怎么回事,图解6种齿轮加工工艺
  11. windows + visual studio 2010 配置SVN
  12. 概率论与数理统计 (二)计算题和应用题
  13. 实验一 熟悉常用的Linux操作,实验2-熟悉常用的HDFS操作
  14. python 图表_python可视化入图表|贵州茅台净利润分析
  15. c语言如何让图片置顶,UIView完全置顶的方法
  16. python怎样控制继电器_使用Python和树莓派控制跨阵M2继电器通断
  17. 由于找不到MSVCR110.dll,无法继续执行代码........启动的解决方法
  18. [转载] 七龙珠第一部——第111话 龟仙人最后的魔封波
  19. this.$refs 获取不到解决办法
  20. 浅析如何衡量程序员的生产效率

热门文章

  1. 淘宝详情接口调用示例
  2. 遇见物联,西电开启智慧校园新大门
  3. 别把“IT信息化”不当“超级工程”
  4. 响应式网站切图实操-姜威-专题视频课程
  5. C++控制台RPG游戏(序)
  6. 桂工877C语言程序设计,新学期,让梦想在桂工起飞
  7. ABAQUS学习之路
  8. 作文经典好词好句好段摘抄大全
  9. 广域红外望远镜的最新发现:最冷的恒星
  10. python的f是什么意思_%f在python中什么意思