2016-07-29 16 views
5

Ich habe eine 2D-Array v, v.shape=(M_1,M_2), die ich mit v.shape=(M_2,N_1,N_2) in einen 3D-Array neu zu gestalten mag, und M_1=N_1*N_2.Python Ravel vs. transponieren, wenn in reshape verwendet

kam ich mit den folgenden Zeilen auf, die das gleiche Ergebnis:

np.reshape(v.T, reshape_tuple) 

und

np.reshape(v.ravel(order='F'), reshape_tuple) 

für reshape_tuple=(M_2,N_1,N_2).

Welcher ist rechnerisch besser und in welchem ​​Sinn (Zeit, Speicher usw.), wenn das Original v eine riesige (möglicherweise komplexwertige) Matrix ist?

Meine Vermutung wäre, dass die Transponierung Verwendung ist besser, aber wenn reshape tut eine automatisches ravel dann vielleicht die Ravel-Option ist schneller (obwohl reshape könnte die ravel in C oder Fortran tun und es ist dann nicht klar)?

Antwort

3

Die Reihenfolge, in der sie Dinge tun - umformen, Schritte ändern und eine Kopie erstellen - unterscheidet sich, aber sie machen dasselbe.

Ich möchte __array_interface__ verwenden, um zu sehen, wo sich der Datenpuffer befindet, und andere Änderungen. Ich nehme an, ich sollte die flags hinzufügen, um die order zu sehen. Aber wir/Sie wissen, dass transpose die Reihenfolge bereits auf F ändert, oder?

In [549]: x=np.arange(6).reshape(2,3) 
In [550]: x.__array_interface__ 
Out[550]: 
{'data': (187732024, False), 
'descr': [('', '<i4')], 
'shape': (2, 3), 
'strides': None, 
'typestr': '<i4', 
'version': 3} 

Transponierte ist eine Ansicht, mit unterschiedlicher Form, Schritten und Reihenfolge:

In [551]: x.T.__array_interface__ 
Out[551]: 
{'data': (187732024, False), 
'descr': [('', '<i4')], 
'shape': (3, 2), 
'strides': (4, 12), 
'typestr': '<i4', 
'version': 3} 

Ravel mit anderen Reihenfolge ist eine Kopie (verschiedene Datenpufferzeiger)

In [552]: x.ravel(order='F').__array_interface__ 
Out[552]: 
{'data': (182286992, False), 
'descr': [('', '<i4')], 
'shape': (6,), 
'strides': None, 
'typestr': '<i4', 
'version': 3} 

Transponierte Ravel ist auch eine Kopie. Ich denke, der gleiche Datenzeiger ist nur ein Fall von Speicherwiederverwendung (da ich nicht zu einer Variablen zuweisen) - aber das kann überprüft werden.

In [553]: x.T.ravel().__array_interface__ 
Out[553]: 
{'data': (182286992, False), 
'descr': [('', '<i4')], 
'shape': (6,), 
'strides': None, 
'typestr': '<i4', 
'version': 3} 

fügen Sie den reshape:

In [554]: x.T.ravel().reshape(2,3).__array_interface__ 
Out[554]: 
{'data': (182286992, False), 
'descr': [('', '<i4')], 
'shape': (2, 3), 
'strides': None, 
'typestr': '<i4', 
'version': 3} 
In [555]: x.ravel(order='F').reshape(2,3).__array_interface__ 
Out[555]: 
{'data': (182286992, False), 
'descr': [('', '<i4')], 
'shape': (2, 3), 
'strides': None, 
'typestr': '<i4', 
'version': 3} 

Ich denke, es gibt eine implizite 'ravel' in reshape:

In [558]: x.T.reshape(2,3).__array_interface__ 
Out[558]: 
{'data': (182286992, False), 
'descr': [('', '<i4')], 
'shape': (2, 3), 
'strides': None, 
'typestr': '<i4', 
'version': 3} 

(ich sollte diese Beispiele überarbeiten dieses Speichers Wiederverwendung Mehrdeutigkeit loszuwerden .) In jedem Fall erfordert die Umformung nach der Transponierung die gleiche Speicherkopie, die ein Umbruch mit der Reihenfolgeänderung ausführt. Und soweit ich das beurteilen kann, ist nur eine Kopie für jeden Fall erforderlich. Die anderen Operationen beinhalten nur Änderungen an Attributen wie Form.

Kann sein, es klarer ist, wenn wir auf den Feldern sehen nur

In [565]: x.T 
Out[565]: 
array([[0, 3], 
     [1, 4], 
     [2, 5]]) 

Im T wir noch durch das Array in numerischer Reihenfolge treten kann. Aber nach der Umformung ist die 1 nicht irgendwo in der Nähe der 0. Offensichtlich gab es eine Kopie.

In [566]: x.T.reshape(2,3) 
Out[566]: 
array([[0, 3, 1], 
     [4, 2, 5]]) 

die Reihenfolge der Werte nach dem Ravel ähnlich sieht, und mehr offensichtlich so nach reshape.

In [567]: x.ravel(order='F') 
Out[567]: array([0, 3, 1, 4, 2, 5]) 
In [568]: x.ravel(order='F').reshape(2,3) 
Out[568]: 
array([[0, 3, 1], 
     [4, 2, 5]]) 
+0

OK Ich sehe, so scheint es wirklich wie es ist egal, was ich wähle. Vielen Dank! –

+0

Interessanterweise zeigte das Timing, dass np.reshape (v.T, reshape_tuple) viel schneller ist als np.reshape (v.ravel (order = 'F'), reshape_tuple). –

+0

Vielleicht ist das 'reshape_tuple' so, dass' np.reshape (v.T, reshape_tuple) 'nicht kopiert werden muss. Das heißt, die neue Form ist mit der transponierten Form kompatibel. Ich würde das '__array_interface__' überprüfen. – hpaulj