[PYTHON] Analyse d'images par apprentissage profond à partir de Kaggle et Keras

introduction

Cet article présente la classification des ensembles de données MNIST à l'aide de l'environnement de développement de Kaggle (bloc-notes Kernel) et Keras comme introduction à l'analyse des moines de peinture. Le noyau est ouvert au public sur Kaggle, alors jetez un œil si vous voulez l'exécuter vous-même.

Si vous avez des erreurs, des questions ou des commentaires, veuillez nous en informer. Ce sera encourageant si vous pouvez obtenir LGTM!

Qu'est-ce que Kaggle

Kaggle est le plus grand concours analytique en ligne au monde. En outre, il existe un environnement de développement en ligne appelé Kernel notebook qui vous permet de travailler immédiatement sur l'analyse, ce qui est idéal pour démarrer l'analyse des données. Cet article est destiné à ceux qui se sont déjà inscrits auprès de Kaggle et savent comment utiliser Kernel. (Il existe de nombreux articles que même ceux qui ne connaissent pas peuvent être utiles, donc je pense que vous pouvez les rattraper immédiatement.)

Voir ci-dessous pour plus de détails.

Qu'est-ce que Keras

Keras est une bibliothèque d'apprentissage en profondeur basée sur Tensorflow, connue pour sa capacité à créer des modèles d'apprentissage en profondeur très rapidement.

Voir ci-dessous pour plus de détails.

Qu'est-ce que MNIST

Il s'agit d'un ensemble de données d'image très connu, composé de nombres manuscrits (0-9) et des nombres qu'ils représentent vraiment (étiquette correcte). image.png

Voir ci-dessous pour plus de détails.

Sujet principal

Encore une fois, cet article est également posté sur le noyau de Kaggle, donc si vous voulez un fork, veuillez le voir également.

Chargement et vérification des données

Vous pouvez voir que les données d'entraînement se composent de 42 000 éléments de données. De plus, bien qu'il y ait 785 colonnes, l'étiquette correcte est la première, vous pouvez donc voir que la quantité de caractéristiques utilisée pour l'apprentissage se compose de 784. Vous pouvez voir que l'étiquette est un entier et que la quantité d'entités est 0 pour la plupart des éléments.

#Chargement des données d'entraînement
train = pd.read_csv("../input/train.csv")
print(train.shape)
train.head()

image.png

Il y a 28000 données de test. Il n'y a pas d'étiquette correcte, il se compose donc de 784 colonnes.

#Chargement des données de test
test= pd.read_csv("../input/test.csv")
print(test.shape)
test.head()

image.png

Conversion de type et conversion en données numpy faciles à utiliser.


#Découpez la partie quantité de fonction des données d'entraînement à l'exclusion de l'étiquette de réponse correcte.
X_train = train.iloc[:,1:].values.astype('float32')
#Découpez uniquement l'étiquette de réponse correcte dans les données d'entraînement.
y_train = train.iloc[:,0].values.astype('int32')
#Ce sont des données de test.
X_test = test.values.astype('float32')

Regardons le pourcentage de 0 dans les données. Le rapport de 0 est d'environ 80%, et vous pouvez voir que la plupart des éléments sont 0. Dans cet ensemble de données, 0 signifie vide = zone non caractérisée.


print(f"Le pourcentage d'éléments non nuls{round((X_train > 0).sum()/(X_train >= 0 ).sum()*100)}%est")
print(f"Le pourcentage de 0 éléments{round((X_train == 0).sum()/(X_train >= 0 ).sum()*100)}%est")

image.png

En regardant la distribution des étiquettes correctes, nous pouvons voir que chaque étiquette de 0 à 9 constitue environ 10%. Par conséquent, il semble que l'ajustement dû au déséquilibre de classe ne soit pas nécessaire.



#Afficher le pourcentage d'étiquettes correctes dans un graphique circulaire
f, ax = plt.subplots(1,figsize=(6,6))
y_count = pd.Series(y_train).value_counts().sort_index()
ax.pie(y_count.values , 
       labels=y_count.index, 
       autopct='%1.1f%%', 
       counterclock = False,
       startangle = 90)
plt.show()

image.png

Ensuite, transformez les données dans un formulaire facile à gérer comme une image. Comme nous l'avons vu précédemment, chaque image se compose de 784 éléments, ce qui est en fait un effondrement unidimensionnel de données carrées comprenant 28 éléments verticaux et 28 éléments horizontaux. Se transforme en 28x28 pour toutes les données d'entraînement (42000 = X_train.shape [0]).


#Transformation des données
X_train = X_train.reshape(X_train.shape[0], 28, 28)

Visualisons les données brutes transformées. Ici, afin de considérer la signification des données brutes, exprimons les données sous forme de chaîne de caractères sans utiliser de bibliothèque d'images. Affiche la partie où l'élément non nul existe sous la forme #. Ensuite, vous pouvez obtenir la sortie comme des nombres manuscrits.

Les données originales sont une liste de nombres difficiles à comprendre pour les humains, mais il s'agissait en fait de données constituées de l'intention de l'encre (qu'elle ne soit pas 0 ou non) et de sa densité (valeur du nombre).


#Convertir les données en chaîne de caractères et afficher
def visualize_str(d):
    d = d.astype("int32").astype("str")    
    d[d != "0"] = "# "
    d[d == "0"] = ". "
    d = pd.DataFrame(d)
    for i in range(d.shape[0]):
        print("".join(d.iloc[i,:]))
    print("") 
        
for i in range(1):
    visualize_str(X_train[i])

image.png

Si vous essayez de l'afficher sous forme d'image, vous obtiendrez toujours le même résultat que l'affichage de chaîne de caractères précédent.


#Visualisez avec l'image
f, ax = plt.subplots(1,3)
for i in range(3):   
    ax[i].imshow(X_train[i], cmap=plt.get_cmap('gray'))

image.png

Étant donné que les images colorées sont parfois utilisées dans l'analyse d'images, on suppose que l'entrée du modèle a une dimension appelée canal de couleur qui comprend des nuances de couleur (principalement Mihara). Puisque cette fois c'est une échelle de gris, il n'y a pas de nouvelles données, mais nous allons convertir le tenseur selon l'idée ci-dessus. De plus, définissez un encodage à chaud et des nombres aléatoires comme préparation avant l'apprentissage.


#Ajouter un canal de couleur
X_train = X_train.reshape(X_train.shape[0], 28, 28,1)
X_test = X_test.reshape(X_test.shape[0], 28, 28,1)

#Un encodage à chaud
from keras.utils.np_utils import to_categorical
y_train= to_categorical(y_train)

#Nombres aléatoires fixes pour la reproductibilité
seed = 0
np.random.seed(seed)

Modèle 1: modèle linéaire

C'est enfin la modélisation, mais essayons d'abord un modèle linéaire très simple.

Et avant cela, définissez les fonctions d'importation et de standardisation de modules requises.

from keras.models import  Sequential
from keras.layers.core import  Lambda , Dense, Flatten, Dropout
#from keras.callbacks import EarlyStopping
from keras.layers import BatchNormalization, Convolution2D , MaxPooling2D

#Définition de la fonction de normalisation
mean_X = X_train.mean().astype(np.float32)
std_X = X_train.std().astype(np.float32)

def standardize(x): 
    return (x-mean_X)/std_X

Créons maintenant le modèle.


#Définition du modèle linéaire

model_linear= Sequential()
#Standardisation
model_linear.add(Lambda(standardize,input_shape=(28,28,1)))
#Passez à une dimension pour insérer la couche entièrement connectée
model_linear.add(Flatten())
#Couche entièrement connectée
model_linear.add(Dense(10, activation='softmax'))
#Visualisation du modèle
print("model_linear")
model_linear.summary()

image.png

Keras se compile après avoir défini le modèle. Lors de la compilation, l'index à optimiser par learning = loss et l'indice à vraiment optimiser sont spécifiés.

#Compiler le modèle
#Spécifiez l'index à optimiser et l'index à observer
from keras.optimizers import Adam ,RMSprop

model_linear.compile(optimizer=RMSprop(lr=0.001),
                     loss='categorical_crossentropy',
                     metrics=['accuracy'])

Maintenant que le modèle est prêt, je souhaite remplir le modèle avec des données, mais je dois préparer les données. Préparez un générateur et divisez les données pour la validation croisée. (Cela devrait être appelé la méthode holdout, mais dans Kaggle, elle est généralement exprimée comme une validation croisée, donc je suis conscient du malentendu et je l'exprime de cette façon.)


#Préparation des données à saisir

#Définition du générateur
from keras.preprocessing import image
generator = image.ImageDataGenerator()

#Toutes les données d'apprentissage utilisées au moment de la soumission
X = X_train
y = y_train

#Validation croisée
from sklearn.model_selection import train_test_split
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.15, random_state=seed)
train_generator = generator.flow(X_train, y_train, batch_size=64)
val_generator = generator.flow(X_val, y_val, batch_size=64)

Préparez également une planche tensorielle pour faciliter la visualisation de la situation d'apprentissage et des résultats. La sortie standard affichera l'URL, alors ouvrez-la dans votre navigateur.


#Lancement de tensorboard

import tensorflow as tf 
!rm -rf ./logs/ 
!mkdir ./logs/
!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
!unzip ngrok-stable-linux-amd64.zip

import os
import multiprocessing
import datetime

pool = multiprocessing.Pool(processes = 10)
results_of_processes = [pool.apply_async(os.system, args=(cmd, ), callback = None )
                        for cmd in [
                        f"tensorboard --logdir ./logs/ --host 0.0.0.0 --port 6006 &",
                        "./ngrok http 6006 &","y"
                        ]]
! curl -s http://localhost:4040/api/tunnels | python3 -c \
    "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])"

        
log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=0)

Maintenant que nous sommes prêts, il est temps de commencer à apprendre. Il montre la progression de l'apprentissage avec la barre de progression et l'index spécifié par compile.


#Apprentissage des données avec epoch3
# ~Je pense que cela prendra environ 15 minutes
import tensorflow as tf
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    history_linear=model_linear.fit_generator(generator=train_generator,
                                              steps_per_epoch=train_generator.n, 
                                              epochs=3, 
                                              validation_data=val_generator, 
                                              validation_steps=val_generator.n, 
                                              callbacks=[tensorboard_callback]
                                             )

image.png

Les résultats ci-dessus montrent comment l'apprentissage se fait, mais nous visualiserons les résultats pour une compréhension plus intuitive.

En regardant les pertes, nous pouvons voir qu'un surapprentissage se produit parce que les résultats de validation augmentent à mesure que l'apprentissage progresse. En revanche, notez que la validation de l'ACC (taux de réponse correcte) n'a pas diminué de manière monotone. Les indicateurs discontinus comme ACC sont difficiles à gérer, vous optimisez donc à la place avec une fonction de perte facile à utiliser.

#Visualisation des résultats

#Définition de la fonction pour tracer le résultat
def plt_history(history,keys):
    history_dict = history.history
    n = len(keys)
    f, ax = plt.subplots(n,figsize=(8,4*n))
    for i in range(n):
        train_value = history_dict[keys[i][0]]
        val_value = history_dict[keys[i][1]]
        epochs = range(1, len(train_value) + 1)
        if n==1:
            ax.plot(epochs, train_value, 'bo',label = keys[i][0])
            ax.plot(epochs, val_value, 'b+',label = keys[i][1])
            ax.legend()
            ax.set_xlabel('Epochs')
            ax.set_ylabel(keys[i][0])
        else:
            ax[i].plot(epochs, train_value, 'bo',label = keys[i][0])
            ax[i].plot(epochs, val_value, 'b+',label = keys[i][1])
            ax[i].legend()
            ax[i].set_xlabel('Epochs')
            ax[i].set_ylabel(keys[i][0])

    plt.show()

#Visualisation
plt_history(history_linear, [["loss","val_loss"],["acc","val_acc"]])

image.png

Modèle 2: modèle entièrement couplé

Dans ce modèle, une couche entièrement connectée est ajoutée pour approfondir la couche. Nous avons également changé l'algorithme d'optimisation en Adam. (Cela devrait être comparé expérimentalement pour déterminer l'optimum.)

De plus, bien que nous ayons défini et traité des modèles séquentiellement plus tôt, en général, nous définissons des types de modèles avec des classes et des fonctions, et créons différents modèles d'entraînement avec plusieurs paramètres et données d'apprentissage différents. Par conséquent, à partir de là, nous définirons le modèle avec une fonction.

#Définition du modèle
def get_fc_model():
    model = Sequential()
    model.add(Lambda(standardize,input_shape=(28,28,1)))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dense(10, activation='softmax'))
    model.compile(optimizer = Adam(), 
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    return model


model_fc = get_fc_model()
model_fc.optimizer.lr=0.01
model_fc.summary()

image.png

Apprenez le modèle de la même manière qu'avant. Si vous souhaitez essayer plusieurs modèles en peu de temps, vous devez faire un compromis tel que la réduction du nombre d'époques. En regardant les résultats, nous pouvons voir que la validation ACC est plus élevée qu'avant.


#Apprentissage de modèle
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    history_fc=model_fc.fit_generator(generator=train_generator, 
                                      steps_per_epoch=train_generator.n, 
                                      epochs=1, 
                                      validation_data=val_generator, 
                                      validation_steps=val_generator.n,
                                      callbacks=[tensorboard_callback]
                                     )

#Résultat d'apprentissage
history_dict_fc = history_fc.history
history_dict_fc

image.png

Modèle 3: modèle CNN

Ensuite, essayez le modèle CNN qui inclut la couche de pliage et la couche de regroupement. Comme CNN peut apprendre efficacement une large zone, une grande précision peut être attendue pour les problèmes d'analyse d'image. Cette fois, nous allons préparer deux types de profondeur de couche et voir la différence.

#Définition du modèle


from keras.layers import Convolution2D, MaxPooling2D

#Un modèle avec deux plis et deux regroupements
def get_cnn_model1():
    model = Sequential([
        Lambda(standardize, input_shape=(28,28,1)),
        Convolution2D(32,(3,3), activation='relu'),
        MaxPooling2D(),
        Convolution2D(64,(3,3), activation='relu'),
        MaxPooling2D(),
        Flatten(),
        Dense(512, activation='relu'),
        Dense(10, activation='softmax')
        ])
    model.compile(optimizer = Adam(), loss='categorical_crossentropy',
                  metrics=['accuracy'])
    return model

#Un modèle avec pliage et mise en commun 3 fois chacun
def get_cnn_model2():
    model = Sequential([
        Lambda(standardize, input_shape=(28,28,1)),
        Convolution2D(32,(3,3), activation='relu'),
        MaxPooling2D(),
        Convolution2D(64,(3,3), activation='relu'),
        MaxPooling2D(),
        Convolution2D(128,(3,3), activation='relu'),
        MaxPooling2D(),
        Flatten(),
        Dense(512, activation='relu'),
        Dense(10, activation='softmax')
        ])
    model.compile(optimizer = Adam(), loss='categorical_crossentropy',
                  metrics=['accuracy'])
    return model

model_cnn1 = get_cnn_model1()
model_cnn2 = get_cnn_model2()
model_cnn1.optimizer.lr=0.01
model_cnn2.optimizer.lr=0.01

Le modèle peu profond apprend 843658 paramètres

model_cnn1.summary()

image.png

Le modèle plus profond apprend 163 850 paramètres, ce qui est inférieur à model_cnn1. En effet, l'effet périphérique de la couche de pliage et de la couche de mise en commun réduit considérablement l'entrée de données dans la couche entièrement connectée. En fait, en regardant les dimensions d'aplatir, il était de 1600 pour cnn1, mais seulement de 128 pour cnn2. Si la taille de l'image est grande, il est souhaitable de réduire la taille des données de cette manière, mais quel genre de résultat sera obtenu avec des données compactes comme cette fois?

model_cnn2.summary()

image.png

Nous étudierons chacun.


with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    history_cnn1=model_cnn1.fit_generator(generator=train_generator, 
                                     steps_per_epoch=train_generator.n, 
                                     epochs=1, 
                                     validation_data=val_generator, 
                                     validation_steps=val_generator.n, 
                                     callbacks=[tensorboard_callback]
                                    )

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    history_cnn2=model_cnn2.fit_generator(generator=train_generator, 
                                     steps_per_epoch=train_generator.n, 
                                     epochs=1, 
                                     validation_data=val_generator, 
                                     validation_steps=val_generator.n, 
                                     #callbacks=[tensorboard_callback]
                                    )

Vérifions le résultat.

Comparé au modèle CNN avec une couche peu profonde, le modèle CNN avec une couche profonde a de mauvais résultats en termes de taux de perte et de précision pour les données d'apprentissage et les données de validation. Il y a plusieurs raisons possibles à cela.

① Le modèle est mauvais La raison pour laquelle le modèle est mauvais est que les paramètres d'apprentissage ont diminué. Le fait qu'il existe de nombreux paramètres qui peuvent être ajustés signifie que vous pouvez créer une expression plus variée. Ce modèle a un petit nombre de paramètres, il n'a donc peut-être pas été suffisamment expressif.

② Les données d'apprentissage sont mauvaises Le surentraînement est susceptible de se produire lorsque le nombre de données d'entraînement est insuffisant. Cette fois, le taux de précision des données d'apprentissage n'est pas si mauvais, mais le résultat de la validation présente une grande divergence, ce qui est un état de surapprentissage typique. Il est peut-être possible de s'améliorer en élargissant les données à essayer à partir de maintenant.

③ Manque d'apprentissage Il est possible que le modèle n'ait pas encore été entièrement formé. Dans ce cas, la perte de données d'apprentissage est plus grande que celle de cnn1, donc si vous augmentez l'époque, la formation peut avoir lieu. Cependant, la divergence par rapport à la validation est un autre problème, donc augmenter l'époque dans cet état ne sera pas une solution essentielle.

history_cnn1.history

image.png

history_cnn2.history

image.png

Expansion des données

On pense que plus il y a de données d'entraînement, plus la performance de généralisation est élevée = un surapprentissage est moins susceptible de se produire. L'augumentation des données est une méthode permettant d'augmenter artificiellement les données d'entraînement à partir d'un nombre limité de données. L'expansion des données est une technique pour gonfler les données en apportant des modifications mineures aux données données.

#Expansion des données

from keras.preprocessing import image


DA_generator =image.ImageDataGenerator(rotation_range=10, 
                                 width_shift_range=0.1, 
                                 shear_range=0.1,
                                 height_shift_range=0.1, 
                                 zoom_range=0.1)
train_DA_generator = DA_generator.flow(X_train, y_train, batch_size=64)
val_DA_generator = DA_generator.flow(X_val, y_val, batch_size=64)

#Exemple de données étendues
tmp_gen = DA_generator.flow(X_train[0].reshape((1,28,28,1)), batch_size = 1)
for i, tmp in enumerate(tmp_gen):
    plt.subplot(330 + (i+1))
    plt.imshow(tmp.reshape((28,28)), cmap=plt.get_cmap('gray'))
    if i == 8:
        break

image.png

Je pense que cela prendra environ 15 minutes pour apprendre. Suite à l'expansion des données, les résultats de la validation ont été améliorés. Les résultats des données d'entraînement et les résultats de la validation s'amélioreront pour chaque époque, donc si vous avez le temps, essayez d'augmenter l'époque et expérimentez.

#CNN 1 couche CNN peu profonde

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    model_cnn1.optimizer.lr=0.005
    history_cnn1_DA=model_cnn1.fit_generator(generator=train_DA_generator, 
                                          steps_per_epoch=train_DA_generator.n, 
                                          epochs=1, 
                                          validation_data=val_DA_generator, 
                                          validation_steps=val_DA_generator.n, 
                                          callbacks=[tensorboard_callback]
                                         )

history_cnn1_DA.history

image.png

Modèle 4: normalisation par lots

Dans les modèles précédents, l'entrée était normalisée. Cependant, cela ne garantit pas que la sortie de chaque couche est normalisée. Ensuite, après une certaine couche, la sortie devient très grande et les paramètres peuvent devenir très petits. Ou vice versa, les paramètres peuvent être très importants.

Dans un tel cas, l'apprentissage ne peut pas être bien fait, mais ce problème peut être résolu en ajoutant une couche de normalisation par lots qui standardise pour chaque couche. On dit que cela améliore à la fois les performances de généralisation et la vitesse d'apprentissage.

Le nombre d'époques est également fixé à 1 cette fois, mais si vous avez du temps à perdre, augmentez le nombre d'époques et observez les conditions de surapprentissage.


from keras.layers.normalization import BatchNormalization

def get_bn_model():
    model = Sequential([
        Lambda(standardize, input_shape=(28,28,1)),
        Convolution2D(32,(3,3), activation='relu'),
        BatchNormalization(axis=1),
        MaxPooling2D(),
        BatchNormalization(axis=1),
        Convolution2D(64,(3,3), activation='relu'),
        BatchNormalization(axis=1),
        MaxPooling2D(),
        BatchNormalization(axis=1),
        Flatten(),
        BatchNormalization(),
        Dense(512, activation='relu'),
        BatchNormalization(),
        Dense(10, activation='softmax')
        ])
    model.compile(optimizer = Adam(), loss='categorical_crossentropy', metrics=['accuracy'])
    return model
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    model_bn= get_bn_model()
    model_bn.optimizer.lr=0.01
    history_bn=model_bn.fit_generator(generator=train_DA_generator, 
                                      steps_per_epoch=train_DA_generator.n, 
                                      epochs=1, 
                                      validation_data=val_DA_generator, 
                                      validation_steps=val_DA_generator.n,
                                      callbacks=[tensorboard_callback]
                                     )

history_bn.history

image.png

Modèle 5: modèle optimal

Enfin, je présenterai le modèle avec le score le plus élevé parmi les modèles présentés dans cet article. La conception de ce modèle nécessite des essais et des erreurs, comme l'ajout de couches et la modification des fonctions d'optimisation, comme nous l'avons vu jusqu'à présent. Ce modèle optimal est un modèle qui a subi une série d'essais et d'erreurs (dans mes capacités et mon environnement de développement actuels).

Nous avons ajouté une couche d'exclusion, le réglage initial de He et un rappel qui modifie le taux d'apprentissage étape par étape.

En conséquence, la variation marque un taux de réponse correcte de 99,4%.


from keras.layers import Dense, Dropout, Flatten, Convolution2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.callbacks import ReduceLROnPlateau

def get_opt_model():
    model = Sequential([
        Lambda(standardize, input_shape=(28,28,1)),
        Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
        Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
        MaxPooling2D(),
        Dropout(0.20),
        Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
        Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
        MaxPooling2D(),
        Dropout(0.25),
        Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
        Dropout(0.25),
        Flatten(),
        Dense(128, activation='relu'),
        BatchNormalization(),
        Dropout(0.25),
        Dense(10, activation='softmax')
    ])
    model.compile(optimizer=Adam(),
                  loss='categorical_crossentropy', 
                  metrics=['accuracy'])
    return model


learning_rate_reduction = ReduceLROnPlateau(monitor='val_loss', 
                                            patience=3, 
                                            verbose=1, 
                                            factor=0.5, 
                                            min_lr=0.0001)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    model_opt = get_opt_model()
    history_opt = model_opt.fit_generator(generator=train_DA_generator, 
                                          steps_per_epoch=train_DA_generator.n, 
                                          epochs=3, 
                                          validation_data=val_DA_generator, 
                                          validation_steps=val_DA_generator.n,
                                          callbacks=[tensorboard_callback, learning_rate_reduction]
                                         )
    Y_pred = model_opt.predict_classes(X_val,verbose = 0)
    Y_pred_prob = model_opt.predict(X_val,verbose = 0)

#Visualisation des résultats
plt_history(history_opt, [["loss","val_loss"],["acc","val_acc"]])

image.png

history_opt.history

image.png

Vérifiez le résultat

Il y avait des réponses incorrectes même dans le modèle optimal, mais quel type de données sont-elles incorrectes? En regardant la matrice mixte, il semble qu'il n'y ait presque pas de réponses incorrectes, mais il y a des cas où 1 est confondu avec 7 et 7 est confondu avec 2.

#Définition d'une fonction qui affiche une matrice de confusion
import itertools
def plt_confusion_mtx(confusion_mtx):
    cmap=plt.cm.Reds
    title='Confusion matrix'
    f, ax = plt.subplots(1,figsize=(6,6))
    im = ax.imshow(confusion_mtx, interpolation='nearest', cmap=cmap)
    ax.set_title(title)
    ax.set_xticks(np.arange(10))
    ax.set_yticks(np.arange(10))
    ax.set_xlabel('Predicted label')
    ax.set_ylabel('True label')
    f.colorbar(im)
    thresh = confusion_mtx.max() / 2
    for i, j in itertools.product(range(confusion_mtx.shape[0]), range(confusion_mtx.shape[1])):
        ax.text(j, i, confusion_mtx[i, j],
                horizontalalignment="center",
                color="white" if confusion_mtx[i, j] > thresh else "black")

        

#Affichage de la matrice de confusion
from sklearn.metrics import confusion_matrix
Y_true = np.argmax(y_val,axis=1) 
confusion_mtx = confusion_matrix(Y_true, Y_pred) 
plt_confusion_mtx(confusion_mtx)

image.png

#Précision pour chaque classe mondiale,Confirmation de rappel, etc.

from sklearn.metrics import classification_report
target_names = ["Class {}".format(i) for i in range(10)]
print(classification_report(Y_true, Y_pred, target_names=target_names))

image.png

Lorsque vous regardez les données de réponse incorrectes, il y a des cas où il est difficile pour les humains de les distinguer, mais on soupçonne plutôt que l'étiquetage est erroné.

#Confirmation de données de réponse incorrectes

errors = (Y_pred - Y_true != 0)
Y_pred_errors = Y_pred[errors]
Y_pred_prob_errors = Y_pred_prob[errors]
Y_true_errors = Y_true[errors]
X_val_errors = X_val[errors]

def display_errors(errors_index,img_errors,pred_errors, obs_errors):
    """ This function shows 6 images with their predicted and real labels"""
    n = 0
    nrows = 2
    ncols = 3
    fig, ax = plt.subplots(nrows,ncols, figsize = (8,8))
    for row in range(nrows):
        for col in range(ncols):
            error = errors_index[n]
            ax[row,col].imshow((img_errors[error]).reshape((28,28)))
            ax[row,col].set_title("Predicted label :{}\nTrue label :{}".format(pred_errors[error],obs_errors[error]))
            n += 1

errors = (Y_pred - Y_true != 0)
tmp = Y_pred_prob[errors] - to_categorical(Y_pred[errors])
display_index = np.argsort(tmp.max(axis=1))[:6]
display_errors(display_index, X_val_errors, Y_pred_errors, Y_true_errors)

image.png

On peut dire que le modèle optimal a des performances suffisantes pour résister à une utilisation pratique.

en conclusion

Ceci conclut l'introduction à l'analyse d'images Deep Learning par Keras. À partir de là, vous pouvez essayer de vous entraîner avec des ensembles de données plus complexes, essayer le transfert d'apprentissage avec des modèles entraînés, essayer des modèles d'apprentissage en profondeur célèbres, et bien plus encore. Je vais. Si cet article est utile à quelqu'un, j'aimerais mettre à jour ces articles de tutoriel à l'avenir, alors veuillez me soutenir chez LGTM.

Aussi, je suis toujours à la recherche d'un emploi, alors faites-le moi savoir si vous en avez l'opportunité.

Recommended Posts

Analyse d'images par apprentissage profond à partir de Kaggle et Keras
Analyse émotionnelle des tweets avec apprentissage en profondeur
Défiez la classification des images avec TensorFlow2 + Keras 9-Apprentissage, sauvegarde et chargement de modèles-
Analyse de données à partir de python (pré-traitement des données-apprentissage automatique)
Mettez vos propres données d'image dans Deep Learning et jouez avec
Apprentissage automatique à partir de zéro (apprentissage automatique appris avec Kaggle)
Apprentissage parallèle du deep learning par Keras et Kubernetes
Reconnaissance d'image avec keras
Prédire les tags en extrayant des fonctionnalités musicales avec Deep Learning
Classer les visages d'anime par suite / apprentissage profond avec Keras
Essayez l'apprentissage en profondeur avec TensorFlow
Apprentissage d'ensemble et analyse de paniers
Analyse de régression multiple avec Keras
Reconnaissance d'image par apprentissage profond 1 théorie
Apprentissage amélioré à partir de Python
Apprentissage profond du noyau avec Pyro
Essayez le Deep Learning avec FPGA
Essayez le machine learning à la légère avec Kaggle
Générez des Pokémon avec Deep Learning
Reconnaissance d'image avec Keras + OpenCV
Classification d'images avec un réseau de neurones auto-fabriqué par Keras et PyTorch
Reconnaissez votre patron avec Deep Learning et masquez l'écran
[Apprentissage en profondeur] Classification d'images avec un réseau neuronal convolutif [DW jour 4]
Créez un environnement GPU avec GCP et l'image officielle de Kaggle (docker)
Apprentissage en profondeur avec Shogi AI sur Mac et Google Colab
HIKAKIN et Max Murai avec vidéo de jeu en direct et apprentissage en profondeur
Essayez le Deep Learning avec les concombres FPGA-Select
Identification de la race de chat avec Deep Learning
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 11
Apprentissage en profondeur avec Shogi AI sur Mac et Google Colab Chapitres 1 à 6
Prédire le Titanic de Kaggle avec Keras (Kaggle ⑦)
Segmentation d'image avec scikit-image et scikit-learn
J'ai essayé de rendre le deep learning évolutif avec Spark × Keras × Docker
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 8
Essayez l'apprentissage en profondeur avec TensorFlow Partie 2
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 12 3
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 7
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 10 6-9
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 10
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 7 5-7
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 9
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 12 3
Comparez DCGAN et pix2pix avec Keras
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 12 3
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 12 1-2
Organisez des plateformes d'apprentissage automatique et d'apprentissage en profondeur
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 12 3
[Note de lecture] Apprentissage automatique pratique avec Scikit-Learn, Keras et TensorFlow Chapitre 1
Vérifiez la forme de squat avec l'apprentissage en profondeur
Implémentation du modèle de reconnaissance d'images d'apprentissage en profondeur 2
Catégoriser les articles de presse grâce au Deep Learning
Prévisions des ventes de collations avec apprentissage en profondeur
Faites sourire les gens avec le Deep Learning
Analyse de données à partir de python (visualisation de données 1)
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 12 3 ~ 5
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 7 9
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 8 5-9
Deep Learning avec Shogi AI sur Mac et Google Colab Chapitre 8 1-4