- 何为基拓展(Basis Expansions)
对于线性模型,有
基扩展后,模型形式为
若 ,则退化为线性模型;
若 或者 ,是利用多项式增强输入;
若 ,则为单个输入的非线性转换。
有时候选的基函数 数量过多,那么如何挑选呢,有以下三种思路:
(1)限制模型的形式。考虑加性模型(additive model),
则模型的尺寸由 确定。
(2)根据策略挑选。逐步地添加对训练结果贡献最大的基函数。Forward Stepwise、Backward Stepwise、Forward Stagewise以及CART、MARS、boosting都属于这种类型。
(3)正则化。包含整个基函数集,但是通过限制系数的大小来减小实际的基函数数量,Lasso就是一个典型的方法。
- 自然样条(natural spline)相对于普通立方样条(cubic spline)的优势
二者的区别在于对边界的处理方法上。立方样条仅在区间内选择若干个knots,边界外的训练结果就放飞自我了。相对于立方样条,自然样条还要求边界外一阶可导。假设有K个knots,则基函数的个数为(K+1 regions)×(4 parameters per region) −(K knots)×(3 constraints per knot)-(2 knots)×(2 constraints per knot)=K。
来康康各种模型在边界外的方差:考虑一个简单的问题,仅有一个输入变量 ,在区间[0, 1]均匀取值,误差为常数1。假设拓展后的参数数量为df,则N个样本可以组成维度为 的基矩阵 。对于模型 ,系数的协方差矩阵为 。每个样本的方差为 。
对于全局线性模型, ;
对于全局立方多项式, ;
对于两个knots的立方样条, ;
对于自然样条,取6个knots, ,其中
下图绘制了各种样条下每个样本的拟合方差。
继续举例,考虑一个实际的问题,利用基拓展的逻辑回归处理非洲心脏病数据(详细描述见+++++上一章非洲心脏病的链接++++++)。拓展后的模型如下:
其中,每个 均为输入变量 自然样条后的基函数。
每个输入变量取5个knots,3个内部knots,另外两个knots分别位于左右的极值处,5个knots对应5个基函数,然后减去1个常数项,也对应于4个基函数。分类变量不进行基拓展。
如何进行模型选择(model selection)呢?这里采用了逐步回退的方式,根据AIC统计量丢弃输入变量,注意到一次丢弃某个输入变量的整个集合,而不是一个系数。对于逻辑回归,AIC统计量的定义如下:
其中, 。每次均丢弃AIC值减小最多的输入变量,丢弃最终模型中的变量均会使得AIC值增加。类似上个例子,可以绘制每个输入变量的逐点方差。
ESL的作者在绘制每个输入变量的逐点方差时,使用了R语言的ns函数,ns实际上构造的是B-spline基函数,原理可以参考ESL第五章最后面,实现起来过于琐碎,还是老老实实调包吧,R语言绘图核心代码如下:
SA "D:\\Program\\R\\SAheart.txt",header=TRUE,sep=",")
SA.glm summary(SA.glm)
library(splines
degf 4
X 1,ns(SA$obesity,df=degf),ns(SA$age,df=degf))
X 1,dim(SA)[1]),scale(X,scale=FALSE))
SA.glm2 coeff
S h1 2:5] %*% coeff[2:5]
se1 2:5] %*% S[2:5,2:5] %*% t(X[,2:5])))
h2 6:9] %*% coeff[6:9]
se2 6:9] %*% S[6:9,6:9] %*% t(X[,6:9])))
h3 10:13] %*% coeff[10:13]
se3 10:13] %*% S[10:13,10:13] %*% t(X[,10:13])))
h5 15:18] %*% coeff[15:18]
se5 15:18] %*% S[15:18,15:18] %*% t(X[,15:18])))
h6 19:22] %*% coeff[19:22]
se6 19:22] %*% S[19:22,19:22] %*% t(X[,19:22])))
par(mfrow=c(3,2))
plot(sort(SA$sbp),h1[order(SA$sbp)],type="l",ylim=c(-1,4),xlab="sbp",ylab="")
lines(sort(SA$sbp),h1[order(SA$sbp)]+2*se1[order(SA$sbp)])
lines(sort(SA$sbp),h1[order(SA$sbp)]-2*se1[order(SA$sbp)])
rug(jitter(SA$sbp))
plot(sort(SA$tobacco),h2[order(SA$tobacco)],type="l",ylim=c(-1,8),xlab="tobacco",ylab="")
lines(sort(SA$tobacco),h2[order(SA$tobacco)]+2*se2[order(SA$tobacco)])
lines(sort(SA$toba