R语言计量经济学与有时间序列模式的机器学习预测

今天,我们正在与一位精算数据科学专业的学生讨论,有关保险费率制定的与索赔频率模型有关的观点。

由Kaizong Ye,Sherry Deng撰写

由于目标是预测理赔频率(以评估保险费水平),因此他建议使用旧数据来训练该模型,并使用最新数据对其进行测试。问题在于该模型没有包含任何时间模式。

这里考虑一个简单的数据集,

> set.seed(1)
> n=50000
> X1=runif(n)
> T=sample(2000:2015,size=n,replace=TRUE)
> L=exp(-3+X1-(T-2000)/20)
> E=rbeta(n,5,1)
> Y=rpois(n,L*E)
> B=data.frame(Y,X1,L,T,E)

×

1. 初始数据集

一开始拿到的数据可能是分好训练集、测试集的,也可能是没分好的。这里我按照竞赛的情况假设一开始的数据集分有训练集和测试集。

对于时间序列数据来说,训练集即为历史数据,测试集即为新数据。历史数据对应的时间均在时间分割点之前(如2018年以前某品牌每家店每天的销售数据),新数据对应的时间均在分割点之后(如2018年以后某品牌每家店每天的销售数据)。

历史数据和新数据均包含N维信息(如某品牌每家店的地理位置、销售的商品信息等),但前者比后者多一列数据:Target,即要预测的对象,如销售额。

基于给出的数据,我们的预测任务是:根据已有数据,预测测试集的Target(如,根据某品牌每家店2018年以前的历史销售情况,预测每家店2018年1月份头15天的销售额)。

2. 数据处理

在构建预测特征上,截面数据和时间序列数据遵循的逻辑截然不同。下面两张图分别是二者的数据处理逻辑示意图。

首先来看针对截面数据的数据处理思路。

对于截面数据来说,训练集数据和测试集数据在时间维度上没有区别,二者唯一的区别是前者包含要预测的目标变量,而后者没有该目标变量。

一般来说,在做完数据清洗之后,我们用“N维数据”来分别给训练集、测试集构建M维预测特征(维度相同),然后用机器学习算法在训练集的预测特征和Target上训练模型,最后通过训练出的模型和测试集的预测特征来计算预测结果(测试集的Target)。

此外,为了给模型调优,我们一般还需要从训练集里面随机分割一部分出来做验证集。

而时间序列的处理思路则有所不同。

时间序列预测的核心思想是:用过去时间里的数据预测未来时间里的Target。

所以,在构建模型的时候,所有过去时间里的数据(训练集里的N维数据和Target,如2018年以前每家店的地理信息、所卖商品信息、日销售额等)都应该拿来构建预测特征。

而新数据本身的N维数据(如2018年1月头15天每家店的地理信息、所卖商品信息等)也应该拿来构建预测特征。

前者是历史特征(对应图上的预测特征A),后者是未来特征(对应图上的预测特征B)。二者合起来构成总预测特征集合。

最后,用预测模型和这个总的预测特征集合来预测未来Target(如未来销售额)。

看到这里,一个问题就产生了:既然所有的数据都拿来构建预测特征了,那预测模型从哪里来?没有Target数据,模型该怎么构建?

你可能会说,那就去找Target呗。对,没有错。但这里需要注意,我们要找的不是未来时间下的Target(毕竟未来的事还没发生,根本无从找起),而是从过去时间里构造“未来的”Target,从而完成模型的构建。这是在处理时间序列上,逻辑最绕的地方。

3. 模型构建

用机器学习算法构造时间序列预测模型,关键的思路在于,通过时间滑窗,人为地构造“未来”Target,来给算法进行学习。

有点绕,请看下面的示意图。


和之前一样,从时间的角度上来看,我们有历史数据,和新数据。但这里,我们不能简单地把历史数据作为训练集、把新数据作为测试集。

怎么做呢。

首先,在历史数据上,我们通过截取不同时间窗口的数据来构造一组或几组数据。比如,我的历史数据是2017年 1月到12月每家店每天的销售数据,那么我可以截取3组数据(见上图的深绿、浅绿部分):2017年1月到10月的数据、2017年2月到11月的数据、2017年3月到12月的数据。

然后,人为地给每组数据划分历史窗口(对应上图的深绿色部分)和未来窗口(对应上图的浅绿色部分)。比如,对于2017年1月到10月的数据,我把1月到9月作为历史窗口、10月作为未来窗口,以此类推。

接着,分别给每组数据构建预测特征,包括历史特征(预测特征A)和未来特征(预测特征B)。而此时,每组数据还有预测Target。

这个时候,我们把得到的所有预测特征(我的例子里是三组预测特征)都合并起来作为训练集特征、把所有预测Target(我的例子里是三组预测Target)合并起来作为训练集Target,之后就可以构建机器学习模型了。

有了训练集和训练模型,还差测试集。测试集的构建遵循之前的数据处理逻辑,拿历史数据构建历史特征,拿新数据构建未来特征,然后把这些特征加入到从训练集上训练出的预测模型中去,即可得到任务需要的最终预测值。

这里需要注意,划多少个时间窗口因数据而异。此外,数据的历史窗口(图上深绿部分)和未来窗口(图上浅绿部分)可以是定长也可以是变长,看具体情况。



频率由泊松过程驱动,具有一个协变量X1,并且我们假设呈指数速率。在此考虑标准线性回归,没有任何时间因素影响

> reg=glm(Y~X1+offset(log(E)),data=B,
+ family=poisson)

我们还可以计算年度经验索赔频率


课程

R语言数据分析挖掘必知必会

从数据获取和清理开始,有目的的进行探索性分析与可视化。让数据从生涩的资料,摇身成为有温度的故事。

立即参加

> u=seq(0,1,by=.01)
> v=predict(re
 
> vp=Vectorize(p)(seq(.05,.95,by=.1))

并在同一张图上绘制两条曲线,

> plot(seq(.05,.95,by=.1),vp,type="b")
> lines(u,exp(v),lty=2,col="red")

这就是我们通常在计量经济学中所做的。在机器学习中,更具体地说,是评估模型的质量以及进行模型选择,通常将数据集分为两部分。训练样本和验证样本。考虑一些随机的训练/验证样本,然后在训练样本上拟合模型,最后使用它来进行预测,

蓝色曲线是对训练样本的预测(就像在计量经济学中所做的那样),红色曲线是对测试样本的预测。

现在,如果我们使用年份作为划分标准,我们将旧数据拟合为模型,并在最近几年对其进行测试,

> B_a=subset(
T>=2014)
> reg=glm(Y~X1+offset(l
 
 
+   B=B_a[abs(B_a$X1-x)<.1,]
+   sum(B$Y)/sum(B$E)
+ }
> vp_a=Vectorize(p)(
y=.1),vp_a,col="blue")
> lines(u,exp(v),lty=2)
> p=function(x){
-x)<.1,]
+   sum(B$Y)/sum(B$E)
+ }
eq(.05,.95,by=.1))
> lines(seq(.05,.95,b=.1),vp_t,

显然,结果不理想。

我花了一些时间来了解训练和验证样本的设计方式对结果产生的影响。

我使用回归模型:

 
glm(Y~X1+T+offset(log(E)),data=B,
+ family=poisson)
 
> u=seq(1999,2016,by=
 

在这里,我们使用线性模型,但是通常没有理由假设线性。所以我们可以考虑样条

 
 
> reg=glm(Y~X1+bs(T)+offse
 
> u=seq(1999,2016,by=.
 
> v2=predict(reg,newdata=
 
> plot(2000:2015,exp(v2),ty

除了假设存在一个基本的平滑函数,我们可以考虑因子的回归

 
as.factor(T)+
 
+ data=B,family=p
g)
> u=seq(1999,2016,by=.1)
> v=exp(-(u-2000)/20
[2:17]),type="b")

另一种选择是考虑一些更通用的模型,例如回归树

 
 
> reg=rpart(Y~X1+T+offset(log(E)),dat
 
> p=function(t){
+   B=B[B$T==t,]
 
+   mean(predict(reg,newdata=B))
+ }
2000:2015)
> u=seq(1999,2016,by=.1)
 
> plot(2000:2015,y_m,ylim=c(

在年化频率上考虑与风险敞口相关的权重 

> reg=rpart(Y/E~X1+T,data
weights=B$E,cp=1
 
+   B=B[B$T==t,]
+   B$E=1
 
+ }
> y_m=Vectorize(function(t) p(t))(
 
> v=exp(-(u-2000)/20-3+.5)
> plot(2000:2015,y_m,ylim=c(.02,.08

从机器学习的角度来看,考虑训练样本(基于旧数据)和验证样本(基于较新的样本)

> B_a=subset(B,T<2014)
> B_t=subset(B,T>=2014)

如果我们考虑使用广义线性模型,那么也很容易获得近年来的预测,

> reg_a=glm(Y~X1+T+offset(l
 
> C=coefficients(reg_a)
> u=seq(1999,20
/20-3)
+C[3]*c(2000:2013,
+ NA,NA)),type="b")
)
> points(2014:2015,exp(C

但是,如果我们以年份为因子,我们需要对训练样本中没有的水平进行预测,结果更加复杂。

> reg_a=glm(Y~0+X1+as.factor(T)+offse
 
> C=coefficients(reg_a)
2014) + A[2]*(B_t$T==2015))
+   Y_t=L*B_t$E
 
> i=optim(c(.4,.4),RMSE)$par
> plot(2000:2015,c(exp(C[2:15]
 
> lines(u,v,lty=2,col="red")
lue")

我们将RMSE量化近年来的预测水平,输出还不错。

获得旧数据的训练数据集,并在最近几年对其进行测试应该谨慎适当地考虑时间模型。


可下载资源

关于作者

Kaizong Ye拓端研究室(TRL)的研究员。

本文借鉴了作者最近为《R语言数据分析挖掘必知必会 》课堂做的准备。

​非常感谢您阅读本文,如需帮助请联系我们!

 
QQ在线咨询
售前咨询热线
15121130882
售后咨询热线
0571-63341498

关注有关新文章的微信公众号


永远不要错过任何见解。当新文章发表时,我们会通过微信公众号向您推送。

技术干货

最新洞察

This will close in 0 seconds