Main Content

La traducción de esta página aún no se ha actualizado a la versión más reciente. Haga clic aquí para ver la última versión en inglés.

Controlar la generación de números aleatorios

En este ejemplo se muestra cómo usar la función rng, que controla la generación de números aleatorios.

Los números (seudo)aleatorios en MATLAB® proceden de las funciones rand, randi y randn. Muchas otras funciones llaman a esas tres, pero esas son los bloques de creación fundamentales. Las tres dependen de un solo generador de números aleatorios compartidos que puede controlar mediante rng.

Es importante darse cuenta de que los números "aleatorios" en MATLAB no son impredecibles en absoluto, sino que los genera un algoritmo determinista. El algoritmo está diseñado para ser suficientemente complicado como para que su salida parezca una secuencia aleatoria independiente para alguien que no conoce el algoritmo, y puede pasar varas pruebas estadísticas de aleatoriedad. La función que se introduce aquí ofrece formas de aprovechar el determinismo para

  • repetir cálculos que impliquen números aleatorios y obtener los mismos resultados o

  • garantizar que números aleatorios diferentes se usan en cálculos repetidos

y para aprovechar la aleatoriedad aparente y justificar la combinación de resultados de cálculos independientes.

"Empezar de nuevo"

Si observa la salida de rand, randi o randn en una nueva sesión de MATLAB, se dará cuenta de que devuelven las mismas secuencias de números cada vez que reinicia MATLAB. Suele ser útil poder restablecer el generador de números aleatorios a ese estado inicial, sin tener que reiniciar MATLAB. Por ejemplo, puede que necesite repetir cálculos que impliquen números aleatorios y obtener los mismos resultados.

Cuando inicia una sesión en MATLAB por primera vez o llama a rng("default"), MATLAB inicializa el generador de números aleatorios usando la semilla y algoritmo predeterminados. A partir de la versión R2023b, puede definir la semilla y algoritmo predeterminados en las preferencias de MATLAB. Si no cambia estas preferencias, rng utiliza el valor de fábrica de "twister" para el generador Mersenne Twister con semilla 0, como en las versiones anteriores. Para obtener más información, consulte Configuración predeterminada del generador de números aleatorios y Reproducibilidad del generador de números aleatorios.

rng("default") ofrece una forma muy sencilla de hacer que el generador de números aleatorios regrese a su configuración predeterminada.

rng("default")
rand % returns the same value as at startup
ans = 0.8147

¿Cuál es la configuración "predeterminada" de los números aleatorios con la que se inicia MATLAB o que le ofrece rng("default")? En versiones anteriores a R2023b, si llama a rng sin entradas, podrá ver que es el algoritmo del generador Mersenne Twister con la semilla establecida en 0.

rng
ans = struct with fields:
     Type: 'twister'
     Seed: 0
    State: [625x1 uint32]

A continuación verá en más detalle cómo utilizar las salidas anteriores, incluido el campo State para controlar y cambiar cómo MATLAB genera números aleatorios. De momento, sirve como una manera de ver qué generador utiliza rand, randi y randn en este momento.

No repetibilidad

Cada vez que llame a rand, randi o a randn, extraerán un nuevo valor de su generador de números aleatorios compartido y los valores sucesivos se podrán tratar como independientes estadísticamente. Pero como se menciona anteriormente, cada vez que reinicie MATLAB, sus funciones se restablecerán y devolverán las mismas secuencias de números. Por supuesto, los cálculos que utilicen los mismos números "aleatorios" no se podrán considerar independientes estadísticamente. Por lo tanto, cuando sea necesario combinar cálculos realizados en dos o más sesiones de MATLAB como si fuesen independientes estadísticamente, no puede utilizar la configuración del generador predeterminada.

Una forma sencilla de evitar repetir los mismos números aleatorios en una nueva sesión de MATLAB es elegir una nueva semilla para el generador de números aleatorios. rng le ofrece una sencilla forma de hacerlo, creando una semilla basada en la hora actual.

rng("shuffle")
rand
ans = 0.6465

Cada vez que utilice "shuffle", vuelve a alimentar el generador con una semilla diferente. Puede llamar a rng sin ninguna entrada para ver qué semilla está usando.

rng
ans = struct with fields:
     Type: 'twister'
     Seed: 1507067353
    State: [625x1 uint32]

rng("shuffle") % creates a different seed each time
rng
ans = struct with fields:
     Type: 'twister'
     Seed: 1507067356
    State: [625x1 uint32]

rand
ans = 0.3008

"shuffle" es una manera muy sencilla de volver a alimentar el generador de números aleatorios. Puede que piense que es una buena idea, o incluso necesario, usarlo para obtener la "verdadera" aleatoriedad en MATLAB. No obstante, para la mayoría de propósitos no es necesario usar "shuffle" en absoluto. Elegir una semilla basada en la hora actual no mejora las propiedades estadísticas de los valores que obtendrá de rand, randi y randn, y no hace que sean "más aleatorios" en ningún sentido real. Mientras que es perfectamente correcto volver a alimentar el generador cada vez que inicie MATLAB, o antes de ejecutar algún tipo de cálculo importante que implique números aleatorios, en realidad no es una buena idea volver a alimentar el generador con demasiada frecuencia en la misma sesión, porque puede afectar a las propiedades estadísticas de los números aleatorios.

Lo que sí le proporciona "shuffle" es una forma de evitar repetir las mismas secuencias de valores. En ciertas ocasiones, eso es algo crucial, algunas veces simplemente "está bien", pero la mayoría de las veces no es importante. Tenga en cuenta que si utiliza "shuffle", puede que le interese guardar la semilla que creó rng para que pueda repetir los cálculos más adelante. Más adelante verá cómo hacerlo.

Más control de la repetibilidad y la no repetibilidad

Hasta ahora, ha visto cómo restablecer el generador de números aleatorios a su configuración predeterminada, y cómo volver a alimentarlo con una semilla creada en función de la hora actual. rng también le ofrece una forma de volver a alimentarlo con una semilla específica.

Puede utilizar la misma semilla varias veces, para repetir los mismos cálculos. Por ejemplo, si ejecuta este código dos veces...

rng(1) % the seed is any non-negative integer < 2^32
x = randn(1,5)
x = 1×5

   -0.6490    1.1812   -0.7585   -1.1096   -0.8456

rng(1)
x = randn(1,5)
x = 1×5

   -0.6490    1.1812   -0.7585   -1.1096   -0.8456

... obtendrá exactamente los mismos resultados. Puede que le interese hacer esto para recrear x después de haberla borrado, para que pueda repetir lo que pasa en los cálculos siguientes que dependan de x, con esos valores específicos.

Por otro lado, puede que le interese elegir distintas semillas para garantizar que no repite los mismos cálculos. Por ejemplo, si ejecuta este código en una sesión de MATLAB...

rng(2)
x2 = sum(randn(50,1000),1); % 1000 trials of a random walk

y este código en otra...

rng(3)
x3 = sum(randn(50,1000),1);

... podría combinar los dos resultados y tener la certeza de que no son simplemente los mismos resultados que se repiten.

x = [x2 x3];

Al igual que ocurre con "shuffle", hay una salvedad al volver a alimentar el generador de números aleatorios de MATLAB, porque afecta a todas las salidas siguientes de rand, randi y randn. A menos que necesite repetibilidad o singularidad, suele ser recomendable simplemente generar valores aleatorios sin volver a alimentar el generador. Si necesita volver a alimentar el generador, se suele hacer mejor en la línea de comandos, o en un punto del código que no pase por alto fácilmente.

Elegir un tipo de generador

No solo puede volver a alimentar el generador de números aleatorios como se muestra anteriormente, sino que también puede elegir el tipo de generador de números aleatorios que quiere usar. Cada tipo de generador produce distintas secuencias de números aleatorios. Por ejemplo, podría elegir un tipo específico por sus propiedades estadísticas. O podría necesitar recrear los resultados de una versión anterior de MATLAB que utilizara otro tipo de generador predeterminado.

Una razón habitual para elegir el tipo de generador surge cuando lleva a cabo una prueba de validación que genera datos de entrada "aleatorios" y debe garantizar que su prueba siempre pueda esperarse exactamente el mismo resultado predecible. Si llama a rng con una semilla antes de crear los datos de entrada, vuelve a alimentar el generador de números aleatorios. Pero si por alguna razón se ha cambiado el tipo de generador, entonces la salida de rand, randi y randn no será lo que espera de esa semilla. Por lo tanto, para tener total certeza de la repetibilidad, también puede especificar un tipo de generador.

Por ejemplo:

rng(0,"twister")

provoca que rand, randi y randn utilicen el algoritmo Mersenne twister después de establecer la semilla en 0.

Utilizar "combRecursive"

rng(0,"combRecursive")

selecciona el algoritmo de generación combinado múltiple recursivo, que admite algunas funcionalidades paralelas que Mersenne twister no.

Este comando

rng(0,"v4")

selecciona el algoritmo de generación predeterminado en MATLAB 4.0.

Además, este comando hace que el generador de números aleatorios regrese a su configuración predeterminada.

rng("default")

Sin embargo, dado que la configuración predeterminada del generador de números aleatorios podría cambiar de una versión a otra de MATLAB, utilizar "default" no garantiza resultados predecibles a largo plazo. "default" es una forma apropiada de restablecer el generador de números aleatorios, pero si desea una predictibilidad incluso mayor, especifique un tipo de generador y una semilla.

Por otro lado, cuando trabaje de forma interactiva y necesite repetibilidad es más sencillo, y suele funcionar, llamar a rng solo con una semilla.

Guardar y restaurar la configuración del generador de números aleatorios

Llamar a rng sin entrada devuelve una estructura escalar con campos que contienen dos datos que ya se han descrito: el tipo de generador y el número entero con el que se volvió a alimentar el generador por última vez.

s = rng
s = struct with fields:
     Type: 'twister'
     Seed: 0
    State: [625x1 uint32]

El tercer campo, State, contiene una copia del vector estado que tiene el generador en ese momento. Este vector estado es la información que el generador conserva internamente para generar el siguiente valor en la secuencia de números aleatorios. Cada vez que llama a rand, randi o randn, el generador que comparten actualiza su estado interno. Así, el vector estado en la estructura de configuración que devuelve rng contiene la información necesaria para repetir la secuencia, a partir del punto en el que se capturó el estado.

Mientras que solo ver esta salida resulta informativo, rng también acepta una estructura de configuración como entrada, para que pueda guardar la configuración, incluido el vector estado y restablecerla más adelante para repetir cálculos. Dado que la configuración contiene el tipo de generador, sabrá exactamente cuál obtiene, y así "posterior" querrá decir cualquier cosa sucedida a partir de los momentos posteriores en la misma sesión de MATLAB, hasta años (y múltiples versiones de MATLAB) después. Puede repetir los resultados desde cualquier punto de la secuencia de números aleatorios en la que guardó la configuración del generador. Por ejemplo

x1 = randn(10,10); % move ahead in the random number sequence
s = rng;           % save the settings at this point
x2 = randn(1,5)
x2 = 1×5

    0.8404   -0.8880    0.1001   -0.5445    0.3035

x3 = randn(5,5);   % move ahead in the random number sequence
rng(s);            % return the generator back to the saved state
x2 = randn(1,5)    % repeat the same numbers
x2 = 1×5

    0.8404   -0.8880    0.1001   -0.5445    0.3035

Tenga en cuenta que mientras volver a establecer la semilla le proporciona solo una reinicialización gruesa, guardar y restaurar el estado del generador con la estructura de configuración le permite repetir cualquier parte de la secuencia de números aleatorios.

La forma más habitual de utilizar la estructura de configuración es restaurar el estado del generador. Sin embargo, dado que la estructura no solo contiene el estado, sino también el tipo de generador y la semilla, también es una manera apropiada para cambiar temporalmente el tipo de generador. Por ejemplo, si necesita crear valores con uno de los generadores heredados de MATLAB 5.0, puede guardar la configuración actual al mismo tiempo que cambia para utilizar el generador antiguo.

previousSettings = rng(0,"v5uniform")
previousSettings = struct with fields:
     Type: 'twister'
     Seed: 0
    State: [625x1 uint32]

Podrá restaurar la configuración original más adelante.

rng(previousSettings)

No debe modificar el contenido de ninguno de los campos en una estructura de configuración. En concreto, no debe construir su propio vector estado, ni siquiera depender del formato del estado del generador.

Escribir código más simple y flexible

rng le permite tanto

  • volver a alimentar el generador de números aleatorios, como

  • guardar y restaurar la configuración del generador de números aleatorios

sin que tenga que saber de qué tipo es. También puede hacer que el generador de números aleatorios vuelva a su configuración predeterminada sin tener que saber cómo es esa configuración. Mientras que hay situaciones en las que quizá quiera especificar un tipo de generador, rng simplifica el proceso y le permite no tener que especificarlo.

Si logra evitar especificar el tipo de generador, el código se adaptará automáticamente a casos en los que haya que usar un generador diferente, y se beneficiará automáticamente de las propiedades mejoradas de un nuevo tipo de generador de números aleatorios predeterminado.

rng y RandStream

rng proporciona una forma apropiada de controlar la generación de números aleatorios en MATLAB para las necesidades más comunes. Sin embargo, las situaciones más complicadas con secuencias múltiples de números aleatorios y generación paralela de números aleatorios exigen una herramienta más compleja. La clase RandStream es esa herramienta, y proporciona la forma más potente de controlar la generación de números aleatorios. Las dos herramientas son complementarias; rng proporciona una sintaxis mucho más simple y concisa que se construye sobre la flexibilidad de RandStream.