En esta sección estudiaremos modelos de variable latente y el algoritmo de esperanza-maximización.
-
El modelo para los datos completos está parametrizado con
$\theta$ :$$p_{\theta}(y)$$ -
El proceso de censura lo incluimos mediante el vector
$I$ de indicadores de faltantes ($I_{j}=1$ cuando el dato$j$ está censurado faltante), entonces si el modelo para el mecanismo de faltantes está parametrizado con$\psi$ :$$p_{\psi} (I|y)$$ -
Entonces generamos los datos según (1) y luego censuramos observaciones según (2). Así, el modelo completo para nuestras observaciones es:
$$p_{\theta,\psi} (y,I)=p_{\theta}(y)p_{\psi}(I|y).$$ -
Escribimos
$y=(y_{obs},y_{falta})$ para denotar por separado datos observados y datos faltantes. De tal manera que la verosimilitud para nuestros datos observados está dada por$$p_{\theta,\psi}(y_{obs},I),$$ pues sabemos los valores de las variables observadas y qué datos faltan. Para hacer máxima verosimilitud calculamos esta conjunta.$$p_{\theta,\psi} (y_{obs},I)=\int p_{\theta,\psi} (y_{obs}, y_{falta},I)d y_{falta}$$ $$=\int p_{\psi}(I|y_{obs},y_{falta})p_{\theta} (y_{obs}, y_{falta})d y_{falta}.$$ Nótese que esta integral (o suma, dependiendo del caso), promedia los valores faltantes según el modelo de los datos$p_{\theta}$ De la ecuación de arriba, vemos que en general tendríamos que modelar también el mecanismo de datos faltantes y estimar todos los parámetros. Esto es difícil no solamente porque hay más parámetros, sino porque en la práctica puede ser difícil proponer un modelo razonable para datos faltantes. Preferimos hacer un supuesto (MCAR, MAR). -
Si se cumple MAR, entonces tenemos que
$$p_{\psi}(I|y_{obs},y_{falta})=p_{\psi}(I|y_{obs}),$$ y por tanto,$$p_{\theta,\psi} (y_{obs},I)= p_{\psi}(I|y_{obs})\int p_{\theta} (y_{obs}, y_{falta})dy_{falta}.$$ notamos que los parámetros$\psi$ y$\theta$ están en factores separados y para encontrar los estimadores de máxima verosimilitud, no es necesario trabajar con$\psi$ ni el mecanismo al azar. El mecanismo de faltantes es entonces ignorable.
Recordemos que el problema de maximización de verosimilitud se vuelve más difícil en la presencia de datos faltantes.
Ejemplo. Escogemos al azar una moneda y luego tiramos un volado con esa moneda (modelo Moneda -> Sol):
ej_1 <- data.frame(moneda = c('A', 'A', 'B', 'B', 'B', NA),
sol = c(1, 0, 0, 0, 1, 0))
ej_1
#> moneda sol
#> 1 A 1
#> 2 A 0
#> 3 B 0
#> 4 B 0
#> 5 B 1
#> 6 <NA> 0
Si parametrizamos con
$$p_{\theta}(x^{6}{sol}=0 )=p{\theta}(x^{6}{sol}=0 |x^{6}{moneda}=A) p_{\theta}(x^{6}{moneda}=A) + p{\theta}(x^{6}{sol}=0 |x^{6}{moneda}=B) p_{\theta}(x^{6}{moneda}=B),$$ y ahora buscamos maximizar $$p{\theta}(y_{obs})=2\log\theta+3\log(1-\theta)+\log\theta_A+\log(1-\theta_A)+2\log(1-\theta_B)+\log\theta_B + \log((1-\theta_A)\theta + (1-\theta_B)(1-\theta)).$$
Notemos que esta expresión es más difícil de maximizar. El algoritmo EM da un
algoritmo iterativo para encontrar máximos locales de la verosimilitud
-
Calcular el valor esperado de la log-verosimilitud promediando sobre datos faltantes con una aproximación de la solución (
$\theta^{(t)}$ ). -
Obtener una nueva aproximación maximizando la cantidad resultante en el paso previo.
Podemos ver que el algorimto EM que el paso de esperanza consiste en un soft assignment de cada valor faltante de acuerdo al modelo de los datos y los datos observados.
Denotemos por
Es así que en el paso esperanza calculamos
Ejemplo. En nuestro ejemplo anterior, haríamos lo siguiente. Primero definimos la función que calcula el esperado de la log verosimilitud:
# logLik: verosimilitude de datos completos
logLik <- function(theta){
2 * log(theta[1]) + 3 * log(1 - theta[1]) + log(theta[2]) + log(1 - theta[2]) +
log(theta[3]) + 2 * log(1 - theta[3])
}
pasoEsperanza <- function(theta_ant){
function(theta){
# a = p(moneda=A|sol=1, theta_ant)
# b = p(moneda=B|sol=1, theta_ant)
a_0 <- theta_ant[1] * (1 - theta_ant[2])
b_0 <- (1 - theta_ant[1]) * (1 - theta_ant[3])
a <- a_0 / (a_0 + b_0)
b <- b_0 / (a_0 + b_0)
logLik(theta) + log(theta[1] * (1 - theta[2])) * a +
log((1 - theta[1]) * (1 - theta[3])) * b
}
}
Ahora escogemos una solución inicial y calculamos el esperado
theta_0 <- c(0.1, 0.1, 0.1)
esperanza_0 <- pasoEsperanza(theta_0)
Optimizamos este valor esperado:
max_1 <- optim(c(0.5, 0.5, 0.5), esperanza_0, control = list(fnscale = -1))
theta_1 <- max_1$par
theta_1
#> [1] 0.3499568 0.4761239 0.2563899
esperanza_1 <- pasoEsperanza(theta_1)
max_2 <- optim(c(0.5, 0.5, 0.5), esperanza_1,control=list(fnscale=-1) )
theta_2 <- max_2$par
theta_2
#> [1] 0.3791749 0.4396194 0.2683535
esperanza_2 <- pasoEsperanza(theta_2)
max_3 <- optim(c(0.5, 0.5, 0.5), esperanza_2,control=list(fnscale=-1) )
theta_3 <- max_3$par
theta_3
#> [1] 0.3864616 0.4313841 0.2715459
Y vemos que recuperamos la misma solución que en el caso de maximizar usando la función optim.
Veamos porque funciona trabajar con
Tomando logaritmos,
Y tomando el valor esperado con respecto la distribuión de
La igualdad anterior es cierta para cualquier valor de
-
El algoritmo EM es una generalización natural de la estiamación por máxima verosimilitud cuando hay presencia de datos faltantes.
-
El problema de maximización que ataca EM es más complejo que el problema de máxima verosimilitud con datos completos. En el caso usual
$\log p(x|\theta)$ tiene un único máximo global que muchas veces se puede encontrar de forma cerrada, por su parte la verosimilitud con datos faltantes tiene muchos máximos locales y no tiene solución cerrada. -
El algoritmo EM reduce el problema de múltiples máximos a una secuencia de subproblemas (
$Q(\theta|\theta^{(t)}$ ) cada uno con un único máximo global.
Estos subproblemas son tales que se garantiza convergencia de las soluciones$\theta^{(1)}, \theta^{(2)}, ...$ a un máximo, pues a cada paso se incrementa monótonamente el valor de la log-verosimilitud de los datos observados. -
El algoritmo EM garantiza convergencia únicamente a un máximo local pues la secuencia de
$\theta^{(t)}$ depende del valor con el que se inicializa el proceso$\theta^{(1)}$ . Por tanto, es conveniente repetir el algoritmo con varios valores iniciales. -
Una manera de entender el algoritmo EM es pensar que en cada paso de esperanza imputas los faltantes, sin embargo, en lugar de una imputación dura se realiza un soft assignment de cada valor faltante. El soft assignment se calcula obteniendo la probabilidad de cada alternativa para el valor faltante (usando el parámetro $\theta^{(t)})$) para crear una base de datos ponderada que considera todos los posibles escenarios de los faltantes. Al usar los valores esperados (o datos ponderados) en lugar de realizar una imputación dura el algoritmo toma en cuenta la confianza del modelo cada vez que completa los datos.
Un caso importante de datos faltantes es cuando una variable está totalmente censurada. Esto puede suceder por dos razones:
-
Alguna variable claramente importante está totalmente censurada (por ejemplo, peso en un estudio de consumo de calorías).
-
Cuando buscamos añadir estructura a nuestro modelo para simplificar su estimación, interpretación o forma. Por ejemplo: hacer grupos de actitudes ante la comida y el ejercicio para explicar con una sola variable el consumo de comida chatarra (por ejemplo, análisis de factores).
En estos casos, estas variables se llaman variables latentes, pues consideramos que tienen un efecto que observamos a través de otras variables, pero no podemos observar directamente los valores de esta variable.
a. MCAR
b. MAR
c. MNAR
d. Ninguno de estos
La siguiente tabla es una clasificación de los modelos de variable latente de acuerdo a la métrica de las variables latentes y observadas.
Latentes/Observadas | Métricas | Categóricas |
---|---|---|
Métricas | Análisis de factores (FA) | Modelos de rasgos latentes (LTM) |
Categóricas | Modelos de perfiles latentes (LPM) | Modelos de clases latentes (LCM) |
El ejemplo más clásico de variables latentes es el de mezcla de normales.
Ejemplo. Modelo de mezcla de dos normales. Consideremos los siguientes datos:
library(ggplot2)
set.seed(280572)
N <- 800
n <- sum(rbinom(N, 1, 0.6))
x_1 <- rnorm(N - n, 0, 0.5)
x_2 <- rnorm(n, 2, 0.3)
qplot(c(x_1, x_2))
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Estos datos tienen una estructura bimodal. Es poco apropiado modelar estos datos
con un modelo normal
Podemos entonces modelar pensando que los datos vienen de dos clases, cada una con una distribución normal pero con distintos parámetros. ¿Cómo ajustaríamos tal modelo?
Ahora, si vemos la mezcla Gaussiana desde la representación generativa, o
formulación en variable latente, tenemos el modelo gráfico
y podemos verificar que la distribución marginal es una mezcla gaussiana:
Ahora, si conocieramos la clase a la que pertenece cada observación (
Aquí, es fácil ver que la verosimilitud se separa en dos partes, una
para
y
En el caso de variables latentes
donde
crearLogLike <- function(x){
logLike <- function(theta){
pi <- exp(theta[1]) / (1 + exp(theta[1]))
mu_1 <- theta[2]
mu_2 <- theta[3]
sigma_1 <- exp(theta[4])
sigma_2 <- exp(theta[5])
sum(log(pi*dnorm(x, mu_1, sd=sigma_1)+(1-pi)*dnorm(x,mu_2,sd=sigma_2)))
}
logLike
}
func_1 <- crearLogLike(c(x_1,x_2))
system.time(salida <- optim(c(0.5,0,0,1,1), func_1, control=list(fnscale=-1)))
#> user system elapsed
#> 0.026 0.001 0.027
salida$convergence
#> [1] 0
exp(salida$par[1]) / (1 + exp(salida$par[1]))
#> [1] 0.5857074
salida$par[2:3]
#> [1] 1.98759218 0.03046366
exp(salida$par[4:5])
#> [1] 0.2977028 0.5159818
Y vemos que hemos podido recuperar los parámetros originales.
Ahora implementamos EM para resolver este problema. Empezamos con la
log-verosimilitud para datos completos (que reescribimos de manera más
conveniente):
Tomamos valores iniciales para los parámetros $\hat{\mu}1,\hat{\mu}2,\hat{\sigma}1^2, \hat{\sigma}2^2, \hat{\pi}$ y comenzamos con el paso Esperanza promediando sobre las variables aleatorias, que en este caso son las $\delta^i$. Calculamos entonces $$\hat{\gamma}^i=E{\hat{\theta}}(\delta^i|x^i)=P(\delta^i=1|x^i),$$ y usamos bayes para expresar en términos de los parámetros: $$\hat{\gamma}^i= \frac{\hat{\pi}\phi{\hat{\theta_1}}} {\hat{\pi}\phi{\hat{\theta_1}}(x_i)+(1-\hat{\pi})\phi{\hat{\theta_2}}(x_i)}$$
Utilizando estas asignaciones de los faltantes pasamos al paso
Maximización, donde la función objetivo es:
La actualización de
y se puede ver sin mucha dificultad que
Implementa EM para el ejemplo de
mezcla de normales.
Un caso más general es suponer que hay
Entonces, la distribución de los datos observados es la mezcla Gaussiana:
donde
La estimación en el caso multivariado con
Consideremos la descomposición de espectral de la
-
$A_k$ es una matriz diagonal con$det(A_k)=1$ y entradas diagonales proporcionales a los eigenvalores de$\Sigma_k$ .$A_k$ controla la forma (shape) del$k$ -ésimo cluster. -
$\lambda_k$ es una constante igual al$det(\Sigma_k)$ que controla el volumen del$k$ -ésimo cluster. -
$D_k$ es la matriz ortonormal de eigenvectores y controla la orientación del$k$ -ésimo cluster.
Utilizando la descomposición de arriba hay modelos de mezclas Gaussianas que se restringen a cluster con propiedades particulares, por ejemplo:
-
$\Sigma_k=\lambda I$ : clusters esféricos de igual volumen. -
$\Sigma_k=\lambda_k I$ : clusters esféricos de distinto volumen. -
$\Sigma_k=\lambda_k A$ : clusters elipsoidales de distinto volumen pero misma forma , orientaciones alineadas con el eje.
...
-
$\Sigma_k=\lambda_k D_k A_k D_k^T$ modelo sin restricciones.
Ahora veremos como ajustar estos modelos. En R hay varios paquetes para ajustar mezclas gaussianas, dos de ellos son mclust y mixtools. También está flexmix
Veamos un ejemplo usando mclust, en este paquete los modelos disponibles son
?mclustModelNames
Mezclas Univariadas
"E" = equal variance (one-dimensional)
"V" = variable variance (one-dimensional)
Mezclas multivariadas
"EII" = spherical, equal volume
"VII" = spherical, unequal volume
"EEI" = diagonal, equal volume and shape
"VEI" = diagonal, varying volume, equal shape
"EVI" = diagonal, equal volume, varying shape
"VVI" = diagonal, varying volume and shape
"EEE" = ellipsoidal, equal volume, shape, and orientation
"EEV" = ellipsoidal, equal volume and equal shape
"VEV" = ellipsoidal, equal shape
"VVV" = ellipsoidal, varying volume, shape, and orientation
La nomenclatura es: E=equal, V=varying, I=identity, y las letras están ordenadas 1ra=volumen, 2a=forma, 3ra=orientación.
En todos los modelos hay
Los modelos con menos restricciones tienen más parámetros por estimar y por tanto necesitan de más datos para alcanzar la misma precisión.
Usaremos los datos wine.
library(mclust)
wine <- read.csv("data/wine.csv", stringsAsFactors=FALSE)[, -1]
w_mclust <- Mclust(wine)
summary(w_mclust)
#> ----------------------------------------------------
#> Gaussian finite mixture model fitted by EM algorithm
#> ----------------------------------------------------
#>
#> Mclust VVE (ellipsoidal, equal orientation) model with 3 components:
#>
#> log-likelihood n df BIC ICL
#> -3015.333 178 158 -6849.387 -6850.694
#>
#> Clustering table:
#> 1 2 3
#> 59 69 50
Podemos ver más detalles:
summary(w_mclust, parameters = TRUE)
#> ----------------------------------------------------
#> Gaussian finite mixture model fitted by EM algorithm
#> ----------------------------------------------------
#>
#> Mclust VVE (ellipsoidal, equal orientation) model with 3 components:
#>
#> log-likelihood n df BIC ICL
#> -3015.333 178 158 -6849.387 -6850.694
#>
#> Clustering table:
#> 1 2 3
#> 59 69 50
#>
#> Mixing probabilities:
#> 1 2 3
#> 0.3300315 0.3903124 0.2796561
#>
#> Means:
#> [,1] [,2] [,3]
#> Alcohol.content 13.7474607 12.2884420 13.1132188
#> Malic.acid 2.0093958 1.9349628 3.2824045
#> As 2.4524717 2.2414826 2.4395874
#> Alcalinity.in.ash 17.0056425 20.2329719 21.4025951
#> Magnesium 106.2591851 93.9990767 100.0646503
#> Total.phenols 2.8408263 2.2829349 1.6680931
#> Falavanoids 2.9836246 2.1105880 0.7895086
#> Nonflavanoid.phenols 0.2892543 0.3671547 0.4401329
#> Proantocyanins 1.8992977 1.6341503 1.1665817
#> Color.Intensity 5.5361641 3.0977312 7.2299462
#> Hue 1.0619246 1.0596060 0.6915761
#> OD280.OD315 3.1576577 2.8052205 1.6972509
#> Proline 1116.9517345 515.2032715 633.5416560
#>
#> Variances:
#> [,,1]
#> Alcohol.content Malic.acid As
#> Alcohol.content 0.2058329968 -0.004024864 -0.009036939
#> Malic.acid -0.0040248637 0.490091195 0.018910721
#> As -0.0090369389 0.018910721 0.055228146
#> Alcalinity.in.ash -0.0828371420 0.331081359 0.341310246
#> Magnesium 0.1068697208 -0.991646554 0.571126451
#> Total.phenols 0.0052597707 -0.023068454 0.009333359
#> Falavanoids 0.0065310325 -0.026137373 0.016676313
#> Nonflavanoid.phenols 0.0009463792 0.011285445 0.007911553
#> Proantocyanins 0.0149987005 -0.038452295 -0.006737493
#> Color.Intensity 0.1653294086 -0.148232480 -0.026834517
#> Hue 0.0037878962 -0.022582987 0.007238772
#> OD280.OD315 -0.0121794833 0.014950157 0.014614274
#> Proline 17.4628451708 -56.678967719 -3.337718902
#> Alcalinity.in.ash Magnesium Total.phenols
#> Alcohol.content -0.082837142 0.10686972 0.0052597707
#> Malic.acid 0.331081359 -0.99164655 -0.0230684544
#> As 0.341310246 0.57112645 0.0093333589
#> Alcalinity.in.ash 5.971450304 2.01734719 0.0187383181
#> Magnesium 2.017347189 139.89193989 0.9193181647
#> Total.phenols 0.018738318 0.91931816 0.0971100170
#> Falavanoids 0.131007162 0.71138669 0.0842443327
#> Nonflavanoid.phenols 0.044245330 -0.11721737 -0.0061705519
#> Proantocyanins -0.002275193 1.30197911 0.0298378638
#> Color.Intensity -0.255590507 1.28678476 0.0493652310
#> Hue 0.004632895 0.21238589 0.0007562286
#> OD280.OD315 0.168893091 -0.06193507 0.0110876746
#> Proline -52.752038513 732.49780801 13.8868978185
#> Falavanoids Nonflavanoid.phenols Proantocyanins
#> Alcohol.content 0.0065310325 0.0009463792 0.014998700
#> Malic.acid -0.0261373726 0.0112854453 -0.038452295
#> As 0.0166763126 0.0079115530 -0.006737493
#> Alcalinity.in.ash 0.1310071620 0.0442453302 -0.002275193
#> Magnesium 0.7113866941 -0.1172173734 1.301979114
#> Total.phenols 0.0842443327 -0.0061705519 0.029837864
#> Falavanoids 0.1349705248 -0.0069115449 0.062565680
#> Nonflavanoid.phenols -0.0069115449 0.0072891701 -0.007172903
#> Proantocyanins 0.0625656802 -0.0071729033 0.164934604
#> Color.Intensity 0.1144048483 -0.0004530542 0.122825687
#> Hue -0.0006350309 0.0008467983 0.002076420
#> OD280.OD315 0.0226408419 -0.0092570244 0.011252864
#> Proline 10.6322090581 -3.0396915543 23.979311959
#> Color.Intensity Hue OD280.OD315
#> Alcohol.content 0.1653294086 0.0037878962 -0.012179483
#> Malic.acid -0.1482324804 -0.0225829875 0.014950157
#> As -0.0268345172 0.0072387724 0.014614274
#> Alcalinity.in.ash -0.2555905072 0.0046328950 0.168893091
#> Magnesium 1.2867847621 0.2123858908 -0.061935066
#> Total.phenols 0.0493652310 0.0007562286 0.011087675
#> Falavanoids 0.1144048483 -0.0006350309 0.022640842
#> Nonflavanoid.phenols -0.0004530542 0.0008467983 -0.009257024
#> Proantocyanins 0.1228256872 0.0020764204 0.011252864
#> Color.Intensity 1.2827176196 -0.0181024064 -0.063963894
#> Hue -0.0181024064 0.0133148261 -0.001197288
#> OD280.OD315 -0.0639638945 -0.0011972880 0.137646988
#> Proline 89.6000335505 8.4888492803 -8.638897429
#> Proline
#> Alcohol.content 17.462845
#> Malic.acid -56.678968
#> As -3.337719
#> Alcalinity.in.ash -52.752039
#> Magnesium 732.497808
#> Total.phenols 13.886898
#> Falavanoids 10.632209
#> Nonflavanoid.phenols -3.039692
#> Proantocyanins 23.979312
#> Color.Intensity 89.600034
#> Hue 8.488849
#> OD280.OD315 -8.638897
#> Proline 48054.698849
#> [,,2]
#> Alcohol.content Malic.acid As
#> Alcohol.content 0.290957199 0.041494976 -0.015172597
#> Malic.acid 0.041494976 0.959616485 0.031392560
#> As -0.015172597 0.031392560 0.100832278
#> Alcalinity.in.ash -0.139222786 0.557508416 0.664954718
#> Magnesium -0.151719216 -0.652094100 1.080065801
#> Total.phenols -0.040256458 -0.002113848 0.029119508
#> Falavanoids -0.060147746 -0.004874673 0.039501254
#> Nonflavanoid.phenols 0.007548535 0.015915807 0.013514996
#> Proantocyanins -0.040749045 -0.009251307 -0.006148156
#> Color.Intensity 0.125146552 -0.080664399 -0.033632185
#> Hue 0.004211772 -0.034179000 0.007228388
#> OD280.OD315 -0.042241674 0.026423741 0.028446620
#> Proline 8.626596290 -27.985876625 -1.659845775
#> Alcalinity.in.ash Magnesium Total.phenols
#> Alcohol.content -0.13922279 -0.15171922 -0.040256458
#> Malic.acid 0.55750842 -0.65209410 -0.002113848
#> As 0.66495472 1.08006580 0.029119508
#> Alcalinity.in.ash 11.66688422 4.59938073 0.047875643
#> Magnesium 4.59938073 234.48630651 1.361037876
#> Total.phenols 0.04787564 1.36103788 0.264992918
#> Falavanoids 0.25897013 1.05405977 0.257799261
#> Nonflavanoid.phenols 0.08314979 -0.14875746 -0.022078478
#> Proantocyanins 0.01893329 1.84347909 0.127681628
#> Color.Intensity -0.40238687 0.53161273 0.007950886
#> Hue 0.02452953 0.21105543 -0.002551795
#> OD280.OD315 0.31725455 0.05715343 0.110329268
#> Proline -26.09488891 359.20264305 6.843821755
#> Falavanoids Nonflavanoid.phenols Proantocyanins
#> Alcohol.content -0.060147746 0.007548535 -0.040749045
#> Malic.acid -0.004874673 0.015915807 -0.009251307
#> As 0.039501254 0.013514996 -0.006148156
#> Alcalinity.in.ash 0.258970125 0.083149785 0.018933288
#> Magnesium 1.054059766 -0.148757464 1.843479090
#> Total.phenols 0.257799261 -0.022078478 0.127681628
#> Falavanoids 0.402859513 -0.030553714 0.219205900
#> Nonflavanoid.phenols -0.030553714 0.013721881 -0.025794233
#> Proantocyanins 0.219205900 -0.025794233 0.397162067
#> Color.Intensity 0.047959574 0.003634641 0.055879900
#> Hue -0.004842160 0.001549258 -0.003299242
#> OD280.OD315 0.160712163 -0.021481045 0.121953613
#> Proline 5.239795551 -1.499604179 11.823144132
#> Color.Intensity Hue OD280.OD315
#> Alcohol.content 0.125146552 0.004211772 -0.042241674
#> Malic.acid -0.080664399 -0.034179000 0.026423741
#> As -0.033632185 0.007228388 0.028446620
#> Alcalinity.in.ash -0.402386869 0.024529529 0.317254548
#> Magnesium 0.531612726 0.211055426 0.057153426
#> Total.phenols 0.007950886 -0.002551795 0.110329268
#> Falavanoids 0.047959574 -0.004842160 0.160712163
#> Nonflavanoid.phenols 0.003634641 0.001549258 -0.021481045
#> Proantocyanins 0.055879900 -0.003299242 0.121953613
#> Color.Intensity 1.025931508 -0.020505202 -0.072269929
#> Hue -0.020505202 0.041007971 -0.002452333
#> OD280.OD315 -0.072269929 -0.002452333 0.215689168
#> Proline 44.247495205 4.190420761 -4.267192790
#> Proline
#> Alcohol.content 8.626596
#> Malic.acid -27.985877
#> As -1.659846
#> Alcalinity.in.ash -26.094889
#> Magnesium 359.202643
#> Total.phenols 6.843822
#> Falavanoids 5.239796
#> Nonflavanoid.phenols -1.499604
#> Proantocyanins 11.823144
#> Color.Intensity 44.247495
#> Hue 4.190421
#> OD280.OD315 -4.267193
#> Proline 23730.772720
#> [,,3]
#> Alcohol.content Malic.acid As
#> Alcohol.content 0.364795175 0.064640215 -0.014255292
#> Malic.acid 0.064640215 1.202742989 0.009619805
#> As -0.014255292 0.009619805 0.034969282
#> Alcalinity.in.ash -0.035993225 0.182864164 0.269439543
#> Magnesium -0.090609764 -0.365698545 0.624920131
#> Total.phenols 0.031616437 -0.055151917 0.023026263
#> Falavanoids 0.083433862 -0.103556511 -0.009829708
#> Nonflavanoid.phenols 0.004430543 0.021256335 0.001934607
#> Proantocyanins 0.077373081 -0.072496459 -0.000510812
#> Color.Intensity 0.769007331 -0.245044458 -0.061093951
#> Hue -0.017715605 -0.035787308 0.004035577
#> OD280.OD315 -0.023346744 -0.013926442 0.013095158
#> Proline 4.869717266 -15.801209810 -0.937506525
#> Alcalinity.in.ash Magnesium Total.phenols
#> Alcohol.content -0.035993225 -0.09060976 0.031616437
#> Malic.acid 0.182864164 -0.36569855 -0.055151917
#> As 0.269439543 0.62492013 0.023026263
#> Alcalinity.in.ash 4.687651663 2.69982780 0.034940535
#> Magnesium 2.699827797 134.94975622 0.783495550
#> Total.phenols 0.034940535 0.78349555 0.112711973
#> Falavanoids 0.135032979 0.60843506 0.005760379
#> Nonflavanoid.phenols 0.032945039 -0.08524479 0.003875283
#> Proantocyanins 0.034275071 1.06047025 0.047307104
#> Color.Intensity 0.022939765 0.29043216 0.184482532
#> Hue 0.005182554 0.12098019 0.000579047
#> OD280.OD315 0.123688178 0.03632290 -0.003086967
#> Proline -14.738807160 202.78506111 3.863769830
#> Falavanoids Nonflavanoid.phenols Proantocyanins
#> Alcohol.content 0.083433862 4.430543e-03 7.737308e-02
#> Malic.acid -0.103556511 2.125633e-02 -7.249646e-02
#> As -0.009829708 1.934607e-03 -5.108120e-04
#> Alcalinity.in.ash 0.135032979 3.294504e-02 3.427507e-02
#> Magnesium 0.608435055 -8.524479e-02 1.060470e+00
#> Total.phenols 0.005760379 3.875283e-03 4.730710e-02
#> Falavanoids 0.179195550 -5.819478e-03 6.602239e-02
#> Nonflavanoid.phenols -0.005819478 1.605783e-02 -4.840697e-05
#> Proantocyanins 0.066022386 -4.840697e-05 1.223608e-01
#> Color.Intensity 0.584663452 2.722327e-02 4.906441e-01
#> Hue -0.016193650 -1.250589e-03 -1.000528e-02
#> OD280.OD315 -0.016412517 -6.006693e-03 -1.510007e-02
#> Proline 2.957297389 -8.467936e-01 6.674755e+00
#> Color.Intensity Hue OD280.OD315
#> Alcohol.content 0.76900733 -0.017715605 -0.023346744
#> Malic.acid -0.24504446 -0.035787308 -0.013926442
#> As -0.06109395 0.004035577 0.013095158
#> Alcalinity.in.ash 0.02293976 0.005182554 0.123688178
#> Magnesium 0.29043216 0.120980192 0.036322896
#> Total.phenols 0.18448253 0.000579047 -0.003086967
#> Falavanoids 0.58466345 -0.016193650 -0.016412517
#> Nonflavanoid.phenols 0.02722327 -0.001250589 -0.006006693
#> Proantocyanins 0.49064410 -0.010005284 -0.015100071
#> Color.Intensity 5.78108574 -0.166574834 -0.231453078
#> Hue -0.16657483 0.015609471 0.007313253
#> OD280.OD315 -0.23145308 0.007313253 0.103382839
#> Proline 24.97418230 2.366371149 -2.409193145
#> Proline
#> Alcohol.content 4.8697173
#> Malic.acid -15.8012098
#> As -0.9375065
#> Alcalinity.in.ash -14.7388072
#> Magnesium 202.7850611
#> Total.phenols 3.8637698
#> Falavanoids 2.9572974
#> Nonflavanoid.phenols -0.8467936
#> Proantocyanins 6.6747551
#> Color.Intensity 24.9741823
#> Hue 2.3663711
#> OD280.OD315 -2.4091931
#> Proline 13399.5878181
Y podemos ver una tabla con el BIC para cada modelo, es importante tomar en cuenta que en mclust el BIC se define como:
round(w_mclust$BIC)
#> Bayesian Information Criterion (BIC):
#> EII VII EEI VEI EVI VVI EEE EVE VEE VVE EEV
#> 1 -27318 -27318 -8161 -8161 -8161 -8161 -7201 -7201 -7201 -7201 -7201
#> 2 -24478 -24297 -7534 -7553 -7440 -7496 -7138 -7099 -7077 -7027 -7328
#> 3 -23210 -22595 -7125 -7065 -7024 -7003 -7026 -6889 -6963 -6849 -7321
#> 4 -22037 -21633 -7055 -7014 -7053 -6993 -7013 -6874 -6943 -6886 -7520
#> 5 -21552 -20974 -7020 -6975 -7107 -7041 -6992 -6937 -6938 -6957 -7860
#> 6 -20777 -20285 -7061 -7006 -7175 -7122 -7000 NA -6933 -7039 -8236
#> 7 -20584 -19978 -7036 -7014 -7214 -7223 -6969 NA NA NA -8514
#> 8 -20511 -19167 -7009 -6988 -7194 -7227 -7018 NA NA NA -8815
#> 9 -19054 -18784 -6995 -7065 -7215 -7236 -7052 NA NA NA -9188
#> VEV EVV VVV
#> 1 -7201 -7201 -7201
#> 2 -7229 -7181 -7169
#> 3 -7250 -7285 -7204
#> 4 -7484 -7563 -7555
#> 5 -7826 -7895 -7905
#> 6 -8125 -8314 -8245
#> 7 -8503 NA NA
#> 8 -8734 NA NA
#> 9 -9039 NA NA
#>
#> Top 3 models based on the BIC criterion:
#> VVE,3 EVE,4 VVE,4
#> -6849 -6874 -6886
w_mclust
#> 'Mclust' model object: (VVE,3)
#>
#> Available components:
#> [1] "call" "data" "modelName" "n"
#> [5] "d" "G" "BIC" "bic"
#> [9] "loglik" "df" "hypvol" "parameters"
#> [13] "z" "classification" "uncertainty"
En la tabla de arriba, los renglones indican el número de conglomerados.
El paquete incluye algunas gráficas auxiliares.
plot(w_mclust, what = "BIC")
# hay 3 plots más:
# plot(w_mclust)
Y podemos hacer otras gráficas, por ejemplo podemos usar tourr para explorar los datos multivariados.
library(tourr)
w_mclust <- Mclust(wine, G = 3, modelNames = "VVI")
summary(w_mclust)
cl_p <- data.frame(cluster = w_mclust$classification, wine)
aps <- 2
fps <- 20
mat <- rescale(wine)
tour <- new_tour(mat, grand_tour(), NULL)
start <- tour(0)
proj_data <- reactive({
invalidateLater(1000 / fps, NULL);
step <- tour(aps / fps)
data.frame(center(mat %*% step$proj),
clusters = factor(w_mclust$classification))
})
proj_data %>% ggvis(~X1, ~X2, fill = ~clusters) %>%
layer_points() %>%
scale_numeric("x", domain = c(-1, 1)) %>%
scale_numeric("y", domain = c(-1, 1)) %>%
set_options(duration = 0)
-
Las mezclas Gaussianas son sensibles a datos atípicos (outliers).
-
Puede haber inestabilidad si los componentes Gaussianos no están separados apropiadamente o si los datos son chicos.
-
A comparación de otros métodos de clustering el tener un modelo probabilístico explícito hace posible verificar supuestos y tener medidas de ajuste. Por ejemplo, podemos usar BIC para elegir el número de clusters.
-
k-medias es un caso particular de mezclas gaussianas donde en cada paso se realizan asignaciones duras.
-
Desventajas: los resultados dependen de la inicialización del algoritmo EM, puede ser demasiado flexible o inestable.
-
Las mezclas gaussianas se pueden extender a mezclas de modelos de regresión que pueden ser modelos lineales estándar o modelos lineales generalizados. Esto esta implementado en el paquete flexmix que utiliza el algoritmo EM.
Background Subtraction es una técnica de procesamiento de imágenes donde se buscan extraer los objetos en el frente de la imagen. Por ejemplo, puede ser de interés detectar autos, animales o personas de una imagen. Ejemplos:
-
Monitoreo de tráfico (contar vehiculos, detectar y seguir vehículos).
-
Reconocimiento de actividades humanas (correr, caminar, brincar).
-
Seguimiento de objetos (seguir la bola en el tenis).
Los modelos de mezclas gaussianas son populares para esta tarea: la idea básica
es suponer que la intensidad de cada pixel en una imagen se puede modelar usando
un modelo de mezclas Gaussianas. Después se determina
que intensidades corresponden con mayor probabilidad al fondo seleccionando
como fondo las gaussianas con menos varianza y mayor evidencia (
En OpencCV hay tres algoritmos implementados para sustraer fondo, estos usan variantes de mezclas gaussianas:
-
An Improved Adaptive Background Mixture Model for Real- time Tracking with Shadow Detection
-
Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction
-
Improved adaptive Gausian mixture model for background subtraction
Continuamos explorando modelos de variable latente, en particular exploramos casos de variable latente continua. Una motivación para estos modelos es que muchos conjuntos de datos tienen la propiedad que los puntos caen en un variedad de dimensión mucho menor a la dimensión original de los datos.
Para entender esta idea consideremos una base de datos consrtuida con uno de
los dígitos de la base de datos mnist,
esta imagen esta representada por una matriz de
Cada una de las imágenes resultantes está representada por un punto en el
espacio de dimensión
Para datos reales habrá más grados de libertad debido por una parte a escalamiento y por otra habrá múltiples grados adicionales debidas a deformaciones debidas a la variabilidad en la escritura de un individuo y entre individuos. Aún así, la la dimensionalidad de los grados de libertad es mucho menor que la de los datos completos.
library(deepnet)
library(RColorBrewer)
mnist <- load.mnist("data/mnist")[["train"]]
ind_tres <- mnist[[3]] == 3
data_tres <- mnist[[2]][ind_tres, ]
par(mfrow=c(1,5))
imageD <- function(vec, main = NULL){
mat_digit <- matrix(vec, nrow = 28)[, 28:1]
image(mat_digit, col = brewer.pal(5, "GnBu"), xaxt = "n", yaxt = "n",
bty = "n", asp = 1, main = main)
}
for(i in sample(1:nrow(data_tres), 5)){
imageD(data_tres[i, ])
}
El modelo de variable latente más simple supone distribuciones Gaussianas para las variables latentes y las observadas, además de usar dependencia lineal Gaussiana entre latentes y observables. Este escenario corresponde a PCA probabilítsico y a análisis de factores.
El análisis de componentes principales (PCA) es una técnica que se utiliza con distintos objetivos:
-
Reducción de dimensionalidad.
-
Compresión de información con pérdida (lossy).
-
Extracción de características o (features).
-
Visualización de datos.
Podemos ver PCA desde dos puntos de vista que nos llevan al mismo resultado:
- PCA se puede definir como la proyección lineal que minimiza el costo medio de proyección, donde el costo promedio es la distancia media al cuadrado entre los puntos y sus proyecciones.
Consideremos un vector de observaciones
Comencemos considerando la proyección en un espacio de dimensión uno, denotamos
la dirección de este espacio por
Ahora maximizamamos la varianza de la proyección respecto a
Si elegimos
Ahora discutimos el segundo punto de vista de PCA. Sea
Como esta es una base de
Esto corresponde a una rotación en el sistema de coordenadas. Utilizando la
propiedad ortonormal obtenemos
Ahora, como buscamos aproximar este punto (
$$\hat{y}i=\sum{j=1}^M x_{ij}{u_j} + \sum_{j=M+1}^D b_j u_j$$
donde los valores
La minimización (derivar e igualar a cero) nos lleva a:
-
$x_{ij}=y_i^Tu_j$ , con$j=1,...,M$ -
$b_{j}=\bar{y}^Tu_j$ , con$j=M+1,...,D$
Sustituyendo
y vemos que el error mínimo ocurre en la proyección ortogonal sobre el
subespacio generado por
Usando lo anterior obtenemos
Aún falta minimizar
por lo que cualquier eigenvector de S corresponde a un punto crítico. Si todos
corresponden a un punto crítico ¿cómo elegimos? Notemos que si sustituimos la
solución de
por lo que para obtener el mínimo valor de
Veamos un par de aplicaciones de PCA, comenzaremos con compresión de imágenes y luego examinaremos PCA como preprocesamiento.
Veamos un ejemplo de PCA para compresión de información usando la base de datos de mnist, en particular veamos los dígitos tres.
data_tres <- mnist[[2]][ind_tres, ]
dim(data_tres)
#> [1] 6131 784
Como cada eigenvector es un vector en el espcio original de
data_tres <- mnist[[2]][ind_tres, ]
tres_mean <- apply(data_tres, 2, mean)
S <- cov(data_tres)
eigen_S <- eigen(S)
lambda <- eigen_S$values
u <- eigen_S$vectors
par(mfrow=c(1,5))
imageD(tres_mean)
for(i in 1:4){
imageD(u[, i])
}
Podemos ver el resto de los eigenvalores en la gráfica de abajo. Graficamos
también la medida de distorsión
D <- length(lambda)
J <- sapply(1:D, function(i){sum(lambda[i:D])})
par(mfrow=c(1,2))
plot(lambda, type = "l")
plot(J, type = "l")
Si vemos las fórmulas de arriba podemos escribir el vector de aproximación correspondiente a una observación.
$$\hat{y}i=\sum{j=1}^M x_{ij}{u_j} + \sum_{j=M+1}^D b_j u_j$$
donde usamos:
La compresión está en que reemplazamos cada vector de observaciones de dimensión
La siguiente figura muestra la compresión para distintos valores de
tres_1 <- data_tres[3, ]
par(mfrow=c(1,5))
imageD(tres_1)
for(M in c(1, 10, 50, 300)){
u_M <- u[, 1:M]
y_M <- tres_1 %*% u_M
y_approx <- tres_mean + y_M %*% t(u_M)
imageD(y_approx)
}
Comprime una imagen en blanco y negro.
Otra aplicación de componentes principales es preprocesamento, en este caso el objetivo no es reducción de dimensión sino la transformación de un conjunto de datos con el fin de estandarizar algunas de sus propiedades. Esto puede ser importante para el correcto funcionamiento de algoritmos o métodos que se desean usar después.
Veamos los datos faithful de erupciones del volcán Old Faithful.
head(faithful)
#> eruptions waiting
#> 1 3.600 79
#> 2 1.800 54
#> 3 3.333 74
#> 4 2.283 62
#> 5 4.533 85
#> 6 2.883 55
Notamos que el tiempo entre erupciones es de un orden de magnitud mayor que la duración de la erupción. Por ejemplo, si quisieramos hacer k-medias sería natural estandarizar los datos. Sin embargo, con PCA podemos normalizar los datos para tener cero media y covarianza unitaria, de tal manera que la correlación entre distintas variables es cero.
Para hacer esto escribimos la ecuación de eigenvectores como
donde
es claro que el conjunto
Esta operación se conoce como whitening o sphereing.
Implementa whitening en los datos
faithful, compara las gráficas de los datos crudos y preprocesados.
La formulación de PCA esta fundada en una proyección lineal de los datos sobre un subespacio de dimensión menor. En esta sección veremos que PCA también se puede expresar como la solución de máxima verosimilitud de en un modelo probabilístico de variable latente.
Para formular PCA probabilístico introducimos una variable latente
Veremos que las columnas de
El siguiente esquema explica el modelo PCA probabilístico desde el punto de vista generativo.
Desde este enfoque vemos que primero selecciona aleatoriamente un valor de la
variable latente (
donde
Ahora, si queremos usar máxima verosimilitud para estimar
dado que este corresponde a un modelo Gaussiano lineal su distribución marginal
es nuevamente Gaussiana con media
Entonces, la distribución
Consideramos la determinación de los parámetros usando máxima verosimilitud: $$ \begin{aligned} \log p(y)&=\sum_{i=1}^N\log p(y_j)\ &=-\frac{ND}{2}-\frac{N}{2}\log(2\pi)\log|C| -\frac{1}{2}\sum_{j=1}^N(y_j-\mu)^TC^{-1}(y_j-\mu) \end{aligned} $$
Derivando e igualando a cero obtenemos
donde
Suponemos que los eigenvectores están ordenados en orden decreciente de
acuerdo a sus eigenvalores correspondientes
notemos que
Ahora, como R es ortogonal se puede interpretar como una matriz de rotación en
el espacio de variables latentes. Por ahora, pensemos
-
El método convencional de PCA se suele describir como una proyección de los puntos en un espacio de dimensión
$D$ en un subespacio de dimensión$M$ . -
PCA probabilístco se expresa de manera más natural como un mapeo del espacio latente al espacio de los datos observados.
-
Una función importante de PCA probabilítico es definir una distribución Gaussiana multivariada en donde el número de grados de libertad se puede controlar al mismo tiempo que podemos capturar las correlaciones más importantes de los datos. En general una distribución Gaussiana multivariada tiene
$p(p+1)/2$ parámetros independientes en la matriz de covarianzas por lo que el número de parámetros crece de manera cuadrática con$p$ . Por otra parte si restringimos a una matriz de covarianzas diagonal tenemos solamente$p$ parámetros, sin embargo en este último caso no podemos entender las correlaciones. PCA probabilístico (y Análisis de Factores) son un punto medio en el que las$q$ correlaciones más fuertes se pueden capturar mientras que el número de parámetros crece de manera lineal con$p$ . En el caso de PCA con$M$ componentes:$p\cdot M + 1 - M\cdot(M-1)/2$ . -
PCA convencional corrresponde al límite
$\sigma^2 \to 0$ -
PCA probabilístico se puede escribir en términos de un espacio latente por lo que la implementación del algoritmo EM es una opción natural. En casos donde
$M<<D$ la estimación mediante EM puede ser más eficiente. -
Debido a que tenemos un modelo probabilitico para PCA podemos trabajar con faltantes (MCAR y MAR) marginalizando sobre la distribución de los no observados. El manejo de faltantes es otra ventaja de la implementación EM.
-
El algoritmo EM se puede extender al caso de Análisis de factores para el cuál no hay una solución cerrada.
El análisis de factores es muy similar a PCA probabilístico, la diferencia
radica en que en la distribución condicional de
Donde
independiente asociada a cada variable en la matriz
La distribución marginal de las variables observadas es
El análisis de factores suele ser criticado cuando se busca interpretar los factores (coordenadas en el espacio latente). El probema resulta de que los factores no están identificados ante rotaciones. Ante esto, Bisop explica que podemos ver el análisis de factores como un modelo de variable latente en el que nos interesa el espacio latente más no la elección particular de coordenadas que elijamos para describirlo.
Trataremos ahora con análisis de factores, los modelos que veremos se enfocan en
variables observadas y latentes continuas. La idea esencial del análisis de
factores es describir las relaciones entre varias variables observadas
(
En la gráfica inferior vemos un ejemplo en educación donde las variables
vocab, reading, maze,... corresponden a las variables observadas mientras que
En ocasiones, el análisis de factores se utiliza como una técnica de reducción de dimensión que esta basada en un modelo. Idealmente, toda la información en la base de datos se puede reproducir por un número menor de factores.
Sea
-
$X_k$ son los factores comunes (variables aleatorias continuas no observables). -
$u_j$ son errores (aleatorios). -
$\lambda_{jk}$ son las cargas de la variable$j$ en el factor$k$ , (parámetros).
En notación matricial el modelo se escribe:
Adicionalmente, tenemos los siguientes supuestos:
-
$X \perp U$ , esto es, los errores y los factores son independientes. -
$E(X)=E(U)=0$ . -
$Cov(X) = I_k$ (modelo ortogonal de factores) ésto se ve en la gráfica pues no hay arcos que unan a$X_1$ y$X_2$ . -
$Cov(U) = \Psi$ , donde$\Psi$ es una matriz diagonal ($p \times p$ ).
Típicamente, se asume que
Lo que buscamos es explicar la relación entre las variables observadas a través de las variables latentes, las relaciones que buscamos explicar están resumidas en la matriz de varianzas y covarianzas. En nuestro ejemplo la matriz es la siguiente:
ability.cov$cov
#> general picture blocks maze reading vocab
#> general 24.641 5.991 33.520 6.023 20.755 29.701
#> picture 5.991 6.700 18.137 1.782 4.936 7.204
#> blocks 33.520 18.137 149.831 19.424 31.430 50.753
#> maze 6.023 1.782 19.424 12.711 4.757 9.075
#> reading 20.755 4.936 31.430 4.757 52.604 66.762
#> vocab 29.701 7.204 50.753 9.075 66.762 135.292
y la matriz de correlaciones es:
cov2cor(ability.cov$cov)
#> general picture blocks maze reading vocab
#> general 1.0000000 0.4662649 0.5516632 0.3403250 0.5764799 0.5144058
#> picture 0.4662649 1.0000000 0.5724364 0.1930992 0.2629229 0.2392766
#> blocks 0.5516632 0.5724364 1.0000000 0.4450901 0.3540252 0.3564715
#> maze 0.3403250 0.1930992 0.4450901 1.0000000 0.1839645 0.2188370
#> reading 0.5764799 0.2629229 0.3540252 0.1839645 1.0000000 0.7913779
#> vocab 0.5144058 0.2392766 0.3564715 0.2188370 0.7913779 1.0000000
Entonces, volviendo al modelo examinemos que implicaciones tiene en la matriz de
varianzas y covarianzas de las variables aleatorias observables. Denotemos la
matriz de varianzas y covarianzas por
Los términos en la diagonal de
La comunalidad de la variable
Los términos fuera de la diagonal están dados por:
Sea
-
Comunalidades:
-
Unicidades:
-
Descomposición de la matriz de varianzas y covarianzas:
Ejemplo: Pruebas de habilidad.
ability_fa <- factanal(factors = 2, covmat = ability.cov, rotation = "none")
ability_fa
#>
#> Call:
#> factanal(factors = 2, covmat = ability.cov, rotation = "none")
#>
#> Uniquenesses:
#> general picture blocks maze reading vocab
#> 0.455 0.589 0.218 0.769 0.052 0.334
#>
#> Loadings:
#> Factor1 Factor2
#> general 0.648 0.354
#> picture 0.347 0.538
#> blocks 0.471 0.748
#> maze 0.253 0.408
#> reading 0.964 -0.135
#> vocab 0.815
#>
#> Factor1 Factor2
#> SS loadings 2.420 1.162
#> Proportion Var 0.403 0.194
#> Cumulative Var 0.403 0.597
#>
#> Test of the hypothesis that 2 factors are sufficient.
#> The chi square statistic is 6.11 on 4 degrees of freedom.
#> The p-value is 0.191
Antes de adentrarnos en la estimación vale la pena considerar dos aspectos:
-
Rotaciones: Al observar la igualdad
$\Sigma = \Lambda\Lambda^T + \Psi$ , notamos que no existe una única$\Lambda$ que la satisfaga. Sea$Q$ una matriz ortonormal de dimensión$K \times K$ ($Q$ es una matriz de rotación),$$Q^T Q = Q Q^T = I$$ Si$\Lambda$ es tal que$Y = \Lambda X + U$ y$\Sigma = \Lambda\Lambda^T + \Psi$ entonces,$$Y=(\Lambda Q)(Q^TX) + U$$ $$\Sigma = (\Lambda Q) (\Lambda Q)^T + \Psi = \Lambda\Lambda^T + \Psi$$ por lo tanto,$\Lambda_1 = (\Lambda Q)$ y$X_1 = Q^TX$ también son una solución para el modelo. Esto nos dice, que cualquier rotación de las cargas nos da una solución. Hay amplia literatura en este tema, típicamente la elección de una rotación busca mejorar la interpretación. -
¿Cuántos factores?: No hay una respuesta directa a la pregunta pero para aspirar a contestarla respondamos primero: ¿Cuántos factores puedo estimar? Contemos el número de parámetros que vamos a estimar y veamos los grados de libertad:
- Parámetros en
$\Sigma:p(p+1)/2$ - Parámetros en
$\Lambda$ y$\Psi:pK + p$ - Restricciones necesarias para fijar la rotación:
$K(K-1)/2$ - Grados de libertad:
$d = p(p+1)/2 - (pK + p - K(K-1)/2)$
Si$d < 0$ , no podemos estimar el modelo, por lo tanto el mayor número de factores que puedo estimar depende del número de variables observadas. Por ejemplo si$p = 5$ , únicamente podemos estimar modelos con 1 ó 2 factores.
Volviendo a la pregunta original: ¿Cuántos factores debo modelar? La respuesta depende del objetivo del análisis de factores, en ocasiones se desea utilizar las variables latentes como un resumen_ de las variables observadas e incorporarlas a ánalisis posteriores, en este caso es conveniente analizar el porcentaje de la varianza en las variables observadas que se puede explicar con los factores, por ejemplo si el tercer factor no contribuye de manera importante a explicar la variabilidad observada, el modelo con dos factores sería preferible. Por otra parte, si asumimos normalidad ($X\sim N(0, I), U\sim N(0, \Psi)$) podemos comparar la verosimilitud (o AIC, BIC) de los modelos con distinto número de factores y elegir de acuerdo a este criterio.
Una vez que fijamos el número de factores, hay varios métodos de estimación, el más popular implementa el algoritmo EM, sin embargo este método requiere supuestos de normalidad. Dentro de los métodos que no requieren supuestos adicionales está el método de factores principales.
En adelante utilzamos la matriz de covarianzas muestral,
-
Inicializa
$\hat{\Psi}$ (cualquier valor) -
$\hat{\Psi}=$ los$K$ mayores eigenvectores de la matriz$$(\hat{S} - \hat{\Psi})$$ Nos fijamos en esta diferencia porque nos interesa explicar las covarianzas a través de los factores comunes. -
$\hat{\Psi} = diag(S-\hat{\Lambda}\hat{\Lambda}^T)$
Los pasos 2 y 3 se repiten hasta alcanzar convergencia. Este algoritmo no es muy
popular debido a que la convergencia no está asegurada, se considera lento y los
valores iniciales de
Supongamos ahora que,
Volviendo al número de factores, una vez que hacemos supuestos de normalidad podemos calcular la devianza del modelo:
library(psych)
#>
#> Attaching package: 'psych'
#> The following object is masked from 'package:mclust':
#>
#> sim
#> The following objects are masked from 'package:ggplot2':
#>
#> %+%, alpha
dev <- function(fit){
S <- fit$correlation
n <- fit$n.obs
p <- nrow(S)
Sigma <- (fit$loadings) %*% t(fit$loadings) + diag(fit$uniqueness)
mat.aux <- solve(Sigma) %*% S
D <- n * (tr(mat.aux) - log(det(mat.aux)) - p)
return(D)
}
BIC <- function(fit){
p <- nrow(fit$loadings)
q <- ncol(fit$loadings)
v <- p - 1/2 * ((p - q) ^ 2 - (p + q))
D <- dev(fit)
BIC <- D + v * log(fit$n.obs) / 2
return(BIC)
}
ability.fa.1 <- factanal(factors = 1, covmat = ability.cov,
rotation = "none")
ability.fa.2 <- factanal(factors = 2, covmat = ability.cov,
rotation = "none")
ability.fa.3 <- factanal(factors = 3, covmat = ability.cov,
rotation = "none")
BIC(ability.fa.1)
#> Warning: partial match of 'uniqueness' to 'uniquenesses'
#> [1] 71.2489
BIC(ability.fa.2)
#> Warning: partial match of 'uniqueness' to 'uniquenesses'
#> [1] 11.12044
BIC(ability.fa.3)
#> Warning: partial match of 'uniqueness' to 'uniquenesses'
#> [1] 14.1555
Veamos también el porcentaje de la varianza observada que se puede explicar con los distintos modelos.
ability.fa.1
#>
#> Call:
#> factanal(factors = 1, covmat = ability.cov, rotation = "none")
#>
#> Uniquenesses:
#> general picture blocks maze reading vocab
#> 0.535 0.853 0.748 0.910 0.232 0.280
#>
#> Loadings:
#> Factor1
#> general 0.682
#> picture 0.384
#> blocks 0.502
#> maze 0.300
#> reading 0.877
#> vocab 0.849
#>
#> Factor1
#> SS loadings 2.443
#> Proportion Var 0.407
#>
#> Test of the hypothesis that 1 factor is sufficient.
#> The chi square statistic is 75.18 on 9 degrees of freedom.
#> The p-value is 1.46e-12
ability.fa.2
#>
#> Call:
#> factanal(factors = 2, covmat = ability.cov, rotation = "none")
#>
#> Uniquenesses:
#> general picture blocks maze reading vocab
#> 0.455 0.589 0.218 0.769 0.052 0.334
#>
#> Loadings:
#> Factor1 Factor2
#> general 0.648 0.354
#> picture 0.347 0.538
#> blocks 0.471 0.748
#> maze 0.253 0.408
#> reading 0.964 -0.135
#> vocab 0.815
#>
#> Factor1 Factor2
#> SS loadings 2.420 1.162
#> Proportion Var 0.403 0.194
#> Cumulative Var 0.403 0.597
#>
#> Test of the hypothesis that 2 factors are sufficient.
#> The chi square statistic is 6.11 on 4 degrees of freedom.
#> The p-value is 0.191
ability.fa.3
#>
#> Call:
#> factanal(factors = 3, covmat = ability.cov, rotation = "none")
#>
#> Uniquenesses:
#> general picture blocks maze reading vocab
#> 0.441 0.217 0.329 0.580 0.040 0.336
#>
#> Loadings:
#> Factor1 Factor2 Factor3
#> general 0.636 0.367 0.139
#> picture 0.350 0.766 -0.272
#> blocks 0.441 0.639 0.263
#> maze 0.236 0.325 0.509
#> reading 0.974 -0.109
#> vocab 0.811
#>
#> Factor1 Factor2 Factor3
#> SS loadings 2.382 1.249 0.427
#> Proportion Var 0.397 0.208 0.071
#> Cumulative Var 0.397 0.605 0.676
#>
#> The degrees of freedom for the model is 0 and the fit was 0
Finalmente, volvamos a las rotaciones. La interpretación de los factores se facilita cuando cada variable observada carga principalmente en un factor, por ello, muchos de los métodos de rotación buscan acentuar esta característica:
-
Rotación varimax: Resulta en algunas cargas altas y otras bajas para cada factor, de manera que las cargas bajas se puedan ignorar en la interpretación. Su nombre se debe a que maximiza la suma de las varianzas de las cargas al cuadrado. En términos de las observaciones (individuos) la rotación varimax busca una base que represente cada individuo de la manera más económica, esto es, cada individuo se puede describir usando una combinación lineal de únicamente unos cuantos factores.
-
Rotación promax: Esta es una rotación oblicua, lo que implica que se pierde la ortogonalidad de los factores. El resultado de esta rotación es que usualmente las cargas se vuelven incluso más extremas que con la rotación varimax.
ability.varimax <- factanal(factors = 2, covmat = ability.cov,
rotation = "varimax")
ability.promax <- factanal(factors = 2, covmat = ability.cov,
rotation = "promax")
cbind(ability.varimax$loadings, ability.promax$loadings) # cutoff = 0.1
#> Factor1 Factor2 Factor1 Factor2
#> general 0.4994378 0.5434490 0.36421826 0.470407977
#> picture 0.1560701 0.6215380 -0.05774698 0.671196536
#> blocks 0.2057870 0.8599259 -0.09148422 0.931885105
#> maze 0.1085308 0.4677610 -0.05365717 0.507997088
#> reading 0.9562425 0.1820963 1.02337231 -0.095493703
#> vocab 0.7847682 0.2248221 0.81123097 0.009105393
Cuando realizamos componentes principales es común querer proyectar los datos en las componentes. En el caso de AF no es tan sencillo porque los factores son aleatorios, pero hay métodos para calcular puntajes (scores).
-
Método de Bartlett. Supongamos que conocemos
$\Lambda$ y$\Psi$ , denotemos los puntajes del individuo$i$ en los factores por$x_i$ , entonces si$y_i$ es el vector de variables observables del i-ésimo individuo, tenemos que$y_i$ dada$x_i$ se distribuye$N(\Lambda x_i, \Psi)$ , por lo que la log-verosimilitud de la observación$y_i$ esta dada por$$-\frac{1}{2} log|2\pi\Psi| - \frac{1}{2}(y_i- \Lambda f_i)^T \Psi^{-1}(y_i - \Lambda x_i)$$ Derivando e igualando a cero se obtiene:$$\hat{x}_i = (\Lambda^T\Psi^{-1}\Lambda)\Lambda^T\Psi^{-1}y_i$$ -
Método de Thompson. Consideramos
$x_i$ aleatorio, i.e.$X\sim N(0,I)$ , entonces$f|y$ se distribuye$N(\Lambda^T\Psi^{-1}y, I-\Lambda^T \Psi^{-1}\Lambda)$ por lo que un estimador natural para$x_i$ es$$\hat{x}_i = \Lambda^T\Psi^{-1}y_i$$
Ejemplo. La base de datos wine contiene medidas en 13 atributos diferentes de 180 vinos.
library(gridExtra)
#>
#> Attaching package: 'gridExtra'
#> The following object is masked from 'package:dplyr':
#>
#> combine
library(ggplot2)
wine <- read.csv("data/wine.csv", header=T)
head(wine)
#> A Alcohol.content Malic.acid As Alcalinity.in.ash Magnesium
#> 1 1 14.23 1.71 2.43 15.6 127
#> 2 1 13.20 1.78 2.14 11.2 100
#> 3 1 13.16 2.36 2.67 18.6 101
#> 4 1 14.37 1.95 2.50 16.8 113
#> 5 1 13.24 2.59 2.87 21.0 118
#> 6 1 14.20 1.76 2.45 15.2 112
#> Total.phenols Falavanoids Nonflavanoid.phenols Proantocyanins
#> 1 2.80 3.06 0.28 2.29
#> 2 2.65 2.76 0.26 1.28
#> 3 2.80 3.24 0.30 2.81
#> 4 3.85 3.49 0.24 2.18
#> 5 2.80 2.69 0.39 1.82
#> 6 3.27 3.39 0.34 1.97
#> Color.Intensity Hue OD280.OD315 Proline
#> 1 5.64 1.04 3.92 1065
#> 2 4.38 1.05 3.40 1050
#> 3 5.68 1.03 3.17 1185
#> 4 7.80 0.86 3.45 1480
#> 5 4.32 1.04 2.93 735
#> 6 6.75 1.05 2.85 1450
pc.wine.1 <- princomp(wine, scores = TRUE)
fa.wine <- factanal(wine, factors = 2, scores = "Bartlett")
fa.pc.wine <- data.frame(fa1 = fa.wine$scores[, 1], pc1 = pc.wine.1$scores[, 1],
fa2 = fa.wine$scores[, 2], pc2 = pc.wine.1$scores[, 2])
comp_1 <- ggplot(fa.pc.wine, aes(x = fa1, y = pc1)) +
geom_point()
comp_2 <- ggplot(fa.pc.wine, aes(x = fa1, y = pc2)) +
geom_point()
grid.arrange(comp_1, comp_2, ncol = 2)
pc.wine.2 <- princomp(wine, scores = T, cor = T)
fa.pc.wine <- data.frame(fa1 = fa.wine$scores[, 1], pc1 = pc.wine.2$scores[, 1],
fa2 = fa.wine$scores[, 2], pc2 = pc.wine.2$scores[, 2])
comp_1 <- ggplot(fa.pc.wine, aes(x = fa1, y = pc1)) +
geom_point()
comp_2 <- ggplot(fa.pc.wine, aes(x = fa2, y = pc2)) +
geom_point()
grid.arrange(comp_1, comp_2, ncol = 2)
par(mfrow=c(1,2))
biplot(pc.wine.1)
#> Warning in arrows(0, 0, y[, 1L] * 0.8, y[, 2L] * 0.8, col = col[2L], length
#> = arrow.len): zero-length arrow is of indeterminate angle and so skipped
#> Warning in arrows(0, 0, y[, 1L] * 0.8, y[, 2L] * 0.8, col = col[2L], length
#> = arrow.len): zero-length arrow is of indeterminate angle and so skipped
#> Warning in arrows(0, 0, y[, 1L] * 0.8, y[, 2L] * 0.8, col = col[2L], length
#> = arrow.len): zero-length arrow is of indeterminate angle and so skipped
#> Warning in arrows(0, 0, y[, 1L] * 0.8, y[, 2L] * 0.8, col = col[2L], length
#> = arrow.len): zero-length arrow is of indeterminate angle and so skipped
#> Warning in arrows(0, 0, y[, 1L] * 0.8, y[, 2L] * 0.8, col = col[2L], length
#> = arrow.len): zero-length arrow is of indeterminate angle and so skipped
#> Warning in arrows(0, 0, y[, 1L] * 0.8, y[, 2L] * 0.8, col = col[2L], length
#> = arrow.len): zero-length arrow is of indeterminate angle and so skipped
#> Warning in arrows(0, 0, y[, 1L] * 0.8, y[, 2L] * 0.8, col = col[2L], length
#> = arrow.len): zero-length arrow is of indeterminate angle and so skipped
biplot(pc.wine.2)
# Ejemplo simulación
x1 <- rnorm(1000)
x2 <- x1 + 0.001 * rnorm(1000)
x3 <- 10 * rnorm(1000)
x <- data.frame(x1, x2, x3)
fact.x <- fa(x, factors = 1, covar = TRUE, fm ="ml")
pc.x <- princomp(x)
fact.x$loadings
#>
#> Loadings:
#> ML1
#> x1 1.006
#> x2 1.006
#> x3 0.580
#>
#> ML1
#> SS loadings 2.359
#> Proportion Var 0.786
pc.x$loadings
#>
#> Loadings:
#> Comp.1 Comp.2 Comp.3
#> x1 0.707 0.707
#> x2 0.707 -0.707
#> x3 1.000
#>
#> Comp.1 Comp.2 Comp.3
#> SS loadings 1.000 1.000 1.000
#> Proportion Var 0.333 0.333 0.333
#> Cumulative Var 0.333 0.667 1.000
y <- scale(x)
fact.y <- fa(y, factors = 1, fm ="ml")
pc.y <- princomp(y)
fact.y$loadings
#>
#> Loadings:
#> ML1
#> x1 0.999
#> x2 0.999
#> x3
#>
#> ML1
#> SS loadings 1.997
#> Proportion Var 0.666
pc.y$loadings
#>
#> Loadings:
#> Comp.1 Comp.2 Comp.3
#> x1 0.706 0.707
#> x2 0.706 -0.707
#> x3 -0.998
#>
#> Comp.1 Comp.2 Comp.3
#> SS loadings 1.000 1.000 1.000
#> Proportion Var 0.333 0.333 0.333
#> Cumulative Var 0.333 0.667 1.000
fact.y
#> Warning: partial match of 'fa' to 'factors'
#> Warning: partial match of 'fa' to 'factors'
#> Factor Analysis using method = ml
#> Call: fa(r = y, fm = "ml", factors = 1)
#> Warning: partial match of 'uniqueness' to 'uniquenesses'
#> Standardized loadings (pattern matrix) based upon correlation matrix
#> ML1 h2 u2 com
#> x1 1.00 0.9975 0.0025 1
#> x2 1.00 0.9975 0.0025 1
#> x3 0.04 0.0019 0.9981 1
#>
#> ML1
#> SS loadings 2.00
#> Proportion Var 0.67
#>
#> Mean item complexity = 1
#> Test of the hypothesis that 1 factor is sufficient.
#>
#> The degrees of freedom for the null model are 3 and the objective function was 13.8 with Chi Square of 13756.86
#> The degrees of freedom for the model are 0 and the objective function was 7.5
#>
#> The root mean square of the residuals (RMSR) is 0
#> The df corrected root mean square of the residuals is NA
#>
#> The harmonic number of observations is 1000 with the empirical chi square 0.01 with prob < NA
#> The total number of observations was 1000 with Likelihood Chi Square = 7469.84 with prob < NA
#>
#> Tucker Lewis Index of factoring reliability = -Inf
#> Fit based upon off diagonal values = 1
#> Measures of factor score adequacy
#> ML1
#> Correlation of (regression) scores with factors 1
#> Multiple R square of scores with factors 1
#> Minimum correlation of possible factor scores 1
En el ejemplo de simulación vemos que el análisis de componentes principales se alinea con la dirección de máxima varianza