使用R中的fda包预测新曲线的响应


10

基本上,我要做的就是使用一些曲线来预测标量响应。我已经做完了回归(使用fda包中的fRegress进行回归),但不知道如何将结果应用于一组新曲线(用于预测)。

我有N = 536曲线和536标量响应。到目前为止,这是我所做的:

  • 我为曲线创建了基础。
  • 我创建了一个fdPar对象来引入罚款
  • 我已经使用smooth.basis创建了fd对象,以在指定的基础上以选定的代价对曲线进行平滑处理。
  • 我使用fRegress()进行了回归,对标量响应上的曲线进行回归。

现在,我要做的就是使用该回归为我拥有的一组新数据生成预测。我似乎找不到简单的方法来做到这一点。

干杯


即使是有关如何根据基础对象,平滑对象(fd)和fRegress()的回归估计手动计算预测的描述,也将非常有帮助。
dcl

只是检查:你尝试过使用predict.fRegress使用newdata选项(从FDA手册这里)?

我有,只是我不确定“ newdata”必须是什么类或格式。它不会接受fd或fdSmooth对象,这是我希望从中预测的平滑曲线。而且它不会让我输入原始参数和协变量值。
dcl

1
我记得大约一年前我在玩这个fda包装时遇到过类似的问题。我正在编写一个涉及手动获取预测的响应,但是由于未保存预测而导致很大一部分丢失。如果有人没有击败我,几天之内我应该为您提供解决方案。

Answers:


14

我不关心Inceptionfda的使用,例如list- in -list-in-list对象结构,但是我的回答将遵守软件包编写者创建的系统。

我认为首先考虑我们正在做的事情是有启发性的。根据您到目前为止所做的描述,这就是我认为您正在做的事情(如果我误解了某些内容,请告诉我)。我将继续使用表示法,由于缺乏实际数据,我将举Ramsay和Silverman的功能数据分析以及Ramsay,Hooker和Graves的R和MATLAB功能数据分析为例 (以下一些方程和代码被直接取消了)从这些书中)。

我们正在通过功能线性模型来建模标量响应,即

yi=β0+0TXi(s)β(s)ds+ϵi

我们会在一定程度上扩展。我们使用基函数。所以,ķβK

β(s)=k=1Kbkθk(s)

用矩阵表示法是。β(s)=θ(s)b

我们也在某些基础上扩展协变量函数(例如基础函数)。所以,L

Xi(s)=k=1Lcikψk(s)

同样,在矩阵符号中,这是。X(s)=Cψ(s)

因此,如果我们让,我们的模型可以表示为J=ψ(s)θ(s)ds

y=β0+CJb

如果让和,则我们的模型是ξ = [ β 0Z=[1CJ]ξ=[β0b]

y=Zξ

对我们来说,这看起来更加熟悉。

现在,我看到您正在添加某种正则化。该fda包装适用以下形式的粗糙度惩罚

P=λ[Lβ(s)]2ds

对于一些线性微分算。现在可以显示出(如果没有详细说明,这很难显示),如果我们将惩罚矩阵为[RLR

R=λ(0000R1000RK)

其中是的基数展开,然后我们将平方的罚和最小化:β Riβi

(yZξ)(yZξ)+λξRξ

所以我们的问题仅仅是解决方案的岭回归:

ξ^=(ZZ+λR)1Zy

我仔细阅读了以上内容,是因为(1)我认为了解我们正在做的事情很重要,并且(2)以上某些内容对于理解以后将要使用的某些代码是必需的。转到代码...

这是带有R代码的数据示例。我正在使用fda包装中提供的加拿大天气数据集。我们将通过功能线性模型对多个气象站的对数年降水量进行建模,并将每个气象站的温度曲线(每天一次记录一次,连续365天记录温度)作为函数协变量。我们将按照您对情况的描述进行类似的处理。数据记录在35个站点。我将数据集划分为34个站(将用作我的数据)和最后一个站(将作为我的“新”数据集)。

我将继续使用R代码和注释(我假设您对fda软件包足够熟悉,因此以下内容都不令人感到惊讶-如果不是这种情况,请告诉我):

# pick out data and 'new data'
dailydat <- daily$precav[,2:35]
dailytemp <- daily$tempav[,2:35]
dailydatNew <- daily$precav[,1]
dailytempNew <- daily$tempav[,1]

# set up response variable
annualprec <- log10(apply(dailydat,2,sum))

# create basis objects for and smooth covariate functions
tempbasis <- create.fourier.basis(c(0,365),65)
tempSmooth <- smooth.basis(day.5,dailytemp,tempbasis)
tempfd <- tempSmooth$fd

# create design matrix object
templist <- vector("list",2)
templist[[1]] <- rep(1,34)
templist[[2]] <- tempfd

# create constant basis (for intercept) and
# fourier basis objects for remaining betas
conbasis <- create.constant.basis(c(0,365))
betabasis <- create.fourier.basis(c(0,365),35)
betalist <- vector("list",2)
betalist[[1]] <- conbasis
betalist[[2]] <- betabasis

# set roughness penalty for betas 
Lcoef <- c(0,(2*pi/365)^2,0)
harmaccelLfd <- vec2Lfd(Lcoef, c(0,365))
lambda <- 10^12.5
betafdPar <- fdPar(betabasis, harmaccelLfd, lambda)
betalist[[2]] <- betafdPar

# regress
annPrecTemp <- fRegress(annualprec, templist, betalist)

现在,大约一年前,当我第一次被告知有关功能数据时,我就试用了这个软件包。我也无法predict.fRegress给我想要的东西。现在回头看,我仍然不知道如何使其表现出来。因此,我们只需要半手动获得预测即可。我将使用直接从代码中提取的片段fRegress()。同样,我继续通过代码和注释。

首先,设置:

# create basis objects for and smooth covariate functions for new data
tempSmoothNew <- smooth.basis(day.5,dailytempNew,tempbasis)
tempfdNew <- tempSmoothNew$fd

# create design matrix object for new data
templistNew <- vector("list",2)
templistNew[[1]] <- rep(1,1)
templistNew[[2]] <- tempfdNew

# convert the intercept into an fd object
onebasis <- create.constant.basis(c(0,365))
templistNew[[1]] <- fd(matrix(templistNew[[1]],1,1), onebasis)

现在获取预测

y^new=Znewξ^

我只fRegress使用用于yhatfdobj略微计算和编辑它的代码。 fRegress计算yhatfdobj通过估计积分通过梯形规则(具有和在其各自的基座展开)。 X β0TXi(s)β(s)Xiβ

通常,fRegress通过遍历存储在中的协变量来计算拟合值annPrecTemp$xfdlist。因此,对于我们的问题,我们用新的协变量列表中的对应变量替换了该协变量列表templistNew。这是代码(fRegress与两次编辑中发现的代码相同,删除了不需要的代码,并添加了一些注释):

# set up yhat matrix (in our case it's 1x1)
yhatmat <- matrix(0,1,1)

# loop through covariates
p <- length(templistNew)
for(j in 1:p){
    xfdj       <- templistNew[[j]]
    xbasis     <- xfdj$basis
    xnbasis    <- xbasis$nbasis
    xrng       <- xbasis$rangeval
    nfine      <- max(501,10*xnbasis+1)
    tfine      <- seq(xrng[1], xrng[2], len=nfine)
    deltat     <- tfine[2]-tfine[1]
    xmat       <- eval.fd(tfine, xfdj)
    betafdParj <- annPrecTemp$betaestlist[[j]]
    betafdj    <- betafdParj$fd
    betamat    <- eval.fd(tfine, betafdj)
    # estimate int(x*beta) via trapezoid rule
    fitj       <- deltat*(crossprod(xmat,betamat) - 
                      0.5*(outer(xmat[1,],betamat[1,]) +
              outer(xmat[nfine,],betamat[nfine,])))
    yhatmat    <- yhatmat + fitj
}

(注意:如果您在中查看此块和周围的代码fRegress,您将看到我上面概述的步骤)。

我通过使用所有35个站点作为我们的数据重新运行天气示例来测试代码,并将上述循环的输出与进行比较,annPrecTemp$yhatfdobj然后一切都匹配了。我还使用不同的站点作为“新”数据运行了几次,一切似乎都很合理。

让我知道以上任何不清楚的地方,或者是否有任何不正常的工作。抱歉,回复过于详细。我帮不上忙:)如果您还不拥有它们,请查看我用来撰写此回复的两本书。他们真的是好书。


看起来正是我所需要的。谢谢。我以为我不必玩nfine / tine / deltat的东西吧?我是否应该认为集成工作足够准确?
dcl

另外,我注意到您没有直接惩罚“新”协变量或“旧”协变量。所有这些都是通过惩罚Beta(以及我猜想的基本函数的数量)来完成的。惩罚lambda应用于beta。通过在回归之前对平滑进行惩罚,您是否能达到相同的效果?(具有相同的lambda值)
dcl

1
用于近似积分的网格非常好,因此近似值应该很好。您总是可以增加nfine并查看积分的变化量,但是我想它不会做太多。至于惩罚,是的,在这种情况下,我们直接惩罚而不是。Ramsay和Silverman讨论了另一种惩罚方法,该方法无需基础函数即可估算,其中我们将惩罚直接应用于。两种方式都在函数上引入了平滑度约束,但是我不确定您是否会获得“相同的效果”。β βξββ^βββ

我已经尝试过处理代码以产生多条曲线的预测,但是我不确定我是否正确完成了它。对于初学者来说,在循环的第一次迭代之后,yhatmat对于所有弯曲者而言并不是恒定的……这是否意味着等于?β0
dcl

1
@dcl在循环中,当,它将到(假设的第一个列表对应于截距项)。您可以将要使用的代码段添加到问题中,以便我查看吗?^ β 0 ÿj=1β0^y^
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.