7-2-2、读取数据
# 读取数据 df = pd.read_csv('./energy.csv') # 更改列名,更改为Prophet指定的列名ds和y dd = df.rename(columns={'Datetime':'ds','AEP_MW':'y'}) # 注意:Prophet模型对于数据格式有要求,日期字段必须是datetime格式,这里通过pd.to_datetime来进行转换。 dd['ds'] = pd.to_datetime(dd['ds']) # 数据读取时为小时数据,我们需要将其聚合为天的数据 dd = dd.set_index('ds').resample('D').sum().reset_index() dd
数据:左侧为日期,右侧为当天对应的用电量。
7-2-3、数据预处理以及进行训练集和测试集的划分。
# 划分数据,划分为训练集和验证集,预测的数据设置为未来一个月 df_train = dd[:5025] df_test = dd[5025:] df_train.plot('ds', ['y'])
现在的df_train如图所示:
观察数据:导入一个好看的包,画的更漂亮一些
import plotly.express as px fig = px.line(df_train, x="ds", y="y") fig.show()
7-2-4、实例化Prophet对象,并且通过fit来训练模型
# 数据的变动会受到季节、周、天的影响,存在一定的规律性,因此我们将这三个参数设置为True m = Prophet(yearly_seasonality=True, weekly_seasonality=True, daily_seasonality=True) # 采用中国的假期模式,其余参数均保持默认 m.add_country_holidays(country_name="CN") m.fit(df_train) # make_future_dataframe: 作用是告诉模型我们要预测多长时间,以及时间的周期是什么。这里设置为30,即预测一个月时间的数据。 future = m.make_future_dataframe(periods=30, freq='D') # 进行预测,返回预测的结果forecast forecast = model.predict(future) # forecast['additive_terms'] = forecast['weekly'] + forecast['yearly']; # 有:forecast['yhat'] = forecast['trend'] + forecast['additive_terms'] 。 # 因此:forecast['yhat'] = forecast['trend'] +forecast['weekly'] + forecast['yearly']。 # 如果有节假日因素,那么就会有forecast['yhat'] = forecast['trend'] +forecast['weekly'] + forecast['yearly'] + forecast['holidays']。 forecast
forecast表示:Dataframe中包含了很多预测结果的信息,其中yhat表示预测的结果。
7-2-5、数据可视化
# 对数据机型可视化操作,黑点表示真实数据,蓝线表示预测结果。蓝色区域表示一定置信程度下的预测上限和下限。 m.plot(forecast) plt.show() # 通过plot_componets()可以实现对数据的年、月、周不同时间周期下趋势性的可视化。 m.plot_components(forecast);
数据可视化:
7-2-6、将预测值和真实值做对比
# 测试 # 测试,把ds列,即data_series列设置为索引列 df_test = df_test.set_index('ds') # 把预测到的数据取出ds列,预测值列yhat,同样把ds列设置为索引列。 forecast = forecast[['ds','yhat']].set_index('ds') # df_test['y'] = np.exp(df_test['y']) # forecast['yhat'] = np.exp(forecast['yhat']) # join:按照索引进行连接, # dropna:能够找到DataFrame类型数据的空值(缺失值),将空值所在的行/列删除后,将新的DataFrame作为返回值返回。 df_all = forecast.join(df_test).dropna() df_all.plot() # 设置左上角小标 plt.legend(['true', 'yhat']) plt.show()
对比图:
总结:相比于股票预测,只预测未来一个月的用电量,可以说很准确了,基本趋势都拟合到了。
7-2-7、模型评估
模型评估:评估模型的准确程度,通过RMSE(均方误差)来度量y与pre之间的差异程度,值越小,说明拟合程度越好
train_len = len(df_train["y"]) rmse = np.sqrt(sum((df_train["y"] - forecast["yhat"].head(train_len)) ** 2) / train_len) print('RMSE Error in forecasts = {}'.format(round(rmse, 2)))
7-2-7、模型存储
模型存储:以上流程实现了Prophet模型搭建,但考虑到未来我们还要复用通过此历史数据训练的模型,因此我们要将模型存储到本地,并在需要的时候将其导入,使用pickle来保存模型
import pickle # 模型保存 with open('../models_pickle/automl.pkl', 'wb') as f: pickle.dump(model, f, pickle.HIGHEST_PROTOCOL) # 模型读取 # with open('prophet_model.json', 'r') as md: # model = model_from_json(json.load(md))
八、其他注意事项
8-1、节假日设置。
# 有的时候,由于双十一或者一些特殊节假日,我们可以设置某些天数是节假日,并且设置它的前后影响范围,也就是 lower_window 和 upper_window。 playoffs = pd.DataFrame({ 'holiday': 'playoff', 'ds': pd.to_datetime(['2008-01-13', '2009-01-03', '2010-01-16', '2010-01-24', '2010-02-07', '2011-01-08', '2013-01-12', '2014-01-12', '2014-01-19', '2014-02-02', '2015-01-11', '2016-01-17', '2016-01-24', '2016-02-07']), 'lower_window': 0, 'upper_window': 1, }) superbowls = pd.DataFrame({ 'holiday': 'superbowl', 'ds': pd.to_datetime(['2010-02-07', '2014-02-02', '2016-02-07']), 'lower_window': 0, 'upper_window': 1, }) holidays = pd.concat((playoffs, superbowls)) m = Prophet(holidays=holidays, holidays_prior_scale=10.0)
参考文章:
解读:一种来自Facebook团队的大规模时间序列预测算法(附github链接).
【python量化】将Facebook的Prophet算法用于股票价格预测.
独家 | 手把手教你用Python的Prophet库进行时间序列预测.
Facebook 时间序列预测算法 Prophet 的研究.
官网.
论文.
数据异常检测:
总结
桥洞底下盖小被,小被里边抹眼泪,抹完眼泪无所谓,说什么啊我都对对对。