Prophet时序数据异常检测方法

 

一.背景

通常app打点数据是有时间周期规律的时序数据,当打点数据出现异常时,需要有一种及时发现问题的方法。

二.发现规则变化的方法

2.1 传统方法

通过人工观察,当某段时间打点数据趋势突然异常的时候(明显增加或者减少),此时可以推测,增加的原因可能是某个规则欠拟合了;而减少的原因,可能是app升级版本后修改了api,导致某个规则失效了等等。

这样的弊端是,当打点规则非常多时,对每个规则都进行比对是非常低效的。

 

2.2 机器学习方法

https://blog.csdn.net/weixin_35834894/article/details/95637081

上文中提到了关于时间序列异常检测算法的一些讨论。

另外两篇文章:时间序列异常检测算法S-H-ESD

https://www.cnblogs.com/en-heng/p/9202654.html

时间序列分解算法:STL

https://www.cnblogs.com/en-heng/p/7390310.html

facebook开源的prophet时间序列预测工具---识别多种周期性、趋势性(线性,logistic)、节假日效应,以及部分异常值

https://www.cnblogs.com/bonelee/p/9577432.html

另外,ElasticSearch也提供了基于日志数据的machine learning算法。

 

三.使用prophet进行趋势预测及异常值检测

项目源码地址

https://github.com/facebook/prophet

参考官方快速开始文档。

https://facebook.github.io/prophet/docs/quick_start.html

3.1 安装prophet

参考如下文章

https://blog.csdn.net/qq_33873431/article/details/90064945

3.1.1 安装anaconda

https://conda.io/miniconda.html

需要勾选将anaconda添加到path中。安装完成后cmd中设置清华镜像。

 

 

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
conda config --show

 

 

3.1.2 安装pyprophet

 

 

conda install -c conda-forge fbprophet

 

 

问题1:python版本过高

使用anaconda安装python3.7,并绑定到conda的虚拟环境python37下面。

 

#不指定3.7.x时默认会找3.7下最新的版本。
conda create --name python37 python=3.7

 

切换到python3.7环境以及切换回默认环境的命令

 

conda activate python37
conda deactivate
#删除已有环境
conda remove --name python37 --all

 

切换到python3.7环境后重新安装成功,这里需要下载一些安装包。

3.2 安装jupyter notebook

为了能够更方便原型验证的开发和调试,这里安装了jupyter notebook。

安装命令:

 

conda install -c conda-forge jupyter notebook

 

启动命令:

 

jupyter notebook

 

3.3 趋势预测

3.3.1 数据格式

导入10天的csv数据,格式如下

appId,actId,ruleId,day,hour,cnt
421,-1,61610,20200728,22,1217421
7873,-1,78166,20200728,22,17520
41,-1,61796,20200728,22,219648
1510,135,64553,20200728,22,174251
1786,-1,69972,20200728,22,36171
6813,-1,76046,20200728,22,82855
3453,-1,73536,20200728,22,6819
1647,-1,67366,20200728,22,49859
2237,-1,70287,20200728,22,1583
7913,-1,78540,20200728,22,41
....

 

 问题2:无法导入plotly

原因是plotly没有安装,用如下命令安装后解决。

 

conda install -c conda-forge plotly

 

3.3.2 导入相关包

 

 

import pandas as pd 
from fbprophet import Prophet
from pandas.plotting import register_matplotlib_converters

 

 

3.3.3 读取csv文件

 

df=pd.read_csv("./data/appId_actId_ruleId_day_hour_cnt.csv")
print(df.head())

 

3.3.4 将csv文件处理为Prophet的输入

Prophet的输入始终是两列数据,ds和y。ds是时间戳,格式为(YYYY-MM-DD或者YYYY-MM-DD HH:MM:SS),y是数字,代表预测的度量。

先筛选某一个规则的命中趋势来进行预测

 

 

df=df[df.appId==0]
df=df[df.actId==1843]
df[df.ruleId==73444]

 

 

 

df['ds']=df['day'].astype('str').str.cat(df['hour'].astype('str'),sep='-')
import datetime
df['ds']=df['ds'].map(lambda x:datetime.datetime.strptime(x, '%Y%m%d-%H').strftime('%Y-%m-%d %H:00:00'))
df['y']=df['cnt']
df=df[['ds','y']]
 # 重置dataframe的行号从0开始
df.reset_index(drop=True, inplace=True)

 

3.3.5 使用fit方法对数据做预处理

 

m=Prophet(weekly_seasonality=True)
m.fit(df)

 

Prophet的参数有weekly_seasonality和yearly_seasonality,表示是否是按年或者是按星期拥有季节性的。

3.3.6 使用predict方法进行预测

 

 

future = m.make_future_dataframe(periods=24*7,freq='H')
future.tail()
forecast = m.predict(future)
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()

 

m.make_future_dataframe()方法中,periods表示要预测的未来的时期,freq表示当前数据的频率,'H'表示小时。

其中yhat代表预测值,yhat_lower代表预测范围的最小值,yhat_upper代表预测范围的最大值。

 

3.3.7 使用plot方法画出预测图

 

 

fig1 = m.plot(forecast)

 

3.3.8 使用plot_components画出趋势的各个分量

trend表示y总体的趋势。

weekly表示y按周的变化趋势。

daily表示y按天的变化趋势。

 

3.4 趋势改变点发现

3.4.1 数据预处理

 

import pandas as pd 
from fbprophet import Prophet
from pandas.plotting import register_matplotlib_converters
df=pd.read_csv("./data/appId_actId_ruleId_day_hour_cnt.csv")
#指定要分析的ruleId
df=df[df.ruleId==59999.0]
print(df.head())
df['ds']=df['day'].astype('str').str.cat(df['hour'].astype('str'),sep='-')
import datetime
df['ds']=df['ds'].map(lambda x:datetime.datetime.strptime(x, '%Y%m%d-%H').strftime('%Y-%m-%d %H:00:00'))
df['y']=df['cnt']
df=df[['ds','y']]
 # 重置dataframe的行号从0开始
df.reset_index(drop=True, inplace=True)

 

3.4.2 趋势变更点发现

 

 

m=Prophet()
m.fit(df)
future = m.make_future_dataframe(periods=3,freq='H')
forecast = m.predict(future)
from fbprophet.plot import add_changepoints_to_plot
fig = m.plot(forecast)
a = add_changepoints_to_plot(fig.gca(), m, forecast)

 

下图中黑点是ruleId 59999实际的pv,蓝线是根据实际的pv拟合的曲线。红色的虚线是趋势变更点,红色的实线是趋势。

对比正常的ruleId 73444,不存在红色的虚线,即无趋势变更点。

可以通过是否存在趋势变更点来判断规则是否正常。

3.4.3 趋势变更点计算源码

上一节中将趋势变更点通过plot方法展示在了图上,如果需要获取趋势变更点的数组,可以参考add_changepoints_to_plot的源码。

源码地址如下:

https://github.com/facebook/prophet/blob/9fb8f103d623fc9e3b45dfd895664cc91bc82d2b/python/fbprophet/plot.py

关键代码为:

 

import numpy as np
threshold = 0.01
signif_changepoints = m.changepoints[np.abs(np.nanmean(m.params['delta'], axis=0)) >= threshold]

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值