R中的PLS:预测新观察值会返回Fitted值

时间:2016-01-04 09:04:27

标签: r regression

在过去的几天里,我在R中开发了多个PLS模型,用于光谱数据(波段作为解释变量)和各种植被参数(作为单独的响应变量)。总的来说,数据集由56组成。前28个(训练集)已经用于模型校准,现在我想要做的就是预测tesset中剩余的28个观测值的响应值。然而,出于某种原因,R继续为给定数量的组件返回校准集的拟合值,而不是针对独立测试集的预测。简而言之,这就是模型的样子。

# first simulate some data
set.seed(123)
bands=101
data <- data.frame(matrix(runif(56*bands),ncol=bands))
colnames(data) <- paste0(1:bands)
data$height <- rpois(56,10)
data$fbm <- rpois(56,10)
data$nitrogen <- rpois(56,10)
data$carbon <- rpois(56,10)
data$chl <- rpois(56,10)
data$ID <- 1:56

data <- as.data.frame(data)
caldata <- data[1:28,] # define model training set
valdata <- data[29:56,] # define model testing set

# define explanatory variables (x)
spectra <- caldata[,1:101]

# build PLS model using training data only
library(pls)
refl.pls <- plsr(height ~ spectra, data = caldata, ncomp = 10, validation = 
"LOO", jackknife = TRUE)

然后确定包含3种组分的模型产生最佳性能而没有过度拟合。因此,使用以下命令来预测测试集中28个观测值的值,使用上述校准的PLS模型,包含3个分量:

predict(refl.pls, ncomp = 3, newdata = valdata)

看似输出很明智,我很快发现所有这些代码生成的是PLS模型的校准/训练数据的拟合值,而不是预测。我发现这是因为下面的代码,其中newdata =被省略,产生相同的结果。

predict(refl.pls, ncomp = 3)
肯定有些事情肯定会出错,虽然我似乎无法找出具体的内容。是否有人能够并且愿意帮助我朝着正确的方向前进?

1 个答案:

答案 0 :(得分:0)

我认为问题在于输入数据的性质。查看与示例一起使用的?plsrstr(yarn)plsr需要一个非常具体的数据框,我觉得这很难处理。输入数据帧应该有一个矩阵作为其元素之一(在您的情况下,是光谱数据)。我认为以下工作正常(注意我改变了训练集的大小,使其不是原始数据的一半,用于故障排除):

library("pls")
set.seed(123)
bands=101
spectra = matrix(runif(56*bands),ncol=bands)
DF <- data.frame(spectra = I(spectra),
        height = rpois(56,10),
        fbm = rpois(56,10),
        nitrogen = rpois(56,10),
        carbon = rpois(56,10),
        chl = rpois(56,10),
        ID = 1:56)
class(DF$spectra) <- "matrix" # just to be certain, it was "AsIs"
str(DF)

DF$train <- rep(FALSE, 56)
DF$train[1:20] <- TRUE

refl.pls <- plsr(height ~ spectra, data = DF, ncomp = 10, validation = 
"LOO", jackknife = TRUE, subset = train)

res <- predict(refl.pls, ncomp = 3, newdata = DF[!DF$train,])

请注意,我将光谱数据作为矩阵保存到数据框中,方法是使用等同于I的{​​{1}}保护它。可能有更标准的方法来做到这一点,但它的工作原理。正如我所说,对我来说,数据框内的矩阵并不完全直观或易于理解。

至于为什么你的版本不能正常工作,我认为最好的解释是,所有内容都需要在传递给AsIs的一个数据框中,以使数据源完全明确。