184 votes

Des réseaux ND aux réseaux 1D

Disons que j'ai un tableau a :

a = np.array([[1,2,3], [4,5,6]])

array([[1, 2, 3],
       [4, 5, 6]])

Je voudrais le convertir en un tableau 1D (c'est-à-dire un vecteur colonne) :

b = np.reshape(a, (1,np.product(a.shape)))

mais cela renvoie

array([[1, 2, 3, 4, 5, 6]])

ce qui n'est pas la même chose que :

array([1, 2, 3, 4, 5, 6])

Je peux prendre le premier élément de ce tableau pour le convertir manuellement en un tableau 1D :

b = np.reshape(a, (1,np.product(a.shape)))[0]

mais cela nécessite de connaître le nombre de dimensions du tableau d'origine (et de concaténer les [0] lorsque l'on travaille avec des dimensions supérieures).

Existe-t-il un moyen indépendant des dimensions d'obtenir un vecteur colonne/ligne à partir d'un ndarray arbitraire ?

344voto

unutbu Points 222216

Utilisez np.ravel (pour une vue 1D) ou np.ndarray.flatten (pour une copie 1D) ou np.ndarray.flat (pour un itérateur 1D) :

In [12]: a = np.array([[1,2,3], [4,5,6]])

In [13]: b = a.ravel()

In [14]: b
Out[14]: array([1, 2, 3, 4, 5, 6])

Notez que ravel() renvoie un view de a lorsque cela est possible. Ainsi, la modification b modifie également a . ravel() renvoie un view lorsque les éléments 1D sont contigus en mémoire, mais renverrait un copy si, par exemple, a ont été réalisées à partir du découpage d'un autre réseau en utilisant une taille d'étape non unitaire (par ex. a = x[::2] ).

Si vous voulez une copie plutôt qu'une vue, utilisez

In [15]: c = a.flatten()

Si vous voulez simplement un itérateur, utilisez np.ndarray.flat :

In [20]: d = a.flat

In [21]: d
Out[21]: <numpy.flatiter object at 0x8ec2068>

In [22]: list(d)
Out[22]: [1, 2, 3, 4, 5, 6]

29voto

NPE Points 169956
In [14]: b = np.reshape(a, (np.product(a.shape),))

In [15]: b
Out[15]: array([1, 2, 3, 4, 5, 6])

ou, tout simplement :

In [16]: a.flatten()
Out[16]: array([1, 2, 3, 4, 5, 6])

14voto

haku Points 855

Je voulais voir un résultat de référence des fonctions mentionnées dans les réponses, notamment d'unutbu .

Je tiens également à souligner que doc numpy recommander l'utilisation arr.reshape(-1) en cas de vue est préférable. (même si ravel est un peu plus rapide dans le résultat suivant)


TL;DR : np.ravel est le plus performant (de très peu).

Point de repère

Fonctions :

Version de numpy : '1.18.0'.

Temps d'exécution sur différents ndarray tailles

+-------------+----------+-----------+-----------+-------------+
|  function   |   10x10  |  100x100  | 1000x1000 | 10000x10000 |
+-------------+----------+-----------+-----------+-------------+
| ravel       | 0.002073 |  0.002123 |  0.002153 |    0.002077 |
| reshape(-1) | 0.002612 |  0.002635 |  0.002674 |    0.002701 |
| flatten     | 0.000810 |  0.007467 |  0.587538 |  107.321913 |
| flat        | 0.000337 |  0.000255 |  0.000227 |    0.000216 |
+-------------+----------+-----------+-----------+-------------+

Conclusion

ravel y reshape(-1) était cohérent et indépendant de la taille de ndarray. Cependant, ravel est un peu plus rapide, mais reshape offre une flexibilité dans le remodelage de la taille. (c'est peut-être pour cela que doc numpy recommande de l'utiliser à la place. Ou bien il peut y avoir des cas où reshape renvoie la vue et ravel ne le fait pas).
Si vous avez affaire à des ndarray de grande taille, l'utilisation de flatten peut causer un problème de performance. Nous vous recommandons de ne pas l'utiliser. Sauf si vous avez besoin d'une copie des données pour faire autre chose.

Code utilisé

import timeit
setup = '''
import numpy as np
nd = np.random.randint(10, size=(10, 10))
'''

timeit.timeit('nd = np.reshape(nd, -1)', setup=setup, number=1000)
timeit.timeit('nd = np.ravel(nd)', setup=setup, number=1000)
timeit.timeit('nd = nd.flatten()', setup=setup, number=1000)
timeit.timeit('nd.flat', setup=setup, number=1000)

6voto

Bikram Pandit Points 744

Pour obtenir la liste des tableaux de différentes tailles, utilisez ce qui suit :

import numpy as np

# ND array list with different size
a = [[1],[2,3,4,5],[6,7,8]]

# stack them
b = np.hstack(a)

print(b)

Sortie :

[1 2 3 4 5 6 7 8]

3voto

DINA TAKLIT Points 563

L'un des moyens les plus simples est d'utiliser flatten() comme cet exemple :

 import numpy as np

 batch_y =train_output.iloc[sample, :]
 batch_y = np.array(batch_y).flatten()

Mon tableau était comme ça :

    0
0   6
1   6
2   5
3   4
4   3
.
.
.

Après avoir utilisé flatten() :

array([6, 6, 5, ..., 5, 3, 6])

C'est aussi la solution des erreurs de ce type :

Cannot feed value of shape (100, 1) for Tensor 'input/Y:0', which has shape '(?,)'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X