Tengo dos matrices numpy de diferentes formas, pero con la misma longitud (dimensión principal). Quiero barajar cada uno de ellos, de modo que los elementos correspondientes sigan correspondiendo, es decir, barajarlos al unísono con respecto a sus índices principales.
Este código funciona e ilustra mis objetivos:
def shuffle_in_unison(a, b):
assert len(a) == len(b)
shuffled_a = numpy.empty(a.shape, dtype=a.dtype)
shuffled_b = numpy.empty(b.shape, dtype=b.dtype)
permutation = numpy.random.permutation(len(a))
for old_index, new_index in enumerate(permutation):
shuffled_a[new_index] = a[old_index]
shuffled_b[new_index] = b[old_index]
return shuffled_a, shuffled_b
Por ejemplo:
>>> a = numpy.asarray([[1, 1], [2, 2], [3, 3]])
>>> b = numpy.asarray([1, 2, 3])
>>> shuffle_in_unison(a, b)
(array([[2, 2],
[1, 1],
[3, 3]]), array([2, 1, 3]))
Sin embargo, esto se siente torpe, ineficiente y lento, y requiere hacer una copia de los arreglos; prefiero mezclarlos en su lugar, ya que serán bastante grandes.
¿Hay una mejor manera de hacerlo? Mis objetivos principales son una ejecución más rápida y un menor uso de memoria, pero un código elegante también sería bueno.
Otro pensamiento que tuve fue este:
def shuffle_in_unison_scary(a, b):
rng_state = numpy.random.get_state()
numpy.random.shuffle(a)
numpy.random.set_state(rng_state)
numpy.random.shuffle(b)
Esto funciona ... pero da un poco de miedo, ya que veo pocas garantías de que continuará funcionando; no parece el tipo de cosa que se garantiza que sobrevivirá a través de la versión numpy, por ejemplo.
Respuestas:
Su solución "aterradora" no me parece aterradora. Llamar
shuffle()
a dos secuencias de la misma longitud da como resultado la misma cantidad de llamadas al generador de números aleatorios, y estos son los únicos elementos "aleatorios" en el algoritmo aleatorio. Al restablecer el estado, se asegura de que las llamadas al generador de números aleatorios darán los mismos resultados en la segunda llamada ashuffle()
, por lo que todo el algoritmo generará la misma permutación.Si no le gusta esto, una solución diferente sería almacenar sus datos en una matriz en lugar de dos desde el principio, y crear dos vistas en esta matriz única simulando las dos matrices que tiene ahora. Puede usar la matriz única para barajar y las vistas para todos los demás fines.
Ejemplo: asumamos las matrices
a
yb
tengamos este aspecto:Ahora podemos construir una matriz única que contenga todos los datos:
Ahora creamos vistas simulando el original
a
yb
:Los datos de
a2
yb2
se comparten conc
. Para barajar ambas matrices simultáneamente, usenumpy.random.shuffle(c)
.En el código de producción, por supuesto, tratará de evitar crear el original
a
yb
crearlo de inmediatoc
,a2
yb2
.Esta solución podría adaptarse al caso
a
yb
tener diferentes tipos.fuente
numpy.random.shuffle()
opera en secuencias mutables arbitrarias, como listas de Python o matrices NumPy. La forma de la matriz no importa, solo la longitud de la secuencia. Es muy poco probable que esto cambie en mi opinión.Puede usar la indexación de matriz de NumPy :
Esto dará como resultado la creación de matrices separadas mezcladas al unísono.
fuente
>>> t = timeit.Timer(stmt = "<function>(a,b)", setup = "import numpy as np; a,b = np.arange(4), np.arange(4*20).reshape((4,20))")>>> t.timeit()
y obtuve 38 segundos para la versión del OP, y 27.5 segundos para la mía, para 1 millón de llamadas cada uno.a.shape
es(31925, 405)
yb.shape
es(31925,)
.Para obtener más información, consulte http://scikit-learn.org/stable/modules/generated/sklearn.utils.shuffle.html
fuente
Solución muy simple:
las dos matrices x, y ahora se mezclan aleatoriamente de la misma manera
fuente
James escribió en 2015 una solución sklearn que es útil. Pero agregó una variable de estado aleatorio, que no es necesaria. En el siguiente código, se supone automáticamente el estado aleatorio de numpy.
fuente
fuente
Mezcle cualquier número de matrices juntas, en el lugar, usando solo NumPy.
Y se puede usar así
Algunas cosas a tener en cuenta:
Después de la combinación aleatoria, los datos se pueden dividir utilizando
np.split
o referenciados mediante sectores, según la aplicación.fuente
RandomState
podría usarse fuera del bucle. Ver la respuesta defor
bucle es si reasignar o reiniciar el estado aleatorio. Dado que se espera que el número de matrices que se pasan a una función aleatoria sea pequeño, no esperaría una diferencia de rendimiento entre las dos. Pero sí, rstate podría asignarse fuera del ciclo y reiniciarse dentro del ciclo en cada iteración.puedes hacer una matriz como:
luego barajarlo:
ahora use esto como argumento de sus matrices. los mismos argumentos barajados devuelven los mismos vectores barajados.
fuente
Una forma de barajar en el lugar para listas conectadas es usar una semilla (podría ser aleatoria) y usar numpy.random.shuffle para barajar.
Eso es. Esto barajará tanto a como b exactamente de la misma manera. Esto también se hace en el lugar, lo que siempre es una ventaja.
EDITAR, no use np.random.seed () use np.random.RandomState en su lugar
Cuando lo llame, simplemente pase cualquier semilla para alimentar el estado aleatorio:
Salida:
Editar: código fijo para volver a sembrar el estado aleatorio
fuente
RandomState
cambia de estado en la primera llamada ya
yb
no se barajan al unísono.Hay una función bien conocida que puede manejar esto:
Solo establecer test_size en 0 evitará la división y le dará datos barajados. Aunque generalmente se usa para dividir el tren y probar datos, también los baraja.
De la documentación
fuente
Digamos que tenemos dos matrices: a y b.
Primero podemos obtener índices de fila permutando la primera dimensión
Luego use indexación avanzada. Aquí estamos usando los mismos índices para mezclar ambas matrices al unísono.
Esto es equivalente a
fuente
Si desea evitar copiar matrices, le sugiero que en lugar de generar una lista de permutación, revise todos los elementos de la matriz y lo cambie aleatoriamente a otra posición en la matriz.
Esto implementa el algoritmo aleatorio Knuth-Fisher-Yates.
fuente
len(a)
porreversed(range(1, len(a)))
. Pero no será muy eficiente de todos modos.Esto parece una solución muy simple:
fuente
Con un ejemplo, esto es lo que estoy haciendo:
fuente
combo = zip(images, labels); shuffle(combo); im, lab = zip(*combo)
, solo que más lento. Como está utilizando Numpy de todos modos, una solución mucho más rápida sería comprimir las matrices usando Numpycombo = np.c_[images, labels]
, barajar y descomprimir nuevamenteimages, labels = combo.T
. Asumiendo quelabels
yimages
son matrices unidimensionales de Numpy de la misma longitud para empezar, esta será fácilmente la solución más rápida. Si son multidimensionales, vea mi respuesta más arriba.Extendí random.shuffle () de python para tomar un segundo argumento:
De esa manera, puedo estar seguro de que la mezcla se realiza en el lugar y que la función no es demasiado larga o complicada.
fuente
Solo usa
numpy
...Primero combine las dos matrices de entrada. La matriz 1D son etiquetas (y) y la matriz 2D son datos (x) y las baraja con el
shuffle
método NumPy . Finalmente sepárelos y regrese.fuente