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
会为您的模型添加截距。因此,最简单的做法是从 x
和 x.test
矩阵中排除截距列。
我使用 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
会为您的模型添加截距。因此,最简单的做法是从 x
和 x.test
矩阵中排除截距列。