【问题标题】:Why is predict.glmnet not predicting probabilities?为什么 predict.glmnet 不预测概率?
【发布时间】:2017-01-04 05:31:02
【问题描述】:

我正在研究一个模型来预测大学棒球运动员进入大联盟的概率。我的数据集有 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

我对这些结果有一些疑问。随意回答其中任何一个或全部(或不回答)。我最感兴趣的是第一个问题的答案。

  1. 为什么来自predict.glmnetpreds 向量)的预测不是概率形式的?我将 preds 值通过逆 logit 函数得到了合理的概率。对吗?

  2. 来自predict.cv.glmnetcv.preds 向量)的预测大多看起来像概率,但其中一些是负数。这是为什么呢?

  3. 当我使用glmnet 函数创建glmmod 对象时,我包含family="binomial" 参数以表明我正在使用逻辑回归。但是,当我使用 cv.glmnet 函数找到 lambda 的最佳值时,我无法指定逻辑回归。如果交叉验证不使用逻辑回归,我是否真的得到了 lambda 的最佳值?

  4. 同样,当我使用 predict.cv.glmnet 函数时,我无法指定逻辑回归。这个函数会产生我想要的预测吗?

【问题讨论】:

  • 这属于 CrossValidated。
  • 谢谢。如何将其移至 CrossValidated?
  • @42-,这些对我来说似乎都是编码问题,而不是解释问题。 SO 似乎是适合它的地方。
  • @42,我认为 OP 说得对,我认为这是一个编码问题。
  • 不管怎样,问题是关于如何让predict 提供概率,以及如何确保cv.glmnet 使用logit 链接函数,这些都是典型的编码问题。

标签: r glmnet


【解决方案1】:

我不能 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" 的输出相同。因此,通过逆 logit 函数将是获得概率的正确方法。至于为什么会发生这种情况,我不知道 - 也许是一个错误。

问题 2...4

对于cv.preds,您得到的结果与概率有关,因为您正在拟合高斯链接。为了适合 logit 链接,您应该指定 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 将沿实线输出,您可以将这些值通过逆 logit 得到概率。

【讨论】:

  • 谢谢,这很有帮助。我没有意识到 cv.glmnet 函数可以接受 family 参数。
  • 我能问一下 - 为什么这里需要 cv.predspreds?我的意思是,我本来预计只有一个预测向量,但在这里我们似乎使用了两个
  • @baxx 抱歉回复晚了。不知道为什么两者都需要。这两个向量表示相同的值但形式不同。考虑模型 $p_i=\frac{\exp(\betaX_i)}{\exp(\beta X_i)+1}$ 。在 OP 的问题中,preds 指的是 \betaX_i 而cv.preds 指的是 $p_i$。在这个问题中,我只提到 $\betaX_i$(即cv.preds),但如果你将cv.preds 通过逆逻辑,你会得到预测的概率。
猜你喜欢
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
  • 1970-01-01
相关资源
最近更新 更多