predict.glm() 在盲测数据上

predict.glm() on blind test data

我使用 glmnet 包对 class 化问题使用正则化逻辑回归。在开发过程中,一切正常,但在盲测数据上进行预测时遇到了问题。

因为我不知道 class 标签,所以我用于测试的数据框比我用于训练的数据框少了一列。这似乎是 predict.glm() 的问题,因为它需要匹配的维度 - 我可以通过在测试数据中添加带有一些任意标签的列来 "fix" 它,但这似乎是个坏主意。希望这个例子能说明问题:

library(glmnet)
example = data.frame(rnorm(20))
colnames(example) = "A"
example$B = rnorm(20)
example$class = ((example$A + example$B) > 0)*1

testframe = data.frame(rnorm(20))
colnames(testframe) = "A"
testframe$B = rnorm(20)

x = model.matrix(class ~ ., data = example)
y = data.matrix(example$class)

# this is similar to the situation I have with my data
# the class labels are ommited on the blind test set

所以如果我这样继续下去,我会得到一个错误:

x.test = as.matrix(testframe)
ridge = glmnet(x,y, alpha = 0, family = "binomial", lambda = 0.01789997)
ridge.pred = predict(ridge, newx = x.test, s = 0.01789997, type = "class")

Error in cbind2(1, newx) %*% nbeta: Cholmod error 'X and/or Y have wrong dimensions' at file ../MatrixOps/cholmod_sdmult.c, line 90

我可以 "fix" 通过向我的测试数据添加 class 列来解决问题:

testframe$class = 0
x.test = model.matrix(class ~ ., data = testframe)
ridge.pred2 = predict(ridge, newx = x.test, s = 0.01789997, type = "class")

所以我对此有几个问题:
a) 这种添加列的解决方法安全吗?做这个感觉很wrong/dangerous,因为不知道predict方法会不会用到(不然为什么要有这个列?
b) 更好的/"the correct" 方法是什么?

提前致谢!

回答

创建矩阵 x 时,删除 (Intercept) 列(始终是第一列)。那么您的 predict 函数将在没有解决方法的情况下运行。具体来说,使用这一行来创建 x.

x = model.matrix(class ~ ., data = example)[,-1]

说明

您收到错误消息,因为 model.matrix 正在为模型中的截距创建一个列,该列不在您的 x.test 矩阵中。

colnames(x)
# [1] "(Intercept)" "A"           "B"          
colnames(x.test)
# [1] "A" "B"

除非您设置 intercept=FALSE,否则 glmnet 会为您的模型添加截距。因此,最简单的做法是从 xx.test 矩阵中排除截距列。