É correto avaliar motoristas individuais com o valor AUC?
Eu tenho uma discussão com meu supervisor sobre o uso de AUC para determinar, basicamente, a importância de três drivers diferentes que consistem em múltiplas variáveis cada. Ele afirma que posso examinar o valor AUC para o modelo geral e, em seguida, tentar executar um modelo semelhante usando apenas um driver por vez, obter o valor AUC para cada driver e, então, avaliar a importância de cada driver.
Inherent driver: 2 variables
Static driver: 2 variables
Dynamic driver: 7 variables
Portanto, minha saída AUC de um modelo ElasticNet binário seria a seguinte:
Overall AUC score (all drivers included): 0.89
Em seguida, executo o mesmo modelo ElasticNet, mas apenas com minhas duas variáveis selecionadas em inherent driver
e a variável dependente. E assim por diante com os próximos drivers etc. etc. Os valores de AUC são os seguintes:
Inherent driver: 0.58
Static driver: 0.67
Dynamic driver: 0.88
- O resultado então me diz que meus
dynamic driver
são relativamente mais importantes, ou apenas melhor em distinguir 0 de 1? - Este é mesmo um método estatisticamente sólido? Se não, de que outra forma posso avaliá-lo?
EDITAR:
V1 dependent V2 V3 V4 V5 V6 V7 V8 V9 V10 V11
1 -1.3 0 494. 34.1 2.23 43.0 4.58 46.7 283. 0.442 34.5 0
2 -4.2 0 231. 16.9 1.01 69.4 0 66.4 277. 0.959 11.1 0
3 -11.7 0 646. 132. 20.5 88.0 0.063 34.0 291. 5.63 21 0
4 -9.3 0 44.0 16.4 0.397 39.1 2.37 77.6 279. 7.24 31.8 0
5 -14.2 0 88.2 128. 40.6 83.4 1.09 47.2 284. 8.23 2.92 0
6 19.4 0 382. 49.4 1.15 54.4 0.914 53.6 279. 3.03 16.8 1
df <- df %>% select(V1, dependent, V2, V3, V4, V5, V6, V7, V8, V9, V11, V12)
training.samples <- df$dependent %>% createDataPartition(p = 0.8, list = FALSE)
train <- df[training.samples, ]
test <- df[-training.samples, ]
x.train <- data.frame(train[, names(train) != "dependent"])
x.train <- data.matrix(x.train)
y.train <- train$dependent
x.test <- data.frame(test[, names(test) != "dependent"])
x.test <- data.matrix(x.test)
y.test <- test$dependent
list.of.fits.overall.model <- list()
for (i in 0:10){
fit.name <- paste0("alpha", i/10)
list.of.fits.overall.model[[fit.name]] <- cv.glmnet(x.train, y.train, type.measure = c("auc"), alpha = i/10, family = "binomial", nfolds = 10, foldid = foldid, parallel = TRUE)
}
predicted <- predict(list.of.fits.overall.model[[fit.name]], s = list.of.fits.overall.model[[fit.name]]$lambda.1se, newx = x.test, type = "response")
#PLOT AUC
pred <- prediction(predicted, y.test)
perf <- performance(pred, "tpr", "fpr")
plot(perf)
abline(a = 0, b = 1, lty = 2, col = "red")
auc_ROCR <- performance(pred, measure = "auc")
auc_ROCR <- [email protected][[1]]
auc_ROCR
Agora, repito todo o procedimento de modelagem de rede elástica (busca pela compensação ideal de crista/laço e valor de penalidade ideal) com apenas duas variáveis. Basicamente, altero o seguinte:
df.inherent <- df %>% select(V1, dependent, V2)
training.samples <- df.inherent$dependent %>% createDataPartition(p = 0.8, list = FALSE)
train <- df.inherent[training.samples, ]
test <- df.inherent[-training.samples, ]
x.train <- data.frame(train[, names(train) != "dependent"])
x.train <- data.matrix(x.train)
y.train <- train$dependent
x.test <- data.frame(test[, names(test) != "dependent"])
x.test <- data.matrix(x.test)
y.test <- test$dependent
list.of.fits.inherent <- list()
for (i in 0:10){
fit.name <- paste0("alpha", i/10)
list.of.fits.inherent[[fit.name]] <- cv.glmnet(x.train, y.train, type.measure = c("auc"), alpha = i/10, family = "binomial", nfolds = 10, foldid = foldid, parallel = TRUE)
}
predicted <- predict(list.of.fits.inherent[[fit.name]], s = list.of.fits.inherent[[fit.name]]$lambda.1se, newx = x.test, type = "response")
Então, eventualmente, a última coisa que @EDM questionou nos comentários.
Respostas
Dado que a penalização é importante para sua modelagem, você está em um caminho potencialmente bom, mas precisa incorporar informações sobre o erro potencial em sua métrica de qualidade de AUC. Você não pode comparar uma AUC de 0,58 com uma de 0,67, a menos que saiba como essas estimativas podem ser variáveis.
Uma maneira simples de lidar com isso seria repetir o processo com várias (digamos, várias centenas) divisões de teste/treinamento em vez de uma única como você executa atualmente. Divisões de teste/treinamento individuais podem não ser confiáveis com conjuntos de dados com algo abaixo de vários milhares de casos . (Como você provavelmente precisaria de menos de 200 casos na classe minoritária para ajustar um modelo não penalizado com 11 preditores de forma confiável, presumo que você não tenha vários milhares de casos e, portanto, deveria fazer mais reamostragem em qualquer evento.) Então você usa. a variabilidade entre os (várias centenas) valores de AUC do conjunto de teste para avaliar se quaisquer diferenças entre os subconjuntos preditores são estatisticamente confiáveis.
Você pode se sair melhor com uma abordagem semelhante baseada em bootstrapping, em vez de várias divisões de teste/treinamento. Você primeiro usa todos os dados para ajustar um modelo completo. Dessa forma, você obtém um modelo completo que, ao contrário de sua abordagem, usa todos os dados disponíveis para construir e não depende dos caprichos de uma divisão específica de teste/treinamento.
Em seguida, você repete todo o processo de modelagem (incluindo a escolha alpha
e lambda
por meio de validação cruzada interna) em algumas centenas de amostras bootstrap do conjunto de dados e usa todo o conjunto de dados como o conjunto de teste em cada caso. Sob o princípio bootstrap, é análogo à construção de modelos em várias amostras de toda a população de interesse e, em seguida, testá-los na população. Assim, você obtém uma estimativa razoável da qualidade do processo de modelagem: otimismo (sobreajuste) nos valores dos coeficientes e viés e variabilidade nas estimativas de sua medida de qualidade.
Em termos de modelagem, mesmo se você optar por usar AUC como sua medida final, você deve usar o deviance em vez de AUC como critério para a escolha de validação cruzada de alpha
e lambda
. O AUC (ou índice C) não é muito sensível para distinguir entre modelos. Além disso, pense cuidadosamente se lambda.1se
é uma boa escolha neste caso. Isso ajuda a obter um modelo parcimonioso, mas com tão poucos preditores para começar (apenas 2 em seu segundo exemplo), você pode estar muito melhor com o lambda.min
valor que minimiza o erro de validação cruzada (novamente, melhor feito com deviance, mesmo que seu resultado final avaliação precisa ser feita com AUC).