我正在进行描述性(非预测性)分析,我希望从逻辑回归类型问题(包括截距)中比较系数的大小。由于需要描述每个变量,我已经尝试过标准的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)
#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),但这可能没有必要!很高兴收到任何建议。
感谢。
答案 0 :(得分:1)
你模型的问题是你对观察所施加的权重的非常大的不平衡,其中一个权重是20000000,而许多是1,没有一个超过10000。
par(mfrow = c(1,2))
boxplot(w)
boxplot(log(w))
在这种情况下,模型可以做的不多,但总是用巨大的权重预测观察,并将所有系数缩小到零。您可以通过以下方式看到:
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)
不幸的是,这产生了相同的模式:
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。鉴于这个阈值,我会放弃一种这种方法,然后回到调整正类的权重。