这是当初刚进公司时,leader给的一个独立练手小项目,关于时间序列预测,情景比较简单,整个过程实现下来代码也仅100多行,但完成过程中踩了很多坑,觉的有必要分(tu)享(cao)一下。完整代码和样例数据放到了我的github上(文章仅粘贴部分): https://github.com/scarlettgin/cyclical_series_predict
1、背景
公司平台上有不同的api,供内部或外部调用,这些api承担着不同的功能,如查询账号、发版、抢红包等等。日志会记录下每分钟某api被访问了多少次,即一个api每天会有1440条记录(1440分钟),将每天的数据连起来观察,有点类似于股票走势的意思。我想通过前N天的历史数据预测出第N+1天的流量访问情况,预测值即作为合理参考,供新一天与真实值做实时对比。当真实流量跟预测值有较大出入,则认为有异常访问,触发报警。
2、数据探索
我放了一份样例数据在data文件夹下, 看一下数据大小和结构
data = pd.read_csv(filename)
print('size: ',data.shape)
print(data.head())
复制代码
数据大小: 共10080条记录,即10080分钟,七天的数据。 字段含义: date:时间,单位分钟 count:该分钟该api被访问的次数
画图看一下序列的走势:(一些画图等探索类的方法放在了test_stationarity.py 文件中,包含时间序列图,移动平均图,有兴趣的可以自己尝试下)。
def draw_ts(timeseries):
timeseries.plot()
plt.show()
data = pd.read_csv(path)
data = data.set_index('date')
data.index = pd.to_datetime(data.index)
ts = data['count']
draw_ts(ts)
复制代码
看这糟心的图,那些骤降为0的点这就是我遇到的第一个坑,我当初一拿到这份数据就开始做了。后来折腾了好久才发现,那些骤降为0的点是由于数据缺失,ETL的同学自动补零造成的,沟通晚了(TДT)。
把坑填上,用前后值的均值把缺失值补上,再看一眼:
发现这份数据有这样几个特点,在模型设计和数据预处理的时候要考虑到:
1、这是一个周期性的时间序列,数值有规律的以天为周期上下波动,图中这个api,在每天下午和晚上访问较为活跃,在早上和凌晨较为稀少。在建模之前需要做分解。
2、我的第二个坑:数据本身并不平滑,骤突骤降较多,而这样是不利于预测的,毕竟模型需要学习好正常的序列才能对未知数据给出客观判断,否则会出现频繁的误报,令气氛变得十分尴尬( ´Д`),所以必须进行平滑处理。
3、这只是一个api的序列图,而不同的api的形态差距是很大的,毕竟承担的功能不同,如何使模型适应不同形态的api也是需要考虑的问题。
3、预处理
3.1 划分训练测试集
前六天的数据做训练,第七天做测试集。