[PYTHON] "Deep Learning from Grund" Memo zum Selbststudium (Teil 12) Deep Learning

Während ich "Deep Learning von Grund auf neu" lese (geschrieben von Yasuki Saito, veröffentlicht von O'Reilly Japan), werde ich die Websites notieren, auf die ich verwiesen habe. Teil 11

8.1.1 Zu einem tieferen Netzwerk

In P243 wird erklärt, dass die Netzwerkdefinition deep_convnet.py im Ordner ch08 lautet, der Trainingscode train_deepnet.py lautet und der gelernte Gewichtungsparameter deep_conv_net_params.pkl lautet, der Gewichtungsparameter jedoch gelesen und die Testdaten gelesen werden. Das zu verarbeitende Programm ist misclassified_mnist.py. Dieses Programm kann ausgeführt werden, indem JupyterNote im Ordner ch08 erstellt wird. p8-2.jpg Wenn Sie versuchen, es im Basisverzeichnis auszuführen, müssen Sie den Speicherort und den Aufruf von deep_convert.py und deep_conv_net_params.pkl ändern.

Ausführungsergebnis von misclassified_mnist.py p8-3.jpg

Der Inhalt der DeepConvNet-Klasse wurde bisher nur erklärt, daher denke ich, dass es notwendig ist, den Inhalt erneut zu überprüfen.

damit,

Verwenden wir diese Klasse dieses Mal, um Kaggles Hunde- und Katzendatensatz zu verarbeiten.

Kaggle Katzen- und Hundedatensatz

Dateninhalt

Download von der folgenden Seite https://www.microsoft.com/en-us/download/details.aspx?id=54765

Bilder sind in den Ordnern Cat and Dog unter dem Ordner PetImages enthalten. Die Dateinamen sind Seriennummern von 0.jpg bis 12499.jpg. Dies bedeutet, dass für jeden Hund und jede Katze 12500 Bilder vorhanden sind. Die Bilder sind farbig und unterschiedlich groß. Wenn Sie 0.jpg dieses Bildes in einem NumPy-Array speichern und den Inhalt anzeigen

(375, 500, 3)

Es wird als dreidimensionales Array von (Höhe, Breite, Farbe) gespeichert. Die Farbe ist 0 für Rot, 1 für Grün und 2 für Blau. In Memo 6-2 wurde es in Graustufen konvertiert, diesmal jedoch in 3 Farben und 3 Datenkanäle.

Richten Sie die Größe des Bildes aus und konvertieren Sie es in ein Format, das verarbeitet werden kann

Bilddaten sind in Kanal 3, Höhe 80 und Breite 80 angeordnet.

import os
import glob
from PIL import Image
import numpy as np 

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
catfiles = glob.glob(dataset_dir + '/Cat/*.jpg')
dogfiles = glob.glob(dataset_dir + '/Dog/*.jpg')

fsize = 80

for f in catfiles:
    try:
        lblA = 0
        pad_u, pad_d, pad_l, pad_r = 0,0,0,0 
        img = Image.open(f)
        w,h=img.size
        if w>h:
            imgr = img.resize((fsize, int(h*fsize/w)))
            wr,hr = imgr.size
            pad_u = int((fsize - hr)/2)
            pad_d = fsize - hr - pad_u
        else:
            imgr = img.resize((int(w*fsize/h),fsize))
            wr,hr = imgr.size
            pad_l = int((fsize - wr)/2)
            pad_r = fsize - wr - pad_l

        imgtr = np.array(imgr).transpose(2,0,1)
        imgA = np.pad(imgtr, [(0, 0),(pad_u,pad_d),(pad_l,pad_r)], 'constant')      
        imgA = imgA.tolist()
    except Exception as e:
        print(f+" : " + str(e))

Informationen der von PIL gelesenen Bilddatei

img = Image.open(f)
print(img.format, img.size, img.mode)

JPEG (500, 375) RGB

Die Größe der Datei ist (Breite, Höhe). Das Konvertieren in ein Numpy-Array ergibt:

imgA = np.array(img)
print(imgA.size, imgA.shape)

562500 (375, 500, 3)

(Höhe, Breite, Farbe). Ändern Sie auf dieser Grundlage die Größe des Bilds auf 80 x 80 und tauschen Sie die Bemaßungsachsen aus, um ein Array mit Kanal 3, Höhe 80 und Breite 80 zu erstellen.

Wenn das obige Programm jedoch die Dateien im Ordner kontinuierlich verarbeitet, tritt dieser Fehler auf.

C:\Users\021133/dataset/Cat\10125.jpg : axes don't match array C:\Users\021133/dataset/Cat\10501.jpg : axes don't match array C:\Users\021133/dataset/Cat\1074.jpg : Python int too large to convert to C ssize_t C:\Users\021133/dataset/Cat\666.jpg : cannot identify image file

Anscheinend gibt es keine Dimensionsachse um die Transponierte (2,0,1). 1074.jpg ist auch ein Fehler, wenn es mit Memo 6-2 verarbeitet wird. Beim Lesen der Datei scheint ein Fehler aufgetreten zu sein. 666.jpg ist eine leere 0-Byte-Datei.

Wenn Sie sich 10125.jpg ansehen

img=Image.open(dataset_dir + '/10125.jpg')
print(img.format, img.size, img.mode)
imgA = np.array(img)
print(imgA.size, imgA.shape,imgA.ndim)

GIF (259, 346) P 89614 (346, 259) 2

Soweit ich im Viewer sehen kann, wird es problemlos als Farbbild angezeigt. Das Problem scheint im P-Paletten-Modus zu liegen. Also habe ich die Lesemethode geändert.

img=Image.open(dataset_dir + '/10501.jpg').convert('RGB')
print(img.format, img.size, img.mode)
imgA = np.array(img)
print(imgA.size, imgA.shape,imgA.ndim)

None (400, 299) RGB 358800 (299, 400, 3) 3

Anscheinend ist das in Ordnung.

Die Problemdatei CAt 1074.jpg 5127.jpg 666.jpg Dog 11702.jpg 829.jpg 8366.jpg wurde in einen anderen Ordner verschoben und die Testdaten auf 100 und die Trainingsdaten auf 4000 erhöht, um Speicherfehler zu vermeiden. Ich beschloss, es zu quetschen.

import os
import glob
import numpy as np 

from PIL import Image

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
catfiles = glob.glob(dataset_dir + '/Cat/*.jpg')
dogfiles = glob.glob(dataset_dir + '/Dog/*.jpg')

fsize = 80

tsl = []
tsi = []
trl = []
tri = []
tst_count = 0
trn_count = 0

count = 0

for f in catfiles:
    try:
        lblA = 0
        img = Image.open(f).convert('RGB')
        w,h=img.size
        pad_u, pad_d, pad_l, pad_r = 0,0,0,0
        if w>h:
            imgr = img.resize((fsize, int(h*fsize/w)))
            wr,hr = imgr.size
            pad_u = int((fsize - hr)/2)
            pad_d = fsize - hr - pad_u
        else:
            imgr = img.resize((int(w*fsize/h),fsize))
            wr,hr = imgr.size
            pad_l = int((fsize - wr)/2)
            pad_r = fsize - wr - pad_l

        imgtr = np.array(imgr).transpose(2,0,1)
        imgA = np.pad(imgtr, [(0, 0),(pad_u,pad_d),(pad_l,pad_r)], 'constant')      
        imgA = imgA.tolist()
    except Exception as e:
        print(f+" : " + str(e))

    if count < 50:
        tsl.append(lblA)
        tsi.append(imgA)
        tst_count += 1
    elif count < 2050:
        trl.append(lblA)
        tri.append(imgA)
        trn_count += 1
    else:
        break

    count += 1
    
count = 0
        
for f in dogfiles:
    try:
        lblA = 1
        img = Image.open(f).convert('RGB')
        w,h=img.size
        pad_u, pad_d, pad_l, pad_r = 0,0,0,0
        if w>h:
            imgr = img.resize((fsize, int(h*fsize/w)))
            wr,hr = imgr.size
            pad_u = int((fsize - hr)/2)
            pad_d = fsize - hr - pad_u
        else:
            imgr = img.resize((int(w*fsize/h),fsize))
            wr,hr = imgr.size
            pad_l = int((fsize - wr)/2)
            pad_r = fsize - wr - pad_l

        imgtr = np.array(imgr).transpose(2,0,1)
        imgA = np.pad(imgtr, [(0, 0),(pad_u,pad_d),(pad_l,pad_r)], 'constant')      
        imgA = imgA.tolist()

    except Exception as e:
        print(f+" : " + str(e))
    
    if count < 50:
        tsl.append(lblA)
        tsi.append(imgA)
        tst_count += 1
    elif count < 2050:
        trl.append(lblA)
        tri.append(imgA)
        trn_count += 1
    else:
        break
        
    count += 1

dataset = {}
dataset['test_label']  = np.array(tsl, dtype=np.uint8)
dataset['test_img']    = np.array(tsi, dtype=np.uint8)
dataset['train_label'] = np.array(trl, dtype=np.uint8)
dataset['train_img']   = np.array(tri, dtype=np.uint8) 

import pickle

save_file = dataset_dir + '/catdog.pkl'    
with open(save_file, 'wb') as f:
    pickle.dump(dataset, f, -1) 
dataset['test_img'].shape

(100, 3, 80, 80)

dataset['train_img'].shape

(4000, 3, 80, 80)

DeepConvNet-Klasse

Der Code für die DeepConvNet-Klasse befindet sich in deep_convnet.py im Ordner ch08, aber es scheint, dass es einen Teil gibt, der der Eingabe von (1,28,28) entspricht.

    def __init__(self, input_dim=(1, 28, 28),
                 conv_param_1 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_2 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_3 = {'filter_num':32, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_4 = {'filter_num':32, 'filter_size':3, 'pad':2, 'stride':1},
                 conv_param_5 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_6 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},
                 hidden_size=50, output_size=10):

input_dim = (1, 28, 28) ist natürlich, aber dies ist kein Problem, da Sie ihm einen anderen Wert als Parameter geben können. Das Problem ist die Größe des Gewichts W7.

        #Gewichtsinitialisierung===========
        #Wie viele Verbindungen hat jedes der Neuronen in jeder Schicht mit den Neuronen in der vorherigen Schicht (TODO)?:Automatisch berechnen)
        pre_node_nums = np.array([1*3*3, 16*3*3, 16*3*3, 32*3*3, 32*3*3, 64*3*3, 64*4*4, hidden_size])
        weight_init_scales = np.sqrt(2.0 / pre_node_nums)  #Empfohlener Anfangswert bei Verwendung von ReLU

Hier können Sie den Kanal x Höhe x Breite des in jeder Ebene verwendeten Filters angeben. Dies geschieht jedoch, wenn die Eingabedaten (3,80,80) werden.

        pre_node_nums = np.array([3*3*3, 16*3*3, 16*3*3, 32*3*3, 32*3*3, 64*3*3, 64*10*10, hidden_size])

Die Größe des Gewichts W7 war auch so,

        self.params['W7'] = weight_init_scales[6] * np.random.randn(64*4*4, hidden_size)

Wenn Sie dies nicht ändern, funktioniert das Programm nicht.

        self.params['W7'] = weight_init_scales[6] * np.random.randn(64*10*10, hidden_size)

Der Grund, warum es 10x10 ist, ist, dass es auf der Höhe x Breite der Eingabedaten basiert. Die Eingabedaten sind diesmal 80 x 80, aber wenn sie einmal in der Mitte durch die Poolebene laufen, sind sie halb so groß. In dieser Klassendefinition wird es dreimal übergeben, also 80 → 40 → 20 → 10. Der 4x4 des ursprünglichen Programms ist 28 → 14 → 7 → 4.

Lernprozess

import sys, os
import pickle
import numpy as np
from common.functions import *
from common.optimizer import *
from deep_convnet import DeepConvNet

def to_one_hot(label):
    t = np.zeros((label.size, 2))
    for i in range(label.size):
        t[i][label[i]] = 1
    return t

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'

mnist_file = dataset_dir + '/catdog.pkl'
with open(mnist_file, 'rb') as f:
    dataset = pickle.load(f)
x_train = dataset['train_img']
t_train = to_one_hot(dataset['train_label'])
    
#Hyperparameter
iters_num = 30
train_size = x_train.shape[0]
batch_size = 12
learning_rate = 0.1

train_loss_list = []

network = DeepConvNet( input_dim=(3, 80, 80),
                 conv_param_1 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_2 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_3 = {'filter_num':32, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_4 = {'filter_num':32, 'filter_size':3, 'pad':2, 'stride':1},
                 conv_param_5 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},
                 conv_param_6 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},
                 hidden_size=50, output_size=2)

optimizer = Adam(lr=learning_rate)

for i in range(iters_num):
    #Holen Sie sich eine Mini-Charge
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    
    #Gradientenberechnung
    grads = network.gradient(x_batch, t_batch) 
    optimizer.update(network.params, grads)
    
    #Aufzeichnung des Lernfortschritts
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)

#Speichern Sie das Netzwerkobjekt mit pickle. Gespeicherte Objekte werden in der Inferenzverarbeitung verwendet
import pickle
save_file = dataset_dir + '/catdogA.pkl'
with open(save_file, 'wb') as f:
    pickle.dump(network, f, -1)

Das Programm hat funktioniert, aber ich konnte es nicht wirklich lernen. Selbst wenn ich versuche zu schließen, erreicht die richtige Antwortrate nicht 50%. Ist es nicht falsch, dass die Anzahl der Daten, die in einem Stapel trainiert werden sollen, nur 12 beträgt? Wenn Sie es jedoch weiter verarbeiten, tritt ein Speicherfehler auf.

network.layers

[common.layers.Convolution at 0x3610030, common.layers.Relu at 0xbad8170, common.layers.Convolution at 0xbabf990, common.layers.Relu at 0xbabf870, common.layers.Pooling at 0xbabf950, common.layers.Convolution at 0xbabf430, common.layers.Relu at 0xbabf0f0, common.layers.Convolution at 0xbabf230, common.layers.Relu at 0xbabf570, common.layers.Pooling at 0xbabf130, common.layers.Convolution at 0xbabf4d0, common.layers.Relu at 0xbabf1f0, common.layers.Convolution at 0xbabf210, common.layers.Relu at 0xbabf190, common.layers.Pooling at 0xbabf9f0, common.layers.Affine at 0xbabf970, common.layers.Relu at 0xbabf270, common.layers.Dropout at 0xbabf9b0, common.layers.Affine at 0xbabf470, common.layers.Dropout at 0xbabf370]

print(x_batch.shape)
print(network.params['W1'].shape)
print(network.params['W2'].shape)
print(network.params['W3'].shape)
print(network.params['W4'].shape)
print(network.params['W5'].shape)
print(network.params['W6'].shape)
print(network.params['W7'].shape)
print(network.params['W8'].shape)

(12, 3, 80, 80) (16, 3, 3, 3) (16, 16, 3, 3) (32, 16, 3, 3) (32, 32, 3, 3) (64, 32, 3, 3) (64, 64, 3, 3) (6400, 50) (50, 2)

Inferenzverarbeitung

#Mit Testdaten auswerten
import numpy as np
import sys, os
import pickle
from deep_convnet import DeepConvNet

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'

mnist_file = dataset_dir + '/catdog.pkl'
with open(mnist_file, 'rb') as f:
    dataset = pickle.load(f)
x_test = dataset['test_img']
t_test = dataset['test_label']

test_size = 10
test_mask = np.random.choice(100, test_size)
x = x_test[test_mask]
t = t_test[test_mask]
 
#network = DeepConvNet()
weight_file = dataset_dir + '/catdogA.pkl'
with open(weight_file, 'rb') as f:
    network = pickle.load(f)

y = network.predict(x)
accuracy_cnt = 0
for i in range(len(y)):
    p= np.argmax(y[i]) 
    if p == t[i]:
        accuracy_cnt += 1

print("Accuracy:" + str(float(accuracy_cnt) / len(x))) 

Accuracy:0.5

import matplotlib.pyplot as plt
class_names = ['cat', 'dog']

def showImg(x):
    example = x.transpose(1,2,0)
    plt.figure()
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(example, cmap=plt.cm.binary)
    plt.show()
    return

for i in range(test_size):
    c = t[i]
    print("Richtige Antwort" + str(c) + " " + class_names[c])
    p = np.argmax(y[i])
    v = y[p]
    print("Beurteilung" + str(p) + " " + class_names[p] + " " + str(v) )
    showImg(x[i])

c9-1.jpg

Die Wahrscheinlichkeit des Beurteilungsergebnisses ist ein sehr kleiner Wert. Schließlich wurde es möglicherweise nicht normal verarbeitet. Es ist jedoch schwierig, den Test in einer Umgebung zu wiederholen, in der sofort ein Speicherfehler auftritt ...

Ich schaute auf den Inhalt des Gewichts

import numpy as np
import matplotlib.pyplot as plt
dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'

def filter_show(filters, nx=8, margin=3, scale=10):
    """
    c.f. https://gist.github.com/aidiary/07d530d5e08011832b12#file-draw_weight-py
    """
    FN, C, FH, FW = filters.shape
    ny = int(np.ceil(FN / nx))

    fig = plt.figure()
    fig.subplots_adjust(left=0, right=1, bottom=0, top=1, 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=plt.cm.binary, interpolation='nearest')

    plt.show()

#network = DeepConvNet()
weight_file = dataset_dir + '/catdogA.pkl'
with open(weight_file, 'rb') as f:
    network = pickle.load(f)

filter_show(network.params['W1'])

W1 c9-w1.jpg

W2 c9-w2.jpg

Es sieht nicht so aus, als gäbe es ein Muster.

Teil 11

Referenzierte Site

Unterschied zwischen PIL- und L-Modus-Bildern von PIL

Recommended Posts

"Deep Learning from Grund" Memo zum Selbststudium (Teil 12) Deep Learning
Selbststudien-Memo "Deep Learning from Grund" (unlesbares Glossar)
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 9) MultiLayerNet-Klasse
"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
Deep Learning von Grund auf neu
[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]
Selbststudien-Memo "Deep Learning from Grund" (Nr. 18) Eins! Miau! Grad-CAM!
Selbststudien-Memo "Deep Learning from Grund" (Nr. 15) TensorFlow-Anfänger-Tutorial
Deep Learning von Grund auf 1-3 Kapitel
Deep Learning von Grund auf neu Kapitel 2 Perceptron (Memo lesen)
[Lernnotiz] Deep Learning von Grund auf ~ Implementierung von Dropout ~
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
"Deep Learning from Grund" Memo zum Selbststudium (Teil 8) Ich habe die Grafik in Kapitel 6 mit matplotlib gezeichnet
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 5 Memo
Tiefes Lernen von Grund auf neu (Kostenberechnung)
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
Ich habe versucht, Perceptron Teil 1 [Deep Learning von Grund auf neu] zu implementieren.
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 16) Ich habe versucht, SimpleConvNet mit Keras zu erstellen
Tiefes Lernen von Grund auf neu (Vorwärtsausbreitung)
Tiefes Lernen / Tiefes Lernen von Grund auf 2-Versuchen Sie, GRU zu bewegen
"Deep Learning from Grund" Memo zum Selbststudium (Nr. 17) Ich habe versucht, DeepConvNet mit Keras zu erstellen
"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
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 von Grund auf neu ① Kapitel 6 "Lerntechniken"
GitHub des guten Buches "Deep Learning von Grund auf neu"
[Deep Learning von Grund auf neu] Ich habe die Affine-Ebene implementiert
Django von vorne anfangen (Teil: 2)
Django von vorne anfangen (Teil: 1)
Deep Learning / LSTM Scratch Code
Anwendung von Deep Learning 2 von Grund auf neu Spam-Filter
Deep Learning aus den mathematischen Grundlagen Teil 2 (während der Teilnahme)
Lua-Version Deep Learning von Grund auf neu Teil 5.5 [Bereitstellung von pkl-Dateien in Lua Torch]
Ich habe versucht, Dropout zu erklären
[Deep Learning von Grund auf neu] Implementierung der Momentum-Methode und der AdaGrad-Methode
[Teil 4] Verwenden Sie Deep Learning, um das Wetter anhand von Wetterbildern vorherzusagen
Ein Amateur stolperte in Deep Learning von Grund auf neu Hinweis: Kapitel 1
[Teil 1] Verwenden Sie Deep Learning, um das Wetter anhand von Wetterbildern vorherzusagen
[Teil 3] Verwenden Sie Deep Learning, um das Wetter anhand von Wetterbildern vorherzusagen
Ein Amateur stolperte über Deep Learning ❷ von Grund auf neu Hinweis: Kapitel 2