使用glmnet进行描述性统计,使用lambda的值

时间:2018-02-09 11:54:18

标签: lambda logistic-regression glmnet

我正在进行描述性(非预测性)分析,我希望从逻辑回归类型问题(包括截距)中比较系数的大小。由于需要描述每个变量,我已经尝试过标准的glm logit回归,并且知道许多变量至少部分相关,我也尝试使用岭回归来查看它的差异。

我遇到的问题是我所看到的所有指南都建议在lambda.min或lambda.1se上识别系数,但对我来说,这个lambda值的系数都是零。我可以随意选择一个lambda来返回值,但我不知道这是正确的。

require(glmnet)

CT.base <- readRDS('CTBaseObj.rds') #readRDS data objects


regular <- glm(Flag ~ . - Occurrences , family = binomial(link="logit"), 
               data = CT.base, weights = Occurrences, maxit = 50)

#Ridge
x <- model.matrix(Flag ~ . - Occurrences, CT.base)
x <- x[, !colnames(x) %in% '(Intercept)']
y <- CT.base$Flag
w <- CT.base$Occurrences

CT.cv <- cv.glmnet(x, y , family = "binomial", 
                   weights = w, alpha = 0.0, parallel = T, type.measure = "class")
plot(CT.cv)

R plot of cv.glmnet results

#CT.reg <- coef(CT.cv, s=CT.cv$lambda.1se) # coefficients here are zero
CT.reg <- coef(CT.cv, s=-3) # Looks like an interesting value!?
CT.reg <- data.frame(name = CT.reg@Dimnames[[1]][CT.reg@i+1], coefficient = CT.reg@x)

我已将此背后的数据集链接到可重复性(https://drive.google.com/open?id=1YMkY-WWtKSwRREqGPkSVfsURaImItEiO),但这可能没有必要!很高兴收到任何建议。

感谢。

1 个答案:

答案 0 :(得分:1)

你模型的问题是你对观察所施加的权重的非常大的不平衡,其中一个权重是20000000,而许多是1,没有一个超过10000。

par(mfrow = c(1,2))
boxplot(w)
boxplot(log(w))

enter image description here

在这种情况下,模型可以做的不多,但总是用巨大的权重预测观察,并将所有系数缩小到零。您可以通过以下方式看到:

CT <- glmnet(x, y , family = "binomial", 
                   weights = w, alpha = 0)

all(predict(CT, x, CT.cv$lambda.min, type= "class") == 0)
#TRUE

y[which.max(w)]
#0

我不确定这些权重的上下文是否适合没有它们的模型。

CT.cv <- cv.glmnet(x, y , family = "binomial", 
                   alpha = 0, type.measure = "class")

另一个问题是,没有权重的模型与具有荒谬权重的模型的行为大致相同,方法是将coef缩小为零并仅预测0级。这可能是由于类不平衡引起的:

table(y)
y
  0   1 
474  75 

事实上,当模型只预测更丰富的类时,模型最小化了错失分类。这可以通过增加与1类成员相关的权重来解释。或者通过选择另一个度量标准,例如平衡精度,平衡误差率或精确调用曲线下的面积进行模型拟合。不幸的是,glment包不提供此选项。但是你可以看一下package caret或mlr。

如果你使用auc:

CT.cv <- cv.glmnet(x, y , family = "binomial", 
                   alpha = 0, type.measure = "auc")
plot(CT.cv)

enter image description here

不幸的是,这产生了相同的模式:

CT <- glmnet(x, y , family = "binomial", 
                    alpha = 0, lambda = CT.cv$lambda.min)

all(predict(CT, x, CT.cv$lambda.min, type= "class") == 0)

我将向您展示如何使用平衡精度和库mlr进行训练:

library(mlr)

让学习者:

lrn <- makeLearner("classif.glmnet", predict.type = 'prob', alpha = 0)

获取所有可调参数:

getParamSet(lrn)

创建一个列车数据集:

mlr_train <- data.frame(x,
                        y = as.factor(y))

创建一个调整任务

task <- makeClassifTask(data = mlr_train, target = "y",  positive = "1")

调控将是对概率阈值调整探索的200个值的网格搜索:

ctrl = makeTuneControlGrid(resolution = 200, tune.threshold = TRUE)

我们将仅调整0到10范围内的lambda:

ps <- makeParamSet(
  makeNumericParam("lambda", lower = 0, upper = 10))

cv10 denotes 10 fold CV
bac is balanced accuracy it wil be used as selection metric

z <- tuneParams(lrn, task, cv10, par.set = ps, control = ctrl, 
          show.info = TRUE, measures = list(bac, setAggregation(bac, test.sd)))

> z
Tune result:
Op. pars: lambda=0.0503
Threshold: 0.07
bac.test.mean=0.5615910,bac.test.sd=0.0394965

因此,为了最大限度地提高平衡精度,您需要选择lambda = 0.0503和阈值0.07。鉴于这个阈值,我会放弃一种这种方法,然后回到调整正类的权重。