Krzywa ROC przekraczająca przekątną

12

W tej chwili prowadzę klasyfikator binarny. Kiedy wykreślam krzywą ROC, na początku uzyskuję dobry skok, a następnie zmienia ona kierunek i przecina przekątną, a następnie oczywiście z powrotem w górę, tworząc krzywą w kształcie litery S.

Jaka może być interpretacja / wyjaśnienie tego efektu?

Dzięki

Cagdas Ozgenc
źródło
1
Co sprawiło, że zależało ci na krzywej ROC? Co sprawiło, że wybrałeś klasyfikator zamiast modelu bezpośredniego prawdopodobieństwa?
Frank Harrell

Odpowiedzi:

18

Otrzymasz ładny symetryczny wykres ROC tylko wtedy, gdy standardowe odchylenia dla obu wyników są takie same. Jeśli różnią się raczej, możesz uzyskać dokładnie opisany wynik.

Poniższy kod Mathematica to pokazuje. Zakładamy, że cel daje rozkład normalny w przestrzeni odpowiedzi, a hałas również daje rozkład normalny, ale przesunięty. Parametry ROC są określone przez obszar poniżej krzywych Gaussa po lewej lub prawej stronie kryterium decyzyjnego. Różnicowanie tego kryterium opisuje krzywą ROC.

Manipulate[
 ParametricPlot[{CDF[NormalDistribution[4, \[Sigma]], c], 
                 CDF[NormalDistribution[0, 3], c]
                }, {c, -10, 10}, 
                Frame -> True, 
                Axes -> None, PlotRange -> {{0, 1}, {0, 1}}, 
                Epilog -> Line[{{0, 0}, {1, 1}}]], 
 {{\[Sigma], 3}, 0.1, 10, Appearance -> "Labeled"}]

Jest to z jednakowymi odchyleniami standardowymi: wprowadź opis zdjęcia tutaj

Jest tak z dość wyraźnymi:

wprowadź opis zdjęcia tutaj

lub z kilkoma innymi parametrami do gry:

Manipulate[
 ParametricPlot[{CDF[NormalDistribution[\[Mu]1, \[Sigma]1], c], 
   CDF[NormalDistribution[\[Mu]2, \[Sigma]2], c]}, {c, -100, 100}, 
  Frame -> True, Axes -> None, PlotRange -> {{0, 1}, {0, 1}}, 
  Epilog -> Line[{{0, 0}, {1, 1}}]], {{\[Mu]1, 0}, 0, 10, 
  Appearance -> "Labeled"},
 {{\[Sigma]1, 4}, 0.1, 20, Appearance -> "Labeled"},
 {{\[Mu]2, 5}, 0, 10, Appearance -> "Labeled"},
 {{\[Sigma]2, 4}, 0.1, 20, Appearance -> "Labeled"}]

wprowadź opis zdjęcia tutaj

Sjoerd C. de Vries
źródło
1

Posiadanie ciągu negatywnych wystąpień w części krzywej o wysokim FPR może stworzyć tego rodzaju krzywą. Jest to w porządku, o ile używasz odpowiedniego algorytmu do generowania krzywej ROC.

Warunek, w którym masz zestaw 2 mln punktów, z których połowa jest dodatnia, a połowa ujemna - wszystkie z dokładnie takim samym wynikiem dla twojego modelu jest trudna. Jeśli podczas sortowania punktów na podstawie wyniku (standardowa procedura w wykreślaniu ROC) napotkane zostaną wszystkie negatywne przykłady, spowoduje to, że twoja krzywa ROC pozostanie płaska i przesunie się w prawo. W tym artykule opisano, jak zająć się takimi problemami :

Fawcett | Rysowanie krzywych ROC

wabbit
źródło
1

(Odpowiedzi @Sjoerd C. de Vries i @Hrishekesh Ganu są poprawne. Pomyślałem, że mimo to mogę przedstawić pomysły w inny sposób, co może pomóc niektórym osobom).


Możesz uzyskać taki ROC, jeśli Twój model jest źle określony. Rozważ poniższy przykład (zakodowany w R), który jest dostosowany do mojej odpowiedzi tutaj: jak użyć wykresów pudełkowych, aby znaleźć punkt, w którym wartości prawdopodobnie będą pochodzić z różnych warunków?

## data
Cond.1 = c(2.9, 3.0, 3.1, 3.1, 3.1, 3.3, 3.3, 3.4, 3.4, 3.4, 3.5, 3.5, 3.6, 3.7, 3.7,
           3.8, 3.8, 3.8, 3.8, 3.9, 4.0, 4.0, 4.1, 4.1, 4.2, 4.4, 4.5, 4.5, 4.5, 4.6,
           4.6, 4.6, 4.7, 4.8, 4.9, 4.9, 5.5, 5.5, 5.7)
Cond.2 = c(2.3, 2.4, 2.6, 3.1, 3.7, 3.7, 3.8, 4.0, 4.2, 4.8, 4.9, 5.5, 5.5, 5.5, 5.7,
           5.8, 5.9, 5.9, 6.0, 6.0, 6.1, 6.1, 6.3, 6.5, 6.7, 6.8, 6.9, 7.1, 7.1, 7.1,
           7.2, 7.2, 7.4, 7.5, 7.6, 7.6, 10, 10.1, 12.5)
dat    = stack(list(cond1=Cond.1, cond2=Cond.2))
ord    = order(dat$values)
dat    = dat[ord,]  # now the data are sorted

## logistic regression models
lr.model1 = glm(ind~values,             dat, family="binomial")  # w/o a squared term
lr.model2 = glm(ind~values+I(values^2), dat, family="binomial")  # w/  a squared term
lr.preds1 = predict(lr.model1, data.frame(values=seq(2.3,12.5,by=.1)), type="response")
lr.preds2 = predict(lr.model2, data.frame(values=seq(2.3,12.5,by=.1)), type="response")

## here I plot the data & the 2 models
windows()
  with(dat, plot(values, ifelse(ind=="cond2",1,0), 
                 ylab="predicted probability of condition2"))
  lines(seq(2.3,12.5,by=.1), lr.preds1, lwd=2, col="red")
  lines(seq(2.3,12.5,by=.1), lr.preds2, lwd=2, col="blue")
  legend("bottomright", legend=c("model 1", "model 2"), lwd=2, col=c("red", "blue"))

wprowadź opis zdjęcia tutaj

Łatwo zauważyć, że czerwony model nie ma struktury danych. Poniżej można zobaczyć, jak wyglądają krzywe ROC:

library(ROCR)  # we'll use this package to make the ROC curve

## these are necessary to make the ROC curves
pred1 = with(dat, prediction(fitted(lr.model1), ind))
pred2 = with(dat, prediction(fitted(lr.model2), ind))
perf1 = performance(pred1, "tpr", "fpr")
perf2 = performance(pred2, "tpr", "fpr")

## here I plot the ROC curves
windows()
  plot(perf1, col="red",  lwd=2)
  plot(perf2, col="blue", lwd=2, add=T)
  abline(0,1, col="gray")
  legend("bottomright", legend=c("model 1", "model 2"), lwd=2, col=c("red", "blue"))

wprowadź opis zdjęcia tutaj

80%

gung - Przywróć Monikę
źródło