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 ←
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. 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
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.
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.
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)
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.
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)
#É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])
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
W2
Il ne semble pas y avoir de modèle.