背景
Logistic回归通常情况下会用在分类问题中,一般是二分类问题。Logistic回归直接将预测限定在(0, 1)区间内,因此也可以将它理解为线性回归的归一化。
数据
数据集为一个医学数据,主要用来预测新生儿是否需要额外的医学护理。数据在这里
R语言实现过程
加载数据
首先加载数据集,并划分训练集和测试集。
load("D:/zmPDSwR-master/CDC/NatalRiskData.rData")
train <- sdata[sdata$ORIGRANDGROUP <= 5,]
test <- sdata[sdata$ORIGRANDGROUP > 5,]
构建模型
由于数据集中变量很多,先构建一个公式来方便建模:
complications <- c("ULD_MECO", "ULD_PRECIP", "ULD_BREECH")
riskfactors <- c("URF_DIAB", "URF_CHYPER", "URF_PHYPER", "URF_ECLAM")
y <- "atRisk"
x <- c("PWGT",
"UPREVIS",
"CIG_REC",
"GESTREC3",
"DPLURAL",
complications,
riskfactors)
fmla <- paste(y, paste(x, collapse = "+"), sep = "~")
> print(fmla)
[1] "atRisk~PWGT+UPREVIS+CIG_REC+GESTREC3+DPLURAL+ULD_MECO+ULD_PRECIP+ULD_BREECH+URF_DIAB+URF_CHYPER+URF_PHYPER+URF_ECLAM"
建模并预测:
model <- glm(fmla, data = train, family = binomial(link = "logit"))
train$pred <- predict(model, newdata = train, type = "response")
test$pred <- predict(model, newdata = test, type = "response")
评价模型
先通过图形来看一下打分情况:
library(ggplot2)
ggplot(train, aes(x = pred, color = atRisk, linetype = atRisk)) + geom_density() + scale_colour_hue()
打分的分布并不是分离的,发现模型的效果不是很好。这个时候需要选择一个阈值,高于该阈值的打分为正例,反之为负例。在选择阈值时,主要是在准确率和召回率之间寻找平衡。下面是用ROC包来做这件事:
library(ROCR)
library(grid)
predObj <- prediction(train$pred, train$atRisk)
precObj <- performance(predObj, measure = "prec")
recObj <- performance(predObj, measure = "rec")
precision <- (precObj@y.values)[[1]]
prec.x <- (precObj@x.values)[[1]]
recall <- (recObj@y.values)[[1]]
rocFrame <- data.frame(threshold = prec.x, precision = precision, recall = recall)
nplot <- function(plist) {
n <- length(plist)
grid.newpage()
pushViewport(viewport(layout = grid.layout(n, 1)))
vplayout = function(x, y) {
viewport(layout.pos.row = x, layout.pos.col = y)
}
for(i in 1:n) {
print(plist[[i]], vp = vplayout(i, 1))
}
}
pnull <- mean(as.numeric(train$atRisk))
p1 <- ggplot(rocFrame, aes(x = threshold)) + geom_line(aes(y = precision / pnull)) + coord_cartesian(xlim = c(0, 0.05), ylim = c(0, 10))
p2 <- ggplot(rocFrame, aes(x = threshold)) + geom_line(aes(y = recall)) + coord_cartesian(xlim = c(0, 0.05))
nplot(list(p1, p2))
选择一个阈值0.02来看看结果:
> ctab.test <- table(pred = test$pred > 0.02, atRisk = test$atRisk)
> ctab.test
atRisk
pred FALSE TRUE
FALSE 9487 93
TRUE 2405 116
> precision <- ctab.test[2, 2] / sum(ctab.test[2, ])
> precision
[1] 0.04601349
> recall <- ctab.test[2, 2] / sum(ctab.test[, 2])
> recall
[1] 0.5550239
> enrich <- precision / mean(as.numeric(test$atRisk))
> enrich
[1] 2.664159
再来看看模型的概要:
> summary(model)
Call:
glm(formula = fmla, family = binomial(link = "logit"), data = train)
Deviance Residuals:
Min 1Q Median 3Q Max
-0.9732 -0.1818 -0.1511 -0.1358 3.2641
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -4.412189 0.289352 -15.249 < 2e-16 ***
PWGT 0.003762 0.001487 2.530 0.011417 *
UPREVIS -0.063289 0.015252 -4.150 3.33e-05 ***
CIG_RECTRUE 0.313169 0.187230 1.673 0.094398 .
GESTREC3< 37 weeks 1.545183 0.140795 10.975 < 2e-16 ***
DPLURALtriplet or higher 1.394193 0.498866 2.795 0.005194 **
DPLURALtwin 0.312319 0.241088 1.295 0.195163
ULD_MECOTRUE 0.818426 0.235798 3.471 0.000519 ***
ULD_PRECIPTRUE 0.191720 0.357680 0.536 0.591951
ULD_BREECHTRUE 0.749237 0.178129 4.206 2.60e-05 ***
URF_DIABTRUE -0.346467 0.287514 -1.205 0.228187
URF_CHYPERTRUE 0.560025 0.389678 1.437 0.150676
URF_PHYPERTRUE 0.161599 0.250003 0.646 0.518029
URF_ECLAMTRUE 0.498064 0.776948 0.641 0.521489
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 2698.7 on 14211 degrees of freedom
Residual deviance: 2463.0 on 14198 degrees of freedom
AIC: 2491
Number of Fisher Scoring iterations: 7
要点总结
- Logistic回归是二元分类首选的统计建模方法。首先尝试Logistic回归,如果适用,再尝试其他方法;
- 处理具有大量变量或者大量类别值得类别型变量的问题时,Logistic回归将遇到麻烦;
- Logistic可以被很好地校准:它再现数据的边缘概率;
- 即便在变量相关的情况下,Logistic回归也能很好地进行预测,但相关的变量会降低模型给出的建议质量;
- 特别大的系数量级、系数估计上得到特别大的标准差、系数上的错误符号,都可能是输入变量具有相关性的征兆;
- 太多的菲舍尔迭代次数,或者具有特别大标准差的特大系数,可能标志着一个输入变量或输入变量组合与所要应答的一个子集完全相关。这可能需要通过分割数据来处理这个问题;
- glm()能提供好的诊断,但利用测试数据对模型进行检查仍然是最有效的诊断方法;
- 伪R-平方是关于拟合优度的一个有用的启发式度量指标。
参考文献
[1][数据科学 理论、方法与R语言实践]