NumPy's Convolve verstehen

71

Bei der Berechnung eines einfachen gleitenden Durchschnitts numpy.convolvescheint dies die Aufgabe zu erfüllen.

Frage: Wie erfolgt die Berechnung bei Verwendung np.convolve(values, weights, 'valid')?

convolution product is only given for points where the signals overlap completelyWorauf beziehen sich die beiden Signale, wenn in den Dokumenten erwähnt ?

Wenn Erklärungen Beispiele und Abbildungen enthalten können, ist dies äußerst nützlich.

window = 10
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
Nyxynyx
quelle
numpy.convolve aus dem NumPy-Handbuch und die Referenzen unten erklären die Faltung und diese spezifische Implementierung sehr gut.
Rickhg12hs

Antworten:

158

Faltung ist ein mathematischer Operator, der hauptsächlich in der Signalverarbeitung verwendet wird. Numpy verwendet einfach diese Signalverarbeitungsnomenklatur, um sie zu definieren, daher die "Signal" -Referenzen. Ein Array in Numpy ist ein Signal. Die Faltung von zwei Signalen ist definiert als das Integral des ersten Signals, das umgekehrt , über das zweite Signal gewobbelt ("gefaltet auf") und an jeder Position überlappender Vektoren (mit dem Skalarprodukt) multipliziert wird. Das erste Signal wird oft als Kernel bezeichnet , insbesondere wenn es sich um eine 2D-Matrix in der Bildverarbeitung oder in neuronalen Netzen handelt und die Umkehrung zu einer Spiegelung in 2D (NICHT transponieren) wird. Es kann anhand der Animationen auf Wikipedia besser verstanden werden .

Faltungen haben je nach Kontext mehrere Definitionen. Einige beginnen die Faltung, wenn die Überlappung beginnt, während andere beginnen, wenn die Überlappung nur teilweise ist. Im "gültigen" Modus von numpy wird die Überlappung so angegeben, dass sie immer vollständig ist. Es wird als "gültig" bezeichnet, da jeder im Ergebnis angegebene Wert ohne Datenextrapolation erfolgt.

Wenn Ihr Array X beispielsweise eine Länge von 2 und Ihr Array Y eine Länge von 4 hat, erhalten Sie durch die Faltung von X auf Y im "gültigen" Modus ein Array mit der Länge 3.

Erster Schritt für X = [4 3]und Y = [1 1 5 5]:

[3 4]                   (X is reversed from [4 3] to [3 4], see note)
[1 1 5 5]
= 3 * 1 + 4 * 1 = 7

Hinweis: Wenn X nicht umgekehrt würde, würde die Operation als Kreuzkorrelation anstelle einer Faltung bezeichnet.

Zweiter Schritt:

  [3 4]
[1 1 5 5]
= 3 * 1 + 4 * 5 = 23

Dritter Schritt:

    [3 4]
[1 1 5 5]
= 3 * 5 + 4 * 5 = 35

Das Ergebnis der Faltung für den Modus "gültig" wäre dann [7 23 35].

Wenn die Überlappung als ein einzelner Datenpunkt angegeben wird (wie im Modus "voll"), hätte das Ergebnis ein Array der Länge 5 ergeben. Der erste Schritt ist:

[3 4]
  [1 1 5 5]
= 3 * undefined (extrapolated as 0) + 4 * 1 = 4

Und so weiter. Es gibt weitere Extrapolationsmodi.

Soravux
quelle
8
Nur um die Dinge zu klären: Der Vektor [2 3] wird in der erklärten Faltung als [3 2] gespiegelt. Das ist richtig. Wenn der Vektor nicht gespiegelt würde, würde die Operation als Kreuzkorrelation bezeichnet. Dies liegt an der mathematischen Definition der Faltung.
Soravux
Was ist mit dem gleichen Faltungsmodus?
Ramon Martinez
3
@RamonMartinez Dieser Modus wird in der Numpy-Dokumentation beschrieben . Grundsätzlich funktioniert es genau so, wie es für den "vollen" Modus hier erläutert wurde, aber die Ergebnisse werden (links und rechts gleichermaßen) abgeschnitten, um die gleiche Länge wie die längste Eingabe zu haben.
Soravux
3
Ich bin mir nicht sicher, warum dies noch nicht als richtige Antwort akzeptiert wurde.
Bombayquant
5
Das Beispiel ist für [4,3]als ersten Parameter np.convolve(), nicht [3,4] . Nach mathematischer Definition kehrt die Faltung den ersten Parameter um.
Soravux
0

Es ist auch bemerkenswert, dass der Kernel in dem Sinne "zentriert" ist, dass Indizes für den Kernel in Bezug auf das zentrale Element des Arrays genommen werden. Mit anderen Worten, für Arrays mit einem Index, der bei 0 beginnt (wie in Python), wird die Funktion B = np.convolve (A, K)berechnet

B [k] = \ sum_i A [i] K [k - i + m]

wo m = (len(K) - 1)//2 (ganzzahlige Division). Dies ist eine ganze Zahl, auch wenn sie gerade len(K)ist.

Die Summierung erfolgt nominal über alle Werte ivon -∞ bis ∞, wobei Werte Aaußerhalb des Bereichs gleich Null angenommen werden. Gleiches gilt für Werte des Kernels. Für np.convolution2Dmüssen Sie die Optionen Modus, Grenze und Füllwert verwenden, um anzugeben, wie Werte Aaußerhalb des Bereichs behandelt werden.

So erhalten Sie beispielsweise unterschiedliche Antworten für np.convolve(A, K)if K = np.array([1, 2, 3])oderK = np.array([1, 2, 3, 0, 0])

Richard Hartley
quelle