1

如果这更适合 CrossValidated,我们深表歉意。

我正在使用 R 中的 mgcv 包将 GAM 模型拟合到二项式数据。协变量之一是周期性的,因此我指定了bs = "cc"循环三次样条。我在交叉验证框架中执行此操作,但是当我使用该predict函数拟合我的保留数据时,出现以下错误:

Error in pred.mat(x, object$xp, object$BD) : 
  can't predict outside range of knots with periodic smoother

这是一些应该复制错误的代码:

# generate data:
x <- runif(100,min=-pi,max=pi)
linPred <- 2*cos(x) # value of the linear predictor
theta <- 1 / (1 + exp(-linPred)) # 
y <- rbinom(100,1,theta)
plot(x,theta)
df <- data.frame(x=x,y=y)

# fit gam with periodic smoother:
gamFit <- gam(y ~ s(x,bs="cc",k=5),data=df,family=binomial())
summary(gamFit)

plot(gamFit)

# predict y values for new data:
x.2 <- runif(100,min=-pi,max=pi)
df.2 <- data.frame(x=x.2)
predict(gamFit,newdata=df.2)

任何关于我哪里出错的建议将不胜感激。也许手动指定结落在 -pi 和 pi 上?

4

2 回答 2

2

第一次运行时我没有收到错误,但我确实在第二次尝试时复制了错误。也许您需要使用set.seed(123) #{no error}and set.seed(223) #{produces error}。看看这是否会产生部分成功。我认为您只是在推导和验证数据集中看到了一些点相对较少的变化。适合 GAM 的 100 分并不是特别“慷慨”。

查看 gamFit 对象,结的范围似乎被编码在 中gamFit$smooth[[1]]['xp'],因此这应该将您的输入限制在适当的范围内:

 x.2 <- runif(100,min=-pi,max=pi); 
 x.2 <- x.2[findInterval(x.2, range(gamFit$smooth[[1]]['xp']) )== 1]

 # Removes the errors in all the situations I tested
 # There were three points outside the range in the set.seed(223) case
于 2012-07-31T22:17:04.973 回答
1

问题是您的测试集包含不在训练集范围内的值。由于您使用了样条曲线,因此在 的最小值和最大值处创建了结x,并且您的拟合函数未定义在该范围之外。因此,当您测试模型时,您应该排除那些超出范围的点。以下是您如何排除测试集中的点:

set.seed(2)
... <Your code>
predict(gamFit,newdata=df.2[df.2$x>=min(df$x) & df.2$x<=max(df$x),,drop=F])

或者,您可以将模型中的“外部”节点指定为整个数据的最小值和最大值。我不知道该怎么做。

于 2012-07-31T22:37:34.083 回答