Beberapa waktu telah berlalu dan saya pikir saya mungkin punya solusi. Saya akan menjelaskan pendekatan saya secara singkat untuk memberi Anda ide umum. Kode harus cukup untuk mengetahui detailnya. Saya suka melampirkan kode di sini, tetapi banyak dan stackexchange membuatnya tidak mudah untuk melakukannya. Saya tentu saja senang menjawab komentar apa pun, juga saya menghargai kritik apa pun.
Kode dapat ditemukan di bawah.
Strategi:
- Perkiraan kurva ROC-halus dengan menggunakan fungsi Logistik dalam interval [0,6]
- Dengan menambahkan parameter k seseorang dapat mempengaruhi bentuk kurva agar sesuai dengan kualitas model yang diinginkan, diukur dengan AUC (Area Di Bawah Kurva). Fungsi yang dihasilkan adalah . Jika k-> 0, AUC mendekati 0,5 (tanpa optimasi), jika k -> Inf, AUC mendekati 1 (model optimal). Sebagai pendekatan praktis, k harus dalam interval [0,0001,100]. Dengan beberapa kalkulus dasar, seseorang dapat membuat fungsi untuk memetakan k ke AUC dan sebaliknya.fk( x ) =1( 1 + e x p ( - k ∗ x ) )
- Sekarang, mengingat Anda memiliki kurva-roc yang cocok dengan AUC yang diinginkan, tentukan skor dengan sampel dari [0,1] secara seragam. Ini mewakili fpr ( False-Positive-Rate ) pada kurva ROC. Untuk kesederhanaan, skor dihitung kemudian sebagai 1-fpr.
- Label sekarang ditentukan dengan pengambilan sampel dari Distribusi Bernoulli dengan p dihitung menggunakan kemiringan ROC-Curve pada fpr ini dan ketepatan keseluruhan skor yang diinginkan. Secara detail: berat (label = "1"): = kemiringan (fpr) dimutilasi oleh overallPrecision, berat (label = "0"): = 1 dikalikan dengan (1-overallPrecision). Menormalkan bobot sehingga jumlahnya hingga 1 untuk menentukan p dan 1-p.
Berikut ini adalah contoh ROC-Curve untuk AUC = 0,6 dan presisi keseluruhan = 0,1 (juga dalam kode di bawah ini)
Catatan:
- AUC yang dihasilkan tidak persis sama dengan input AUC, pada kenyataannya, ada kesalahan kecil (sekitar 0,02). Kesalahan ini berasal dari cara label skor ditentukan. Perbaikan bisa berupa menambahkan parameter untuk mengontrol ukuran kesalahan.
- skor ditetapkan sebagai 1-fpr. Ini sewenang-wenang karena ROC-Curve tidak peduli bagaimana skor terlihat seperti selama mereka dapat diurutkan.
kode:
# This function creates a set of random scores together with a binary label
# n = sampleSize
# basePrecision = ratio of positives in the sample (also called overall Precision on stats.stackexchange)
# auc = Area Under Curve i.e. the quality of the simulated model. Must be in [0.5,1].
#
binaryModelScores <- function(n,basePrecision=0.1,auc=0.6){
# determine parameter of logistic function
k <- calculateK(auc)
res <- data.frame("score"=rep(-1,n),"label"=rep(-1,n))
randUniform = runif(n,0,1)
runIndex <- 1
for(fpRate in randUniform){
tpRate <- roc(fpRate,k)
# slope
slope <- derivRoc(fpRate,k)
labSampleWeights <- c((1-basePrecision)*1,basePrecision*slope)
labSampleWeights <- labSampleWeights/sum(labSampleWeights)
res[runIndex,1] <- 1-fpRate # score
res[runIndex,2] <- sample(c(0,1),1,prob=labSampleWeights) # label
runIndex<-runIndex+1
}
res
}
# min-max-normalization of x (fpr): [0,6] -> [0,1]
transformX <- function(x){
(x-0)/(6-0) * (1-0)+0
}
# inverse min-max-normalization of x (fpr): [0,1] -> [0,6]
invTransformX <- function(invx){
(invx-0)/(1-0) *(6-0) + 0
}
# min-max-normalization of y (tpr): [0.5,logistic(6,k)] -> [0,1]
transformY <- function(y,k){
(y-0.5)/(logistic(6,k)-0.5)*(1-0)+0
}
# logistic function
logistic <- function(x,k){
1/(1+exp(-k*x))
}
# integral of logistic function
intLogistic <- function(x,k){
1/k*log(1+exp(k*x))
}
# derivative of logistic function
derivLogistic <- function(x,k){
numerator <- k*exp(-k*x)
denominator <- (1+exp(-k*x))^2
numerator/denominator
}
# roc-function, mapping fpr to tpr
roc <- function(x,k){
transformY(logistic(invTransformX(x),k),k)
}
# derivative of the roc-function
derivRoc <- function(x,k){
scalFactor <- 6 / (logistic(6,k)-0.5)
derivLogistic(invTransformX(x),k) * scalFactor
}
# calculate the AUC for a given k
calculateAUC <- function(k){
((intLogistic(6,k)-intLogistic(0,k))-(0.5*6))/((logistic(6,k)-0.5)*6)
}
# calculate k for a given auc
calculateK <- function(auc){
f <- function(k){
return(calculateAUC(k)-auc)
}
if(f(0.0001) > 0){
return(0.0001)
}else{
return(uniroot(f,c(0.0001,100))$root)
}
}
# Example
require(ROCR)
x <- seq(0,1,by=0.01)
k <- calculateK(0.6)
plot(x,roc(x,k),type="l",xlab="fpr",ylab="tpr",main=paste("ROC-Curve for AUC=",0.6," <=> k=",k))
dat <- binaryModelScores(1000,basePrecision=0.1,auc=0.6)
pred <- prediction(dat$score,as.factor(dat$label))
performance(pred,measure="auc")@y.values[[1]]
perf <- performance(pred, measure = "tpr", x.measure = "fpr")
plot(perf,main="approximated ROC-Curve (random generated scores)")