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 17 ← → Partie 19
Sur Google Colaboratory, j'ai pu confirmer que le script du livre peut être remplacé par Keras et exécuté.
donc,
Cette fois, j'ai décidé de laisser Kaggle faire la distinction entre les ensembles de données de chat et de chien. Quand je l'ai fait avec la Note d'auto-apprentissage n ° 6-2, le taux de réponse correct était de 60%, ce qui était un peu mieux que la réponse. À ce moment-là, des erreurs de mémoire se produisaient fréquemment lors de la création de données, j'ai donc réduit le nombre de données d'entraînement, et comme le réseau neuronal était un réseau à deux couches entièrement connecté que j'avais compris à ce stade, je l'ai converti en une dimension. fait. Dans Self-study memo 12, j'ai essayé de traiter avec un réseau neuronal convolutif, mais je n'ai pas pu apprendre correctement en raison d'une erreur de mémoire, et le taux de réponse correct était de 50%. Et au même niveau que l'adresse.
Cette fois, je vais essayer à nouveau le réseau de neurones convolutifs sans me soucier de l'erreur de mémoire dans Google Colaboratory.
Les données pour les chats et les chiens représentent environ 400 Mo chacun, et il y a quelques gigaoctets d'espace libre dans My Drive, il n'y a donc aucun problème de capacité. Cependant, lorsque j'ai essayé de télécharger cela pour chaque dossier, cela a pris trop de temps et a expiré. Puisqu'il y a 12500 fichiers dans un dossier, cela peut être un problème avec le nombre de fichiers, mais le dossier dog s'est arrêté au milieu, mais le dossier cat peut tout être téléchargé, donc je ne comprends pas bien la cause. Cela ne peut pas être aidé car cela a pris beaucoup de temps car la ligne était occupée, la charge sur le serveur était élevée et les circonstances à ce moment-là.
Il a été dit que si vous laissez le script s'exécuter pendant une longue période et que vous n'utilisez pas l'écran, il expirera, de sorte que le processus de mise en forme de l'image est divisé en chiens et chats et enregistré séparément, puis un Je l'ai résumé dans.
J'ai traité l'image de la même manière que je l'ai fait dans Self-study memo 12, mais le mémo d'auto-apprentissage 12 était les données pour DeepConvNet du livre. , Channels_first (lot, canaux, hauteur, largeur) a été traité par transpose afin qu'il soit au format. Keras est au format channels_last (lot, hauteur, largeur, canaux), il est donc enregistré sans transposition.
#Préparation des données d'entrée
from google.colab import drive
drive.mount('/content/drive')
import os
import pickle
mnist_file = '/content/drive/My Drive/Colab Notebooks/deep_learning/dataset/catdog.pkl'
with open(mnist_file, 'rb') as f:
dataset = pickle.load(f)
x_train = dataset['train_img'] / 255.0 #C'est normalisé.
t_train = dataset['train_label']
x_test = dataset['test_img'] / 255.0
t_test = dataset['test_label']
print(x_train.shape)
(23411, 80, 80, 3)
Les données d'image sont une valeur entière de 0 à 255, mais celle-ci est divisée par 255,0 et convertie de sorte qu'elle se situe dans la plage de 0,0 à 1,0. Faire cela a accéléré l'apprentissage. Sans normalisation, le taux de réponse correcte n'atteignait pas 60% même après 5 époques, mais après normalisation, il dépassait 60% dans la 4ème fois.
#TensorFlow et tf.importer des keras
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from keras.layers import Dense, Activation, Flatten, Conv2D, MaxPooling2D, Dropout
#Importer la bibliothèque d'aide
import numpy as np
import matplotlib.pyplot as plt
def create_model(input_shape, output_size, hidden_size):
import numpy as np
import matplotlib.pyplot as plt
filter_num = 16
filter_size = 3
filter_stride = 1
filter_num2 = 32
filter_num3 = 64
pool_size_h=2
pool_size_w=2
pool_stride=2
model = keras.Sequential(name="DeepConvNet")
model.add(keras.Input(shape=input_shape))
model.add(Conv2D(filter_num, filter_size, strides=filter_stride, padding="same", activation="relu", kernel_initializer='he_normal'))
model.add(Conv2D(filter_num, filter_size, strides=filter_stride, padding="same", activation="relu", kernel_initializer='he_normal'))
model.add(MaxPooling2D(pool_size=(pool_size_h, pool_size_w),strides=pool_stride))
model.add(Conv2D(filter_num2, filter_size, strides=filter_stride, padding="same", activation="relu", kernel_initializer='he_normal'))
model.add(Conv2D(filter_num2, filter_size, strides=filter_stride, padding="same", activation="relu", kernel_initializer='he_normal'))
model.add(MaxPooling2D(pool_size=(pool_size_h, pool_size_w),strides=pool_stride))
model.add(Conv2D(filter_num3, filter_size, strides=filter_stride, padding="same", activation="relu", kernel_initializer='he_normal'))
model.add(Conv2D(filter_num3, filter_size, strides=filter_stride, padding="same", activation="relu", kernel_initializer='he_normal'))
model.add(MaxPooling2D(pool_size=(pool_size_h, pool_size_w),strides=pool_stride))
model.add(keras.layers.Flatten())
model.add(Dense(hidden_size, activation="relu", kernel_initializer='he_normal'))
model.add(Dropout(0.5))
model.add(Dense(output_size))
model.add(Dropout(0.5))
model.add(Activation("softmax"))
#Compiler le modèle
model.compile(loss="sparse_categorical_crossentropy",
optimizer="adam",
metrics=["accuracy"])
return model
input_shape=(80,80,3)
output_size=2
hidden_size=100
model = create_model(input_shape, output_size, hidden_size)
model.summary()
Model: "DeepConvNet" Layer (type) Output Shape Param #
conv2d (Conv2D) (None, 80, 80, 16) 448
conv2d_1 (Conv2D) (None, 80, 80, 16) 2320
max_pooling2d (MaxPooling2D) (None, 40, 40, 16) 0
conv2d_2 (Conv2D) (None, 40, 40, 32) 4640
conv2d_3 (Conv2D) (None, 40, 40, 32) 9248
max_pooling2d_1 (MaxPooling2 (None, 20, 20, 32) 0
conv2d_4 (Conv2D) (None, 20, 20, 64) 18496
conv2d_5 (Conv2D) (None, 20, 20, 64) 36928
max_pooling2d_2 (MaxPooling2 (None, 10, 10, 64) 0
flatten (Flatten) (None, 6400) 0
dense (Dense) (None, 100) 640100
dropout (Dropout) (None, 100) 0
dense_1 (Dense) (None, 2) 202
dropout_1 (Dropout) (None, 2) 0
activation (Activation) (None, 2) 0
Total params: 712,382 Trainable params: 712,382 Non-trainable params: 0
À l'exception de input_shape et output_size, c'est le même que le script créé dans la partie 17.
model.fit(x_train, t_train, epochs=10, batch_size=128)
test_loss, test_acc = model.evaluate(x_test, t_test, verbose=2)
Epoch 1/10 195/195 [==============================] - 385s 2s/step - loss: 0.7018 - accuracy: 0.5456 Epoch 2/10 195/195 [==============================] - 385s 2s/step - loss: 0.6602 - accuracy: 0.5902 Epoch 3/10 195/195 [==============================] - 383s 2s/step - loss: 0.6178 - accuracy: 0.6464 Epoch 4/10 195/195 [==============================] - 383s 2s/step - loss: 0.5844 - accuracy: 0.6759 Epoch 5/10 195/195 [==============================] - 383s 2s/step - loss: 0.5399 - accuracy: 0.7090 Epoch 6/10 195/195 [==============================] - 383s 2s/step - loss: 0.5001 - accuracy: 0.7278 Epoch 7/10 195/195 [==============================] - 382s 2s/step - loss: 0.4676 - accuracy: 0.7513 Epoch 8/10 195/195 [==============================] - 382s 2s/step - loss: 0.4485 - accuracy: 0.7611 Epoch 9/10 195/195 [==============================] - 380s 2s/step - loss: 0.4295 - accuracy: 0.7713 Epoch 10/10 195/195 [==============================] - 382s 2s/step - loss: 0.4099 - accuracy: 0.7788 4/4 - 0s - loss: 0.3249 - accuracy: 0.8500
Le taux de réponse correcte est de 85%. J'ai essayé d'afficher le résultat du jugement.
#Prédire
predictions = model.predict(x_test)
def plot_image(i, predictions_array, t_label, img):
class_names = ['cat', 'dog']
predictions_array = predictions_array[i]
img = img[i].reshape((80, 80, 3))
true_label = t_label[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
#Affiche les images de test X, les étiquettes prédites et les étiquettes correctes.
#Les prédictions correctes sont affichées en bleu et les mauvaises prédictions sont affichées en rouge.
num_rows = 10
num_cols = 10
num_images = num_rows*num_cols
plt.figure(figsize=(2*num_cols, 2.5*num_rows))
for i in range(num_images):
plt.subplot(num_rows, num_cols, i+1)
plot_image(i, predictions, t_test, x_test)
plt.show()
Neuf cas ont confondu les chats avec des chiens et six cas ont confondu les chiens avec les chats. Si votre visage est grand et tourné droit devant vous, il n'y a pas d'erreur. Vous pouvez être confondu avec le fait d'être sur le côté ou d'avoir un petit visage. Est-ce un fait que tous les chats ont des oreilles triangulaires et que de nombreux chiens ont des oreilles dégoulinantes?
En disant
Je voulais savoir à quoi je faisais attention dans l'image, j'ai donc décidé d'utiliser GRAD-CAM pour la voir.
Grad-CAM Mappage d'activation de classe pondéré par gradient (Grad-CAM) Cela semble être appelé une méthode de cartographie d'activation de classe pondérée par gradient. Est-ce que ça va avec Gradcam?
Le gradient Grad est apparu dans la fonction de perte, mais il semble que plus le gradient est grand a le plus grand effet sur la classification. Je renoncerai à aller plus loin, exécuterai le programme et ne verrai que les résultats.
Pour le programme de calcul Grad-CAM, reportez-vous ici. → J'ai implémenté Grad-CAM avec keras et tensorflow
import numpy as np
import cv2
#Pour le calcul Grad-CAM
from tensorflow.keras import models
import tensorflow as tf
def grad_cam(input_model, x, layer_name):
"""
Args:
input_model(object):Objet modèle
x(ndarray):image
layer_name(string):Le nom de la couche convolutive
Returns:
output_image(ndarray):Image colorée de l'image originale
"""
#Prétraitement d'image
#Puisqu'il n'y a qu'une seule image à lire, le mode doit être augmenté..Je ne peux pas prévoir
h, w, c = x.shape
IMAGE_SIZE = (h, w)
X = np.expand_dims(x, axis=0)
preprocessed_input = X.astype('float32') / 255.0
grad_model = models.Model([input_model.inputs], [input_model.get_layer(layer_name).output, input_model.output])
with tf.GradientTape() as tape:
conv_outputs, predictions = grad_model(preprocessed_input)
class_idx = np.argmax(predictions[0])
loss = predictions[:, class_idx]
#Calculer le gradient
output = conv_outputs[0]
grads = tape.gradient(loss, conv_outputs)[0]
gate_f = tf.cast(output > 0, 'float32')
gate_r = tf.cast(grads > 0, 'float32')
guided_grads = gate_f * gate_r * grads
#Faire la moyenne des poids et multiplier par la sortie de la couche
weights = np.mean(guided_grads, axis=(0, 1))
cam = np.dot(output, weights)
#Redimensionner l'image à la même taille que l'image d'origine
cam = cv2.resize(cam, IMAGE_SIZE, cv2.INTER_LINEAR)
#Au lieu de ReLU
cam = np.maximum(cam, 0)
#Calculer la carte thermique
heatmap = cam / cam.max()
#Images monochromes pseudo-couleurs
jet_cam = cv2.applyColorMap(np.uint8(255.0*heatmap), cv2.COLORMAP_JET)
#Convertir en RVB
rgb_cam = cv2.cvtColor(jet_cam, cv2.COLOR_BGR2RGB)
#Combiné avec l'image d'origine
output_image = (np.float32(rgb_cam) / 2 + x / 2 )
return output_image , rgb_cam
from keras.preprocessing.image import array_to_img, img_to_array, load_img
predictions = model.predict(x_test)
def hantei_hyouji(i, x_test, t_test, predictions, model):
class_names = ['cat', 'dog']
x = x_test[i]
true_label = t_test[i]
predictions_array = predictions[i]
predicted_label = np.argmax(predictions_array)
target_layer = 'conv2d_5'
cam, heatmap = grad_cam(model, x, target_layer)
moto=array_to_img(x, scale=True)
hantei=array_to_img(heatmap, scale=True)
hyouji=array_to_img(cam, scale=True)
print("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]))
row = 1
col = 3
plt.figure(figsize=(15,15))
plt.subplot(row, col, 1)
plt.imshow(moto)
plt.axis('off')
plt.subplot(row, col, 2)
plt.imshow(hantei)
plt.axis('off')
plt.subplot(row, col, 3)
plt.axis('off')
plt.imshow(hyouji)
plt.show()
return
for i in range(100):
hantei_hyouji(i, dataset['test_img'], t_test, predictions, model)
Et le résultat est
Apparemment, quand il s'agit de chats, c'est comme regarder le motif du corps et la forme du corps, pas les oreilles ou les yeux. Les chiens semblent accorder plus d'attention à leur visage, en particulier à leur nez. Dans le premier exemple d'image, nous prêtons attention à la forme du corps, mais en accordant plus d'attention au visage, il est mal jugé en tant que chien par une petite marge. Dans le dernier exemple d'image, tout en faisant attention au nez, il semble qu'il ait été jugé à tort comme un chat en faisant attention à la forme du corps, probablement au dos arrondi. Dans le deuxième exemple, vous accordez plus d'attention à l'environnement qu'au chat lui-même, et probablement parce que vous ne pouvez pas du tout voir le nez ou les caractéristiques du chien, vous avez décidé que c'était un chat.
J'ai implémenté Grad-CAM avec keras et tensorflow
Explication du code source Grad-CAM et Grad-CAM guidé
Partie 17 ← → Partie 19 Cliquez ici pour la liste des mémos, etc. Glossaire illisible
Recommended Posts