[PYTHON] Deep Learning / Deep Learning von Grund auf neu Kapitel 7 Memo

1. Zuallererst

Ich lese ein Meisterwerk, ** "Deep Learning from Zero" **. Diesmal ist ein Memo von Kapitel 7. Um den Code auszuführen, laden Sie den gesamten Code von Github herunter und verwenden Sie das Jupiter-Notizbuch in Kapitel 07.

2. Beispielimplementierung

Ich werde ein Beispiel implementieren, um ** Convolution, Pooling **, das ich im Lehrbuch studiert habe, tatsächlich zu bewegen. Die verwendeten Daten sind MNIST und die Gewichte des Faltungsfilters werden gelernt (params.pkl wird im Ordner ch07 gespeichert). Der Code für Convolution and Pooling wird aus common / layer.py importiert und verwendet.

Lassen Sie es uns zuerst ausführen.

import sys, os
sys.path.append(os.pardir)  #Einstellungen zum Importieren von Dateien in das übergeordnete Verzeichnis
import numpy as np
import matplotlib.pyplot as plt
from simple_convnet import SimpleConvNet
from common.layers import *  #Ebenenimport
from dataset.mnist import load_mnist

#Anzeigefunktion(FH, FW) 
def show(filters):    
    FH, FW = filters.shape  
    fig = plt.figure(figsize=(FH*0.1, FW*0.1))  #Anzeige der Größenangabe
    plt.imshow(((filters)), cmap='gray')
    plt.tick_params(left=False, labelleft=False, bottom=False, labelbottom=False)  #Löschen Sie die Achsenskala / Beschriftung
    plt.show()

#MNIST-Daten lesen
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)
x_train = x_train[5:6]  #Wählen Sie die 5. Daten von Anfang an

#Gelernte Parameter laden
network = SimpleConvNet()  #Instanziieren Sie SimpleConvNet
network.load_params("params.pkl")  #Lesen Sie den gesamten Parameter
W1, b1 = network.params['W1'][:1], network.params['b1'][:1]  #Nur der erste

#Schichterzeugung
conv = Convolution(W1, b1, stride=1, pad=0)  
pool = Pooling(pool_h=2, pool_w=2, stride=2, pad=0)

#Vorwärtsausbreitung
out1 = conv.forward(x_train)  #Falten
out2 = pool.forward(out1)  #Pooling

#Anzeige
print('input.shape = ',x_train.shape)
show(x_train.reshape(28, 28))
print('filter.shape = ', W1.shape)
show(W1.reshape(5, 5))
print('convolution.shape = ', out1.shape)
show(out1.reshape(24, 24))
print('pooling.shape = ', out2.shape)
show(out2.reshape(12, 12))

スクリーンショット 2020-05-13 09.31.29.png

Das MNIST-Bild (1, 1, 28, 28) wird mit Filter 5 * 5 gefaltet, Auffüllen = 0, Schritt = 1, und die Daten von (1, 1, 24, 24) werden weiter zu Filter 2 * 2 hinzugefügt, Auffüllen = 0, Das Pooling erfolgt mit Schritt = 2 (1, 1, 12, 12) und die Daten werden erhalten.

Schauen wir uns nun die wichtigsten Punkte des Codes an.

3.Convolution

# ------------- from common_layers.py -------------
    def forward(self, x):
        FN, C, FH, FW = self.W.shape
        N, C, H, W = x.shape
        out_h = 1 + int((H + 2*self.pad - FH) / self.stride)
        out_w = 1 + int((W + 2*self.pad - FW) / self.stride)

        #① Konvertieren Sie Bilddaten mit im2col in Matrixdaten
        col = im2col(x, FH, FW, self.stride, self.pad)

        #② Formen Sie den Filter neu und erweitern Sie ihn zu einem zweidimensionalen Array
        col_W = self.W.reshape(FN, -1).T

        #③ Berechnen Sie die Ausgabe durch Matrixberechnung
        out = np.dot(col, col_W) + self.b

        #④ Passen Sie die Form der Ausgabe an
        out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)

        self.x = x
        self.col = col
        self.col_W = col_W
        return out

Ein Diagramm, das zeigt, wie ein 4-dimensionales Bild (Stapelgröße, Anzahl der Kanäle, Bildhöhe, Bildbreite) durch die Faltungsoperation verarbeitet wird, sieht folgendermaßen aus. スクリーンショット 2020-05-10 15.44.23.png Werfen wir einen Blick auf die wichtigste Funktion ** ① im2col **.

4.im2col

# ------------- from common_layers.py -------------
def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
    N, C, H, W = input_data.shape
    out_h = (H + 2*pad - filter_h)//stride + 1
    out_w = (W + 2*pad - filter_w)//stride + 1
    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

    # 24*24 Filter 5*5 mal schneiden(stride=Wenn 1)
    for y in range(filter_h):  #5 Schleifen
        y_max = y + stride*out_h  # y_max = y + 24
        for x in range(filter_w):  #5 Schleifen
            x_max = x + stride*out_w  # x_max = x + 24

            #y bis y+Bis zu 24,x bis x+Bis zu 24、スライシング
            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
    return col

"y: y_max: Schritt, x: x_max: Schritt" bedeutet, dass der Bereich von y bis y_max für jeden Schritt angegeben wird und der Bereich von x bis x_max für jeden Schritt angegeben wird.

Mit y_max = y + 24, x_max = x + 24, Schritt = 1 ist jede for-Schleife 5-mal eine Doppelschleife, sodass Sie am Ende 5 * 5-mal mit einem ** 24 * 24-Filter ** schneiden.

Auf der anderen Seite sollte es, wenn man bedenkt, was ich im Lehrbuch gelernt habe, 24 * 24-mal das Schneiden ** mit dem ** 5 * 5-Filter sein. Wenn Sie daraus einen Code machen, sieht es so aus.

    # 5*24 mit 5 Filtern*24 mal schneiden(stride=Wenn 1)
    for y in range(0, out_h, stride):    
        for x in range(0, out_w, stride):  
            col[:, :, y, x, :, :] = img[:, :, y:y+filter_h, x:x+filter_w]

In der Tat ist die Gesamtzahl der Elemente, die vom ** 24 * 24-Filter 5 * 5-fach geschnitten ** und vom ** 5 * 5-Filter 24 * 24-fach geschnitten ** gleich sind, gleich. Wenn die Ergebnisse gleich sind, welche ist besser? Natürlich ** der erstere **. Der Grund dafür ist, dass die Anzahl der for-Schleifen, die viel Verarbeitungszeit in Anspruch nehmen, überwiegend gering ist.

Wenn Sie die beiden Methoden in der Abbildung zeigen, sieht es so aus スクリーンショット 2020-05-11 21.47.25.png

5. Vergleich zweier im2cols

Lassen Sie uns überprüfen, ob die Ergebnisse von beiden wirklich gleich sind. Führen Sie den folgenden Code aus, um das ursprüngliche im2col und die Funktion my_im2col zu visualisieren, die ** 24 * 24-mal mit einem ** 5 * 5-Filter in Scheiben schneidet, einschließlich der zu berechnenden Daten.

import sys, os
sys.path.append(os.pardir)  #Einstellungen zum Importieren von Dateien in das übergeordnete Verzeichnis
import numpy as np
from dataset.mnist import load_mnist
import matplotlib.pyplot as plt

#Datenanzeigefunktion( x =Anzeigebreite, y=Anzeigehöhe, nx =Anzahl der Spalten)
def show(filters, x, y, nx, margin=1, scale=10):
    FN, C, FH, FW = filters.shape
    ny = int(np.ceil(FN / nx))    
    fig = plt.figure(figsize=(x, y))
    fig.subplots_adjust(left=0, right=1.3, bottom=0, top=1.3, hspace=0.05, wspace=0.05)
    
    for i in range(FN):
        ax = fig.add_subplot(ny, nx, i+1, xticks=[], yticks=[])
        ax.imshow(filters[i, 0], cmap='gray', interpolation='nearest') 
    plt.show()

def my_im2col(input_data, filter_h, filter_w, stride=1, pad=0):
    N, C, H, W = input_data.shape
    out_h = (H + 2*pad - filter_h)//stride + 1  #Ausgangshöhe
    out_w = (W + 2*pad - filter_w)//stride + 1  #Ausgabebreite
    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')  #Bildauffüllung
    col = np.zeros((N, C, out_h, out_w, filter_h, filter_w))  #Vorbereitung der Col-Berechnungsmatrix
    
    # 5*24 mit 5 Filtern*24 mal schneiden(stride=Wenn 1)
    for y in range(0, out_h, stride):    
        for x in range(0, out_w, stride):  
            col[:, :, y, x, :, :] = img[:, :, y:y+filter_h, x:x+filter_w]
            
    # check1
    print('col.shape after slicing = ', col.shape)
    show(col.reshape(576, 1, 5, 5), x = 3.5, y = 3.5, nx = 24)
    
    #Transponieren & umformen
    col = col.transpose(0, 2, 3, 1, 4, 5).reshape(N*out_h*out_w, -1)
    
    # check2
    print('col.shape after transpose & reshape = ', col.shape)
    show(col.reshape(1, 1, 25, 576), x = 18, y =3, nx=1)
    
    return col

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
    N, C, H, W = input_data.shape
    out_h = (H + 2*pad - filter_h)//stride + 1  #Ausgangshöhe
    out_w = (W + 2*pad - filter_w)//stride + 1  #Ausgabebreite
    img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')  #Bildauffüllung
    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))  #col Matrixvorbereitung zur Berechnung

    # 24*24 Filter 5*5 mal schneiden(stride=Wenn 1)
    for y in range(filter_h):
        y_max = y + stride*out_h
        for x in range(filter_w):
            x_max = x + stride*out_w
            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]
            
    # check1
    print('col.shape after slicing = ', col.shape)
    show(col.reshape(25, 1, 24, 24), x = 3.5, y = 3.5, nx = 5)
            
    #Transponieren & umformen
    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
    
    # check2
    print('col.shape after transpose & reshape = ', col.shape)
    show(col.reshape(1, 1, 25, 576), x = 18, y =3, nx=1)
    
    return col

#MNIST-Daten lesen
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)
x_train = x_train[5:6]  #Wählen Sie die 5. Daten von Anfang an

out1 = my_im2col(x_train, 5, 5)
out2 = im2col(x_train, 5, 5)
print('all elements are same = ', (out1 == out2).all()) #Ob alle Elemente gleich sind

スクリーンショット 2020-05-10 19.20.10.png スクリーンショット 2020-05-10 19.20.24.png Die erste Hälfte ist das Ergebnis von "my_im2col" und die zweite Hälfte ist das Ergebnis von "im2col". In beiden Fällen beträgt die Spaltenform nach Transponieren und Umformen tatsächlich 576 Zeilen x 25 Spalten, was vertikal lang ist, aber nicht gut aussieht. Daher ist die Anzeige mit 25 Zeilen x 576 Spalten durch Vertauschen von Zeilen und Spalten horizontal lang. Ich werde. Und wenn Sie sich die beiden Bilder ansehen, haben sie sicherlich das gleiche Muster.

In der letzten Zeile der Ausgabe ** True ** beim Vergleich aller Elemente des mehrdimensionalen Arrays **, sodass wir sehen können, dass my_im2col und im2col genau das gleiche Ergebnis liefern. Wenn stride = 1 ist, müssen Sie im Allgemeinen nur ** filter_h * filter_w Slice **. Das ist eine großartige Technik, nicht wahr?

Hier ist ein einfaches, intuitives Beispiel dafür, warum Sie dies tun können. スクリーンショット 2020-05-13 09.02.10.png

6.Pooling

# ------------- from common_layers.py -------------
    def forward(self, x):
        N, C, H, W = x.shape
        out_h = int(1 + (H - self.pool_h) / self.stride)
        out_w = int(1 + (W - self.pool_w) / self.stride)

        col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)
        col = col.reshape(-1, self.pool_h*self.pool_w)

        arg_max = np.argmax(col, axis=1)
        out = np.max(col, axis=1)
        out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)

        self.x = x
        self.arg_max = arg_max
        return out

Es sieht so aus, wenn das 4D-Bild (Stapelgröße, Anzahl der Kanäle, Bildhöhe, Bildbreite) durch Pooling verarbeitet wird.

スクリーンショット 2020-05-10 20.24.24.png Wie bei der Faltung wird die im2col-Funktion verwendet, um die Matrix abzurufen und mit pool_h, pool_w, stride und pad als Argumenten zu verarbeiten.

Recommended Posts

[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 7]
Deep Learning / Deep Learning von Grund auf neu Kapitel 6 Memo
[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 5]
[Lernnotiz] Deep Learning von Grund auf neu gemacht [Kapitel 6]
Deep Learning / Deep Learning von Grund auf neu Kapitel 7 Memo
[Lernnotiz] Deep Learning von Grund auf neu gemacht [~ Kapitel 4]
Deep Learning von Grund auf neu Kapitel 2 Perceptron (Memo lesen)
Deep Learning / Deep Learning von Grund auf neu 2 Kapitel 4 Memo
Deep Learning / Deep Learning von Grund auf neu Kapitel 3 Memo
Deep Learning / Deep Learning von Null 2 Kapitel 7 Memo
Deep Learning / Deep Learning von Null 2 Kapitel 8 Memo
Deep Learning / Deep Learning von Grund auf neu Kapitel 5 Memo
Deep Learning / Deep Learning von Grund auf neu Kapitel 4 Memo
Deep Learning / Deep Learning von Grund auf neu 2 Kapitel 3 Memo
Deep Learning Memo von Grund auf neu gemacht
Deep Learning / Deep Learning von Null 2 Kapitel 6 Memo
Deep Learning von Grund auf neu
"Deep Learning from Grund" Memo zum Selbststudium (Teil 12) Deep Learning
Selbststudien-Memo "Deep Learning from Grund" (unlesbares Glossar)
Deep Learning von Grund auf 1-3 Kapitel
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 9) MultiLayerNet-Klasse
Deep Learning von Grund auf neu ① Kapitel 6 "Lerntechniken"
[Lernnotiz] Deep Learning von Grund auf ~ Implementierung von Dropout ~
"Deep Learning from Grund" Memo zum Selbststudium (10) MultiLayerNet-Klasse
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 11) CNN
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 19) Datenerweiterung
Anwendung von Deep Learning 2 von Grund auf neu Spam-Filter
Tiefes Lernen von Grund auf neu (Kostenberechnung)
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 5
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 2
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 3
Ein Amateur stolperte in Deep Learning von Grund auf neu. Hinweis: Kapitel 7
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 5
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 1
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 4
Selbststudien-Memo "Deep Learning from Grund" (Nr. 18) Eins! Miau! Grad-CAM!
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 4
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 2
Selbststudien-Memo "Deep Learning from Grund" (Nr. 15) TensorFlow-Anfänger-Tutorial
Tiefes Lernen von Grund auf neu (Vorwärtsausbreitung)
"Deep Learning von Grund auf neu" mit Haskell (unvollendet)
[Windows 10] Aufbau einer "Deep Learning from Scratch" -Umgebung
Lernbericht über das Lesen von "Deep Learning von Grund auf neu"
[Deep Learning von Grund auf neu] Über die Optimierung von Hyperparametern
Schreiben Sie Ihre Eindrücke von der Deep Learning 3 Framework Edition, die von Grund auf neu erstellt wurde
Selbststudien-Memo "Deep Learning from Grund" (Nr. 13) Verwenden Sie Google Colaboratory
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 10-2) Anfangswert des Gewichts
Kapitel 3 Neuronales Netz Schneiden Sie nur die guten Punkte des Deeplearning aus, die von Grund auf neu erstellt wurden
Django Memo # 1 von Grund auf neu
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 14) Führen Sie das Programm in Kapitel 4 in Google Colaboratory aus
"Deep Learning from Grund" Memo zum Selbststudium (Teil 8) Ich habe die Grafik in Kapitel 6 mit matplotlib gezeichnet
Kapitel 2 Implementierung von Perceptron Schneiden Sie nur die guten Punkte des Deeplearning aus, die von Grund auf neu erstellt wurden
GitHub des guten Buches "Deep Learning von Grund auf neu"
Python vs Ruby "Deep Learning von Grund auf neu" Zusammenfassung
Python vs Ruby "Deep Learning von Grund auf neu" Kapitel 2 Logikschaltung von Perceptron
Python vs Ruby "Deep Learning von Grund auf neu" Kapitel 4 Implementierung der Verlustfunktion
Kapitel 1 Einführung in Python Schneiden Sie nur die guten Punkte des Deeplearning aus, die von Grund auf neu erstellt wurden
[Deep Learning von Grund auf neu] Ich habe die Affine-Ebene implementiert