[PYTHON] Einführung in Deep Learning ~ Falten und Pooling ~

Zielperson

Der vorherige Artikel war hier DNN (Deep Neural Network) ist zum letzten Mal abgeschlossen. (Ich habe vor, in einem anderen Artikel mit DNN zu spielen, einschließlich der Verwendung des Ebenenmanagers.) Hier erstellen wir ein CNN (Convolutional Neural Network) zur Bilderkennung. Die hier verwendeten Funktionen im2col und col2im sind hier und hier. ) Ist vorgestellt. Der nächste Artikel ist hier

Inhaltsverzeichnis

Faltschicht

Ein Prozess namens ** Faltung ** bietet einen großen Vorteil für die Bilderkennung. Als Einführung gilt für Daten wie Bilder, bei denen die Positionsbeziehung wichtig zu sein scheint, das einfache Glätten in ein neuronales Netzwerk in einer Dimension und das Fließen wie das Wegwerfen der wichtigen Informationen der Positionsbeziehung, was eine Verschwendung ist. Es ist wie es ist. Die Rolle der Faltungsschicht besteht darin, Daten durch das neuronale Netzwerk zu fließen, während die Eingabedimension beibehalten wird, dh wichtige Informationen wie Positionsbeziehungen beibehalten werden. filter_image.gif Für die Faltungsschicht entspricht dieser Filter dem Gewicht in einer normalen Schicht. Danach können Sie den Code schreiben, der gemäß diesem GIF funktioniert. Wenn Sie ihn jedoch so implementieren, wie er ist, handelt es sich um einen schweren Code, der nicht praktikabel ist. Denn wenn Sie diesen GIF-Teil vereinfachen und implementieren

Image = I_h×I_Array von w
Filter = F_h×F_Array von w
Output = O_h×O_Array von w
for h in range(O_h):
    h_lim = h + F_h
    for w in range(O_w):
        w_lim = w + F_w
        Output[h, w] = Image[h:h_lim, w:w_lim] * Filter

Es wird so, als würde man in einer Doppelschleife auf das numpy-Array zugreifen, das Elementprodukt auf den entsprechenden Teil der Eingabe anwenden und das Ergebnis in der Ausgabe speichern. Darüber hinaus ist diese Schleife, hier eine Doppelschleife, eine Vierfachschleife, da die tatsächliche Eingabe vierdimensional ist. Es ist leicht vorstellbar, dass die Anzahl der Schleifen schnell zunimmt. Da numpy die Spezifikation hat, dass es langsam ist, wenn Sie mit der Anweisung for darauf zugreifen, möchten Sie den Zugriff in einer Schleife so weit wie möglich vermeiden. Hier kommt die im2col Funktion ins Spiel. Das vorherige GIF ist

a = 1W + 2X + 5Y + 6Z \\
b = 2W + 3X + 6Y + 7Z \\
c = 3W + 4X + 7Y + 8Z \\
d = 5W + 6X + 9Y + 10Z \\
e = 6W + 7X + 10Y + 11Z \\
f = 7W + 8X + 11Y + 12Z \\
g = 9W + 10X + 13Y + 14Z \\
h = 10W + 11X + 14Y + 15Z \\
i = 11W + 12X + 15Y + 16Z

Es ist so, aber wenn Sie dies als Matrixprodukt ausdrücken

\left(
  \begin{array}{c}
    a \\
    b \\
    c \\
    d \\
    e \\
    f \\
    g \\
    h \\
    i
  \end{array}
\right)^{\top}
=
\left(
  \begin{array}{cccc}
    W & X & Y & Z
  \end{array}
\right)
\left(
  \begin{array}{ccccccccc}
    1 & 2 & 3 & 5 & 6 & 7 & 9 & 10 & 11 \\
    2 & 3 & 4 & 6 & 7 & 8 & 10 & 11 & 12 \\
    5 & 6 & 7 & 9 & 10 & 11 & 13 & 14 & 15 \\
    6 & 7 & 8 & 10 & 11 & 12 & 14 & 15 & 16
  \end{array}
\right)

Es wird sein. Die im2col Funktion ist eine Funktion zum Konvertieren eines Eingabebildes oder Filters in eine Matrix wie diese. Weitere Informationen finden Sie unter hier. Übrigens kann mit dieser im2col -Funktion das obige Problem erheblich gelöst werden. Wenn jedoch die Funktion "im2col" verwendet wird, ist die Form der ursprünglichen Eingabe natürlich unterschiedlich, sodass das Lernen mit der Fehlerrückvermehrungsmethode nicht so fortgesetzt werden kann, wie sie ist. Daher ist es notwendig, die "col2im" -Funktion zu beißen, die zum Zeitpunkt der Rückausbreitung die entgegengesetzte Operation ausführt. Weitere Informationen finden Sie unter hier.

Bisher habe ich den Umriss der Faltschicht kurz erklärt, daher zeige ich Ihnen die Konstruktionszeichnung. conv_layer.png

Vorwärtsausbreitung der gefalteten Schicht

Beginnen wir mit der Vorwärtsausbreitung. Der relevante Teil ist der Farbteil in der folgenden Abbildung. conv_layer_forward.png Operativ

  1. Werfen Sie das Eingabebild in die Funktion "im2col"
  2. Berechnen Sie das Matrixprodukt aus dem Rückgabewert und dem Filter (transformiert).
  3. Addieren Sie den Ausgang von 2. und die Vorspannung
  4. Übergeben Sie die Aktivierungsfunktion

Die Grundoperation ist dieselbe wie die Vorwärtsausbreitung eines normalen neuronalen Netzwerks. Der einzige Unterschied besteht darin, dass Sie die Funktion "im2col" davor stellen. Lass uns genauer hinschauen. Erstens ist die Faltungsoperation wie in der folgenden Abbildung gezeigt. conv_filtering.png Vorspannung wird weggelassen. Die Eingabe ist ein Tensor mit der Stapelgröße $ B $, der Anzahl der Kanäle $ C $ und der Bildgröße $ (I_h, I_w) $. Es gibt $ M $ Filter für jeden Kanal, der die gleiche Anzahl von Kanälen wie der Eingang hat und ein Tensor mit einer Filtergröße von $ (F_h, F_w) $ ist. Der jedem Eingangskanal entsprechende Kanalfilter wird nach allen Chargendaten gefiltert, was zu einem Tensor mit der Form $ (B, M, O_h, O_w) $ führt. Mal sehen, wie man diesen Prozess konkret macht. Verarbeiten Sie die Eingänge und Filter wie in der folgenden Abbildung gezeigt. input_im2col.png filter_reshape.png Infolgedessen kann der 4-dimensionale Tensor in 2 Dimensionen fallen gelassen werden, und Matrixprodukte können durchgeführt werden. convolution.png Fügen Sie dieser Ausgabe eine Vorspannung hinzu (Form ist eine zweidimensionale Matrix von $ (M, 1) $). Verwenden Sie zu diesem Zeitpunkt die Broadcast-Funktion von "numpy", um allen Spalten den gleichen Wert hinzuzufügen. Danach wird dieser Ausgang transformiert und die Dimensionen werden ausgetauscht, um den Ausgangstensor zu erhalten. output_reshape_transpose.png Wirf diesen Ausgangstensor in die Aktivierungsfunktion, um die Vorwärtsausbreitung der Faltungsschicht zu vervollständigen.

Rückausbreitung der gefalteten Schicht

Als nächstes kommt die Rückausbreitung. Der zugehörige Teil ist der Farbteil in der folgenden Abbildung. conv_layer_backward.png Als Operation

  1. Nehmen Sie das Elementprodukt des Ausgangsgradienten und die Differenzierung der Aktivierungsfunktion
  2. Einer wird als Vorspannungsgradient verwendet
  3. Das Matrixprodukt mit dem durch die Funktion "im2col" geführten Eingabebild wird als Gradient des Filters verwendet.
  4. Das Matrixprodukt mit dem Filter wird als Eingabegradient über die Funktion col2im verwendet.

Es ist wie es ist. Lass uns genauer hinschauen. grad_transpose_reshape.png Der propagierte Gradient ist ein Tensor von $ (B, M, O_h, O_w) $. Transformieren Sie zunächst diesen Gradienten in umgekehrter Reihenfolge der Vorwärtsausbreitung. grad_w.png grad_w_reshape.png Die Steigung zum Filter wird als Produkt aus Steigung und Eingangsmatrix berechnet. Da das resultierende Ergebnis eine zweidimensionale Matrix ist, kann sie in einen vierdimensionalen Tensor mit der gleichen Form wie der Filter umgewandelt werden. grad_b.png Der Schlüssel zum zu verzerrenden Gradienten besteht darin, allen Spalten während der Vorwärtsausbreitung den gleichen Wert hinzuzufügen. Das Hinzufügen des gleichen Werts zu mehreren Elementen zeigt, dass dies einem Netzwerk entspricht, das wie in der folgenden Abbildung dargestellt geformt ist. broadcast.png (Die Nummer ist angemessen) Daher ist $ axis = 1 $, dh die Rückausbreitung wird von jeder Spaltenrichtung in Richtung einer Vorspannung durchgeführt, und die Summe davon ist der Gradient zur Vorspannung. grad_x.png Der Gradient zur Eingabe wird durch das Matrixprodukt des Filters und den Gradienten berechnet. Wie Sie anhand des Tensors des Berechnungsergebnisses sehen können, entspricht dies dem Ergebnis des Werfens des Eingangstensors auf die Funktion "im2col", wenn sich die Form vorwärts ausbreitet. Wenn Sie dies in die Funktion "col2im" werfen, die das Gegenteil bewirkt, entsteht ein Gradiententensor für die Eingabe. grad_x_col2im.png Dies vervollständigt die Rückausbreitung der Faltungsschicht.

Faltschicht lernen

Nun, Sie müssen den Filter nicht jedes Mal umwandeln. Sie müssen es am Anfang nur einmal tun. Der Grund ist, dass "der Filter sich jedes Mal gleich verformt, so dass es nicht erforderlich ist, ihn zu wiederholen." Der Filter bleibt wie nach der ersten Transformation, was bedeutet, dass der durch Backpropagation berechnete Gradient zum Filter ebenfalls nicht transformiert werden muss. Als solches hat das Lernen der Faltungsschicht die gleiche Form wie die normale Schicht. update_filter_reshape.png update_filter_backward.png

Faltschichtmontage

Also werde ich es umsetzen. Ein wenig Einfallsreichtum ist jedoch erforderlich, um den "BaseLayer" zu erben.

conv.py

conv.py


import numpy as np


class ConvLayer(BaseLayer):
    def __init__(self, *, I_shape=None, F_shape=None,
                 stride=1, pad="same",
                 name="", wb_width=5e-2,
                 act="ReLU", opt="Adam",
                 act_dic={}, opt_dic={}, **kwds):
        self.name = name
        
        if I_shape is None:
            raise KeyError("Input shape is None.")
        if F_shape is None:
            raise KeyError("Filter shape is None.")
        
        if len(I_shape) == 2:
            C, I_h, I_w = 1, *I_shape
        else:
            C, I_h, I_w = I_shape
        self.I_shape = (C, I_h, I_w)
        
        if len(F_shape) == 2:
            M, F_h, F_w = 1, *F_shape
        else:
            M, F_h, F_w = F_shape
        self.F_shape = (M, C, F_h, F_w)
        
        if isinstance(stride, tuple):
            stride_ud, stride_lr = stride
        else:
            stride_ud = stride
            stride_lr = stride
        self.stride = (stride_ud, stride_lr)
        
        if isinstance(pad, tuple):
            pad_ud, pad_lr = pad
        elif isinstance(pad, int):
            pad_ud = pad
            pad_lr = pad
        elif pad == "same":
            pad_ud = 0.5*((I_h - 1)*stride_ud - I_h + F_h)
            pad_lr = 0.5*((I_w - 1)*stride_lr - I_w + F_w)
        self.pad = (pad_ud, pad_lr)
        
        O_h = get_O_shape(I_h, F_h, stride_ud, pad_ud)
        O_w = get_O_shape(I_w, F_w, stride_lr, pad_lr)
        self.O_shape = (M, O_h, O_w)
        
        self.n = np.prod(self.O_shape)
        
        #Stellen Sie Filter und Vorspannung ein
        self.w = wb_width*np.random.randn(*self.F_shape).reshape(M, -1).T
        self.b = wb_width*np.random.randn(M)
        
        #Aktivierungsfunktion(Klasse)Erhalten
        self.act = get_act(act, **act_dic)

        #Optimierer(Klasse)Erhalten
        self.opt = get_opt(opt, **opt_dic)
    
    
    def forward(self, x):
        B = x.shape[0]
        M, O_h, O_w = self.O_shape
        
        x, _, self.pad_state = im2col(x, self.F_shape,
                                      stride=self.stride,
                                      pad=self.pad)
        super().forward(x.T)
        return self.y.reshape(B, O_h, O_w, M).transpose(0, 3, 1, 2)
    
    
    def backward(self, grad):
        B = grad.shape[0]
        I_shape = B, *self.I_shape
        M, O_h, O_w = self.O_shape
        
        grad = grad.transpose(0, 2, 3, 1).reshape(-1, M)
        super().backward(grad)
        self.grad_x = col2im(self.grad_x.T, I_shape, self.O_shape,
                             stride=self.stride, pad=self.pad_state)
        return self.grad_x

Ich werde erklären, welchen Bereich Sie planen. Wenn Sie es wie oben beschrieben ohne Einfallsreichtum implementieren, wird es wie folgt aussehen.

Kein Einfallsreichtum ver.

conv.py


import numpy as np


class ConvLayer(BaseLayer):
    def __init__(self, *, I_shape=None, F_shape=None,
                 stride=1, pad="same",
                 name="", wb_width=5e-2,
                 act="ReLU", opt="Adam",
                 act_dic={}, opt_dic={}, **kwds):
        self.name = name
        
        if I_shape is None:
            raise KeyError("Input shape is None.")
        if F_shape is None:
            raise KeyError("Filter shape is None.")
        
        if len(I_shape) == 2:
            C, I_h, I_w = 1, *I_shape
        else:
            C, I_h, I_w = I_shape
        self.I_shape = (C, I_h, I_w)
        
        if len(F_shape) == 2:
            M, F_h, F_w = 1, *F_shape
        else:
            M, F_h, F_w = F_shape
        self.F_shape = (M, C, F_h, F_w)
        
        _, O_shape, self.pad_state = im2col(np.zeros((1, *self.I_shape)), self.F_shape,
                                            stride=stride, pad=pad)
        self.O_shape = (M, *O_shape)
        self.stride = stride
        
        self.n = np.prod(self.O_shape)
        
        #Stellen Sie Filter und Vorspannung ein
        self.w = wb_width*np.random.randn(*self.F_shape).reshape(M, -1)
        self.b = wb_width*np.random.randn(M, 1)
        
        #Aktivierungsfunktion(Klasse)Erhalten
        self.act = get_act(act, **act_dic)

        #Optimierer(Klasse)Erhalten
        self.opt = get_opt(opt, **opt_dic)


    def forward(self, x):
        B = x.shape[0]
        M, O_h, O_w = self.O_shape

        self.x, _, self.pad_state = im2col(x, self.F_shape,
                                           stride=self.stride,
                                           pad=self.pad)
        
        self.u = [email protected] + self.b
        self.u = self.u.reshape(M, B, O_h, O_w).transpose(1, 0, 2, 3)
        self.y = self.act.forward(self.u)
        
        return self.y
    
    
    def backward(self, grad):
        B = grad.shape[0]
        I_shape = B, *self.I_shape
        _, O_h, O_w = self.O_shape
        
        dact = grad*self.act.backward(self.u, self.y)
        dact = dact.transpose(1, 0, 2, 3).reshape(M, -1)
        self.grad_w = [email protected]
        self.grad_b = np.sum(dact, axis=1).reshape(M, 1)
        self.grad_x = self.w.T@dact
        self.grad_x = col2im(self.grad_x, I_shape, self.O_shape,
                             stride=self.stride, pad=self.pad_state)
        
        return self.grad_x

Schauen wir uns die Unterschiede zu "BaseLayer" genauer an und lassen den Code weg.

Achtungsteil BaseLayer gestalten ConvLayer gestalten
w randn(prev, n) (prev, n) randn(*F_shape).reshape(M, -1) (M, CF_hF_w)
b randn(n) (n, ) randn(M, 1) (M, 1)
x - (B, prev) im2col(x) (CF_hF_w, BO_hO_w)
u x@w + b (B, prev)@(prev, n)+(n)=(B, n) w@x + b (M, CF_hF_w)@(CF_hF_w, BO_hO_w)+(M, 1)=(M, BO_hO_w)
u - - u.reshape(M, B, O_h, O_w).transpose(1, 0, 2, 3) (B, M, O_h, O_w)
y act.forward(u) (B, n) act.forward(u) (B, M, O_h, O_w)
grad - (B, n) - (B, M, O_h, O_w)
dact grad*act.backward(u, y) (B, n) grad*act.backward(u, y) (B, M, O_h, O_w)
dact - - dact.transpose(1, 0, 2, 3).reshape(M, -1) (M, BO_hO_w)
grad_w x.T@dact (prev, B)@(B, n)=(prev, n) [email protected] (M, BO_hO_w)@(BO_hO_w, CF_hF_w)=(M, CF_hF_w)
grad_b sum(dact, axis=0) (n) sum(dact, axis=1).reshape(M, 1) (M, 1)
grad_x [email protected] (B, n)@(n, prev)=(B, prev) w.T@dact (CF_hF_w, M)@(M, BO_hO_w)=(CF_hF_w, BO_hO_w)
grad_x - - col2im(grad_x) (B, C, I_h, I_w)

Lassen Sie uns zunächst die Vorwärtsausbreitung ausrichten. Der größte Unterschied in der Vorwärtsausbreitung ist die Berechnung von "u".

\boldsymbol{x}@\boldsymbol{w} + \boldsymbol{b} \quad \Leftrightarrow \quad \boldsymbol{w}@\boldsymbol{x} + \boldsymbol{b}

Die Reihenfolge des Matrixprodukts kann durch Setzen von $ \ boldsymbol {w} @ \ boldsymbol {x} = \ boldsymbol {x} ^ {\ top} @ \ boldsymbol {w} ^ {\ top} $ umgekehrt werden. Zum,

\begin{align}
  \boldsymbol{x} &\leftarrow \textrm{im2col}(\boldsymbol{x})^{\top} = (BO_hO_w, CF_hF_w) \\
  \boldsymbol{w} &\leftarrow \boldsymbol{w}^{\top} = (CF_hF_w, M) \\
  \boldsymbol{b} & \leftarrow (M, )
\end{align}

Es ist möglich, sich an der Vorwärtsausbreitungsformel auszurichten, indem Sie als einstellen. In Bezug auf die Vorspannung ist es auch möglich, ein eindimensionales Array anstelle einer zweidimensionalen Matrix mit $ (M, 1) $ zu erstellen, um die Rundfunkfunktion von "numpy" zu aktivieren. Wenn Sie die Vorwärtsausbreitung so ändern

\boldsymbol{x}@\boldsymbol{w} + \boldsymbol{b} = (BO_hO_w, CF_hF_w)@(CF_hF_w, M) + (M) = (BO_hO_w, M)

Nach dem Berechnen mit "vorwärts" von "BaseLayer" ist die Ausbreitung zur nächsten Schicht "self.y.reshape" (B, O_h, O_w, M) .transpose (0, 3, 1, 2) Es kann durch Setzen von) `in $ (B, M, O_h, O_w) $ umgewandelt werden. Wenn Sie sich den Code der Person ansehen, die ihn entwickelt hat, transformiert die Anweisung "return" ihn wie oben beschrieben und fließt ihn, wobei jedoch die Formen von "u" und "y" als $ (BO_hO_w, M) $ verbleiben. Das ist in Ordnung so wie es ist.

Als nächstes kommt die Rückausbreitung. Der Gradient "grad" ist $ (B, M, O_h, O_w) $, und das Elementprodukt von "grad * act.backward (u, y)" kann nicht so berechnet werden, wie es ist.

\boldsymbol{grad} \otimes \textrm{act.backward}(\boldsymbol{u}, \boldsymbol{y}) = (B, M, O_h, O_w) \otimes (BO_hO_w, M)

Also transformieren wir grad und richten es aus. Sie können dies mit grad.transpose (0, 2, 3, 1) .reshape (-1, M) tun. Danach, wenn Sie es auf den "Rückwärts" des "BaseLayer" werfen

\begin{array}[cccc]
   d\boldsymbol{dact} &= \boldsymbol{grad} \otimes \textrm{act.backward}(\boldsymbol{u}, \boldsymbol{y}) &= (BO_hO_w, M) & \\
  \boldsymbol{grad_w} &= \boldsymbol{x}^{\top}@\boldsymbol{dact} &= (CF_hF_w, BO_hO_w)@(BO_hO_w, M) &= (CF_hF_w, M)\\
  \boldsymbol{grad_b} &= \textrm{sum}(\boldsymbol{dact}, \textrm{axis}=0) &= (M, ) & \\
  \boldsymbol{grad_x} &= \boldsymbol{dact}@\boldsymbol{w}^{\top} &= (BO_hO_w, M)@(M, CF_hF_w) &= (BO_hO_w, CF_hF_w)
\end{array}

Weil es wird

\boldsymbol{grad_x} \leftarrow \textrm{col2im}(\boldsymbol{grad_x}^{\top}) = (B, C, I_h, I_w)

Wenn ja, ist es OK. Es ist nicht erforderlich, die "Update" -Funktion von "BaseLayer" wie oben beschrieben zu ändern. Damit ist die Faltschicht fertig.

Pooling-Schicht

Als nächstes kommt die Pooling-Schicht. Erstens ist die Pooling-Ebene eine Ebene, die die Datengröße reduziert, indem nur die Informationen extrahiert werden, die aus dem Eingabebild wichtig zu sein scheinen. Die wichtige Information in diesem Fall ist normalerweise das Maximum oder der Durchschnitt. pooling.gif Wenn dies implementiert wird, ist es außerdem schneller und effizienter, wenn die Funktion "im2col" und die Funktion "col2im" sowie die Faltungsschicht verwendet werden. pooling_act.png Die Konstruktionszeichnung der Poolebene sieht wie folgt aus. pooling_layer.png

Vorwärtsausbreitung der Pooling-Schicht

Schauen wir uns die Vorwärtsausbreitung an. Es ist der Farbteil, der relevant ist. pooling_layer_forward.png Als Operation

  1. Werfen Sie das Eingabebild in die Funktion "im2col"
  2. Ermitteln Sie die Form des Rückgabewerts
  3. Ermitteln Sie den Maximalwert und seinen Index aus dem Rückgabewert
  4. Rekonstruieren Sie die Form des Ausgabebildes

Es ist wie es ist. Es gibt einige Dinge, die für die Rückausbreitung aufbewahrt werden müssen. Lass uns genauer hinschauen. Die Zieloperation ist wie in der folgenden Abbildung dargestellt. pool.png Werfen Sie zuerst den Eingangstensor in die Funktion "im2col", um ihn in eine zweidimensionale Matrix umzuwandeln. pool_im2col.png Weiterhin wird diese zweidimensionale Matrix transformiert. pool_T_reshape.png Fügen Sie nach der Transformation in eine solche vertikal lange Matrix die Summe in Spaltenrichtung hinzu und transformieren und vertauschen Sie schließlich die Dimensionen, um die Ausgabe abzuschließen. pool_sum_reshape_transpose.png Außerdem müssen Sie den Index des Maximalwerts abrufen, bevor Sie die Spaltensumme verwenden.

Backpropagation der Pooling-Schicht

Als nächstes kommt die Rückausbreitung. Es ist der Farbteil der Nummer, der verwandt ist. pooling_layer_backward.png Als Operation

  1. Transformieren Sie den Farbverlauf des Ausgabebildes
  2. Generieren Sie eine leere Matrix mit der gleichen Form wie der Rückgabewert, wenn Sie das Eingabebild in die Funktion im2col werfen
  3. Platzieren Sie die Gradienteninformationen am Index der generierten leeren Matrix mit dem maximalen ursprünglichen Rückgabewert.
  4. Aktivieren Sie die Funktion col2im

Es ist wie es ist. Es ist schwer, die Operation mit nur wenigen Worten zu verstehen ... Es sieht wie folgt aus. pool_backward_transpose_reshape_push.png pool_backward_reshape_T.png pool_backward_col2im.png

Pooling Layering Learning

Wie Sie der Konstruktionszeichnung entnehmen können, sind in der Poolebene keine Parameter zu lernen. Also lerne ich nicht einmal.

Montage der Poolschicht

Die Erklärung der Poolschicht war viel einfacher als die der Faltschicht. Die Implementierung ist auch nicht so kompliziert.

pool.py

pool.py


import numpy as np


class PoolingLayer(BaseLayer):
    def __init__(self, *, I_shape=None,
                 pool=1, pad=0,
                 name="", **kwds):
        self.name = name
        
        if I_shape is None:
            raise KeyError("Input shape is None.")
        
        if len(I_shape) == 2:
            C, I_h, I_w = 1, *I_shape
        else:
            C, I_h, I_w = I_shape
        self.I_shape = (C, I_h, I_w)
        
        _, O_shape, self.pad_state = im2col(np.zeros((1, *self.I_shape)), (pool, pool),
                                            stride=pool, pad=pad)
        self.O_shape = (C, *O_shape)
        
        self.n = np.prod(self.O_shape)
        
        self.pool = pool
        self.F_shape = (pool, pool)
    
    
    def forward(self, x):
        B = x.shape[0]
        C, O_h, O_w = self.O_shape
        
        self.x, _, self.pad_state = im2col(x, self.F_shape,
                                           stride=self.pool,
                                           pad=self.pad_state)
        
        self.x = self.x.T.reshape(B*O_h*O_w*C, -1)
        self.max_index = np.argmax(self.x, axis=1)
        self.y = np.max(self.x, axis=1).reshape(B, O_h, O_w, C).transpose(0, 3, 1, 2)
        
        return self.y
    
    
    def backward(self, grad):
        B = grad.shape[0]
        I_shape = B, *self.I_shape
        C, O_h, O_w = self.O_shape
        
        grad = grad.transpose(0, 2, 3, 1).reshape(-1, 1)
        self.grad_x = np.zeros((grad.size, self.pool*self.pool))
        self.grad_x[:, self.max_index] = grad
        self.grad_x = self.grad_x.reshape(B*O_h*O_w, C*self.pool*self.pool).T
        self.grad_x = col2im(self.grad_x, I_shape, self.O_shape,
                             stride=self.pool, pad=self.pad_state)
        
        return self.grad_x
    
    
    def update(self, **kwds):
        pass

abschließend

Als ich den experimentellen Code von CNN zusammenstellte, funktionierte er nicht gut und ich untersuchte ihn die ganze Zeit ... Aus der Schlussfolgerung heraus gab es kein Problem mit der Faltungsschicht und der Pooling-Schicht, und die Aktivierungsfunktion war das Problem. Die Implementierung von Liste der Aktivierungsfunktionen wurde ebenfalls geändert. Ich werde den experimentellen Code im nächsten Artikel veröffentlichen. Ich habe auch die "LayerManager" -Klasse geändert und so weiter.

Deep Learning-Serie

Recommended Posts

Einführung in Deep Learning ~ Falten und Pooling ~
Einführung in Deep Learning ~ Lokalisierungs- und Verlustfunktion ~
Einführung in Deep Learning ~ Lernregeln ~
Tiefe Stärkung des Lernens 1 Einführung in die Stärkung des Lernens
Einführung in Deep Learning ~ Backpropagation ~
Einführung in das tiefe Lernen ~ Funktionsnäherung ~
Einführung in Deep Learning ~ Codierungsvorbereitung ~
Einführung in Deep Learning ~ Dropout Edition ~
Einführung in Deep Learning ~ Forward Propagation ~
Einführung in Deep Learning ~ CNN Experiment ~
Einführung in das maschinelle Lernen
Einführung in Deep Learning ~ Falten und Pooling ~
Grad-CAM und erweiterte Faltung
Kerzenbalkendiagramm und gleitender Durchschnittsliniendiagramm
Künstliche Intelligenz, maschinelles Lernen, tiefes Lernen zu implementieren und zu verstehen
Super Einführung in das maschinelle Lernen
Maschinelles Lernen mit Nogisaka 46 und Keyakizaka 46 Teil 1 Einführung
Einführung in das maschinelle Lernen Schreiben von Notizen
[Einführung in Python3 Tag 1] Programmierung und Python
Tiefes Lernen, um ohne GPU zu beginnen
Organisation von Plattformen für maschinelles Lernen und tiefes Lernen
Einführung in die Bibliothek für maschinelles Lernen SHOGUN
Einführung in Deep Learning (2) - Versuchen Sie Ihre eigene nichtlineare Regression mit Chainer-
Tiefes Lernen
Einführung in das maschinelle Lernen: Funktionsweise des Modells
Verbessertes Lernen, um von null bis tief zu lernen
Bedeutung von Deep-Learning-Modellen und -Parametern
Eine Einführung in OpenCV für maschinelles Lernen
So studieren Sie den Deep Learning G-Test
Bildausrichtung: von SIFT bis Deep Learning
Eine Einführung in Python für maschinelles Lernen
[Einführung in AWS] Text-Voice-Konvertierung und Wiedergabe ♪
Einführung in TensorFlow - Erläuterung der Begriffe und Konzepte des maschinellen Lernens
[Deep Learning von Grund auf neu] Ich habe versucht, Sigmoid Layer und Relu Layer zu implementieren
Ich habe versucht, Oba Hanana und Otani Emiri durch tiefes Lernen zu klassifizieren
Einführung in Deep Learning (1) --Chainer wird Anfängern leicht verständlich erklärt.
Einführung in Scrapy (1)
[Python] Einfache Einführung in das maschinelle Lernen mit Python (SVM)
[Super Einführung in das maschinelle Lernen] Lernen Sie Pytorch-Tutorials
Eine Einführung in maschinelles Lernen für Bot-Entwickler
Einführung in Scrapy (3)
Einführung in die Thano-Funktionsdefinition und automatische Differenzierung
Erste Schritte mit Supervisor
Einführung in Tkinter 1: Einführung
Chainer und Deep Learning durch Funktionsnäherung gelernt
Ein Amateur versuchte Deep Learning mit Caffe (Einführung)
[Einführung in Python3 Tag 12] Kapitel 6 Objekte und Klassen (6.3-6.15)
Deep Learning von Grund auf neu ① Kapitel 6 "Lerntechniken"
[Einführung in StyleGAN2] Unabhängiges Lernen mit 10 Anime-Gesichtern ♬
Ein Memorandum zum Studieren und Implementieren von Deep Learning
Deep Learning Memorandum
Einführung in PyQt
Einführung in Scrapy (2)
Starten Sie Deep Learning
[Einführung in Python3, Tag 22] Kapitel 11 Parallele Verarbeitung und Vernetzung (11.1 bis 11.3)
Erweitern und erweitern Sie Ihren eigenen Deep Learning-Datensatz
[Einführung in die Udemy Python3 + -Anwendung] 64. Namespace und Gültigkeitsbereich
[Einführung in Python3 Tag 11] Kapitel 6 Objekte und Klassen (6.1-6.2)
[Linux] Einführung in Linux
Erstellen Sie eine Python-Umgebung, um die Theorie und Implementierung von Deep Learning zu erlernen
Python Deep Learning
Paralleles Lernen von Deep Learning durch Keras und Kubernetes