predict.lm() 循环。警告:来自秩不足拟合的预测可能具有误导性

Posted

技术标签:

【中文标题】predict.lm() 循环。警告:来自秩不足拟合的预测可能具有误导性【英文标题】:predict.lm() in a loop. warning: prediction from a rank-deficient fit may be misleading 【发布时间】:2014-12-20 22:10:26 【问题描述】:

此 R 代码引发警告

# Fit regression model to each cluster
y <- list() 
length(y) <- k
vars <- list() 
length(vars) <- k
f <- list()
length(f) <- k

for (i in 1:k) 
  vars[[i]] <- names(corc[[i]][corc[[i]]!= "1"])
  f[[i]]  <- as.formula(paste("Death ~", paste(vars[[i]], collapse= "+")))
  y[[i]]  <- lm(f[[i]], data=C1[[i]]) #training set
  C1[[i]] <- cbind(C1[[i]], fitted(y[[i]]))
  C2[[i]] <- cbind(C2[[i]], predict(y[[i]], C2[[i]])) #test set

我有一个训练数据集 (C1) 和一个测试数据集 (C2)。每一个都有 129 个变量。我在 C1 上做了 k 表示聚类分析,然后根据集群成员拆分我的数据集并创建了一个不同集群的列表(C1[[1]]、C1[[2]]、...、C1[[k] ])。我还为 C2 中的每个案例分配了一个集群成员资格,并创建了 C2[[1]]、...、C2[[k]]。然后我对 C1 中的每个集群进行线性回归。我的因变量是“死亡”。我的预测变量在每个集群中都不同,并且 vars[[i]] (i=1,...,k) 显示了预测变量名称的列表。我想预测测试数据集中每个案例的死亡 (C2[[1]],..., C2[[k])。当我运行以下代码时,对于某些集群。

我收到此警告:

In predict.lm(y[[i]], C2[[i]]) :
prediction from a rank-deficient fit may be misleading

我阅读了很多关于此警告的信息,但我无法弄清楚问题所在。

【问题讨论】:

问题是你得到了排名不足的拟合。您需要找出哪些适合发出警告并检查它们。 【参考方案1】:

您可以使用body(predict.lm) 检查预测功能。在那里你会看到这一行:

if (p < ncol(X) && !(missing(newdata) || is.null(newdata))) 
    warning("prediction from a rank-deficient fit may be misleading")

此警告检查您的数据矩阵的秩是否至少等于您要拟合的参数数量。调用它的一种方法是使用一些共线协变量:

data <- data.frame(y=c(1,2,3,4), x1=c(1,1,2,3), x2=c(3,4,5,2), x3=c(4,2,6,0), x4=c(2,1,3,0))
data2 <- data.frame(x1=c(3,2,1,3), x2=c(3,2,1,4), x3=c(3,4,5,1), x4=c(0,0,2,3))
fit <- lm(y ~ ., data=data)

predict(fit, data2)
       1        2        3        4 
4.076087 2.826087 1.576087 4.065217 
Warning message:
In predict.lm(fit, data2) :
  prediction from a rank-deficient fit may be misleading

请注意,data 中的 x3 和 x4 具有相同的方向。一个是另一个的倍数。这可以通过length(fit$coefficients) &gt; fit$rank进行检查

另一种方法是参数多于可用变量:

fit2 <- lm(y ~ x1*x2*x3*x4, data=data)
predict(fit2, data2)
Warning message:
In predict.lm(fit2, data2) :
  prediction from a rank-deficient fit may be misleading

【讨论】:

感谢您的回复。在集群 2 中,C1[[2]] 有 130 行,我有 67 个预测变量。我找到了回归函数 y[[2]]。然后,我使用 y[[2]] 来预测 C2[[2]] 中所有案例的“死亡”。 C2[[2]] 只有 32 行。这是警告的原因吗?因为我有 32 个案例,而我的回归函数有 67 个变量?当我们使用 predict.lm 时,我假设我们已经找到了该函数,并且该函数将用于预测 C2[[2]] 中每个案例的死亡。因此,我认为拥有比预测变量数量更多的案例并不重要。我说的对吗? 模型中的案例比变量多很重要。您可以尝试在案例少于所需案例的情况下执行此操作,但您应该记住,在这种情况下您的预测可能不可靠。这就是 R 给你“警告”而不是错误的原因。只是为了引起你的注意。即使出现警告(它们不是错误),您也应该能够得到答案并继续工作,但尝试简化模型是明智的。【参考方案2】:

此警告:

In predict.lm(model, test) :
  prediction from a rank-deficient fit may be misleading

从 R 的 predict.lm 抛出。见:http://stat.ethz.ch/R-manual/R-devel/library/stats/html/predict.lm.html

了解秩不足:让 R 告诉你矩阵的秩:

train <- data.frame(y=c(1234, 325, 152, 403), 
                   x1=c(3538, 324, 382, 335), 
                   x2=c(2985, 323, 223, 288), 
                   x3=c(8750, 322, 123, 935))
test <- data.frame(x1=c(3538, 324, 382, 335), 
                   x2=c(2985, 323, 223, 288), 
                   x3=c(8750, 322, 123, 935))
library(Matrix)
cat(rankMatrix(train), "\n")   #prints 4
cat(rankMatrix(test), "\n")    #prints 3

没有“满秩”的矩阵被称为“秩不足”。如果矩阵的秩等于其列数或等于其行数(或两者),则称该矩阵具有满秩。

问题是 predict.lm 会抛出这个警告,即使你的矩阵是满秩的(不是秩不足的),因为 predict.lm 通过丢弃它认为无用的特性,修改你的完整排名输入为排名不足。然后它通过警告来抱怨它。

此外,对于其他情况,此警告似乎是一个包罗万象的信息,例如您有太多输入特征并且您的数据密度太稀疏,并且它提出了预测很脆弱的观点。

通过全秩矩阵的示例,但 predict.lm 仍然抱怨秩不足

train <- data.frame(y=c(1,2,3,4),
                        x1=c(1,1,2,3),
                        x2=c(3,4,5,2),
                        x3=c(4,2,6,0),
                        x4=c(2,1,3,0)
                   )
test <- data.frame(x1=c(1, 2,  3,  9),
                   x2=c(3, 5,  1, 15),
                   x3=c(5, 9,  5, 22),
                   x4=c(9, 13, 2, 99))
library(Matrix)
cat(rankMatrix(train), "\n")    #prints 4, is full rank, good to go
cat(rankMatrix(test), "\n")     #prints 4, is full rank, good to go
myformula = as.formula("y ~ x1+x2+x3+x4")
model <- lm(myformula, train)
predict(model, test) 
    #Warning: prediction from a rank-deficient fit may be misleading

解决方法:

假设 predict 返回良好的预测,您可以忽略警告。 predict.lm 在视角不足的情况下提供了它的意见,你来了。

所以在预测步骤中禁用警告,如下所示:

options(warn=-1)      #turn off warnings
predict(model, test)
options(warn=1)      #turn warnings back on

【讨论】:

我认为这个答案是错误的。您需要获取设计矩阵的等级,而不是 包含具有响应变量的列的数据框的等级!第二个示例中的train 数据(列yx4 排名不足。试试X &lt;- model.matrix(y ~ ., train); rankMatrix(X) &lt; ncol(X),你会发现设计矩阵秩不足。我相信您关于 R 将修改“您的全等级输入为等级不足”的断言是错误的。【参考方案3】:

这是因为,您的一个因变量对 lm(..) 函数输出的系数具有 NA。这样的变量对模型没有影响,通常是由于多重共线性问题,即预测变量线性依赖于其他预测变量,或者因为预测变量对于所有记录(行)都是恒定的。最好的办法是从 lm(..) 函数的公式中删除该变量并再次进行回归。这不会降低模型的准确性。 就我而言,

model <- lm(Happiness.Score ~ Economy..GDP.per.Capita.+year+Health..Life.Expectancy., data=dfTrain)

> model
Call:
lm(formula = Happiness.Score ~ Economy..GDP.per.Capita. + year + 
    Health..Life.Expectancy., data = dfTrain)

Coefficients:
             (Intercept)  Economy..GDP.per.Capita.                      year  
                   3.036                     1.569                        NA  
Health..Life.Expectancy.  
                   1.559

可变年份对于所有记录具有相同的值。去掉年份变量后

model <- lm(Happiness.Score ~ Economy..GDP.per.Capita.+Health..Life.Expectancy., data=dfTrain)

preds <- predict.lm(model, dfTest[, c(1:nrow(dfTest)-1]))

这不会给出警告信息

【讨论】:

以上是关于predict.lm() 循环。警告:来自秩不足拟合的预测可能具有误导性的主要内容,如果未能解决你的问题,请参考以下文章

predict.lm() 在测试数据中具有未知因子水平

lm() 和 predict.lm() 的奇怪行为取决于显式命名空间访问器的使用

来自 PMD 的 Java 流 while 循环异常警告

如何调试线性模型和预测的“因子具有新水平”错误[重复]

来自 Pylint 的 Cell-var-from-loop 警告

使用仪器解决内存不足警告