Hmm, después de que yo' hecho un ejemplo en mi MatMate-lenguaje veo que ya hay un python-respuesta, que podría ser preferible porque python es ampliamente utilizado. Pero como todavía tienes preguntas te muestro mi enfoque usando el lenguaje Matmate-matrix, tal vez sea más autocomentario.
Método 1
(Utilizando MatMate):
v=12 // 12 variables
f=3 // subset-correlation based on 3 common factors
vg = v / f // variables per subsets
// generate hidden factor-matrix
// randomu(rows,cols ,lowbound, ubound) gives uniform random matrix
// without explicite bounds the default is: randomu(rows,cols,0,100)
L = { randomu(vg,f) || randomu(vg,f)/100 || randomu(vg,f)/100 , _
randomu(vg,f)/100 || randomu(vg,f) || randomu(vg,f)/100 , _
randomu(vg,f)/100 || randomu(vg,f)/100 || randomu(vg,f) }
// make sure there is itemspecific variance
// by appending a diagonal-matrix with random positive entries
L = L || mkdiag(randomu(v,1,10,20))
// make covariance and correlation matrix
cov = L *' // L multiplied with its transpose
cor = covtocorr(cov)
set ccdezweite=3 ccfeldweite=8
list cor
cor =
1.000, 0.321, 0.919, 0.489, 0.025, 0.019, 0.019, 0.030, 0.025, 0.017, 0.014, 0.014
0.321, 1.000, 0.540, 0.923, 0.016, 0.015, 0.012, 0.030, 0.033, 0.016, 0.012, 0.015
0.919, 0.540, 1.000, 0.679, 0.018, 0.014, 0.012, 0.029, 0.028, 0.014, 0.012, 0.012
0.489, 0.923, 0.679, 1.000, 0.025, 0.022, 0.020, 0.040, 0.031, 0.014, 0.011, 0.014
0.025, 0.016, 0.018, 0.025, 1.000, 0.815, 0.909, 0.758, 0.038, 0.012, 0.018, 0.014
0.019, 0.015, 0.014, 0.022, 0.815, 1.000, 0.943, 0.884, 0.035, 0.012, 0.014, 0.012
0.019, 0.012, 0.012, 0.020, 0.909, 0.943, 1.000, 0.831, 0.036, 0.013, 0.015, 0.010
0.030, 0.030, 0.029, 0.040, 0.758, 0.884, 0.831, 1.000, 0.041, 0.017, 0.022, 0.020
0.025, 0.033, 0.028, 0.031, 0.038, 0.035, 0.036, 0.041, 1.000, 0.831, 0.868, 0.780
0.017, 0.016, 0.014, 0.014, 0.012, 0.012, 0.013, 0.017, 0.831, 1.000, 0.876, 0.848
0.014, 0.012, 0.012, 0.011, 0.018, 0.014, 0.015, 0.022, 0.868, 0.876, 1.000, 0.904
0.014, 0.015, 0.012, 0.014, 0.014, 0.012, 0.010, 0.020, 0.780, 0.848, 0.904, 1.000
El problema aquí podría ser, que definimos bloques de submatrices que tienen altas correlaciones dentro con poca correlación entre y esto no es programáticamente sino por las constantes expresiones de concatenación . Tal vez esto acercarse a podría modelarse de forma más elegante en python.
Método 2(a)
Después de eso, hay un enfoque completamente diferente, donde llenamos la posible covarianza restante por cantidades aleatorias del 100% en una matriz de carga de factores. Esto se hace en Pari/GP:
{L = matrix(8,8); \\ generate an empty factor-loadings-matrix
for(r=1,8,
rv=1.0; \\ remaining variance for variable is 1.0
for(c=1,8,
pv=if(c<8,random(100)/100.0,1.0); \\ define randomly part of remaining variance
cv= pv * rv; \\ compute current partial variance
rv = rv - cv; \\ compute the now remaining variance
sg = (-1)^(random(100) % 2) ; \\ also introduce randomly +- signs
L[r,c] = sg*sqrt(cv) ; \\ compute factor loading as signed sqrt of cv
)
);}
cor = L * L~
y la matriz de correlación producida es
1.000 -0.7111 -0.08648 -0.7806 0.8394 -0.7674 0.6812 0.2765
-0.7111 1.000 0.06073 0.7485 -0.7550 0.8052 -0.8273 0.05863
-0.08648 0.06073 1.000 0.5146 -0.1614 0.1459 -0.4760 -0.01800
-0.7806 0.7485 0.5146 1.000 -0.8274 0.7644 -0.9373 -0.06388
0.8394 -0.7550 -0.1614 -0.8274 1.000 -0.5823 0.8065 -0.1929
-0.7674 0.8052 0.1459 0.7644 -0.5823 1.000 -0.7261 -0.4822
0.6812 -0.8273 -0.4760 -0.9373 0.8065 -0.7261 1.000 -0.1526
0.2765 0.05863 -0.01800 -0.06388 -0.1929 -0.4822 -0.1526 1.000
Es posible que esto genere una matriz de correlación con componentes principales dominantes debido a la regla de generación acumulativa de la matriz de cargas factoriales. También podría ser mejor asegurar la definición positiva haciendo que la última parte de la varianza sea un factor único. Lo dejé en el programa para mantener el enfoque en el principio general.
Una matriz de correlaciones de 100x100 tenía las siguientes frecuencias de correlaciones (redondeadas a 1 lugar dec)
e f e: entry(rounded) f: frequency
-----------------------------------------------------
-1.000, 108.000
-0.900, 460.000
-0.800, 582.000
-0.700, 604.000
-0.600, 548.000
-0.500, 540.000
-0.400, 506.000
-0.300, 482.000
-0.200, 488.000
-0.100, 464.000
0.000, 434.000
0.100, 486.000
0.200, 454.000
0.300, 468.000
0.400, 462.000
0.500, 618.000
0.600, 556.000
0.700, 586.000
0.800, 536.000
0.900, 420.000
1.000, 198.000
[actualización]. Hmm, la matriz 100x100 está mal condicionada; Pari/GP no puede determinar los valores propios correctamente con la función polroots(charpoly())-incluso con 200 dígitos de precisión. He hecho una rotación de Jacobi a pca-forma en la matriz de carga L y encuentro en su mayoría valores propios extremadamente pequeños, imprimiéndolos en logaritmos a base 10 (que dan aproximadamente la posición del punto decimal). Leer de izquierda a derecha y luego fila por fila:
log_10(eigenvalues):
1.684, 1.444, 1.029, 0.818, 0.455, 0.241, 0.117, -0.423, -0.664, -1.040
-1.647, -1.799, -1.959, -2.298, -2.729, -3.059, -3.497, -3.833, -4.014, -4.467
-4.992, -5.396, -5.511, -6.366, -6.615, -6.834, -7.535, -8.138, -8.263, -8.766
-9.082, -9.482, -9.940, -10.167, -10.566, -11.110, -11.434, -11.788, -12.079, -12.722
-13.122, -13.322, -13.444, -13.933, -14.390, -14.614, -15.070, -15.334, -15.904, -16.278
-16.396, -16.708, -17.022, -17.746, -18.090, -18.358, -18.617, -18.903, -19.186, -19.476
-19.661, -19.764, -20.342, -20.648, -20.805, -20.922, -21.394, -21.740, -21.991, -22.291
-22.792, -23.184, -23.680, -24.100, -24.222, -24.631, -24.979, -25.161, -25.282, -26.211
-27.181, -27.626, -27.861, -28.054, -28.266, -28.369, -29.074, -29.329, -29.539, -29.689
-30.216, -30.784, -31.269, -31.760, -32.218, -32.446, -32.785, -33.003, -33.448, -34.318
[actualización 2]
Método 2(b)
Una mejora podría ser aumentar la varianza específica del ítem a algún nivel no marginal y reducir a un número razonablemente menor de factores comunes (por ejemplo, la raíz cuadrada entera del número de ítems):
{ dimr = 100;
dimc = sqrtint(dimr); \\ 10 common factors
L = matrix(dimr,dimr+dimc); \\ loadings matrix
\\ with dimr itemspecific and
\\ dimc common factors
for(r=1,dim,
vr=1.0; \\ complete variance per item
vu=0.05+random(100)/1000.0; \\ random variance +0.05
\\ for itemspecific variance
L[r,r]=sqrt(vu); \\ itemspecific factor loading
vr=vr-vu;
for(c=1,dimc,
cv=if(c<dimc,random(100)/100,1.0)*vr;
vr=vr-cv;
L[r,dimr+c]=(-1)^(random(100) % 2)*sqrt(cv)
)
);}
cov=L*L~
cp=charpoly(cov) \\ does not work even with 200 digits precision
pr=polroots(cp) \\ spurious negative and complex eigenvalues...
La estructura del resultado
en términos de la distribución de las correlaciones:
sigue siendo similar (también la desagradable no descomponibilidad por PariGP), pero los valores propios, cuando se encuentran por jacobi-rotación de la matriz de cargas, tienen ahora una mejor estructura, para un ejemplo recién calculado obtuve los valores propios como
log_10(eigenvalues):
1.677, 1.326, 1.063, 0.754, 0.415, 0.116, -0.262, -0.516, -0.587, -0.783
-0.835, -0.844, -0.851, -0.854, -0.858, -0.862, -0.862, -0.868, -0.872, -0.873
-0.878, -0.882, -0.884, -0.890, -0.895, -0.896, -0.896, -0.898, -0.902, -0.904
-0.904, -0.909, -0.911, -0.914, -0.920, -0.923, -0.925, -0.927, -0.931, -0.935
-0.939, -0.939, -0.943, -0.948, -0.951, -0.955, -0.956, -0.960, -0.967, -0.969
-0.973, -0.981, -0.986, -0.989, -0.997, -1.003, -1.005, -1.011, -1.014, -1.019
-1.022, -1.024, -1.031, -1.038, -1.040, -1.048, -1.051, -1.061, -1.064, -1.068
-1.070, -1.074, -1.092, -1.092, -1.108, -1.113, -1.120, -1.134, -1.139, -1.147
-1.150, -1.155, -1.158, -1.166, -1.171, -1.175, -1.184, -1.184, -1.192, -1.196
-1.200, -1.220, -1.237, -1.245, -1.252, -1.262, -1.269, -1.282, -1.287, -1.290
1 votos
Se puede crear una matriz ortogonal aleatoria mediante procesos QR o Gram-Schmidt. Eso será "vectores propios de PCA". Añadir escala a sus columnas (convertirlas en "cargas"). Obtener la matriz de covarianza a partir de estas cargas. Algo así...
0 votos
@ttnphns: Sí, pero si genero una matriz ortogonal aleatoria y elijo valores propios aleatorios, entonces la matriz de covarianza/correlación resultante vuelve a ser bastante diagonal (acabo de probar).
1 votos
Uhm, bueno.. Imagina que queremos crear un
nXk
matriz de carga W, no totalmente aleatoria pero sí la que queramos (será,WW'+diag(noise)
, definen la matriz cov que buscamos. La única tarea es corregir la columna normalizada W (es decir, los k "vectores propios") para que sean ortogonales. Cualquier método para descorrelacionar variables correlacionadas (aquí las variables son los vectores propios) probablemente servirá. (Esto es una idea bruta).0 votos
Puede obtener un perfectamente distribución uniforme de todos los elementos no diagonales de varias maneras triviales haciéndolos todos iguales a $\pm \rho$ (con la elección adecuada de patrones de signos) y el dibujo $\rho$ uniformemente en $(-1,0)$ (para algunas opciones de signos) o en $(0,1)$ (para otras opciones de signos). Yo no recomendaría esto porque el conjunto de matrices es muy especial: la cuestión es que tal vez debería aplicar criterios adicionales a sus matrices de correlación para que cubran un conjunto más realista de posibilidades.
0 votos
Gracias, @whuber, pero no estoy seguro de entenderlo: si genero de forma independiente los valores no diagonales, la matriz resultante no será positiva-definida, es decir, no puede ser una matriz de covarianza/correlación.
0 votos
No se generan de forma independiente. Se puede generar una mezcla de matrices en la que (1) todos los valores de la fuera de la diagonal sean iguales a $\rho$ o (2) son iguales a $(-1)^{i+j}\rho$ en el $(i,j)$ posición.
1 votos
Ah, @whuber, ahora entiendo lo que quieres decir. Sí, tienes razón: si todos los elementos no diagonales son idénticos e iguales a $\rho$ entonces la matriz es efectivamente de rango completo y definida positivamente... Por supuesto, esto no es lo que tenía en mente: Me gustaría que la distribución de los elementos no diagonales en cada matriz para estar razonablemente "repartido", no la distribución a través de las matrices ...
3 votos
Puede que quieras mirar la distribución de LKJ
1 votos
@ssdecontrol: He leído el artículo de LKJ y efectivamente ha dado una respuesta. Mira mi propia respuesta aquí si te interesa. ¡Muchas gracias por la pista!
2 votos
@ttnphns: Creo que por fin he comprendido que tenías razón todo el tiempo: lo que sugeriste es la forma más sencilla de llegar al objetivo. He añadido una actualización a mi respuesta implementando esencialmente lo que has escrito arriba.
1 votos
Adjunto un enlace a un artículo sobre matrices de correlación aleatoria. Si haces que cada elemento fuera de la diagonal sea U(0, 1) entonces corres el riesgo de que la propia matriz no sea positiva definida, por lo que los elementos marginalmente U(0, 1) requieren una fuerte correlación entre los elementos. rob-mcculloch.org/algunos_documentos_y_charlas/documentos/publicados/