Построение кривой ROC в glmnet

РЕДАКТИРОВАТЬ: как Двин указал в комментариях, приведенный ниже код не для кривой ROC. Кривая ROC должна быть проиндексирована в вариации t, а не lambda (как я делаю ниже). Я отредактирую приведенный ниже код, когда у меня будет возможность.

Ниже представлена ​​моя попытка создать кривую ROC для glmnet, предсказывающую двоичный результат. Я смоделировал матрицу, которая аппроксимирует результаты glmnet в приведенном ниже коде. Как некоторые из вас знают, учитывая матрицу входных данных n x p, glmnet выводит матрицу предсказанных вероятностей n x 100 [$ \ Pr (y_i = 1) $] для 100 различных значений лямбды. Результат будет меньше 100, если дальнейшие изменения лямбда перестанут увеличивать предсказательную силу. Смоделированная матрица предсказанных вероятностей glmnet ниже представляет собой матрицу 250x69.

Во-первых, есть ли более простой способ построить кривую ROC для glmnet? Во-вторых, если нет, кажется ли, что приведенный ниже подход верен? В-третьих, нужно ли мне отображать (1) вероятность ложных / истинных срабатываний ИЛИ (2) просто наблюдаемую частоту ложных / истинных срабатываний?

set.seed(06511)

# Simulate predictions matrix
phat = as.matrix(rnorm(250,mean=0.35, sd = 0.12))
lambda_effect = as.matrix(seq(from = 1.01, to = 1.35, by = 0.005))
phat = phat %*% t(lambda_effect)


#Choose a cut-point
t = 0.5

#Define a predictions matrix
predictions = ifelse(phat >= t, 1, 0)

##Simulate y matrix
y_phat = apply(phat, 1, mean) + rnorm(250,0.05,0.10)
y_obs = ifelse(y_phat >= 0.55, 1, 0)

#percentage of 1 observations in the validation set, 
p = length(which(y_obs==1))/length(y_obs)

#   dim(testframe2_e2)

#probability of the model predicting 1 while the true value of the observation is 0, 
apply(predictions, 1, sum)

## Count false positives for each model
## False pos ==1, correct == 0, false neg == -1
error_mat = predictions - y_obs
## Define a matrix that isolates false positives
error_mat_fp = ifelse(error_mat ==1, 1, 0)
false_pos_rate = apply(error_mat_fp, 2,  sum)/length(y_obs)

# Count true positives for each model
## True pos == 2, mistakes == 1, true neg == 0
error_mat2 = predictions + y_obs
## Isolate true positives
error_mat_tp = ifelse(error_mat2 ==2, 1, 0)
true_pos_rate = apply(error_mat_tp, 2,  sum)/length(y_obs)


## Do I care about (1) this probability OR (2) simply the observed rate?
## (1)
#probability of false-positive, 
p_fp = false_pos_rate/(1-p)
#probability of true-positive, 
p_tp = true_pos_rate/p

#plot the ROC, 
plot(p_fp, p_tp)


## (2)
plot(false_pos_rate, true_pos_rate)

По этому поводу есть один вопрос по SO, но ответ был грубым и не совсем правильным: glmnet lasso Графики ROC


person Dr. Beeblebrox    schedule 08.08.2013    source источник
comment
График зависимости точности прогноза от лямбда НЕ является кривой ROC.   -  person IRTFM    schedule 08.08.2013
comment
@DWin Вы говорите, что это действительно кривая ROC, только если вход, который мы меняем, является порогом дискриминации, здесь t?   -  person Dr. Beeblebrox    schedule 08.08.2013
comment
Да, именно это он и говорит.   -  person Hong Ooi    schedule 08.08.2013
comment
Во-первых, кривая ROC является монотонной, в то время как кривая (для которой я не вижу имени, данного в моих ссылках), которое вы описываете, нет, по крайней мере, если она находится в OOB или данных проверки.   -  person IRTFM    schedule 08.08.2013
comment
@HongOoi +1 и DWin +1 Спасибо, что указали на это. Отредактирую вопрос соответственно. Тем не менее, я все еще придерживаюсь фундаментального вопроса: как вывести кривую ROC из результатов glmnet. Кроме того, почему я не мог построить график FPR против TPR по значениям лямбда, чтобы выбрать лямбда? Это не кривая ROC, но разве она не будет полезна?   -  person Dr. Beeblebrox    schedule 08.08.2013
comment
Я запустил этот код и был удивлен, увидев совместный рост FPR и FNR. Я не должен понимать, что они измеряют. Разве у них не ожидаются взаимные отношения?   -  person IRTFM    schedule 09.08.2013
comment
TPR / FPR на ROC представляет собой вероятность получения истинного положения на определенном вероятностном пороге, поэтому любая лямбда будет иметь полный спектр вероятностей от 0 до 1 на ROC. Вы можете посмотреть на площадь под кривой для различных лямбда-выражений, которая, по сути, показывает, насколько более вероятно, что ваша модель будет генерировать TPR, чем FPR.   -  person NiuBiBang    schedule 04.08.2014


Ответы (2)


Вариант, который использует ROCR для расчета AUC и построения кривой ROC:

library(ROCR)
library(glmnet)
library(caret)

df <- data.matrix(… ) # dataframe w/ predictor variables & a response variable
                      # col1 = response var; # cols 2:10 = predictor vars

# Create training subset for model development & testing set for model performance testing
inTrain <- createDataPartition(df$ResponsVar, p = .75, list = FALSE)
Train <- df[ inTrain, ]
Test <- df[ -inTrain, ]

# Run model over training dataset
lasso.model <- cv.glmnet(x = Train[,2:10], y = Train[,1], 
                         family = 'binomial', type.measure = 'auc')

# Apply model to testing dataset
Test$lasso.prob <- predict(lasso.model,type="response", 
                           newx = Test[,2:10], s = 'lambda.min')
pred <- prediction(Test$lasso.prob, Test$ResponseVar)

# calculate probabilities for TPR/FPR for predictions
perf <- performance(pred,"tpr","fpr")
performance(pred,"auc") # shows calculated AUC for model
plot(perf,colorize=FALSE, col="black") # plot ROC curve
lines(c(0,1),c(0,1),col = "gray", lty = 4 )

Для Test$lasso.prob выше вы можете ввести разные лямбды, чтобы проверить предсказательную силу для каждого значения.

person NiuBiBang    schedule 04.08.2014

Вот как с помощью прогнозов и меток создать базовую кривую ROC.

# randomly generated data for example, binary outcome
predictions = runif(100, min=0, max=1) 
labels = as.numeric(predictions > 0.5) 
labels[1:10] = abs(labels[1:10] - 1) # randomly make some labels not match predictions

# source: https://blog.revolutionanalytics.com/2016/08/roc-curves-in-two-lines-of-code.html
labels_reordered = labels[order(predictions, decreasing=TRUE)]
roc_dat = data.frame(TPR=cumsum(labels_reordered)/sum(labels_reordered), FPR=cumsum(!labels_reordered)/sum(!labels_reordered))

# plot the roc curve
plot(roc_dat$FPR, roc_dat$TPR)

сгенерированный график

person Leo Brueggeman    schedule 26.03.2019