[PYTHON] Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 18) One! Miaou! Grad-CAM!

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.

Télécharger des photos sur Google Drive

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à.

L'écran Colab expirera-t-il s'il est laissé sans surveillance pendant une longue période?

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.

J'ai essayé d'apprendre avec la version Keras de Deep ConvNet créée la dernière fois

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

k-18-1.jpg k-18-2.jpg k-18-3.jpg

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

k-18-4.jpg k-18-5.jpg k-18-6.jpg k-18-7.jpg k-18-8.jpg k-18-9.jpg

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.

Site de référence

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

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 ° 11) CNN
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 19) Augmentation des données
Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 12) Deep learning
Mémo d'auto-apprentissage "Deep Learning from scratch" (n ° 15) Tutoriel pour débutants TensorFlow
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" (n ° 13) Essayez d'utiliser Google Colaboratory
Mémo d'auto-apprentissage «Deep Learning from scratch» (10) Classe MultiLayerNet
Mémo d'auto-apprentissage «Deep Learning from scratch» (n ° 10-2) Valeur initiale du poids
[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]
Deep learning / Deep learning made from scratch Chapitre 7 Mémo
[Mémo d'apprentissage] Deep Learning fait de zéro [~ Chapitre 4]
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 16) J'ai essayé de créer SimpleConvNet avec Keras
"Deep Learning from scratch" Mémo d'auto-apprentissage (n ° 17) J'ai essayé de créer DeepConvNet avec Keras
Apprentissage profond à 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 Chapter 2 Perceptron (lecture du mémo)
[Mémo d'apprentissage] Apprentissage profond à partir de zéro ~ Mise en œuvre de l'abandon ~
Apprentissage profond à partir de zéro 1 à 3 chapitres
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
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
Mémo d'auto-apprentissage "Deep Learning from scratch" (partie 8) J'ai dessiné le graphique du chapitre 6 avec matplotlib
Pourquoi ModuleNotFoundError: Aucun module nommé'dataset.mnist 'n'apparaît dans "Deep Learning from scratch".
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" 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
GitHub du bon livre "Deep Learning from scratch"
Résumé Python vs Ruby "Deep Learning from scratch"
Django memo n ° 1 à partir de zéro
Application de Deep Learning 2 à partir de zéro Filtre anti-spam
[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
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 1
Un amateur a trébuché dans le Deep Learning ❷ fait à partir de zéro Note: Chapitre 5
Un amateur a trébuché dans le Deep Learning ❷ fait à partir de zéro Note: Chapitre 2
Apprentissage profond / code de travail LSTM
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 3
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 7
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 5
Un amateur a trébuché dans le Deep Learning ❷ fait de zéro Note: Chapitre 1
Un amateur a trébuché dans le Deep Learning ❷ fait à partir de zéro Note: Chapitre 4
Un mémo lors de l'exécution de l'exemple de code de Deep Learning créé à partir de zéro avec Google Colaboratory
Un amateur a trébuché dans le Deep Learning à partir de zéro.
Un amateur a trébuché dans le Deep Learning à partir de zéro Note: Chapitre 2