¿Cuál es una estructura de datos apropiada para una matriz con entradas de variables aleatorias?

Actualmente estoy trabajando en un área relacionada con la simulación e intento diseñar una estructura de datos que pueda incluir variables aleatorias dentro de matrices. Para motivar esto, déjeme decir que tengo la siguiente matriz:

[a b; c d]

Quiero encontrar una estructura de datos que permita a, b, c, d sean números reales o variables aleatorias. Como ejemplo, digamos que a = 1, b = -1, c = 2 pero deja d ser una variable aleatoria distribuida normalmente con media 0 y desviación estándar 1.

La estructura de datos que tengo en mente no dará ningún valor a d. Sin embargo, también quiero poder diseñar una función que pueda incorporar la estructura, simular un uniform(0,1), obtenga un valor para d usando un CDF inverso y luego escupe una matriz real.

Tengo varias ideas para hacer esto (todas relacionadas con MATLAB icdf función) pero me gustaría saber cómo los programadores más experimentados harían esto. En esta aplicación, es importante que la estructura sea lo más "ajustada" posible, ya que trabajaré con matrices muy grandes y la memoria será un problema.

EDICIÓN # 1:

Gracias por toda la retroalimentación. Decidí usar una estructura de celda y almacenar variables aleatorias como manejadores de funciones. Para ahorrar algo de tiempo de procesamiento para aplicaciones a gran escala, he decidido hacer referencia a la ubicación de las variables aleatorias para ahorrar tiempo durante la parte de "evaluación".

preguntado el 08 de enero de 11 a las 19:01

¿Todos los elementos aleatorios que se van a admitir están siempre distribuidos normalmente e independientes? ¿O necesita admitir otras distribuciones y / o covarianza? -

Algunos detalles más sobre cómo se verán estas matrices grandes nos ayudarán a brindarle soluciones más específicas. En particular, ¿los valores aleatorios se agruparán en submatrices dentro de la matriz más grande, o estarán dispersos por toda la matriz más grande? -

@aschepler: lo necesito para admitir variables aleatorias definidas por el usuario, así como otros tipos de variables aleatorias genéricas (es decir, normal, beta, uniforme, etc.) -

@gnovice: estarán dispersos por toda la matriz más grande, así que creo que también almacenaré los índices de los RV en lugar de tener que iterar sobre la matriz -

2 Respuestas

Una solución es crear su matriz inicialmente como un matriz de celdas que contiene tanto valores numéricos como manijas de función a funciones diseñadas para generar un valor para esa entrada. Para su ejemplo, puede hacer lo siguiente:

generatorMatrix = {1 -1; 2 @randn};

Entonces podrías crear una función que tome una matriz de la forma anterior, evalúa las celdas que contienen identificadores de funciones, luego combina los resultados con las entradas numéricas de celda para crear una matriz numérica a utilizar para cálculos adicionales:

function numMatrix = create_matrix(generatorMatrix)
  index = cellfun(@(c) isa(c,'function_handle'),...  %# Find function handles
                  generatorMatrix);
  generatorMatrix(index) = cellfun(@feval,...        %# Evaluate functions
                                   generatorMatrix(index),...
                                   'UniformOutput',false);
  numMatrix = cell2mat(generatorMatrix);  %# Change from cell to numeric matrix
end

Algunas cosas adicionales que puede hacer serían utilizar funciones anónimas para hacer cosas más complicadas con funciones integradas o crear entradas de celda de tamaño variable. Esto se ilustra con la siguiente matriz de muestra, que se puede utilizar para crear una matriz en la que la primera fila contenga un 5 seguido de 9 unos y las otras 9 filas contengan un 1 seguido de 9 números extraídos de una distribución uniforme entre 5 y 10:

generatorMatrix = {5 ones(1,9); ones(9,1) @() 5*rand(9)+5};

Y cada vez que esta matriz se pasa a create_matrix creará una nueva matriz de 10 por 10 donde la submatriz de 9 por 9 contendrá un conjunto diferente de valores aleatorios.


Una solución alternativa ...

Si su matriz se puede dividir fácilmente en bloques de submatrices (como en el segundo ejemplo anterior), entonces usar una matriz de celdas para almacenar valores numéricos y controles de función puede ser su mejor opción.

Sin embargo, si los valores aleatorios son elementos individuales dispersos escasamente por toda la matriz, entonces una variación similar a la user57368 sugirió puede funcionar mejor. Puede almacenar los datos de su matriz en tres partes: una matriz numérica con marcadores de posición (como Yaya) donde irán los valores generados aleatoriamente, un vector de índice que contiene índices lineales de las posiciones de los valores generados aleatoriamente, y una matriz de celdas de la misma longitud que el vector de índice que contiene manijas de función para las funciones que se utilizarán para generar los valores aleatorios. Para facilitar las cosas, incluso puede almacenar estos tres datos en un estructura.

Como ejemplo, lo siguiente define una matriz de 3 por 3 con 3 valores aleatorios almacenados en los índices 2, 4 y 9 y extraídos respectivamente de un distribución normal, y distribución uniforme de 5 a 10, y un distribución exponencial:

matData = struct('numMatrix',[1 nan 3; nan 2 4; 0 5 nan],...
                 'randIndex',[2 4 9],...
                 'randFcns',{{@randn , @() 5*rand+5 , @() -log(rand)/2}});

Y puedes definir un nuevo create_matrix función para crear fácilmente una matriz a partir de estos datos:

function numMatrix = create_matrix(matData)
  numMatrix = matData.numMatrix;
  numMatrix(matData.randIndex) = cellfun(@feval,matData.randFcns);
end

contestado el 23 de mayo de 17 a las 15:05

Si la matriz es muy grande y tiene un número relativamente pequeño de variables aleatorias, entonces la primera cellfun La llamada desperdiciará mucho tiempo y destruirá mucha memoria, ya que una matriz de celdas es una matriz de punteros, y cada puntero tendría que ser desreferenciado para el isa llamada. El método que sugerí (usando dos matrices, la segunda escasa) casi con certeza funcionaría mejor (ya que find en una matriz dispersa es casi imposible), pero hace que el código sea más opaco. - user57368

@ user57368: Por eso agregué el segundo ejemplo. Ilustra cómo puede dividir la matriz entre celdas de modo que cada celda contenga una matriz en lugar de solo un valor escalar, de modo que termine con menos celdas totales para operar. - gnovice

Está bien. Ahora que ha agregado el @ (), veo cómo funcionaría. Definitivamente la forma más limpia de manejarlo para una matriz que se puede definir en unas pocas líneas. - user57368

Gracias por esto. Actualmente estoy pensando en dirigirme de la manera que describiste por primera vez. Decidí usar una matriz de celdas con entradas reales y controles de función para las variables aleatorias. Sin embargo, todavía tengo algunos problemas con respecto a la generación de variables aleatorias, por lo que agradecería cualquier comentario al respecto. - Berk U.

@ squall14414: Basándome en la información adicional en sus comentarios, agregué una solución alternativa a mi respuesta que es posible que desee consultar. - gnovice

Si estuviera usando NumPy, entonces las matrices enmascaradas serían el lugar obvio para comenzar, pero no conozco ningún equivalente en MATLAB. Es posible que las matrices de celdas no sean lo suficientemente compactas, y si usó una matriz de celdas, entonces tendría que encontrar una forma eficiente de encontrar las entradas no reales y reemplazarlas con una muestra de la distribución correcta.

Intente usar una matriz regular o dispersa para mantener los valores reales y déjela en cero donde desee una variable aleatoria. Luego, junto con eso, almacene una matriz dispersa de la misma forma cuyas entradas distintas de cero corresponden a las variables aleatorias en su matriz. Si lo desea, el valor de la entrada en la segunda matriz se puede utilizar para indicar qué distribución (es decir, 1 para uniforme, 2 para normal, etc.).

Siempre que desee obtener una matriz puramente real para trabajar, iterará sobre los valores distintos de cero en la segunda matriz para convertirlos en muestras, y luego agregue esa matriz a la primera.

Respondido el 08 de enero de 11 a las 23:01

@ user57368: ¿Por qué querría una matriz dispersa para el n. ° 2? Simplemente podría poner los datos en un vector, ahorrando espacio y tiempo. - Jonas

Necesita almacenar tanto la definición de la variable aleatoria como su ubicación en la primera matriz. Una matriz dispersa hará esto tan bien como un vector, pero el código para convertir la matriz dispersa en una matriz de muestras aleatorias debería ser más limpio, y el resultado solo necesitaría agregarse a la matriz real. - user57368

@ user57368: Puede definir la ubicación en la primera matriz poniendo NaN donde quieras tener una variable aleatoria más tarde. - Jonas

Supongo que sí, pero luego tendrías que iterar sobre toda la matriz para encontrar y reemplazar esos NaN. Para m by n matriz con r variables aleatorias, es la diferencia entre O(mn+r) y O(r) para el proceso de conversión. - user57368

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.