――Ceci est le résultat de mon propre dossier d'étude sur l'apprentissage automatique et l'apprentissage profond.
--Cible: identique à la précédente. Pour plus de détails ** ici **. --Article de référence ** Détection d'anomalies et visualisation des pièces anormales en implémentant vgg16 et Grad-CAM avec ○ keras **
--Acquis ** JDLA Deep Learning pour Engeneer 2019 # 2 ** en septembre 2019. ――Jusqu'à la fin mars 2020, vous occuperez le bureau d'une société d'intérêt public. À partir d'avril 2020, il a changé de carrière en ingénieur de données. Pour plus de détails ** ici **.
--Les fichiers images (jpg) à analyser ont été augmentés à 120 photos de chiens de compagnie (chiens Shiba) et 120 photos de chiens Shiba (autres que les chiens de compagnie), pour un total de 240 photos, et ils ont été à nouveau classés en 2 par apprentissage profond. .. De plus, grâce à l'apprentissage par transfert et à la mise au point avec le modèle ImageNet (VGG16) et à la vérification avec les données de test, la précision de la classification est passée d'environ 75% à environ 95%.
** Étape 1 Conversion de données, construction de modèles et apprentissage ** ** Étape 2 Mise en œuvre de Grad-CAM **
-Cet article de @T_Tao ** ([Détection d'anomalies et visualisation des pièces anormales en implémentant vgg16 et Grad-CAM avec keras](https: // qiita. L'implémentation de Grad-CAM a été introduite à l'adresse com / T_Tao / items / 0e869e440067518b6b58)) **.
Je voudrais implémenter le code introduit dans cet article et continuer à utiliser les données de photo de chien Shiba pour la visualisation avec Grad-CAM. Il est très intéressant de voir quelle partie de l'image du chien le deep learning considère comme une caractéristique et de faire la distinction entre les deux. Dans l'implémentation suivante, écrivez essentiellement le code de l'article de référence tel quel. De plus, les données de Google Drive configurées dans l'analyse précédente (2) seront utilisées telles quelles.
Montez-le pour pouvoir charger des données dans Colab à partir du dossier contenant l'image du chien Shiba.
#Monture Google Drive
from google.colab import drive
drive.mount('/content/drive')
Importez avec le code suivant.
#Importer la bibliothèque
from __future__ import print_function
import keras
from keras.applications import VGG16
from keras.models import Sequential, load_model, model_from_json
from keras import models, optimizers, layers
from keras.optimizers import SGD
from keras.layers import Dense, Dropout, Activation, Flatten
from sklearn.model_selection import train_test_split
from PIL import Image
from keras.preprocessing import image as images
from keras.preprocessing.image import array_to_img, img_to_array, load_img
from keras import backend as K
import os
import numpy as np
import glob
import pandas as pd
import cv2
Jusqu'à la dernière fois, j'ai utilisé le générateur de données d'image de keras pour convertir les données d'image. Cette fois, au lieu d'utiliser Image Data Generator, utilisez le code suivant pour convertir le fichier image en tenseur.
# cd '/content/drive/'My Drive/'Colab Notebooks'Déplacer vers le dossier de travail dans
%cd '/content/drive/'My Drive/Colab Notebooks/Self_Study/02_mydog_or_otherdogs/
num_classes = 2 #Nombre de cours
folder = ["mydog2", "otherdogs2"] #Nom du dossier dans lequel les données photo sont stockées
image_size = 312 #La taille d'un morceau d'image d'entrée
x = []
y = []
for index, name in enumerate(folder):
dir = "./original_data/" + name
files = glob.glob(dir + "/*.jpg ")
for i, file in enumerate(files):
image = Image.open(file)
image = image.convert("RGB")
image = image.resize((image_size, image_size))
data = np.asarray(image)
x.append(data)
y.append(index)
#Np si vous souhaitez convertir la liste en un tableau Numpy.array、np.Il existe deux types, un tableau.
#Si vous souhaitez faire une copie du tableau Numpy, np.Utilisez un tableau.
#Si vous souhaitez faire une copie qui reste synchronisée avec le tableau Numpy d'origine, np.Utilisez un tableau.
x = np.array(x)
y = np.array(y)
Vérifions comment les données sont converties et stockées en x et y.
#Vérifiez le contenu de x
display(x)
Le contenu de x qui a converti les données d'image est converti dans la liste suivante.
array([[[[114, 109, 116],
[116, 111, 118],
[104, 99, 105],
...,
[ 37, 38, 30],
[ 37, 38, 30],
[ 36, 37, 29]],
[[117, 112, 119],
[120, 115, 121],
[110, 105, 111],
...,
[ 37, 38, 30],
[ 37, 38, 30],
[ 37, 38, 30]],
[[118, 113, 120],
[121, 116, 122],
[114, 109, 115],
...,
[ 37, 38, 30],
[ 38, 39, 31],
[ 38, 39, 31]],
(Omis)
...,
[[ 60, 56, 53],
[ 60, 56, 53],
[ 61, 57, 54],
...,
[105, 97, 84],
[105, 97, 84],
[104, 96, 83]]]], dtype=uint8)
'\n[[[0, 0, 0],\n [0, 0, 0],\n [0, 0, 0],\n ...,\n [0, 0, 0],\n [0, 0, 0],\n [0, 0, 0]],\n'
Vérifiez le contenu de y (étiquette).
#Vérifiez le contenu de y
y
y est généré avec deux types d'étiquettes, "0" et "1".
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
Le tenseur transformé est divisé sur train_test_split de sklearn pour l'entraînement avec le modèle construit plus tard.
#Divisé en données de train et données de test
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
#a changé l'étiquette y en expression one-hot
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
Vous devriez voir un résultat similaire au suivant:
192 train samples
48 test samples
Créez le modèle avec le code suivant. Cet optimiseur spécifie SDG (méthode de descente de gradient probabiliste).
vgg_conv = VGG16(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3))
last = vgg_conv.output
mod = Flatten()(last)
mod = Dense(1024, activation='relu')(mod)
mod = Dropout(0.5)(mod)
preds = Dense(2, activation='sigmoid')(mod)
model = models.Model(vgg_conv.input, preds)
model.summary()
epochs = 100
batch_size = 48
model.compile(loss='binary_crossentropy',
optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
metrics=['accuracy'])
Former le modèle.
history = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
validation_data=(x_test, y_test),
shuffle=True)
Enregistrez le modèle.
model.save('mydog_or_otherdogs3(Grad-Cam).h5')
Affichez le résultat avec le code suivant et tracez un graphique. Le résultat de la validation est également élevé probablement parce que le fichier image utilise toutes les données (240 feuilles).
#affichage du score
scores = model.evaluate(x_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])
#précision et graphique des pertes
import matplotlib.pyplot as plt
acc = history.history["acc"]
val_acc = history.history["val_acc"]
loss = history.history["loss"]
val_loss = history.history["val_loss"]
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, label = "Training acc" )
plt.plot(epochs, val_acc, label = "Validation acc")
plt.title("Training and Validation accuracy")
plt.legend()
plt.show()
plt.plot(epochs, loss, label = "Training loss" )
plt.plot(epochs, val_loss, label = "Validation loss")
plt.title("Training and Validation loss")
plt.legend()
plt.show()
Le résultat est le suivant.
Test loss: 0.04847167782029327
Test accuracy: 0.9795918367346939
Entrez le code ci-dessous. D'après @T_Tao ** Grad-CAM avec un modèle que j'ai fait avec des keras * Cela signifie qu'il est basé sur le code de *.
K.set_learning_phase(1) #set learning phase
def Grad_Cam(input_model, pic_array, layer_name):
#Prétraitement
pic = np.expand_dims(pic_array, axis=0)
pic = pic.astype('float32')
preprocessed_input = pic / 255.0
#Calcul de la classe de prédiction
predictions = input_model.predict(preprocessed_input)
class_idx = np.argmax(predictions[0])
class_output = input_model.output[:, class_idx]
#Obtenir un dégradé
conv_output = input_model.get_layer(layer_name).output # layer_Sortie de la couche de nom
grads = K.gradients(class_output, conv_output)[0] # gradients(loss, variables)Renvoie le gradient par rapport à la perte de variables
gradient_function = K.function([input_model.input], [conv_output, grads]) # input_model.Lorsque vous entrez l'entrée, conv_Fonction de sortie de sortie et de grades
output, grads_val = gradient_function([preprocessed_input])
output, grads_val = output[0], grads_val[0]
#Faire la moyenne des poids et multiplier par la sortie de la couche
weights = np.mean(grads_val, axis=(0, 1))
cam = np.dot(output, weights)
#Image et combiner comme une carte thermique
cam = cv2.resize(cam, (312, 312), cv2.INTER_LINEAR)
cam = np.maximum(cam, 0)
cam = cam / cam.max()
jetcam = cv2.applyColorMap(np.uint8(255 * cam), cv2.COLORMAP_JET) #Images monochromes pseudo-couleurs
jetcam = cv2.cvtColor(jetcam, cv2.COLOR_BGR2RGB) #Convertir la couleur en RVB
jetcam = (np.float32(jetcam) + pic / 2) #Combiné avec l'image d'origine
return jetcam
Appliquons le résultat à quelques photos de chiens Shiba. Tout d'abord, de mon chien.
# cd '/content/drive/'My Drive/'Colab Notebooks'Déplacer vers le dossier spécifié dans
%cd '/content/drive/'My Drive/Colab Notebooks/
pic_array = img_to_array(load_img('/content/drive/My Drive/Colab Notebooks/Self_Study/02_mydog_or_otherdogs/original_data/mydog2/mydog1.jpg', target_size=(312, 312)))
pic = pic_array.reshape((1,) + pic_array.shape)
array_to_img(pic_array)
Superposer la carte de chaleur
picture = Grad_Cam(model, pic_array, 'block5_conv3')
picture = picture[0,:,:,]
array_to_img(picture)
C'est comme ça? En visualisant avec la carte thermique de Grad-CAM, il a été dessiné de quel côté l'apprentissage profond est considéré comme une fonctionnalité. La partie où la couleur est la plus rouge est la partie qui contribue grandement à la perte de la classe de prédiction (la partie avec un grand dégradé), mais après tout c'est la partie qui frappe de sous les yeux au nez du visage, etc. Je me suis demandé si je regardais la partie où l'individualité apparaissait sur le visage. Ce qui était un peu surprenant, c'est que la couleur de la carte thermique est plus foncée entre les yeux et les oreilles (là?).
J'ai également appliqué environ 2 photos de nos Mirin et environ 3 photos d'autres chiens Shiba et les ai arrangées.
Certaines images regardent des parties similaires (des yeux au nez), tandis que d'autres regardent des parties complètement différentes, ce qui est assez intéressant. Je pense qu'il semble y avoir une tendance générale pour les fonctionnalités, mais cela peut être un peu difficile à expliquer avec cette seule carte de chaleur.
Cette fois, nous avons créé une carte thermique à l'aide de Grad-CAM. Il semble y avoir diverses autres méthodes pour visualiser les parties de fonctionnalités, telles que Grad-CAM ++ et Guided-Grad-CAM, donc j'aimerais essayer diverses méthodes à partir de la prochaine fois.
Recommended Posts