Geração aleatória de pontuações semelhantes às de um modelo de classificação

8

Olá colegas trituradores de números

Eu quero gerar n pontuações aleatórias (junto com um rótulo de classe) como se tivessem sido produzidas por um modelo de classificação binária. Em detalhes, são necessárias as seguintes propriedades:

  • cada pontuação está entre 0 e 1
  • toda pontuação está associada a um rótulo binário com os valores "0" ou "1" (este é a classe positiva)
  • a precisão geral das pontuações deve ser, por exemplo, 0,1 (<- parâmetro do gerador)
  • a proporção de pontuações com o rótulo "1" deve ser maior que a precisão geral na seção superior e menor na seção inferior (<- a "qualidade do modelo" também deve ser um parâmetro do gerador)
  • as pontuações devem ser de tal maneira que uma curva roc resultante seja suave (e não por exemplo, que várias pontuações com o rótulo "1" estejam no topo e o restante das pontuações com o rótulo "1" esteja na parte inferior de a lista).

Alguém tem uma idéia de como abordar isso? Talvez através da geração de uma curva roc e depois gerando os pontos dessa cura? Desde já, obrigado!

Steffen
fonte
escreveu "a precisão geral das pontuações deve ser, por exemplo, 0,1", quer dizer que deseja que a pontuação seja uma variável aleatória com média de 0,1? por que você não gera um problema de classificação (digamos, com variáveis ​​gaussianas) e usa algo rápido e simples (como o LDA) para resolvê-lo? você pode nos contar mais sobre suas motivações?
Robin girard
@ Robin: Não, estou falando de "precisão" como medida da qualidade de um modelo de classificação binária (veja, por exemplo, en.wikipedia.org/wiki/Sensitivity_and_specificity aqui). Em relação à sua segunda pergunta: eu exijo as pontuações para uma simulação em que vários modelos de classificação binária são combinados (mais na área de processamento de dados do que em Mineração de Dados). É difícil explicar a tarefa em detalhes, mas tenho certeza de que preciso dessas pontuações: D
steffen

Respostas:

4

Algum tempo se passou e acho que posso ter uma solução em mãos. Descreverei brevemente minha abordagem para lhe dar uma idéia geral. O código deve ser suficiente para descobrir os detalhes. Eu gosto de anexar código aqui, mas é muito, e o stackexchange não facilita. É claro que estou feliz em responder a quaisquer comentários, também aprecio qualquer crítica.

O código pode ser encontrado abaixo.

A estratégia:

  1. Aproximar uma curva ROC suave usando a função Logística no intervalo [0,6]
  2. fk(x)=1(1+exp(-kx))
  3. Agora, dado que você tem uma curva roc que corresponde à AUC desejada, determine uma pontuação por amostra de [0,1] uniformemente. Isso representa o fpr ( taxa de falsos positivos ) na curva ROC. Por simplicidade, a pontuação é calculada como 1-fpr.
  4. O rótulo é agora determinado por amostragem de uma distribuição de Bernoulli com p calculado usando a inclinação da curva ROC a esta pressão e a precisão geral desejada das pontuações. Em detalhes: weight (label = "1"): = slope (fpr) mutiplicado por overallPrecision, weight (label = "0"): = 1 multiplicado por (1-overallPrecision). Normalize os pesos para que eles somam 1 para determinar pe 1-p.

Aqui está um exemplo de curva ROC para AUC = 0,6 e precisão geral = 0,1 (também no código abaixo) texto alternativo texto alternativo

Notas:

  • a AUC resultante não é exatamente igual à AUC de entrada; de fato, há um pequeno erro (em torno de 0,02). Este erro se origina da maneira como o rótulo de uma pontuação é determinado. Uma melhoria poderia ser adicionar um parâmetro para controlar o tamanho do erro.
  • a pontuação é definida como 1-fpr. Isso é arbitrário, pois a Curva ROC não se importa com a aparência das pontuações, desde que possam ser classificadas.

código:

# 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)")
Steffen
fonte
Eu gostaria que alguém com mais habilidades em látex pudesse editar o cálculo em 4. para que fique mais legível.
Steffen
como é exatamente isso que eu queria, vou marcar como "a resposta". No entanto, ainda estou aberto a sugestões e idéias.
amigos estão dizendo sobre steffen