- fjroar
- 23 nov
- 5 Min. de lectura
Hace ya la friolera de casi 90 años, en 1936 R. A. Fisher publica el artículo “The Use of Multiple Measurements in Taxonomic Problems”.
Aunque el conjunto de datos ha sido extremadamente explotado a lo largo de la historia de la estadística, una de las cosas que resalto es que cuando se lee el paper original, hay un diagrama que me encanta y que es el siguiente:

Es un ejemplo que pongo en alguna de las clases que imparto en el Master Executive en Advanced Analytic & Data Sciencie de la UIC en https://www.uic.es/en/estudis-uic/business-administration/masters-degree-data-science-advanced-analytics
Es un dibujo ¡Hecho a mano! porque claro, en 1936 los ordenadores no existían y ni se le esperaban, estábamos en una situación pre-bélica y el mundo estaba más pendiente de lo que pasaba con Hitler que en pensar en la IA por ejemplo.
Lo que me sorprende de todo esto, aparte de la técnica que comento después, es el proceso de recolección de la información. Cualquiera que vea el dataset, que obtiene rápidamente a partir de R o Python, observa que se generan unos 125 registros de medidas tomadas sobre 125 flores de Iris que Fisher seleccionó. Me gusta hacer especial hincapié en ¿Cómo lo hizo Fisher? Yo me imagino a un señor bien vestido de la época que se iba al campo con un cuadernito, una lupa y algo para medir e iba buscando distintas variedades de flores hasta completar una tabla tal como la siguiente que también se puede observar en el paper que he mencionado:

Esta tabulación, obviamente viene ya por defecto tanto en R como en Python y la usamos sin darle mayor importancia, como si tuviera que estar ahí porque sí y siendo este por ejemplo el aspecto de algunos de los registros que están en R:

Pues bien, Fisher no sólo tuvo la "santa paciencia" de recoger y anotar los datos "en su libretilla", sino que además en ese artículo que trataba de taxonomía, desarrolla el análisis discriminante para cuya introducción en las clase que lo trato recurro a una referencia mucho más moderna como es An introduction to statistical learning del 2013, donde con notación más clara se desarrolla y explica de un modo muy sencillo como Fischer llega a establecer la siguiente regla de discriminación para el caso de 2 poblaciones:

Cuando explico esta fórmula, me gusta dar contexto a los datos y para ello me imagino que soy Fisher, pero con el inconveniente de que no estoy en el campo, ni tengo el tiempo para ir recogiendo y midiendo flores por ahí, son muy de ciudad, ... Por lo que tengo que simular datos, en este sentido desarrollo un programa en R que consta de 2 partes:
Una parte desconocida para el investigador y que es el proceso de generación de la información, es decir la simulación que se puede hacer del siguiente modo:
#S simulan dos conjuntos de 1000 datos acordes a dos distribuciones
#normales multivariantes
n <- 2000
p <- 2
#Parámetros estadísticos de los datos
sigmapos <- matrix(c(0.5,0.4,0.4,0.5), 2)
sigmaneg <- matrix(c(0.5,0.2,0.2,0.5), 2)
meanpos <- c(1,1)
meanneg <- c(2,1)
#Número de datos positivos y negativos
npos <- round(n / 2)
nneg <- n - npos
#Generación de datos
library(MASS)
set.seed(1)
xpos <- mvrnorm(npos, meanpos, sigmapos)
xneg <- mvrnorm(nneg, meanneg, sigmaneg)
x <- rbind(xpos, xneg)
y <- matrix(c(rep(1, npos), rep(-1,nneg)))
plot(x, col=ifelse(y>0, 1, 2))
Que genera el siguiente gráfico:

Y ahora que se tienen "datos para investigar" hay que comprobar si con la fórmula dada por Fisher se puede o no separar las poblaciones que visualmente se ve que existiría una línea (plano discriminante), pero que debe ser encontrada. Por tanto lo que resalto es que el investigador lo que realmente conoce son estos datos finales (aka simulados) y debe calcular los parámetros de la fórmula por tanto mediante código vamos a calcular las medias observadas y las covarianzas observadas para obtener las matrices correspondientes que son bien distintas de las reales y que en el anterior código se han denominado meanpos, meanneg, sigmapos, sigmaneg. Eso sí previamente separamos en training - test porque en una investigación, no se tendría el conocimiento de si lo hecho en una muestra tendría una mínima base de extrapolación:
#1.- Construcción Training - Validation
ntrain <- round(n * 0.7)
tindex <- sample(n, ntrain)
xtrain <- x[tindex,]
xtest <- x[-tindex,]
ytrain <- y[tindex]
ytest <- y[-tindex]
training <- data.frame(cbind(xtrain, ytrain))
names(training)<-c("x1", "x2", "y")
validation <- data.frame(cbind(xtest, ytest))
names(validation)<-c("x1", "x2", "y")
xytrain <- cbind(xtrain, ytrain)
xtrainpos <- xytrain[which(ytrain ==1),][,c(1,2)]
ytrainpos <- xytrain[which(ytrain ==1),][,c(3)]
xtrainneg<- xytrain[which(ytrain ==-1),][,c(1,2)]
ytrainneg<- xytrain[which(ytrain ==-1),][,c(2)]
#¿Qué ocurriría si se reestiman los vectores de medias de las distribuciones con
#estas simulaciones con los datos de varianza-covarianzas?
media1 = c(mean(xtrainpos[,1]),mean(xtrainpos[,2]))
media2 = c(mean(xtrainneg[,1]),mean(xtrainneg[,2]))
desviacion1 <- cov(xtrainpos)
desviacion2 <- cov(xtrainneg)
prior1 = length(ytrainpos) / (length(ytrainpos) + length(ytrainneg))
prior2 = length(ytrainneg) / (length(ytrainpos) + length(ytrainneg))
Lo que realmente conozco es por tanto los vectores media1, media2 y la matrices de varianzas-covarianzas observada de cada población desviacioin1 y desviacion2 y que supongo representantes de la población a estudiar ya que recuerdo, en una situación real, no conocería en general los vectores de medias y las matrices de varianzas-covarianzas reales (aka simuladas).
Aunque en R el uso de una librería como le e1071 te permitiría el cálculo de un linear discriminant análisis (que era la propuesta simplificada de Fisher ya que en la época la fórmula que él dio resultaba aún complicada de manejar, aunque R dispone también de la qda para la fórmula al completo) según:
library(e1071)
Modelo_LDA <- lda(y~x1 + x2, data = training, prior =c(0.5, 0.5))
Prediction_LDA <- predict(Modelo_LDA, validation)$class
#Confusion Matrix
table(`Actual Class` = ytest, `Predicted Class` = Prediction_LDA)
error.rate.Prediction_LDA <- sum(ytest != Prediction_LDA)/length(ytest)
print(paste0("Accuary (Precision): ", 1 - error.rate.Prediction_LDA))
Yo prefiero plantear previamente a lo anterior la función según su estado original donde se observa, cómo se incorporan todos los elementos:
Fischer <- function(x, mu1, mu2, sigma1, sigma2, pr1, pr2){
LD <- sign(-0.5* (x - mu1) %*% solve(sigma1) %*% (x - mu1) +
0.5* (x - mu2) %*% solve(sigma2) %*% (x - mu2) +
0.5* log(det(sigma2)/det(sigma1), base = exp(1)) -
log(pr2/pr1, base = exp(1)))
return(LD)
}
FischerPred <- vector("numeric", length(ytest))
#Aplicación en test
for (i in 1:length(ytest))
{
FischerPred[i] <- Fischer(xtest[i,], media1, media2, desviacion1, desviacion2, prior1, prior2)
}
#Confusion Matrix
table(`Actual Class` = ytest, `Predicted Class` = FischerPred)
error.rate.FischerPred <- sum(ytest != FischerPred)/length(ytest)
print(paste0("Accuary (Precision): ", 1 - error.rate.FischerPred))
Aunque si se observan las matrices de confusión, existen algunas diferencias, estas son mínimas y están provocadas por la elección de las prior que "si fuésemos por el camino fácil", al no tener mucho conocimiento, los valores 0.5 y 0.5 se muestran razonables.
Por tanto y para finalizar, con esta clase lo que pretendo enseñar es:
El alumno tome conciencia de que los datos vienen de algún sitio y antes de tabularlos, no siempre son fáciles de conseguir
Que se entienda que por un lado está la población real, que será desconocida y por otro está lo que observamos, una muestra que fluctúa y que se espera, represente a la población real, claramente si Fisher hubiera tomado 150 flores el resultado hubiera sido análogo, pero los número distintos, no fijos
También que las fórmulas y/o modelos que están en R tienen un sustrato matemático que ya nos lo sirve el programa de un modo sencillo, pero si no se entiende lo que hay por detrás, estamos usando cajas totalmente negras sin entender el por qué
Espero que estas notas sean de utilidad a alguien y si habéis llegado hasta aquí, al menos os haya motivado a aprender más sobre análisis discriminante que aunque muchos puedan pensar que es bastante viejuno, ¡Oh sorpresa! Son la base de los modelos de Altman de finales de los 60 básicos para entender el riesgo business to business y por supuesto es otra técnica más para complementar aquellas que tratan de clasificación o de separación de poblaciones como la regresión logística, decision trees, ...













