Coursera Learner working on a presentation with Coursera logo and
Coursera Learner working on a presentation with Coursera logo and

Einführung

Die Faltung ist eine mathematische Operation, die das Produkt integral aus 2 Funktionen (Signalen) macht, wobei eines der Signale auf dem Kopf steht. Zum Beispiel falten wir unten 2 f(t)- und g(t)-Signale.

Als erstes muss also das g-Signal horizontal (180 Grad) umgedreht werden und dann das g auf f umgedreht werden, wobei alle seine Werte multipliziert und akkumuliert werden.

Die Reihenfolge, in der die Signale gefaltet werden, hat keine Bedeutung für das Endergebnis, also conv(a,b)==conv(b,a)

In diesem Fall ist zu bedenken, dass das blaue Signal f(τ) unser Eingangssignal und g(t) unser Kernel ist, der Begriff Kernel wird verwendet, wenn Faltungen zur Filterung von Signalen verwendet werden.

Ausgangssignalgröße 1D

Im Falle der 1D-Faltung wird die Ausgabegröße auf diese Weise berechnet:

outputSize=(InputSize-KernelSize)+1

Anwendung von Convolutions

Menschen verwenden die Faltung zur Signalverarbeitung für die folgenden Anwendungsfälle:

Filterung von Signalen (1D-Audio, 2D-Bildverarbeitung)

Prüfen, wie sehr ein Signal mit einem anderen in Beziehung steht

Auffinden von Mustern in Signalen

Ein einfaches Beispiel in Matlab und Python (betäubt)

Unten sind zwei Signale x = (0,1,2,3,4) mit w = (1,-1,2).

Von Hand machen

Um das Konzept der Faltung besser zu verstehen, nehmen wir das obige Beispiel von Hand. Im Grunde werden wir 2 Signale (x,w) falten. Zuerst wird W horizontal gespiegelt (O nach links um 180 Grad gedreht)

Danach müssen wir das umgedrehte W über den Eingang X

Beachten Sie, dass in den Schritten 3,4,5 das invertierte Fenster vollständig innerhalb des Eingangssignals liegt. Diese Ergebnisse werden als “gültige” Faltungen bezeichnet. In den Fällen, in denen das invertierte Fenster nicht vollständig innerhalb des Eingangsfensters liegt (X), können wir sie als Null betrachten, oder wir können berechnen, was berechnet werden kann, z.B. in Schritt 1 multiplizieren wir 1 mit Null und der Rest wird einfach ignoriert.

Auffüllen der Eingabe

Um die Größe des Faltungsergebnisses gleich der Größe der Eingabe zu halten und um einen Effekt namens zirkuläre Faltung zu vermeiden, füllen wir das Signal mit Nullen auf.

Wo Sie die Nullen anbringen, hängt davon ab, was Sie tun möchten, d.h.: im 1D-Fall können Sie sie an jedem Ende verknüpfen, aber im 2D-Fall platzieren Sie sie normalerweise um das Originalsignal herum.

Auf Matlab können Sie den Befehl ‘padarray’ verwenden, um die Eingabe aufzufüllen:

>> x

x(:,:,1) =

1 1 0 2 0

2 2 2 2 1

0 0 0 2 1

2 2 2 2 1

2 0 2 2 1

x(:,:,2) =

2 1 0 0 0

0 2 0 1 0

1 0 1 2 0

1 2 0 2 1

1 2 1 2 2

x(:,:,3) =

2 1 1 2 2

1 1 1 0 0

2 0 1 0 2

0 2 0 2 1

0 0 2 1 0

>> padarray(x,[1 1 1])

ans(:,:,1) =

0 0 0 0 0 0 0

0 1 1 0 2 0 0

0 2 2 2 2 1 0

0 0 0 0 2 1 0

0 2 2 2 2 1 0

0 2 0 2 2 1 0

0 0 0 0 0 0 0

ans(:,:,2) =

0 0 0 0 0 0 0

0 2 1 0 0 0 0

0 0 2 0 1 0 0

0 1 0 1 2 0 0

0 1 2 0 2 1 0

0 1 2 1 2 2 0

0 0 0 0 0 0 0

ans(:,:,3) =

0 0 0 0 0 0 0

0 2 1 1 2 2 0

0 1 1 1 0 0 0

0 2 0 1 0 2 0

0 0 2 0 2 1 0

0 0 0 2 1 0 0

0 0 0 0 0 0 0

Ausgabegröße für 2D

Informieren Sie sich bitte über den Umfang unserer Ausgabe, nachdem wir einige Faltungsoperationen daran durchgeführt haben. Glücklicherweise gibt es eine praktische Formel, die uns genau dies sagt.

Wenn wir die Faltung einer Eingabe mit räumlichen Dimensionen [H, W], die mit P aufgefüllt wird, mit einem quadratischen Kern der Größe F und unter Verwendung der Schrittweite S betrachten, dann ist die Ausgabegröße der Faltung definiert als

outputSizeW=(W-F+2P)/S+1 outputSizeH=(H-F+2P)/S+1 output

F ist die Größe des Kerns, wir verwenden normalerweise quadratische Kerne, also ist F sowohl die Breite als auch die Höhe des Kerns

Implementierung der Faltungsoperation

Im folgenden Beispiel handelt es sich um eine 5x5x3 Eingabe (LxHx3), mit einem Conv-Level mit den folgenden Parametern Stride=2, Pad=1, F=3 (3×3 Kernel) und K=2 (zwei Filter).

Unsere Eingabe hat 3 Kanäle, daher benötigen wir eine 3x3x3-Kernel-Gewichtung. Wir haben 2 Filter (K=2), so dass wir am Ende 2 Ausgangsaktivierungen haben werden. Weiter können wir die Größe dieser beiden Ausgänge berechnen, um zu sein: (5 – 3 + 2)/2 + 1 = 3.

Dieser untenstehende Code (Vanille-Version) kann im wirklichen Leben nicht verwendet werden, weil er langsam sein wird, aber er ist gut für ein grundlegendes Verständnis. In der Regel werden tiefe Lernbibliotheken die Faltung als Einzelmatrix-Multiplikation mit der im2col/col2im-Methode durchführen.

%% Faltung n Dimensionen

% Der folgende Code ist nur eine Erweiterung von conv2d_vanila für n Dimensionen.

% Parameter:

% Eingabe: H x B x Tiefe

% K: Kern F x F x Tiefe

% S: schreiten (Wie viele Pixel wird das Fenster auf der Eingabe gleiten)

% Diese Implementierung ist wie der ‘gültige’ Parameter bei normaler Faltung

Funktion outConv = convn_vanilla(Eingabe, Kernel, S)

% Ermittelt die Eingabegröße in Form von Zeilen und Spalten. Die Gewichte sollten

% gleiche Tiefe wie das Eingangsvolumen (Bild)

[rowsIn, colsIn, ~] = Größe(Eingabe);

% Volumendimensio erhalten

depthInput = ndims(eingabe);

% Ermittelt die Kernelgröße, wobei ein quadratischer Kernel immer

F = Größe(Kernel,1);

%% Ausgaben initialisieren

sizeRowsOut = ((rowsIn-F)/S) + 1;

sizeColsOut = ((colsIn-F)/S) + 1;

outConvAcc = Nullen(sizeRowsOut , sizeColsOut, depthInput);

%% Führen Sie die Faltung aus

% Jeden Kanal auf der Eingabe mit seinem jeweiligen Kernel-Kanal falten,

% am Ende die Summe aller Kanalergebnisse.

für Tiefe=1:TiefeEingabe

% Auswahl des Eingangs- und Kernelstromkanals

inputCurrDepth = input(:,:,Tiefe);

kernelCurrDepth = kernel(:,::,Tiefe);

% Iterieren Sie in jeder Zeile und Spalte, (unter Verwendung von stride)

für r=1:S:(rowsIn-1)

für c=1:S:(colsIn-1)

% Vermeiden Sie Stichproben aus dem Bild.

wenn (((c+F)-1) <= colsIn) && (((r+F)-1) <= rowsIn)

% Auswahlfenster auf Eingangsvolumen (Patch)

sampleWindow = inputCurrDepth(r:(r+F)-1,c:(c+F)-1);

% Do das Punktprodukt

dotProd = Summe(sampleWindow(:) .* kernelCurrDepth(:));

% Ergebnis speichern

outConvAcc(ceil(r/S),ceil(c/S),depth) = dotProd;

Ende

Ende

Ende

Ende

% Summenelemente über die Dimension des Eingangsvolumens (Summe aller Kanäle)

outConv = Summe(outConvAcc,depthInput);

Ende