[PYTHON] Bestimmen, ob es mein Kind ist, anhand des Bildes eines Shiba-Hundes durch tiefes Lernen (3) Visualisierung durch Grad-CAM

Einführung

――Dies ist das Ergebnis meiner eigenen Studienaufzeichnung über maschinelles Lernen und tiefes Lernen.

Zielgruppe dieses Artikels / Artikel, auf die verwiesen wird

über mich

Überblick über die vorherige Analyse (2)

Verfahrensablauf dieser Zeit (3)

** Schritt 1 Datenkonvertierung, Modellbau und Lernen ** ** Schritt 2 Implementierung von Grad-CAM **

-Dieser Artikel von @T_Tao ** ([Erkennung und Visualisierung abnormaler Teile durch Implementierung von vgg16 und Grad-CAM mit Keras](https: // qiita. Die Implementierung von Grad-CAM wurde unter com / T_Tao / items / 0e869e440067518b6b58)) ** eingeführt.

――Ich möchte den in diesem Artikel eingeführten Code implementieren und weiterhin die Fotodaten des Shiba-Hundes verwenden, um ihn mit Grad-CAM zu visualisieren. Es ist sehr interessant zu sehen, welcher Teil des Bildes eines Hundes als Merkmal angesehen wird, indem man tief lernt, zwischen den beiden zu unterscheiden. ――In der folgenden Implementierung schreiben Sie den Code des Referenzartikels grundsätzlich so, wie er ist. Außerdem werden die in der vorherigen Analyse (2) eingerichteten Daten von Google Drive unverändert verwendet.

Schritt 1 Datenkonvertierung, Modellbildung und Lernen

(1) Hängen Sie Google Drive ein

Hängen Sie es so ein, dass Sie Daten aus dem Ordner, der das Bild des Shiba-Hundes enthält, in Colab laden können.

#Google Drive-Mount
from google.colab import drive
drive.mount('/content/drive')

(2) Importieren Sie die erforderliche Bibliothek

Importieren Sie mit dem folgenden Code.

#Bibliothek importieren
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

(3) Datenvorverarbeitung

Bis zum letzten Mal habe ich den Image Data Generator von keras verwendet, um Bilddaten zu konvertieren. Verwenden Sie dieses Mal anstelle der Verwendung des Bilddatengenerators den folgenden Code, um die Bilddatei in einen Tensor zu konvertieren.

# cd '/content/drive/'My Drive/'Colab Notebooks'Wechseln Sie in den Arbeitsordner in
%cd '/content/drive/'My Drive/Colab Notebooks/Self_Study/02_mydog_or_otherdogs/

num_classes = 2 #Anzahl der Klassen
folder = ["mydog2", "otherdogs2"] #Ordnername, in dem Fotodaten gespeichert sind
image_size = 312 #Die Größe eines Eingabebildes
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, wenn Sie die Liste in ein Numpy-Array konvertieren möchten.array、np.Es gibt zwei Arten, Asarray.
#Wenn Sie eine Kopie des Numpy-Arrays erstellen möchten, np.Array verwenden.
#Wenn Sie eine Kopie erstellen möchten, die mit dem ursprünglichen Numpy-Array synchron bleibt, np.Verwenden Sie Asarray.

x = np.array(x)   
y = np.array(y)

(4) Bestätigung der konvertierten Daten

Lassen Sie uns überprüfen, wie die Daten konvertiert und in x und y gespeichert werden.

#Überprüfen Sie den Inhalt von x
display(x)

Der Inhalt von x, der die Bilddaten konvertiert hat, wird in die folgende Liste konvertiert.

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]],
(Weggelassen)

       ...,

        [[ 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'

Überprüfen Sie den Inhalt von y (Etikett).

#Überprüfen Sie den Inhalt von y
y

y wird mit zwei Arten von Beschriftungen erzeugt, "0" und "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])

(5) Teilen Sie die konvertierten Daten in Zugdaten und Testdaten auf

Der konvertierte Tensor wird durch sklearns train_test_split aufgeteilt, um mit dem später erstellten Modell zu trainieren.

#Unterteilt in Zugdaten und Testdaten
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

(6) Konvertieren Sie Etiketten in eine One-Hot-Darstellung

#Das y-Label wurde in einen heißen Ausdruck geändert
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')

Sie sollten ein ähnliches Ergebnis sehen:

192 train samples
48 test samples

(7) Modellbau und Zusammenstellung

Erstellen Sie das Modell mit dem folgenden Code. Dieser Optimierer spezifiziert SDG (probabilistische Gradientenabstiegsmethode).

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

(7) Modelllernen

Trainiere das Modell.

history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    validation_data=(x_test, y_test),
                    shuffle=True)

Speichern Sie das Modell.

model.save('mydog_or_otherdogs3(Grad-Cam).h5')

(8) Bewertung des trainierten Modells und Übergang von Genauigkeit und Verlust

Zeigen Sie das Ergebnis mit dem folgenden Code an und zeichnen Sie ein Diagramm. Das Validierungsergebnis ist wahrscheinlich auch hoch, weil die Bilddatei alle Daten verwendet (240 Blatt).

#Score-Anzeige
scores = model.evaluate(x_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])

#Genauigkeits- und Verlustdiagramm
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()

Das Ergebnis ist wie folgt.

Test loss: 0.04847167782029327
Test accuracy: 0.9795918367346939

traial07.png

Schritt 2 Implementierung von Grad-CAM

(1) Implementierung von Grad-CAM

Geben sie den untenstehenden Code ein. Laut @T_Tao ** Grad-CAM mit einem von mir mit Keras erstellten Modell * Dies bedeutet, dass es auf dem Code von * basiert.

K.set_learning_phase(1) #set learning phase

def Grad_Cam(input_model, pic_array, layer_name):

    #Vorverarbeitung
    pic = np.expand_dims(pic_array, axis=0)
    pic = pic.astype('float32')
    preprocessed_input = pic / 255.0

    #Berechnung der Vorhersageklasse
    predictions = input_model.predict(preprocessed_input)
    class_idx = np.argmax(predictions[0])
    class_output = input_model.output[:, class_idx]

    #Steigung bekommen
    conv_output = input_model.get_layer(layer_name).output   # layer_Ausgabe der Namensschicht
    grads = K.gradients(class_output, conv_output)[0]  # gradients(loss, variables)Gibt den Gradienten in Bezug auf den Verlust von Variablen zurück
    gradient_function = K.function([input_model.input], [conv_output, grads])  # input_model.Wenn Sie eine Eingabe eingeben, wird conv_Funktion zur Ausgabe von Output und Absolventen

    output, grads_val = gradient_function([preprocessed_input])
    output, grads_val = output[0], grads_val[0]

    #Mitteln Sie die Gewichte und multiplizieren Sie sie mit der Ausgabe der Ebene
    weights = np.mean(grads_val, axis=(0, 1))
    cam = np.dot(output, weights)

    #Bild und kombinieren als Heatmap
    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)  #Pseudofarbige monochrome Bilder
    jetcam = cv2.cvtColor(jetcam, cv2.COLOR_BGR2RGB)  #Konvertieren Sie Farbe in RGB
    jetcam = (np.float32(jetcam) + pic / 2)   #Kombiniert mit dem Originalbild
    return jetcam

Wenden wir das Ergebnis auf einige Bilder von Shiba-Hunden an. Zuallererst von meinem Hund.

# cd '/content/drive/'My Drive/'Colab Notebooks'Wechseln Sie in den angegebenen Ordner in
%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)

gradcam01b.png

Überlagern Sie die Heatmap

picture = Grad_Cam(model, pic_array, 'block5_conv3')
picture = picture[0,:,:,]
array_to_img(picture)

gradcam01.png

Ist es so Durch die Visualisierung mit der Heatmap von Grad-CAM wurde gezeichnet, auf welcher Seite das Deep Learning als Merkmal betrachtet wird. Der Teil, in dem die Farbe röter ist, trägt wesentlich zum Verlust der Vorhersageklasse bei (der Teil mit einem großen Gradienten), aber schließlich ist es der Teil, der unter den Augen auf die Nase des Gesichts usw. trifft. Ich fragte mich, ob ich den Teil betrachtete, in dem die Individualität im Gesicht erschien. Ein wenig überraschend ist, dass die Farbe der Wärmekarte zwischen Augen und Ohren (dort?) Dunkler ist.

Ich habe auch ungefähr 2 Bilder von unserem Mirin und ungefähr 3 Bilder von anderen Shiba-Hunden angewendet und sie arrangiert. gradcam02b.pnggradcam02.png gradcam03b.pnggradcam03.png

gradcam11b.pnggradcam11.png gradcam12b.pnggradcam12.png gradcam13b.pnggradcam13.png

Einige Bilder betrachten ähnliche Teile (von den Augen bis zur Nase), während andere völlig andere Teile betrachten, was sehr interessant ist. Ich denke, es scheint eine allgemeine Tendenz für die Merkmale zu geben, aber es kann ein wenig schwierig sein, dies allein mit dieser Heatmap zu erklären.

Dieses Mal haben wir mit Grad-CAM eine Heatmap erstellt. Es scheint verschiedene andere Methoden zur Visualisierung der Feature-Teile zu geben, wie z. B. Grad-CAM ++ und Guided-Grad-CAM. Daher möchte ich ab dem nächsten Mal verschiedene Methoden ausprobieren.

Recommended Posts

Bestimmen, ob es mein Kind ist, anhand des Bildes eines Shiba-Hundes durch tiefes Lernen (3) Visualisierung durch Grad-CAM
Nach dem Bild des Shiba-Hundes zu urteilen, indem man tief lernt, ob es mein Kind ist (1)
Beurteilung, ob es sich um mein Kind handelt oder nicht, nach dem Bild des Shiba-Hundes durch tiefes Lernen (2) Datenerhöhung, Transferlernen, Feinabstimmung
Sprachverarbeitung durch tiefes Lernen: Lassen Sie uns anhand der Stimme herausfinden, wer der Sprecher ist
Othello ~ Aus der dritten Zeile von "Implementation Deep Learning" (4) [Ende]
Die Kopiermethode von pandas.DataFrame ist standardmäßig Deep Copy
Bewerten Sie die Genauigkeit des Lernmodells durch einen Kreuztest von scikit learn
Den Namen der Methode, die ihn aufgerufen hat, finden Sie in der Python-Methode