[PYTHON] [Pour les débutants en IA] Expliquez mnist_cnn.py ligne par ligne (apprenez MNIST avec Keras)

introduction

Cet article est le deuxième article prévu pour les trois fois. Cet article n'est qu'une explication ligne par ligne de mnist_cnn.py. Il y a des chevauchements avec le précédent, mais veuillez noter qu'une partie du contenu peut être dupliquée pour faciliter la lecture de l'article seul.

Il est destiné aux personnes qui s'intéressent à l'IA mais ne l'ont pas encore touchée. Je pense que si vous lisez ceci, vous devriez être en mesure de comprendre le flux d'apprentissage de base de l'apprentissage profond. (À l'origine, il a été créé en interne avec l'intention de l'utiliser pour la formation)

  1. [Pour les débutants en IA] Expliquez mnist_mlp.py ligne par ligne (apprenez MNIST avec Keras)
  2. [Pour les débutants en IA] Expliquez mnist_cnn.py ligne par ligne (apprenez MNIST avec Keras)
  3. [Pour les débutants en IA] mnist_transfer_cnn.py sera expliqué ligne par ligne (apprendre MNIST avec Keras)

À propos de la méthode de vérification du fonctionnement

Puisque MNIST est une image, il est préférable d'avoir un GPU pour exécuter ce code (c'est un peu pénible pour un CPU). La méthode recommandée consiste à utiliser Google Colaboratory. colab.gif Il n'y a que deux choses à faire. · Ouvrez un nouveau notebook Python 3 · Activer le GPU à partir du runtime Vous pouvez maintenant utiliser le GPU. Collez simplement le code dans la cellule et exécutez-le (le raccourci est CTRL + ENTRÉE) et cela fonctionnera.

À propos de mnist

Un ensemble de données d'images de texte manuscrit, souvent utilisé dans les didacticiels d'apprentissage automatique. Contenu: caractères manuscrits de 0 à 9 Taille de l'image: 28px * 28px Couleur: noir et blanc Taille des données: 70000 feuilles (60000 données d'entraînement, 10000 images et étiquettes de données de test sont disponibles)

Qu'est-ce que cnn

Convolutional Neural Network, un réseau de neurones convolutifs. Cet article est uniquement à des fins de code, je n'entrerai donc pas dans les détails du processus de convolution. Pour le dire très simplement, vous pouvez ** extraire les caractéristiques d'une image ** en effectuant un processus de convolution.

À propos de mnist_cnn.py

C'est le code pour créer un modèle pour juger les caractères manuscrits de mnist en utilisant Keras et TensorFlow. Reçoit 10 types de caractères manuscrits de 0 à 9 en entrée et crée un modèle qui les classe en 10 types de 0 à 9.

La fonction est la même que le premier mnist_mlp.py, mais le traitement dans le modèle est différent.

De plus, dans mlp, 28 * 28 données bidimensionnelles (telles données → [[0, 0, ..., 0, 0], ... [0, 0, ..., 0, 0]]) 784 une dimension Il a été converti en données (telles que les données → [0, 0, ... 0, 0]) et utilisé comme valeur d'entrée. Dans ce cnn, 28 * 28 données bidimensionnelles sont utilisées comme valeur d'entrée telle quelle.

Description du code

Préparation

'''Trains a simple convnet on the MNIST dataset.
Gets to 99.25% test accuracy after 12 epochs
(there is still a lot of margin for parameter tuning).
16 seconds per epoch on a GRID K520 GPU.
'''

#Aucun code spécial nécessaire (requis si Python version 3 mais le code est écrit en Python 2)
from __future__ import print_function

#Importer les bibliothèques requises
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

#constant
batch_size = 128  #Taille du lot. Taille des données à apprendre en une seule fois
num_classes = 10  #Nombre d'étiquettes à classer. Cette fois, nous classerons les images manuscrites en 10 types de 0 à 9.
epochs = 12       #Nombre d'époques. Combien de fois pour apprendre toutes les données(Dans l'article précédent mlp, c'était 20)
img_rows, img_cols = 28, 28  #Nombre de dimensions de l'image d'entrée

Dense: couche entièrement connectée Il existe un processus appelé Dropout: Dropout, qui désactive la sortie (0) à un certain taux (probabilité). Aplatir: convertir les données en une dimension Conv2D: couche pliante MaxPooling2D: couche de regroupement

Parmi les constantes définies au début, batch_size et epochs sont des ** hyperparamètres ** que les humains doivent ajuster. En modifiant cela, les performances du modèle changeront.

Pour expliquer brièvement, plus le batch_size est grand, plus l'apprentissage est stable, mais plus il faut de mémoire. epochs est le nombre de fois pour s'entraîner. Je pense qu'il sera plus intelligent d'étudier beaucoup, mais s'il est trop grand, il tombera dans un état de ** sur-apprentissage ** et les performances de généralisation diminueront. (= Vous pouvez juger des données utilisées pour l'apprentissage, mais vous ne serez pas en mesure de traiter des données inconnues.) Bien sûr, au moins cela reste fou en raison du manque d'apprentissage.

Prétraitement des données

#Lire les données mnist et former les données(60000 caisses)Et tester les données(10000 caisses)Diviser en
(x_train, y_train), (x_test, y_test) = mnist.load_data()

#Convertir la forme des données
'''
Le backend Keras est Theano(channels_first)Ou tensorflow(channels_last)Le format de l'image est différent selon
K.image_data_format()Est"channels_last"Ou"channels_first"Renvoie l'un des éléments ci-dessus, donc classez en fonction de ceci
Dans le cas du noir et blanc, le nombre de canaux est de 1. S'il s'agit d'une image couleur RVB, le nombre de canaux sera de 3.
Cette fois x_train:(60000, 28, 28)->(60000, 28, 28, 1)devenir
'''
if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

#Les données d'image prennent une valeur de 0 à 255, donc standardisez les données en les divisant par 255.
# .astype('float32')Convertissez le type de données avec.(Sinon, vous devriez obtenir une erreur lorsque vous vous brisez)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

#Vérifier en sortant la dimension et le nombre de données
print('x_train shape:', x_train.shape)    # x_train shape: (60000, 28, 28, 1)
print(x_train.shape[0], 'train samples')  # 60000 train samples
print(x_test.shape[0], 'test samples')    # 10000 test samples

#Étiqueter les données un-hot-Vectoriser
'''one-hot-L'image du vecteur ressemble à ceci
label  0 1 2 3 4 5 6 7 8 9
0:    [1,0,0,0,0,0,0,0,0,0]
8:    [0,0,0,0,0,0,0,0,1,0]'''
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

À propos de la normalisation: la valeur de chaque pixel de l'image est comprise entre 0 et 255. C'est une image qui convertit cela en 0 ~ 1. Lors de l'apprentissage automatique avec des images, la valeur est normalisée en divisant par 255.

À propos de one-hot-vector: Cette fois, il existe 10 types d'étiquettes de 0 à 9, et chacun est représenté par un nombre de 0 à 9. Cependant, les chiffres sur l'étiquette elle-même n'ont pas de sens car je veux simplement les classer en 10 types. Par conséquent, par un vecteur chaud, il est converti de sorte que seuls 0 et 1 puissent représenter quelle étiquette.

Définition du modèle

#Instancier la classe séquentielle
model = Sequential()

#Couche intermédiaire
#Couche pliante (filtre: 32 feuilles, taille du filtre:(3, 3), Fonction d'activation: Relu, Taille d'entrée reçue:( 28, 28, 1))Ajouter
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
#Couche pliante (filtre: 64 feuilles, taille du filtre:(3, 3), Fonction d'activation: Relu, la taille d'entrée reçue est automatiquement déterminée)Ajouter
model.add(Conv2D(64, (3, 3), activation='relu'))
#Couche de regroupement
model.add(MaxPooling2D(pool_size=(2, 2)))
# 0.25 chances de décrochage
model.add(Dropout(0.25))
#Convertir les données en une dimension
model.add(Flatten())
#Ajout d'une couche entièrement connectée (128 unités, fonction d'activation: relu, la taille d'entrée à recevoir est automatiquement déterminée)
model.add(Dense(128, activation='relu'))
# 0.5 chances d'abandonner
model.add(Dropout(0.5))

#Couche de sortie
#Ajout d'une couche entièrement connectée (10 unités, fonction d'activation: SoftMax, la taille d'entrée reçue est automatiquement déterminée)
model.add(Dense(num_classes, activation='softmax'))

Le modèle séquentiel est un modèle réalisé en empilant des couches de DNN. Vous devez spécifier input_shape uniquement pour la toute première couche. Puisque la fonction d'activation de la couche de sortie est cette fois un modèle de classification à valeurs multiples, softmax est utilisé.

Dense (couche entièrement connectée) ne peut être reçu que sous forme de données unidimensionnelles. Donc, avant Dense, vous devez convertir les données en 1D avec ** Flatten () **.

Apprentissage

#Mettre en place le processus d'apprentissage

model.compile(
              #Réglez la fonction de perte. Cette fois, c'est une classification, si catégorique_crossentropy
              loss=keras.losses.categorical_crossentropy,
              #L'algorithme d'optimisation est Adadelta(Différence avec mlp)
              optimizer=keras.optimizers.Adadelta(),
              #Spécifier la fonction d'évaluation
              metrics=['accuracy'])

#Apprendre
model.fit(x_train, y_train,      #Données d'entraînement, étiquette
          batch_size=batch_size, #Taille du lot (128)
          epochs=epochs,         #Nombre d'époques (12)
          verbose=1,             # #Afficher la progression de l'apprentissage sous forme de graphique à barres en temps réel(Cacher à 0)
          validation_data=(x_test, y_test))  #données de test(Pour tester chaque époque et calculer l'erreur)

Après avoir défini le modèle, spécifiez la fonction de perte et l'algorithme d'optimisation et compilez. Ensuite, transmettez les données au modèle pour l'entraînement.

L'algorithme d'optimisation Adadelta spécifié ici est également un type d'hyperparamètre. Je pense que l'algorithme appelé Adam est souvent utilisé, mais il n'y a absolument rien de bon, il faut donc faire des essais et des erreurs.

Évaluation

#Passer les données de test(verbose=0 ne donne pas de message de progression)
score = model.evaluate(x_test, y_test, verbose=0)
#Erreur de généralisation de la sortie
print('Test loss:', score[0])
#Performances de généralisation de sortie
print('Test accuracy:', score[1])

Après l'apprentissage, utilisez les données de test pour évaluer les performances que vous avez obtenues. Plus la perte est faible et plus la précision est élevée, meilleur est le modèle.

Recommended Posts

[Pour les débutants en IA] Expliquez mnist_cnn.py ligne par ligne (apprenez MNIST avec Keras)
[Pour les débutants en IA] Je vais expliquer mnist_transfer_cnn.py ligne par ligne (apprendre MNIST avec Keras)
[Pour les débutants en IA] Expliquez mnist_mlp.py ligne par ligne (apprenez MNIST avec Keras)
[Pour les débutants] J'ai fait un capteur humain avec Raspberry Pi et notifié LINE!
J'ai essayé de déplacer GAN (mnist) avec keras
J'ai essayé le tutoriel MNIST de tensorflow pour les débutants.
Classer les numéros mnist par keras sans apprentissage par l'enseignant [Auto Encoder Edition]
J'ai essayé de classer MNIST par GNN (avec PyTorch géométrique)
Pour les débutants, comment gérer les erreurs courantes dans les keras
Détection d'anomalies par encodeur automatique à l'aide de keras [Exemple d'implémentation pour les débutants]