Граница принятия решения в анализе ROC

#r

#r

Вопрос:

Я новичок в машинном обучении, и я нашел очень хороший пакет регрессии LASSO под названием SIAMCAT.

Публикация, в которой использовался этот пакет «Потенциал фекальной микробиоты для выявления колоректального рака на ранних стадиях (http://europepmc.org/article/MED/25432777 )»описано очень хорошо, так что я мог легко подойти к сложному методу машинного обучения. Однако есть одна вещь, которую я не мог понять в их методе, поэтому я вежливо прошу о помощи.

вопрос, который у меня есть, особенно важен для границы принятия решений. авторы заявили, что их граница принятия решения составляет 0,275 (рис. 1А, 2А). Однако я понятия не имею, откуда взялось значение.

Если автор может ответить на этот вопрос, я хочу спросить, откуда взялось значение (определенное значение 0,275)

Большое вам спасибо

Ответ №1:

Граница принятия решения основана на прогнозах модели. В SIAMCAT вы можете получить доступ к прогнозам модели с помощью средства pred_matrix доступа:

 # load packages
library("tidyverse")
library("SIAMCAT")

# extract the mean predictions as data.frame
pred <- enframe(rowMeans(pred_matrix(siamcat_example)),
                name='Sample_ID', value='prediction')
# get the metadata information for the same dataset also as data.frame
meta.data <- as_tibble(meta.crc.zeller, rownames = 'Sample_ID')
# join the two data.frames together
df.plot <- full_join(pred, meta.data)
df.plot %>% 
  ggplot(aes(x=Group, y=prediction, fill=Group))   
    geom_boxplot()
  

Если теперь вы выбрали случайное ограничение для прогнозов, вы можете назвать все, что выше этого ограничения, положительным, а все, что ниже него, отрицательным. Таким образом, вы получите ложноположительную скорость и истинную положительную скорость для ограничения прогноза:

 cutoff <- 0.55
df.plot %>% 
  mutate(positive=prediction > cutoff) %>% 
  group_by(Group) %>% 
  summarise(rate=sum(positive)/n())
  
 # A tibble: 2 x 2
Group  rate
<fct> <dbl>
1 CRC   0.585
2 CTR   0.148
  

Здесь частота ложных срабатываний будет равна 0,148, а истинная положительная частота будет равна 0,585.

Для вычисления AUROC вы в основном проходите через все возможные границы прогноза или границы принятия решения, а затем записываете истинную положительную скорость и ложноположительную скорость в этой точке. Затем эти два вектора накладываются друг на друга, и вы получаете ROC-кривую.

В случае упомянутой вами статьи (Zeller et al.) Авторы выбрали конкретную частоту ложных срабатываний для оценки своей модели. Таким образом, они проверили, какая граница принятия решения приведет к желаемой частоте ложных срабатываний.

Эта информация хранится в объекте roc в данных оценки объекта SIAMCAT:

 # get the roc curve out of the siamcat object
roc.all <- eval_data(siamcat_example)$roc

# the roc object contains all decision boundaries and the resulting 
# sensitivity/specificities
# if we are interested in a false positive rate of 10%, this means
# we have to find the decision boundary corresponding to a specificity of 90%
# (specifity=1-fpr)
idx <- which(roc.all$specificities > 0.90)[1]
boundary <- roc.all$thresholds[idx]

# generate a similar plot as figure 2a in zeller et al.

df.plot %>% 
  # sort the samples by predictions and turn them into a factor to preserve
  # the order
  arrange(prediction) %>% 
  mutate(Sample_ID=factor(Sample_ID, levels=Sample_ID)) %>% 
  # then, generate the relative rank
  group_by(Group) %>% 
  mutate(rel_rank=seq_len(n())) %>% 
  mutate(rel_rank=rel_rank/n()) %>% 
  ungroup() %>% 
  # additionally, check if the samples are above or below the decision boundary
  mutate(predicted_positive=prediction > boundary) %>% 
  # turn the group variable into a factor as well
  mutate(Group=factor(Group, levels = c('CTR', 'CRC'))) %>% 
  
  ggplot(aes(x=rel_rank, y=prediction, col=predicted_positive))   
    geom_hline(yintercept = boundary)  
    geom_point()   
    facet_grid(~Group, scales = 'free', space = 'free')   
    xlab('Relative rank within the dataset')   
    ylab('Model prediciton')   
    theme_bw()   
    theme(panel.grid = element_blank())