[PYTHON] Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 12) Deep learning

En lisant "Deep Learning from scratch" (écrit par Yasuki Saito, publié par O'Reilly Japan), je noterai les sites auxquels j'ai fait référence. Partie 11

8.1.1 Vers un réseau plus profond

Dans P243, il est expliqué que la définition du réseau est deep_convnet.py dans le dossier ch08, le code d'apprentissage est train_deepnet.py et le paramètre de poids appris est deep_conv_net_params.pkl, mais le paramètre de poids est lu et les données de test sont lues. Le programme à traiter est misclassified_mnist.py. Ce programme peut être exécuté en créant JupyterNote dans le dossier ch08. p8-2.jpg Si vous essayez de l'exécuter sur le répertoire de base, vous devrez changer l'emplacement et appeler deep_convert.py et deep_conv_net_params.pkl.

Résultat de l'exécution de misclassified_mnist.py p8-3.jpg

Le contenu de la classe DeepConvNet n'a été expliqué que jusqu'à présent, donc je pense qu'il est nécessaire de vérifier à nouveau le contenu.

alors,

Cette fois, utilisons cette classe pour traiter l'ensemble de données chien et chat de Kaggle.

Ensemble de données Kaggle pour chats et chiens

Contenu des données

Télécharger depuis le site suivant https://www.microsoft.com/en-us/download/details.aspx?id=54765

Les images sont contenues dans les dossiers Chat et Chien sous le dossier PetImages. Les noms de fichiers sont des numéros de série de 0.jpg à 12499.jpg. Cela signifie qu'il y a 12500 images pour chaque chien et chat. Les images sont en couleur et de taille différente. Si vous stockez un 0.jpg de cette image dans un tableau NumPy et regardez le contenu

(375, 500, 3)

Il est stocké sous la forme d'un tableau tridimensionnel de (hauteur, largeur, couleur). La couleur est 0 pour le rouge, 1 pour le vert et 2 pour le bleu. Dans Memo 6-2, il a été converti en échelle de gris, mais cette fois il est converti en 3 couleurs et 3 canaux de données.

Alignez la taille de l'image et convertissez-la dans un format pouvant être traité

Les données d'image sont disposées dans le canal 3, hauteur 80 et largeur 80.

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))

Informations du fichier image lu par PIL

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

JPEG (500, 375) RGB

La taille du fichier est (largeur, hauteur). La conversion en un tableau numpy donne:

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

562500 (375, 500, 3)

(Hauteur, largeur, couleur). Sur cette base, redimensionnez l'image à 80 x 80 et permutez les axes de dimensions pour créer un tableau avec le canal 3, la hauteur 80 et la largeur 80.

Toutefois, lorsque le programme ci-dessus traite en continu les fichiers dans le dossier, l'erreur suivante se produit.

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

Apparemment, il n'y a pas d'axe de dimension autour de la transposée (2,0,1). 1074.jpg est également une erreur lors du traitement avec Memo 6-2. Il semble y avoir une erreur lors de la lecture du fichier. 666.jpg est un fichier vide de 0 octet.

Si vous regardez 10125.jpg

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

Autant que je puisse voir dans le visualiseur, il est affiché comme une image couleur sans aucun problème. Le problème semble être en mode palette P. J'ai donc modifié la méthode de lecture.

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

Apparemment, ça va.

Déplacement du fichier de problème CAt 1074.jpg 5127.jpg 666.jpg Dog 11702.jpg 829.jpg 8366.jpg dans un autre dossier et augmentation des données de test à 100 et des données d'entraînement à 4000 pour éviter les erreurs de mémoire. J'ai décidé de le presser.

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)

Classe DeepConvNet

Le code de la classe DeepConvNet se trouve dans deep_convnet.py dans le dossier ch08, mais il semble qu'il y ait une partie qui correspond à l'entrée de (1,28,28).

    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) est naturel, mais ce n'est pas un problème car vous pouvez lui donner une valeur différente en tant que paramètre. Le problème est la taille du poids W7.

        #Initialisation du poids===========
        #Combien de connexions chacun des neurones de chaque couche a-t-il avec les neurones de la couche précédente (TODO)?:Calculer automatiquement)
        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)  #Valeur initiale recommandée lors de l'utilisation de ReLU

Ici, vous pouvez spécifier le canal x hauteur x largeur du filtre utilisé dans chaque couche, mais cela se produira lorsque les données d'entrée deviendront (3,80,80).

        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])

La taille du poids W7 était également comme ça,

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

Si vous ne changez pas cela, le programme ne fonctionnera pas.

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

La raison pour laquelle il est 10x10 est qu'il est basé sur la hauteur x la largeur des données d'entrée. Les données d'entrée cette fois sont 80x80, mais si elles passent par la couche de pooling une fois au milieu, elles auront la moitié de la taille. Dans cette définition de classe, il passe 3 fois, donc 80 → 40 → 20 → 10. Le 4x4 du programme d'origine est 28 → 14 → 7 → 4.

Processus d'apprentissage

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'])
    
#Hyper paramètres
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):
    #Obtenez un mini lot
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    
    #Calcul du gradient
    grads = network.gradient(x_batch, t_batch) 
    optimizer.update(network.params, grads)
    
    #Registre des progrès d'apprentissage
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)

#Enregistrez l'objet réseau avec pickle. Les objets enregistrés sont utilisés dans le traitement des inférences
import pickle
save_file = dataset_dir + '/catdogA.pkl'
with open(save_file, 'wb') as f:
    pickle.dump(network, f, -1)

Le programme a fonctionné, mais je n'ai pas pu l'apprendre. Même si j'essaie de déduire, le taux de réponse correcte n'atteint pas 50%. Après tout, n'est-il pas faux que le nombre de données à entraîner dans un lot ne soit que de 12? Cependant, si vous le traitez plus loin, une erreur de mémoire se produira.

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)

Traitement des inférences

#Évaluer avec des données de test
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("Bonne réponse" + str(c) + " " + class_names[c])
    p = np.argmax(y[i])
    v = y[p]
    print("Jugement" + str(p) + " " + class_names[p] + " " + str(v) )
    showImg(x[i])

c9-1.jpg

La probabilité du résultat du jugement est une très petite valeur. Après tout, cela n'a peut-être pas été traité normalement. Cependant, il est difficile de répéter le test dans un environnement où une erreur de mémoire se produit immédiatement ...

J'ai regardé le contenu du poids

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

Il ne semble pas y avoir de modèle.

Partie 11

Site référencé

Différence entre les images en mode P et en mode L de PIL

Recommended Posts

Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 12) Deep learning
Mémo d'auto-apprentissage "Deep Learning from scratch" (glossaire illisible)
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 9) Classe MultiLayerNet
Mémo d'auto-apprentissage «Deep Learning from scratch» (10) Classe MultiLayerNet
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 11) CNN
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 19) Augmentation des données
Apprentissage profond à partir de zéro
[Mémo d'apprentissage] Le Deep Learning fait de zéro [Chapitre 7]
Deep learning / Deep learning made from scratch Chapitre 6 Mémo
[Mémo d'apprentissage] Deep Learning fait de zéro [Chapitre 5]
[Mémo d'apprentissage] Le Deep Learning fait de zéro [Chapitre 6]
Deep learning / Deep learning made from scratch Chapitre 7 Mémo
[Mémo d'apprentissage] Deep Learning fait de zéro [~ Chapitre 4]
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 18) One! Miaou! Grad-CAM!
Mémo d'auto-apprentissage "Deep Learning from scratch" (n ° 15) Tutoriel pour débutants TensorFlow
Apprentissage profond à partir de zéro 1 à 3 chapitres
Deep Learning from scratch Chapter 2 Perceptron (lecture du mémo)
[Mémo d'apprentissage] Apprentissage profond à partir de zéro ~ Mise en œuvre de l'abandon ~
Mémo d'auto-apprentissage "Deep Learning from scratch" (n ° 13) Essayez d'utiliser Google Colaboratory
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 10-2) Valeur initiale du poids
Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 8) J'ai dessiné le graphique du chapitre 6 avec matplotlib
Deep learning / Deep learning from scratch 2 Chapitre 4 Mémo
Deep learning / Deep learning made from scratch Chapitre 3 Mémo
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 5 Mémo
Apprentissage profond à partir de zéro (calcul des coûts)
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 7 Mémo
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 8 Mémo
Deep learning / Deep learning made from scratch Chapitre 5 Mémo
Deep learning / Deep learning made from scratch Chapitre 4 Mémo
Deep learning / Deep learning from scratch 2 Chapitre 3 Mémo
Mémo d'apprentissage profond créé à partir de zéro
Deep Learning / Deep Learning à partir de Zero 2 Chapitre 6 Mémo
J'ai essayé d'implémenter Perceptron Part 1 [Deep Learning from scratch]
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 16) J'ai essayé de créer SimpleConvNet avec Keras
Apprentissage profond à partir de zéro (propagation vers l'avant)
Apprentissage profond / Apprentissage profond à partir de zéro 2-Essayez de déplacer GRU
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 17) J'ai essayé de créer DeepConvNet avec Keras
"Deep Learning from scratch" avec Haskell (inachevé)
[Windows 10] Construction de l'environnement "Deep Learning from scratch"
Enregistrement d'apprentissage de la lecture "Deep Learning from scratch"
[Deep Learning from scratch] À propos de l'optimisation des hyper paramètres
Django memo n ° 1 à partir de zéro
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 14) Exécutez le programme du chapitre 4 sur Google Colaboratory
Deep Learning from scratch ① Chapitre 6 "Techniques liées à l'apprentissage"
GitHub du bon livre "Deep Learning from scratch"
[Deep Learning from scratch] J'ai implémenté la couche Affine
Django à partir de zéro (partie: 2)
Django à partir de zéro (partie: 1)
Apprentissage profond / code de travail LSTM
Application de Deep Learning 2 à partir de zéro Filtre anti-spam
Apprendre en profondeur à partir des bases mathématiques Partie 2 (pendant la fréquentation)
Version Lua Deep Learning from scratch Part 5.5 [Rendre les fichiers pkl disponibles dans Lua Torch]
[Deep Learning from scratch] J'ai essayé d'expliquer le décrochage
[Deep Learning from scratch] Implémentation de la méthode Momentum et de la méthode AdaGrad
[Partie 4] Utilisez le Deep Learning pour prévoir la météo à partir d'images météorologiques
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 1
[Partie 1] Utilisez le Deep Learning pour prévoir la météo à partir d'images météorologiques
[Partie 3] Utilisez le Deep Learning pour prévoir la météo à partir d'images météorologiques
Un amateur a trébuché dans le Deep Learning ❷ fait à partir de zéro Note: Chapitre 2