J'ai deux tableaux numpy de formes différentes, mais avec la même longueur (dimension principale). Je veux mélanger chacun d'eux, de sorte que les éléments correspondants continuent de correspondre - c'est-à-dire les mélanger à l'unisson par rapport à leurs principaux indices.
Ce code fonctionne et illustre mes objectifs:
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
Par exemple:
>>> 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]))
Cependant, cela semble maladroit, inefficace et lent, et cela nécessite de faire une copie des tableaux - je préfère les mélanger en place, car ils seront assez grands.
Y a-t-il une meilleure façon de procéder? Une exécution plus rapide et une utilisation réduite de la mémoire sont mes principaux objectifs, mais un code élégant serait également bien.
Une autre pensée que j'avais était la suivante:
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)
Cela fonctionne ... mais c'est un peu effrayant, car je ne vois aucune garantie que cela continuera à fonctionner - cela ne ressemble pas au genre de chose qui est garantie de survivre à travers la version numpy, par exemple.
Réponses:
Votre solution "effrayante" ne me semble pas effrayante. L'appel
shuffle()
de deux séquences de même longueur entraîne le même nombre d'appels au générateur de nombres aléatoires, et ce sont les seuls éléments "aléatoires" de l'algorithme de lecture aléatoire. En réinitialisant l'état, vous vous assurez que les appels au générateur de nombres aléatoires donneront les mêmes résultats dans le deuxième appel àshuffle()
, de sorte que l'ensemble de l'algorithme générera la même permutation.Si vous n'aimez pas cela, une solution différente serait de stocker vos données dans un tableau au lieu de deux dès le début, et de créer deux vues dans ce tableau unique simulant les deux tableaux que vous avez maintenant. Vous pouvez utiliser le tableau unique pour le mélange et les vues à toutes autres fins.
Exemple: supposons les tableaux
a
etb
ressemblons à ceci:Nous pouvons maintenant construire un seul tableau contenant toutes les données:
Nous créons maintenant des vues simulant l'original
a
etb
:Les données de
a2
etb2
sont partagées avecc
. Pour mélanger les deux tableaux simultanément, utiliseznumpy.random.shuffle(c)
.Dans le code de production, vous essayez bien sûr d'éviter de créer l'original
a
et deb
créer tout de suitec
,a2
etb2
.Cette solution pourrait être adaptée au cas
a
etb
avoir des dtypes différents.la source
numpy.random.shuffle()
fonctionne sur des séquences mutables arbitraires, telles que les listes Python ou les tableaux NumPy. La forme du tableau n'a pas d'importance, seule la longueur de la séquence. Il est très peu probable que cela change à mon avis.Vous pouvez utiliser NumPy's indexation des tableaux :
Cela se traduira par la création de tableaux séparés mélangés à l'unisson.
la source
>>> 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()
et j'ai obtenu 38 secondes pour la version OP et 27,5 secondes pour la mienne, pour 1 million d'appels chacune.a.shape
est(31925, 405)
etb.shape
est(31925,)
.Pour en savoir plus, voir http://scikit-learn.org/stable/modules/generated/sklearn.utils.shuffle.html
la source
Solution très simple:
les deux tableaux x, y sont maintenant tous les deux mélangés au hasard de la même manière
la source
James a écrit en 2015 une solution sklearn qui est utile. Mais il a ajouté une variable d'état aléatoire, qui n'est pas nécessaire. Dans le code ci-dessous, l'état aléatoire de numpy est automatiquement supposé.
la source
la source
Mélangez n'importe quel nombre de tableaux ensemble, en place, en utilisant uniquement NumPy.
Et peut être utilisé comme ça
Quelques points à noter:
Après la lecture aléatoire, les données peuvent être divisées en utilisant
np.split
ou référencées en utilisant des tranches - selon l'application.la source
RandomState
pourrait être utilisé en dehors de la boucle. Voir la réponse d'for
boucle est de réaffecter ou de réamorcer un état aléatoire. Avec le nombre de tableaux passés dans une fonction de lecture aléatoire qui devrait être petit, je ne m'attendrais pas à une différence de performances entre les deux. Mais oui, rstate pourrait être assigné en dehors de la boucle et réamorcé à l'intérieur de la boucle à chaque itération.vous pouvez créer un tableau comme:
puis mélangez-le:
utilisez maintenant ce s comme argument de vos tableaux. les mêmes arguments mélangés renvoient les mêmes vecteurs mélangés.
la source
Une manière dont le brassage sur place peut être effectué pour les listes connectées consiste à utiliser une graine (elle peut être aléatoire) et à utiliser numpy.random.shuffle pour effectuer le brassage.
C'est tout. Cela va mélanger a et b exactement de la même manière. Cela se fait également sur place, ce qui est toujours un plus.
EDIT, n'utilisez pas np.random.seed () utilisez plutôt np.random.RandomState
Lorsque vous l'appelez, passez simplement une graine pour nourrir l'état aléatoire:
Production:
Edit: code fixe pour redéfinir l'état aléatoire
la source
RandomState
change d'état au premier appela
etb
n'est pas mélangé à l'unisson.Il existe une fonction bien connue qui peut gérer cela:
La simple définition de test_size sur 0 évitera le fractionnement et vous donnera des données mélangées. Bien qu'il soit généralement utilisé pour diviser les données de train et de test, il les mélange également.
De la documentation
la source
Disons que nous avons deux tableaux: a et b.
On peut d'abord obtenir des indices de lignes en permutant la première dimension
Utilisez ensuite l'indexation avancée. Ici, nous utilisons les mêmes indices pour mélanger les deux tableaux à l'unisson.
Cela équivaut à
la source
Si vous voulez éviter de copier des tableaux, je suggère qu'au lieu de générer une liste de permutation, vous parcouriez chaque élément du tableau et le permutiez au hasard à une autre position du tableau
Cela implémente l'algorithme de shuffle Knuth-Fisher-Yates.
la source
len(a)
parreversed(range(1, len(a)))
. Mais ce ne sera pas très efficace de toute façon.Cela semble être une solution très simple:
la source
Avec un exemple, voici ce que je fais:
la source
combo = zip(images, labels); shuffle(combo); im, lab = zip(*combo)
, juste plus lent. Comme vous utilisez de toute façon Numpy, une solution encore plus rapide serait de compresser les tableaux en utilisant Numpycombo = np.c_[images, labels]
, de mélanger et de décompresser à nouveauimages, labels = combo.T
. En supposant quelabels
etimages
sont unidimensionnels Les tableaux NumPy de la même longueur pour commencer, ce sera facilement la solution la plus rapide. S'ils sont multidimensionnels, voir ma réponse ci-dessus.J'ai étendu random.shuffle () de python pour prendre un deuxième argument:
De cette façon, je peux être sûr que le brassage se produit sur place et que la fonction n'est pas trop longue ou compliquée.
la source
Utilisez simplement
numpy
...Fusionnez d'abord les deux tableaux d'entrée. Le tableau 1D correspond aux étiquettes (y) et le tableau 2D correspond aux données (x) et les mélange avec la
shuffle
méthode NumPy . Enfin, divisez-les et revenez.la source