就在最近,一次偶然的机会学习了以下fbprophet时序预测模型,就决定使用这个框架来进行未来20天人数的预测。但是传染病模型通常比较复杂,此次使用此模型来预测,仅仅是用来练习,结果仅供参考。
更多关于这个模型的介绍,腾讯技术写过一篇我见过最详细的介绍,我就不做重复工作了,大家自行查看把
腾讯技术工程 | 基于Prophet的时间序列预测
首先强调一下安装fbprophet我遇到的坑:
我所使用的数据是湖北省从2019年12月1日到2020年2月29日的确诊人数数据【数据下载】(提取码:vmnv):
根据官网的描述,只要用 csv 文件存储两列即可,第一列的名字是 ‘ds’, 第二列的名称是 ‘y’。第一列表示时间序列的时间戳,第二列表示时间序列的取值。所以这里我们可以手动在文件中更改列名,也可以在程序中改。这里我们使用后者方法。
import pandas as pd
import pystan
from fbprophet import Prophet
import matplotlib.pyplot as plt
pdata = pd.read_csv("data/20200301-nCoV-hb.csv")
pdata.rename(columns={'date':'ds','confirmed':'y'},inplace=True)
pdata['ds'] = pd.to_datetime(pdata['ds'],format='%Y%m%d')
首先我们将列名修改成了官方要求的’ds’和’y’,其次我们将’ds‘的格式修改成了datatime时间格式。
#创建一个模型
m = Prophet()
# pdata['cap']=69000
m.fit(pdata)#传入模型需要预测的数据
#创建一个包含预测时间的dataframe,这里period时预测时,单位默认是天
future = m.make_future_dataframe(periods=20)
# future['cap']=69000
#进行预测,返回预测值及其其他相关值,格式是dataframe。
forecast = m.predict(future)
#绘画出图形
m.plot(forecast)
plt.show()#显示图片
test = forecast[['ds','yhat']].tail(20)#输出预测的20天的值
print(forecast[-20:])
结果图:
图中,黑色的点是我们文件中的数据,也就是确诊人数,中间深蓝色的线就是我们预测的曲线,曲线轮廓的上下边界有浅蓝色区域,它表示模型预测值的上、下边界。
这个结果肯定不能让我们满意,好了,我们来调整一下模型。
模型可以调整的参数(prophet()中的参数):
好了,我们首先将模式改为逻辑回归(非线性),注意容量值的设置。
m = Prophet(growth='logistic')
pdata['cap']=69000#容量值设置
m.fit(pdata)
#创建一个包含预测时间的dataframe
future = m.make_future_dataframe(periods=20)
future['cap']=69000#容量值设置
看一下这次的结果吧
这次比上次好了很多,已经非常拟合了,接下来咱们再修改一下增长趋势拟合度,这个值默认是0.05,咱们修改为2
m = Prophet(growth='logistic',changepoint_prior_scale=2)
看上面咱们说得调整模型参数,changepoints,会不会是因为我们没有设置固定得改变点,使得图片拟合没有发生什么变化,试一试。
m = Prophet(growth='logistic',changepoint_prior_scale=2,changepoints=['2020-01-24','2020-02-14','2020-02-20'])
好了,这个模型趋势看起来已经相当拟合,但是这里需要注意,changepoint_prior_scale值过大会出现过拟合的情况,所以需要你多去尝试,寻找合适的值。
咱们把最终调整完模型预测的值写一下,看看未来几天跟我们的预测有多大差距,想想还是很激动的:
import numpy as np
import pandas as pd
import pystan
from fbprophet import Prophet
import matplotlib.pyplot as plt
pdata = pd.read_csv("data/20200301-nCoV-hb.csv")
pdata.rename(columns={'date':'ds','confirmed':'y'},inplace=True)
pdata['ds'] = pd.to_datetime(pdata['ds'],format='%Y%m%d')
m = Prophet(growth='logistic',changepoint_prior_scale=2,changepoints=['2020-01-24','2020-02-14','2020-02-20'])
pdata['cap']=69000
m.fit(pdata)
#创建一个包含预测时间的dataframe
future = m.make_future_dataframe(periods=20)
future['cap']=69000
forecast = m.predict(future)
m.plot(forecast)
plt.show()
test = forecast[['ds','yhat']].tail(20)
print(test[-20:])
参考文章: