3 votos

Obteniendo conjuntos de variables correlacionadas al azar

Para el entrenamiento de un modelo de aprendizaje automático necesito agregar características adicionales (variables macro), y estas características están correlacionadas. Necesito ejecutar el modelo N veces, y para cada vez tengo que agregar las características aleatorias.

Ahora, estas características tienen rangos, por ejemplo:

Característica 1 (Crecimiento del PIB) entre 2.0 y 3.5
Característica 2 (Desempleo) entre 4.4 y 5.1
Característica 3 (Índice Dow Jones) entre 22000 y 24000

Con la descomposición de Cholesky puedo tomar una de las características y obtener las otras utilizando una matriz de correlación. La entrada sería el valor fijo de una de las características, y el resultado los valores de las otras características correlacionadas.

Pero lo que necesito es que el sistema calcule N conjuntos de características aleatorias, dentro de los rangos. Así que no hay una entrada para generar las características.

¿Hay alguna manera de lograr esto (ya sea con o sin Cholesky)?

3voto

BigCanOfTuna Puntos 210

Aquí hay una receta, en caso de que puedas vivir con la correlación de rango de Spearman. (Lo cual deberías: la correlación lineal a menudo no es adecuada en el caso no normal. Y en el caso normal, casi no hay diferencia entre los dos tipos de correlación.)

  1. Genera muestras de tus $k$ características con todos los atributos deseados. Estas muestras pueden ser aleatorias o datos históricos. Las muestras no necesitan tener el mismo tamaño.

  2. Supongamos que deseas generar $n$ escenarios. Luego genera $n$ normales $k$-dimensionales con la correlación deseada (es decir, una matriz de tamaño $n$ veces $k$). Aquí puedes usar Cholesky. (Estrictamente hablando, necesitarías modificar las correlaciones en $2\sin(\rho\pi/6)$. Pero esta corrección es tan pequeña que puedes dejarla fuera.)

  3. Alimenta estos variados normales correlacionados en la función de distribución normal. El resultado será $n$ vectores de uniformes que tienen la misma correlación de rango que las normales (porque la función de distribución es monótonamente creciente).

  4. Alimenta estos uniformes en las inversas de las funciones de distribución empírica de tus muestras del paso 1. (Esto es fácil: para un variable uniforme $u$, ordena una muestra de características dadas y luego elige el elemento en la posición ceiling(u*length(feature_sample)).) Debido a que las inversas son no decrecientes, la correlación de rango se mantendrá.

En caso de que uses R: Todo este procedimiento está implementado en la función resampleC en el paquete NMOF (que mantengo). Aquí tienes un ejemplo.

library("NMOF")

gdp <- runif(10000, min = 2,     max = 3.5)
une <- runif(10000, min = 4.4,   max = 5.1)
dji <- runif(10000, min = 22000, max = 24000)

cor <- array(c(1.0, 0.5, 0.3,
               0.5, 1.0, 0.9,
               0.3, 0.9, 1.0), dim = c(3,3))

smp <- resampleC(gdp, une, dji, cormat = cor, size = 1000)
cor(smp)
##           var1      var2      var3
## var1 1.0000000 0.5140693 0.3041248
## var2 0.5140693 1.0000000 0.9012560
## var3 0.3041248 0.9012560 1.0000000

Podemos verificar los rangos.

apply(smp, 2, range)
##          var1     var2     var3
## [1,] 2.000432 4.401090 22005.30
## [2,] 3.499644 5.098867 23998.15

Un enfoque completamente diferente es crear muestras de tus características (esta vez de la misma longitud), ponerlas en las columnas de una matriz, y luego reorganizar los elementos dentro de las columnas para que te acerques a la matriz de correlación deseada. Ver esta respuesta.

0 votos

Gracias Enrico, trabajo con Python, ¿hay una biblioteca en Python similar a NMOF?

0 votos

Las correlaciones de rango son un buen punto! Con esta excepción, es exactamente la misma idea que describí (algo abstracta) a continuación.

0 votos

@ps0604: no tengo idea; lo siento. (Algunos esfuerzos están en marcha para traducir al menos partes del código NMOF a Python, desde el código en R y MATLAB que se utilizó en el libro.)

2voto

Lie Ryan Puntos 15629

Cholesky (o SVD u cualquier otro enfoque basado en multiplicación de matrices) solo funciona para distribuciones normales, lo cual tus características no pueden ser, dado que tienen valores dentro de intervalos finitos.

Para ver por qué Cholesky no funciona, asume dos características adicionales, las cuales son uniformes e independientes $(U_1,U_2)$. Ahora quieres crear características con correlación $\rho$ multiplicando $U$ con el factor Cholesky $C$ es decir $Y = U C$. No es difícil ver que el factor Cholesky es $$ C=\begin{pmatrix} 1 & \rho \\ 0 & \sqrt{1-\rho^2}\end{pmatrix}.$$

Esto significa que $$ Y = (U_1, U_1 + \sqrt{1 - \rho^2}U_2).$$ Mientras que la primera característica $Y_1=U_1$ está bien, tu segunda variable $Y_2$ ya no es uniforme y tendrá un rango diferente a $U_2$.

Ahora podrías tener la idea de que podrías empezar con $Y_2$ y luego intentar ingeniería inversa con $U_2$ y $U_1$ desde esto para obtener la entrada adecuada para tus simulaciones. El problema con esta idea es que tal par no siempre puede existir. Comenzando con márgenes arbitrarios (es decir, características independientes independientes) una distribución conjunta con la matriz de correlación prescrita podría no existir. Hay restricciones acerca de qué combinaciones de distribuciones marginales y matrices de correlación son posibles. Echa un vistazo a este artículo de Embrechts, McNeil y Straumann.

¿Entonces QUÉ puedes hacer? Si tienes suerte y no eres muy exigente en cuanto a precisión, el siguiente enfoque pragmático podría funcionar:

  1. Simula desde una copula Gaussiana ver Wikipedia, toma como parámetros los parámetros de correlación que te gustaría obtener
  2. Aplica la transformación integral de probabilidad para reordenar tus características de acuerdo a 1.
  3. Mide las correlaciones de las características reordenadas, si están bien entonces has terminado
  4. Si no están bien, repite 1. con parámetros ligeramente cambiados de la copula Gaussiana

0 votos

Gracias, g g. ¿En lugar de implementar el método de la cópula de Gauss que describiste manualmente, hay una biblioteca de Python que ya lo hace?

0 votos

No soy consciente de ningún paquete de Python que realice esta transformación. Pero el proceso en sí no es demasiado difícil. El desafío principal es entender cómo funciona la transformación integral de la probabilidad. Y no necesitas una fórmula explícita para la Cópula de Gauss. Puedes usar normales multivariadas.

0 votos

Leí que las cópulas gaussianas no hacen un buen trabajo capturando la dependencia de la cola, ¿no es eso un problema en mi ejemplo de variables macro?

1voto

Arlene Serrano Puntos 6

Dado que la matriz de correlación $C=LL^{\top}$ también es $C=U^{\top}U$, donde $U$ es la matriz triangular superior, en lugar de $L$ la matriz triangular inferior, puedes transformar una matriz de características $F$ sin correlación que contiene características 1, 2 y 3 en sus columnas multiplicando esta matriz $F$ con $U$, obteniendo la matriz de características correlacionadas $F_c$:

$$F_c = F U $$

En otras palabras, genera aleatoriamente las características en sus respectivos rangos como vectores columna sin especificar la correlación, concaténalas en una matriz, luego transfórmalas con Cholesky en la fórmula anterior en características correlacionadas. No lo he intentado, pero espero que los rangos todavía se conserven en los datos transformados.

0 votos

Para su información, svd es una mejor manera de hacer esto en lugar de cholesky.

0 votos

@will ¿Puedes proporcionar un enlace a un ejemplo? Veo que SVD se usa ampliamente, pero no puedo encontrar información sobre la generación de variables aleatorias.

0 votos

De la misma manera en que utilizas la descomposición de Cholesky para calcular $\sqrt{\Sigma}$, simplemente usa svd en su lugar, y luego utiliza el resultado de la misma manera que lo harías con la descomposición de Cholesky.

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X