为什么 predict.glmnet 不预测概率?
Why is predict.glmnet not predicting probabilities?
我正在研究一个模型来预测大学棒球运动员进入大联盟的可能性。我的数据集有 633 个观测值和 13 个具有二元响应的预测变量。下面的代码生成较小的可重现的训练和测试数据集示例:
set.seed(1)
OBP <- rnorm(50, mean=1, sd=.2)
HR.PCT <- rnorm(50, mean=1, sd=.2)
AGE <- rnorm(50, mean=21, sd=1)
CONF <- sample(c("A","B","C","D","E"), size=50, replace=TRUE)
CONF <- factor(CONF, levels=c("A","B","C","D","E"))
df.train <- data.frame(OBP, HR.PCT, AGE, CONF)
df.train <- df.train[order(-OBP),]
df.train$MADE.MAJORS <- 0
df.train$MADE.MAJORS[1:10] <- 1
OBP <- rnorm(10, mean=1, sd=.2)
HR.PCT <- rnorm(10, mean=1, sd=.2)
AGE <- rnorm(10, mean=21, sd=1)
CONF <- sample(c("A","B","C","D","E"), size=10, replace=TRUE)
CONF <- factor(CONF, levels=c("A","B","C","D","E"))
MADE.MAJORS <- sample(0:1, size=10, replace=TRUE, prob=c(0.8,0.2))
df.test <- data.frame(OBP, HR.PCT, AGE, CONF, MADE.MAJORS)
然后我使用 glmnet
执行带有逻辑回归的套索并生成预测。我希望预测采用概率的形式(即介于 0 和 1 之间)。
library(glmnet)
train.mtx <- with(df.train, model.matrix(MADE.MAJORS ~ OBP + HR.PCT + AGE + CONF)[,-1])
glmmod <- glmnet(x=train.mtx, y=as.factor(df.train$MADE.MAJORS), alpha=1, family="binomial")
cv.glmmod <- cv.glmnet(x=train.mtx, y=df.train$MADE.MAJORS, alpha=1)
test.mtx <- with(df.test, model.matrix(MADE.MAJORS ~ OBP + HR.PCT + AGE + CONF)[,-1])
preds <- predict.glmnet(object=glmmod, newx=test.mtx, s=cv.glmmod$lambda.min, type="response")
cv.preds <- predict.cv.glmnet(object=cv.glmmod, newx=test.mtx, s="lambda.min")
预测如下:
> preds
1
1 -3.2589440
2 -0.4435265
3 3.9646670
4 0.3772816
5 0.9952887
6 -7.3555661
7 0.2283675
8 -2.3871317
9 -8.1632749
10 -1.3563051
> cv.preds
1
1 0.1568839
2 0.3630938
3 0.7435941
4 0.4808428
5 0.5261076
6 -0.1431655
7 0.4123054
8 0.2207381
9 -0.1446941
10 0.2962391
我对这些结果有几个问题。请随意回答其中的任何一个或所有(或 none)。我对第一个问题的答案最感兴趣。
为什么 predict.glmnet
(preds
向量)的预测不是概率形式?我将 preds
值通过逆 logit 函数并得到合理的概率。对吗?
来自 predict.cv.glmnet
(cv.preds
向量)的预测大部分看起来像概率,但其中一些是负面的。这是为什么?
当我使用 glmnet
函数创建 glmmod 对象时,我包含了 family="binomial"
参数以表明我正在使用逻辑回归。但是,当我使用 cv.glmnet
函数查找 lambda 的最佳值时,我无法指定逻辑回归。如果交叉验证不使用逻辑回归,我实际上是否获得了 lambda 的最佳值?
同样,当我使用 predict.cv.glmnet
函数时,我无法指定逻辑回归。这个函数会产生我想要的预测吗?
我不是 100% 确定以下内容,因为正如您已经注意到的那样,该软件包似乎确实与其文档背道而驰,但它可能会产生一些迹象表明您的想法是否正确。
问题 1
是的,你是对的。请注意,
> predict.glmnet(object=glmmod, newx=test.mtx, s=cv.glmmod$lambda.min, type="link")
1
1 -3.2589440
2 -0.4435265
3 3.9646670
4 0.3772816
5 0.9952887
6 -7.3555661
7 0.2283675
8 -2.3871317
9 -8.1632749
10 -1.3563051
与 type="response"
的输出相同。因此,将其通过反逻辑函数将是获得概率的正确方法。至于为什么会发生这种情况,我没有任何线索-也许是一个错误。
问题 2...4
对于 cv.preds
,您得到的是概率线,因为您拟合的是高斯分布 link。为了适应 logit link,您应该指定 family
参数。即:
cv.glmmod <- cv.glmnet(x=train.mtx, y=df.train$MADE.MAJORS, alpha=1, family="binomial")
> cv.preds
1
1 -10.873290
2 1.299113
3 15.812671
4 3.622259
5 5.621857
6 -24.826551
7 1.734000
8 -5.420878
9 -26.160403
10 -4.496020
在这种情况下,cv.preds
将沿实线输出,您可以将这些值通过反逻辑得到概率。
我正在研究一个模型来预测大学棒球运动员进入大联盟的可能性。我的数据集有 633 个观测值和 13 个具有二元响应的预测变量。下面的代码生成较小的可重现的训练和测试数据集示例:
set.seed(1)
OBP <- rnorm(50, mean=1, sd=.2)
HR.PCT <- rnorm(50, mean=1, sd=.2)
AGE <- rnorm(50, mean=21, sd=1)
CONF <- sample(c("A","B","C","D","E"), size=50, replace=TRUE)
CONF <- factor(CONF, levels=c("A","B","C","D","E"))
df.train <- data.frame(OBP, HR.PCT, AGE, CONF)
df.train <- df.train[order(-OBP),]
df.train$MADE.MAJORS <- 0
df.train$MADE.MAJORS[1:10] <- 1
OBP <- rnorm(10, mean=1, sd=.2)
HR.PCT <- rnorm(10, mean=1, sd=.2)
AGE <- rnorm(10, mean=21, sd=1)
CONF <- sample(c("A","B","C","D","E"), size=10, replace=TRUE)
CONF <- factor(CONF, levels=c("A","B","C","D","E"))
MADE.MAJORS <- sample(0:1, size=10, replace=TRUE, prob=c(0.8,0.2))
df.test <- data.frame(OBP, HR.PCT, AGE, CONF, MADE.MAJORS)
然后我使用 glmnet
执行带有逻辑回归的套索并生成预测。我希望预测采用概率的形式(即介于 0 和 1 之间)。
library(glmnet)
train.mtx <- with(df.train, model.matrix(MADE.MAJORS ~ OBP + HR.PCT + AGE + CONF)[,-1])
glmmod <- glmnet(x=train.mtx, y=as.factor(df.train$MADE.MAJORS), alpha=1, family="binomial")
cv.glmmod <- cv.glmnet(x=train.mtx, y=df.train$MADE.MAJORS, alpha=1)
test.mtx <- with(df.test, model.matrix(MADE.MAJORS ~ OBP + HR.PCT + AGE + CONF)[,-1])
preds <- predict.glmnet(object=glmmod, newx=test.mtx, s=cv.glmmod$lambda.min, type="response")
cv.preds <- predict.cv.glmnet(object=cv.glmmod, newx=test.mtx, s="lambda.min")
预测如下:
> preds
1
1 -3.2589440
2 -0.4435265
3 3.9646670
4 0.3772816
5 0.9952887
6 -7.3555661
7 0.2283675
8 -2.3871317
9 -8.1632749
10 -1.3563051
> cv.preds
1
1 0.1568839
2 0.3630938
3 0.7435941
4 0.4808428
5 0.5261076
6 -0.1431655
7 0.4123054
8 0.2207381
9 -0.1446941
10 0.2962391
我对这些结果有几个问题。请随意回答其中的任何一个或所有(或 none)。我对第一个问题的答案最感兴趣。
为什么
predict.glmnet
(preds
向量)的预测不是概率形式?我将preds
值通过逆 logit 函数并得到合理的概率。对吗?来自
predict.cv.glmnet
(cv.preds
向量)的预测大部分看起来像概率,但其中一些是负面的。这是为什么?当我使用
glmnet
函数创建 glmmod 对象时,我包含了family="binomial"
参数以表明我正在使用逻辑回归。但是,当我使用cv.glmnet
函数查找 lambda 的最佳值时,我无法指定逻辑回归。如果交叉验证不使用逻辑回归,我实际上是否获得了 lambda 的最佳值?同样,当我使用
predict.cv.glmnet
函数时,我无法指定逻辑回归。这个函数会产生我想要的预测吗?
我不是 100% 确定以下内容,因为正如您已经注意到的那样,该软件包似乎确实与其文档背道而驰,但它可能会产生一些迹象表明您的想法是否正确。
问题 1
是的,你是对的。请注意,
> predict.glmnet(object=glmmod, newx=test.mtx, s=cv.glmmod$lambda.min, type="link")
1
1 -3.2589440
2 -0.4435265
3 3.9646670
4 0.3772816
5 0.9952887
6 -7.3555661
7 0.2283675
8 -2.3871317
9 -8.1632749
10 -1.3563051
与 type="response"
的输出相同。因此,将其通过反逻辑函数将是获得概率的正确方法。至于为什么会发生这种情况,我没有任何线索-也许是一个错误。
问题 2...4
对于 cv.preds
,您得到的是概率线,因为您拟合的是高斯分布 link。为了适应 logit link,您应该指定 family
参数。即:
cv.glmmod <- cv.glmnet(x=train.mtx, y=df.train$MADE.MAJORS, alpha=1, family="binomial")
> cv.preds
1
1 -10.873290
2 1.299113
3 15.812671
4 3.622259
5 5.621857
6 -24.826551
7 1.734000
8 -5.420878
9 -26.160403
10 -4.496020
在这种情况下,cv.preds
将沿实线输出,您可以将这些值通过反逻辑得到概率。