La dernière fois, nous avons présenté la bibliothèque Deep Learning Keras à Windows et effectué une classification binaire indiquant si le carré est portrait ou paysage. Si vous ne l'avez pas encore lu, il sera peut-être plus facile de le comprendre à partir de là. En passant, cette fois, je pense que la classification binaire n'est pas intéressante jusqu'à ce que vous utilisiez l'apprentissage en profondeur, donc comme prochaine étape, je vais effectuer une classification multi-classe des nombres en utilisant un ensemble de données de caractères manuscrits de 0 à 9 appelé MNIST. .. Dans cet article également, le réseau continuera à utiliser Multilayer Perceptron (MLP). Je n'ai pas parlé de perceptrons multicouches, alors parlons brièvement d'abord. La valeur initiale et l'explication des paramètres d'optimisation seront abordées séparément dans environ 5.
Qu'est-ce que Perceptron exactement? D'après le premier livre de la bibliographie
Perceptron est un algorithme mis au point en 1957 par un chercheur américain nommé Rosen Blood, qui est à l'origine du réseau neuronal (deep learning).
Il semble que (l'expression a un peu changé). Je ne pense pas pouvoir dire exactement ce que c'est, alors je vais expliquer ce qu'est le Perceptron lui-même. Pour expliquer avec des mots, c'est "un appareil qui reçoit plusieurs signaux comme entrées et qui sort un signal", et le signal de sortie prend deux valeurs, 0 ou 1. Le neurone calcule la somme des signaux envoyés et ne délivre 1 que lorsque la somme dépasse une certaine valeur limite. On dit que cela est parfois exprimé par "** le feu des neurones **". La valeur limite est appelée valeur seuil, et lorsqu'elle est exprimée par $ \ theta $, la sortie $ y $ peut être exprimée par la formule suivante.
\begin{eqnarray}
y=\left\{ \begin{array}{ll}
0 & (\omega_1 x_1 + \omega_2 x_2 \leq \theta) \\
1 & (\omega_1 x_1 + \omega_2 x_2 > \theta) \\
\end{array} \right.
\end{eqnarray}
En d'autres termes, le ** poids $ \ omega $ de Perceptron représente l'importance du signal **, et ** biais $ b $ est un ** paramètre qui ajuste la facilité de déclenchement. Le biais $ b $ est $ b = - \ theta $. Dans certains contextes, ce biais est également appelé poids. Cependant, comme vous pouvez le voir à partir de l'équation ci-dessus, un seul perceptron peut être identifié par une ligne droite. Par conséquent, il n'est pas possible de traiter des événements non linéaires.
Les perceptrons simples ne peuvent être utilisés que dans des problèmes linéaires. Cependant, Perceptron peut également être superposé, ce qui lui permet de gérer également des problèmes non linéaires. C'est ce qu'on appelle un perceptron multicouche. Il y a quelques choses à savoir ici. Ce que l'on appelle communément un perceptron multicouche est différent du perceptron simple décrit précédemment. La valeur de sortie du perceptron multicouche est 0 ou 1 pour le perceptron, tandis que la valeur de sortie est un nombre réel de 0 à 1 lorsque la fonction d'activation est sigmoïde. Eh bien, tout à coup, je suis venu avec la fonction d'activation de mot. La fonction d'activation est que le perceptron simple détermine si la sortie est 0 ou 1 par la valeur de seuil, alors que dans le perceptron multicouche, elle est sortie en passant la fonction d'activation non linéaire $ h $ avec la somme des entrées comme variable. Détermine le nombre réel de.
\begin{eqnarray}
a =& \omega_1 x_1 + \omega_2 x_2 + b\\
y =& h(a)
\end{eqnarray}
Par exemple, la fonction sigmoïde est la fonction suivante, qui génère une valeur réelle entre 0 et 1 en fonction de la valeur de la variable d'entrée. sigmoïde
\begin{equation}
h(x) = \frac{1}{1+\exp(-x)}
\end{equation}
Enfin, le Perceptron multicouche peut être résumé comme suit.
Pourriez-vous en quelque sorte comprendre le Perceptron multicouche? À ce stade, nous identifions enfin les caractères manuscrits à l'aide d'un perceptron multicouche.
MNIST peut lire les données d'entraînement et de test sous la forme d'un ensemble de données dans Keras. Vous n'avez donc pas à télécharger l'ensemble de données comme vous l'avez fait la dernière fois. Vous pouvez afficher la formation et ses résultats avec un script comme celui-ci: J'ai utilisé la fonction sigmoïde pour la fonction d'activation du perceptron multicouche la dernière fois, mais cette fois j'utilise la fonction ReLU. La raison de l'utilisation de la fonction ReLU est qu'elle est plus précise, mais j'expliquerai la raison en détail dans un autre article. Veillez également à définir la fonction d'activation de la couche finale sur Softmax lorsque vous souhaitez classer. Sinon, il ne sera pas classé. Le bloc-notes Jupyter a été téléchargé sur Gist.
mnist_detect_class10.py
import numpy as np
import matplotlib.pyplot as plt
from keras.utils import np_utils
from scipy.misc import toimage
#Requis pour lire l'ensemble de données MNIST
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
#Définition du nombre de classes à classer
class_num = 10
#Charger le jeu de données mnist
(X_train, y_train),(X_test, y_test) = mnist.load_data()
#Normaliser les données d'entraînement
X_train = X_train/255
X_test = X_test/255
#Formater les données pour l'entrée
#Convertissez un tableau bidimensionnel de 28 pixels x 28 pixels par image en un vecteur de 784 dimensions
X_train = X_train.reshape(-1,784)
X_test = X_test.reshape(-1,784)
#Changer l'étiquette en un tableau correspondant au nombre de classes
#Exemple: y_train:[0 1 7 5] -> Y_train:[[1 0 0 0 0 0 0 0 0 0],[0 1 0 0 0 0 0 0 0 0],[0 0 0 0 0 0 0 1 0 0],[0 0 0 0 0 1 0 0 0 0]]
Y_train = np_utils.to_categorical(y_train,class_num)
Y_test = np_utils.to_categorical(y_test,class_num)
#Création d'un réseau Perceptron multicouche
#Dimensions d'entrée 784(28x28)Et définissez la sortie finale sur le nombre de classes
model = Sequential()
model.add(Dense(512, input_dim=784, init='uniform'))
#Utilisez la fonction ReLU pour la fonction d'activation
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(512, init='uniform'))
#Utilisez la fonction ReLU pour la fonction d'activation
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(class_num, input_dim=512, init='uniform'))
#Dans le cas de la classification, utilisez toujours Softmax pour la couche finale
model.add(Activation('softmax'))
#Sélectionnez catégoriel car il s'agit d'une classification à valeurs multiples, sélectionnez RMSprop comme algorithme d'optimisation
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
#Former le modèle avec un nombre fixe d'essais (itérations de jeux de données)
model.fit(X_train, Y_train,
nb_epoch=5,
batch_size=100)
#Évaluer les paramètres post-apprentissage
score = model.evaluate(X_test, Y_test, batch_size=100)
print(score)
#Estimer l'étiquette des données de test, la valeur de retour sera l'étiquette
classified_label = model.predict_classes(X_test[0:10,:])
#Affichage de l'étiquette et de l'image estimées
for i in range(10):
#Convertir les données vectorielles en tableau et les convertir en données d'image
img = toimage(X_test[i,:].reshape(28,28))
plt.subplot(2,5,i+1)
plt.imshow(img, cmap='gray')
plt.title("Class {0}".format(classified_label[i]))
plt.axis('off')
plt.show()
#Enregistrer le modèle et le poids
model_json = model.to_json()
open('mnist_architecture.json', 'w').write(model_json)
model.save_weights('mnist_weights.h5', overwrite=True)
Les 10 étiquettes et images estimées depuis le début des données de test sont les suivantes. Vous pouvez voir que la classe et le personnage correspondent. À propos, le résultat du test de cette image était un niveau suffisamment pratique avec un taux de réponse correcte de 97,7%. En regardant l'image de test, il semble que 5 soit confondu avec 8, mais il peut être classé correctement. À propos, avec Sigmaid, le taux de réponse correct n'était que d'environ 80%, il est donc important de définir les paramètres appropriés.
À ce stade, l'apprentissage semble être assez précis. Cependant, je veux toujours tester avec les personnages que j'ai écrits. Par conséquent, j'ai créé une image avec des nombres de 0 à 9 écrits sur une toile de 56 pixels x 56 pixels avec de la peinture. J'ai essayé de prédire la classe en lisant les poids entraînés avec le code suivant. Le bloc-notes Jupyter a été téléchargé sur Gist.
my_mnist.py
import numpy as np
import matplotlib.pyplot as plt
from keras.utils import np_utils
from keras.models import Sequential,model_from_json
from keras.preprocessing import image
from keras.applications.imagenet_utils import preprocess_input, decode_predictions
#Nombre d'images préparées pour le test
test_num = 10
#Modèle de charge
model = model_from_json(open('mnist_architecture.json').read())
#Poids du modèle de charge
model.load_weights('mnist_weights.h5')
for i in range(test_num):
#Spécifiez le nom du fichier
img_path = str(i)+".jpg "
#28 pixels x 28 pixels, charge l'image en échelle de gris
img = image.load_img(img_path, grayscale=True, target_size=(28, 28))
#Convertir l'image chargée en tableau
x = image.img_to_array(img)
#Vérification de la taille de la baie
print(x.shape)
#Formez un tableau bidimensionnel 28x28 en un vecteur de taille 784 pour l'entrée dans le modèle
x = x[:,:,0].reshape(-1,784)
#Prédiction de classe
classified_label = model.predict_classes(x)
#Graphique des résultats de prédiction
plt.subplot(2,5,i+1)
plt.imshow(img, cmap='gray')
plt.title("Class {0}".format(classified_label[0]))
plt.axis('off')
plt.show()
Je pensais que tous les résultats de prédiction étaient corrects, mais le nombre que j'ai écrit montrait que le taux de réponse correcte était de 70%. C'est probablement parce qu'il est différent de l'écriture manuscrite de l'ensemble de données. Ce n'est pas très soigné, donc je publierai ce que j'ai appris dans CNN ici dans un post-scriptum plus tard.
Cela prend trop de temps pour un PC normal avec seulement un CPU pour former CNN, donc je l'ai formé sur le cloud avec un environnement GPU. L'environnement d'exécution à ce moment-là était comme ça. L'apprentissage de MNIST dans cet environnement a pris moins d'une minute.
my_mnist_cnn_learning.py
import numpy as np
from keras.utils import np_utils
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras import backend as K
#Nombre de lots
batch_size = 128
#Nombre de classes à classer
nb_classes = 10
#Nombre d'époques
nb_epoch = 12
#Nombre de dimensions de l'image à saisir
img_rows, img_cols = 28, 28
#Nombre de filtres utilisés pour la convolution
nb_filters = 32
#Spécifiez la taille de la couche de regroupement
pool_size = (2, 2)
#Spécifie la taille du noyau de convolution
kernel_size = (3, 3)
#Lire les données mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
if K.image_dim_ordering() == 'th':
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)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
#Normalisation
X_train /= 255
X_test /= 255
#Convertir en matrice binaire
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
#Modélisation CNN
model = Sequential()
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1],
border_mode='valid',
input_shape=input_shape))
model.add(Activation('relu'))
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
#Compiler le modèle
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
#Apprentissage
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch,
verbose=1, validation_data=(X_test, Y_test))
#Évaluation du modèle
score = model.evaluate(X_test, Y_test, verbose=0)
print(score)
#Enregistrer le modèle et le poids
model_json = model.to_json()
open('mnist_cnn_architecture.json', 'w').write(model_json)
model.save_weights('mnist_cnn_weights.h5', overwrite=True)
Je l'exécutais dans le cloud plus tôt, mais le script suivant est dans le premier environnement Windows Fonctionnement
my_mnist_cnn.py
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt
from keras.utils import np_utils
from keras.models import Sequential,model_from_json
from keras.preprocessing import image
from keras.applications.imagenet_utils import preprocess_input, decode_predictions
from keras.datasets import mnist
#Nombre de classes classées
nb_classes = 10
#Nombre d'images préparées pour le test
test_num = 10
#Lire les données mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_test = X_test.astype('float32')
#Normaliser les données
X_test /= 255
#Convertir en un tableau binaire
Y_test = np_utils.to_categorical(y_test, nb_classes)
#Modèle de charge
model = model_from_json(open('mnist_cnn_architecture.json').read())
#Poids du modèle de charge
model.load_weights('mnist_cnn_weights.h5')
#Après avoir chargé l'architecture et les poids, vous devez compiler si vous souhaitez évaluer le modèle
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
#Évaluation du modèle
score = model.evaluate(X_test.reshape(-1,28,28,1), Y_test, verbose=0)
print(score)
for i in range(test_num):
#Spécifiez le nom du fichier
img_path = str(i)+".jpg "
#28 pixels x 28 pixels, charge l'image en échelle de gris
img = image.load_img(img_path, grayscale=True, target_size=(28, 28))
#Convertir l'image chargée en tableau
x = image.img_to_array(img)
#Vérification de la taille de la baie
print(x.shape)
#Prédiction de classe
classified_label = model.predict_classes(x.reshape(-1,28,28,1))
#Graphique des résultats de prédiction
plt.subplot(2,5,i+1)
plt.imshow(img, cmap='gray')
plt.title("Class {0}".format(classified_label[0]))
plt.axis('off')
plt.show()
Maintenant, qu'arrive-t-il au résultat avec un réseau neuronal convolutif? Le résultat de l'exécution dans Jupyter Notebook est téléchargé sur Gist.
Le taux de réponse correcte est de 80%, mais comparé aux résultats de ce que j'ai appris en MLP, dans le cas des nombres que j'ai écrits, 6 et 8,7 et 1 ont des caractéristiques similaires, il peut donc être facile de se tromper. De plus, si j'ajoute ce que j'ai écrit en plus des données d'entraînement existantes, la réponse peut être correcte, mais je n'ai pas l'intention de le faire.
Cette fois, nous avons classé les caractères manuscrits MNIST. Bien que les résultats de l'apprentissage et des tests aient été bons, le taux de réponse correct pour les images que j'ai écrites n'était pas bon. La prochaine fois, je parlerai du réseau de neurones convolutifs (CNN).
Recommended Posts