Ich versuche, jeden der Begriffe in einem 2D-Array mit den entsprechenden Begriffen in einem 1D-Array zu multiplizieren. Dies ist sehr einfach, wenn ich jede Spalte mit dem 1D-Array multiplizieren möchte, wie in der Funktion numpy.multiply gezeigt . Aber ich möchte das Gegenteil tun und jeden Begriff in der Reihe multiplizieren. Mit anderen Worten, ich möchte multiplizieren:
[1,2,3] [0]
[4,5,6] * [1]
[7,8,9] [2]
und bekomme
[0,0,0]
[4,5,6]
[14,16,18]
aber stattdessen bekomme ich
[0,2,6]
[0,5,12]
[0,8,18]
Weiß jemand, ob es einen eleganten Weg gibt, dies mit Numpy zu tun? Vielen Dank, Alex
A * B
Sie tun müssten,A * B[...,None]
was transponiert,B
indem Sie eine neue Achse hinzufügen (None
).x = [[1],[2],[3]]
oder so.Antworten:
Normale Multiplikation wie Sie gezeigt haben:
>>> import numpy as np >>> m = np.array([[1,2,3],[4,5,6],[7,8,9]]) >>> c = np.array([0,1,2]) >>> m * c array([[ 0, 2, 6], [ 0, 5, 12], [ 0, 8, 18]])
Wenn Sie eine Achse hinzufügen, wird diese wie gewünscht multipliziert:
>>> m * c[:, np.newaxis] array([[ 0, 0, 0], [ 4, 5, 6], [14, 16, 18]])
Sie können auch zweimal transponieren:
>>> (m.T * c).T array([[ 0, 0, 0], [ 4, 5, 6], [14, 16, 18]])
quelle
[a,b] op [c,d] -> [[a*c, b*c], [a*d, b*d]]
.Ich habe die verschiedenen Optionen für die Geschwindigkeit verglichen und festgestellt, dass - sehr zu meiner Überraschung - alle Optionen (außer
diag
) gleich schnell sind. Ich persönlich benutzeA * b[:, None]
(oder
(A.T * b).T
) weil es kurz ist.Code zur Reproduktion der Handlung:
import numpy import perfplot def newaxis(data): A, b = data return A * b[:, numpy.newaxis] def none(data): A, b = data return A * b[:, None] def double_transpose(data): A, b = data return (A.T * b).T def double_transpose_contiguous(data): A, b = data return numpy.ascontiguousarray((A.T * b).T) def diag_dot(data): A, b = data return numpy.dot(numpy.diag(b), A) def einsum(data): A, b = data return numpy.einsum("ij,i->ij", A, b) perfplot.save( "p.png", setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)), kernels=[ newaxis, none, double_transpose, double_transpose_contiguous, diag_dot, einsum, ], n_range=[2 ** k for k in range(14)], logx=True, logy=True, xlabel="len(A), len(b)", )
quelle
Sie können auch die Matrixmultiplikation (auch als Punktprodukt bezeichnet) verwenden:
a = [[1,2,3],[4,5,6],[7,8,9]] b = [0,1,2] c = numpy.diag(b) numpy.dot(c,a)
Was eleganter ist, ist wahrscheinlich Geschmackssache.
quelle
dot
ist hier wirklich übertrieben. Sie machen nur unnötige Multiplikation mit 0 und Additionen zu 0.diag
Matrix viel Speicher .Noch ein Trick (ab v1.6)
A=np.arange(1,10).reshape(3,3) b=np.arange(3) np.einsum('ij,i->ij',A,b)
Ich beherrsche die Numpy Broadcasting (
newaxis
), finde mich aber immer noch in diesem neueneinsum
Tool zurecht . Also musste ich ein bisschen herumspielen, um diese Lösung zu finden.Timings (mit Ipython timeit):
einsum: 4.9 micro transpose: 8.1 micro newaxis: 8.35 micro dot-diag: 10.5 micro
Übrigens erzeugt das Ändern von a
i
zuj
,np.einsum('ij,j->ij',A,b)
die Matrix, die Alex nicht will. Undnp.einsum('ji,j->ji',A,b)
macht tatsächlich die doppelte Transponierung.quelle
einsumm
(25 Mikro) ist doppelt so schnell wie die anderen (Punktdiag verlangsamt sich mehr). Dies ist np 1.7, frisch kompiliert mit 'libatlas3gf-sse2' und 'libatlas-base-dev' (Ubuntu 10.4, Einzelprozessor).timeit
gibt das Beste aus 10000 Schleifen.numpy
Versionen zurück.Für diese verlorenen Seelen bei Google funktioniert die Verwendung von
numpy.expand_dims
thennumpy.repeat
und auch in höherdimensionalen Fällen (dh Multiplizieren einer Form (10, 12, 3) mit a (10, 12)).>>> import numpy >>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]]) >>> b = numpy.array([0,1,2]) >>> b0 = numpy.expand_dims(b, axis = 0) >>> b0 = numpy.repeat(b0, a.shape[0], axis = 0) >>> b1 = numpy.expand_dims(b, axis = 1) >>> b1 = numpy.repeat(b1, a.shape[1], axis = 1) >>> a*b0 array([[ 0, 2, 6], [ 0, 5, 12], [ 0, 8, 18]]) >>> a*b1 array([[ 0, 0, 0], [ 4, 5, 6], [14, 16, 18]])
quelle
Warum tust du es nicht einfach?
>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]]) >>> c = np.array([0,1,2]) >>> (m.T * c).T
??
quelle