基于Prophet的高铁乘客数量纯时序预测---TOP10方案(非排行版提交方案)

基于Prophet的高铁乘客数量纯时序预测---TOP10方案(非排行版提交方案) - 知乎

赛题地址:AI研习社 - 研习AI产学研新知,助力AI学术开发者成长。

赛题简介:给出某条高铁线路2012-08-25至2014-06-25的客流量数据,要求预测2014-06-25至2014-09-25上午某时刻或者下午某时刻的乘客数量,预测上午乘客数量时,下午数据会给出,预测下午数据时,上午数据会给出。

赛题评分:100-MAE

数据理解:从赛题简介中的黑色粗体部分可以看出该题数据存在未来(预测时间段内)数据泄露(或者说训练数据穿越)的问题,所以实际应用意义不大。

线上分数:42.6881

上分技巧:

1.历史数据总体趋势呈递增,而且差距很大,采用太久远的历史数据训练反而会降低模型的预测能力。本方案中仅采用了2014年6月10号以后的数据进行训练建模。

2.由于训练数据存在缺失上午或下午的数据,采用“上午”、“下午”分别建模预测效果会更好。给上下午打引号,是因为实际操作的时候,选择了上午8点至晚上20点作为“上午”,剩下的时间段作为“下午”。之所以采取这样的分段是因为,8点至22点正好是一个单调递增到峰值之后再递减的一个相对完整的过程(用大佬 小学四年级学生 的话说就是,服从泊松分布)。具体可以自行画图理解,或者找出更优的划分方式。

3.经过1-2步骤的操作+参数优化,分数能达到39+。在此基础之上将label做boxcox变换能再上3分多,达到42分+。

以下是代码讲解部分:

导入相关包

import warnings
warnings.filterwarnings("ignore")
import numpy as np
import pandas as pd
from fbprophet import Prophet
import matplotlib.pyplot as plt
from scipy import stats
from scipy.special import inv_boxcox

数据加载及处理

#读取训练数据
rese_df = pd.read_csv('../data/train.csv', names =['ds', 'y'], header=0)
rese_df['ds'] = rese_df['ds'].astype('datetime64[ns]')
rese_df['y'] = rese_df['y'].astype(int)

#读取测试数据
test = pd.read_csv('../data/test.csv', names =['id', 'ds'], header=0)
test['ds'] = test['ds'].astype('datetime64[ns]')

#构造预测时间点
test_df = test[['ds']].copy()

#构造线上提交数据
subs = test[['id']].copy()

数据拆分

hours = np.arange(8, 21)
#训练数据拆分
rese_df_mor = rese_df[rese_df['ds'].dt.hour.isin( hours) ]
rese_df_aft = rese_df[~rese_df['ds'].dt.hour.isin(hours) ]
#预测时间点拆分
test_df_mor = test_df[test_df['ds'].dt.hour.isin( hours) ]
test_df_aft = test_df[~test_df['ds'].dt.hour.isin(hours) ]

分开建模

#分上午下午建模
#选择20140610以后的数据作为训练数据
cut_off = pd.date_range(start='06/10/2014', freq='1M', periods=1)

#"上午"部分建模预测
tail_df = rese_df_mor[ rese_df_mor['ds']>cut_off[len(cut_off)-1] ].copy()
#y做boxcox变换
tail_df.loc[tail_df['y']==0, 'y'] = tail_df['y'].mean()
xt, fitted_lambda_mor = stats.boxcox(tail_df['y'])
tail_df['y'] = xt

m = Prophet(yearly_seasonality=False
            , daily_seasonality=True
            , weekly_seasonality=True
            , seasonality_mode='multiplicative'
            , interval_width=0.95
            , changepoint_range=0.95
            , changepoint_prior_scale=0.1
           )
m.fit(tail_df)
preds_mor = m.predict(test_df_mor)['yhat']

#"下午"部分建模预测
tail_df = rese_df_aft[ rese_df_aft['ds']>cut_off[len(cut_off)-1] ].copy()
#y做boxcox变换
tail_df.loc[tail_df['y']==0, 'y'] = tail_df['y'].mean()
xt, fitted_lambda_aft = stats.boxcox(tail_df['y'])
tail_df['y'] = xt

m = Prophet(yearly_seasonality=False
            , daily_seasonality=True
            , weekly_seasonality=True
            , seasonality_mode='multiplicative'
            , interval_width=0.95
            , changepoint_range=0.95
            , changepoint_prior_scale=0.1
           )
m.fit(tail_df)
preds_aft = m.predict(test_df_aft)['yhat']

生成线上提交文件

#预测值做boxcox逆变换
test_df_mor['y'] = inv_boxcox( np.array( preds_mor ), fitted_lambda_mor)
test_df_aft['y'] = inv_boxcox( np.array( preds_aft ), fitted_lambda_aft)
#合并结果
result = pd.concat([test_df_mor, test_df_aft]).sort_values(by=['ds'], ascending=True)

#生成线上提交文件
subs['y'] = result['y']
subs.to_csv('../subs/prophet39_boxcox.csv', index=None,header=False)

发布于 2020-11-16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值