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) > 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
数据(列y
到x4
) 排名不足。试试X <- model.matrix(y ~ ., train); rankMatrix(X) < 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() 循环。警告:来自秩不足拟合的预测可能具有误导性的主要内容,如果未能解决你的问题,请参考以下文章
lm() 和 predict.lm() 的奇怪行为取决于显式命名空间访问器的使用