MariaDB
 sql >> Base de données >  >> RDS >> MariaDB

Partie 2 :Classification d'images avec MariaDB Server et TensorFlow - un tutoriel

Formater les données pour TensorFlow

La partie 1 de cette série de blogs a démontré les avantages de l'utilisation d'une base de données relationnelle pour stocker et effectuer l'exploration de données d'images à l'aide de simples instructions SQL. Dans ce didacticiel, partie 2, les données utilisées dans la première partie seront accessibles à partir d'une base de données MariaDB Server et converties dans les structures de données nécessaires à TensorFlow. Les résultats de l'application du modèle pour classer de nouvelles images seront stockés dans une table relationnelle pour une analyse plus approfondie.

Ceci est un tutoriel rapide d'un programme TensorFlow avec les détails décrits au fur et à mesure. Si vous n'êtes pas familier avec les concepts de base, un bon point de départ est ce didacticiel TensorFlow, "Classification de base :classer les images de vêtements". Certains des exemples et du code du didacticiel sont utilisés ici.

Packages supplémentaires nécessaires

Certains packages supplémentaires sont nécessaires pour créer et entraîner le modèle de classification d'images :

  1. Cornichon implémente des protocoles binaires pour la sérialisation et la désérialisation d'une structure d'objet Python.
  2. NumPy prend en charge les grands tableaux et matrices multidimensionnels, ainsi que des fonctions mathématiques de haut niveau pour opérer sur ces tableaux.
  3. TensorFlow est une bibliothèque Python pour le calcul numérique rapide. Il s'agit d'une bibliothèque de base qui peut être utilisée pour créer des modèles d'apprentissage en profondeur directement ou en utilisant des bibliothèques wrapper qui simplifient le processus construit au-dessus de TensorFlow.
  4. Kéras est une bibliothèque de réseaux de neurones open source écrite en Python.
import pickleimport numpy as npimport tensorflow as tffrom tensorflow import kerasprint('Tensorflow version :', tf.__version__)print('Numpy version :', np.__version__)Tensorflow version :2.0.0Numpy version :1.16.2 

Récupérer des images

Une fois les packages importés, l'étape suivante consiste à récupérer les images d'entraînement de la base de données et à diviser les données en deux numpy tableaux. Tout d'abord, nous devons initialiser les tableaux d'images d'entraînement (train_images) et d'étiquettes d'entraînement (train_labels). Puisque nous avons déjà vectorisé les images, nous pouvons utiliser l'attribut img_vector pour remplir le tableau train_images avec l'instruction SQL ci-dessous.

# Initialiser le tableau numpystrain_images =np.empty((60000,28,28), dtype='uint8')train_labels =np.empty((60000), dtype='uint8')# Récupérer les images d'entraînement à partir du databasesql="SELECT img_label, img_vector, img_idx \FROM tf_images INNER JOIN img_use ON img_use =use_id \WHERE use_name ='Training'"cur.execute(sql)result =cur.fetchall()# Remplissez les tableaux numpy. row[2] contient l'index d'image pour la ligne dans le résultat :nparray =pickle.loads(row[1])train_images[row[2]] =nparraytrain_labels[row[2]] =row[0]

De la même manière, les images à tester peuvent être extraites de la base de données. Le numpy les tableaux utilisés dans ce cas sont test_images et test_labels. Dans ce cas, les données de test sont de 10 000 images à une résolution de 28 × 28 pixels.

# Initialiser le tableau numpytest_images =np.empty((10000,28,28), dtype='uint8')test_labels =np.empty((10000), dtype='uint8')# Récupérer les images de test du databasesql="SELECT img_label, img_vector, img_idx \FROM tf_images INNER JOIN img_use ON img_use =use_id \WHERE use_name ='Testing'"cur.execute(sql)result =cur.fetchall()# Remplissez les tableaux numpy. row[2] contient l'index d'image pour la ligne dans le résultat :nparray =pickle.loads(row[1])test_images[row[2]] =nparraytest_labels[row[2]] =row[0]

Enfin, chaque image est associée à une seule étiquette. Les noms d'étiquettes sont stockés dans la table categories et chargés dans le tableau class_names :

sql="SELECT class_name FROM categories"cur.execute(sql)class_names =cur.fetchall()

Prétraiter les données

Les données doivent être prétraitées avant de former le réseau. Si vous inspectez la première image de l'ensemble d'apprentissage, vous verrez que les valeurs de pixel se situent dans la plage de 0 à 255 :

plt.figure()plt.imshow(train_images[0])plt.colorbar()plt.grid(False)plt.show()


ci-dessus :image de l'ensemble de données fashion_mnist

Avant de transmettre les images au modèle de réseau neuronal, les valeurs doivent être mises à l'échelle dans une plage de 0 à 1. Pour ce faire, divisez les valeurs par 255. Il est important que l'ensemble d'apprentissage et l'ensemble de test soient prétraités de la même manière. .

Vous pouvez utiliser matplotlib pour afficher les 25 premières images afin de vérifier que les données sont au format correct et prêtes pour la création et l'apprentissage du réseau :

train_images =train_images / 255.0test_images =test_images / 255.0plt.figure(figsize=(10,10))for i in range(25):plt.subplot(5,5,i+1)plt.xticks([ ])plt.yticks([])plt.grid(False)plt.imshow(train_images[i], cmap=plt.cm.binary)plt.xlabel(class_names[train_labels[i]])plt.show() 


ci-dessus :images de l'ensemble de données fashion_mnist

Construire le modèle

Une fois les données prétraitées en deux sous-ensembles, vous pouvez procéder à une formation de modèle. Ce processus consiste à "alimenter" l'algorithme avec des données d'apprentissage. L'algorithme traitera les données et générera un modèle capable de trouver une valeur cible (attribut) dans de nouvelles données, c'est-à-dire classer l'image présentée au réseau de neurones.

La plupart des réseaux de neurones d'apprentissage en profondeur sont produits en enchaînant des couches simples.

La première couche du réseau transforme le format d'image d'un tableau bidimensionnel (de 28 x 28 pixels) en un tableau unidimensionnel (de 28 * 28 =784 pixels). Cette couche n'a aucun paramètre à apprendre; il ne fait que reformater les données.

Une fois les pixels aplatis, le réseau se compose de deux couches entièrement connectées qui doivent être activées. Dans un réseau de neurones, la fonction d'activation est chargée de transformer l'entrée pondérée sommée du nœud en activation du nœud ou en sortie pour cette entrée.

La première couche dense a 128 nœuds (ou neurones) et utilise une méthode d'activation d'unité linéaire rectifiée (ReLU). La fonction d'activation linéaire rectifiée est une fonction linéaire par morceaux qui produira l'entrée directement si elle est positive, sinon, elle produira zéro.

La deuxième (et dernière) couche est une couche softmax à 10 nœuds. Une fonction softmax génère un vecteur qui représente les distributions de probabilité d'une liste de résultats potentiels. Il renvoie un tableau de 10 scores de probabilité dont la somme est égale à 1. Chaque nœud contient un score qui indique la probabilité que l'image actuelle appartienne à l'une des 10 classes.

La plupart des couches, telles que tf.keras.layers.Dense, ont des paramètres qui sont appris lors de la formation.

model =keras.Sequential([keras.layers.Flatten(input_shape=(28, 28)),keras.layers.Dense(128, activation='relu'),keras.layers.Dense(10, activation='softmax')])

Compilation du modèle

L'étape de compilation du modèle est utilisée pour ajouter quelques paramètres supplémentaires avant qu'il ne soit prêt pour la formation. Dans ce cas, les paramètres suivants sont activés.

  1. Optimiseur :met à jour le modèle en fonction des données qu'il voit et de sa fonction de perte (voir ci-dessous).
  2. Fonction de perte :mesure la précision du modèle pendant l'entraînement. Vous souhaitez minimiser cette fonction pour "orienter" le modèle dans la bonne direction.
  3. Métriques :surveillez les étapes de formation et de test. L'exemple suivant utilise la précision, la fraction des images correctement classées.
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])

Entraîner le modèle

La formation du modèle de réseau neuronal nécessite les étapes suivantes.

  1. Introduisez les données d'entraînement dans le modèle.
  2. Le modèle apprend à associer des images et des étiquettes.
  3. Effectuer des prédictions sur un ensemble de tests.
  4. Vérifiez que les prédictions correspondent aux étiquettes du tableau test_labels.

Pour commencer l'entraînement, appelez la méthode model.fit, ainsi appelée car elle "adapte" le modèle aux données d'entraînement :

model.fit(train_images, train_labels, epochs=10)Trainer sur 60000 échantillonsEpoque 1/1060000/60000 [===============================] - 5s 83us/échantillon - perte :0,4964 - précision :0,8236Epoque 2/1060000/60000 [==============================] - 4s 65us/échantillon - perte :0.3735 - précision :0.8642Epoque 3/1060000/60000 [==============================] - 3s 55us/échantillon - perte :0.3347 - précision :0.8773Epoque 4/1060000/60000 [==============================] - 3s 56us/échantillon - perte :0.3106 - précision :0.8861Epoque 5/1060000/60000 [==============================] - 3s 58us/échantillon - perte :0,2921 - précision :0,8924s - perte :0,2928 - précision - ETA :0s - perte :0,2925 - précisionEpoque 6/1060000/60000 [==============================] - 3s 57us/échantillon - perte :0.2796 - précision :0.8969sEpoque 7/1060000/60000 [=============================] - 4s 70us/échantillon - perte :0.2659 - précision :0.9007Epoque 8/1060000/60000 [=============================] - 4s 61us/échantillon - perte :0.2548 - précision :0.9042Epoque 9/1060000/60000 [ =============================] - 4s 61us/échantillon - perte :0.2449 - précision :0.9084Epoque 10/1060000/60000 [==============================] - 5s 76us/échantillon - perte :0,2358 - précision :0,9118

À la fin de chaque époque, le réseau de neurones est évalué par rapport à l'ensemble de validation. C'est à cela que se réfèrent la perte et la précision.

Évaluer la précision et prévoir

Pour estimer la précision globale du modèle, calculez la moyenne des dix occurrences de la valeur de précision, dans ce cas 88 %.

Ensuite, exécutez model.evaluate sur l'ensemble de test pour obtenir la précision prédictive du réseau neuronal entraîné sur des données inédites.

test_loss, test_acc =model.evaluate(test_images, test_labels, verbose=2)10000/1 - 0s - perte :0,2766 - précision :0,8740

L'ensemble de données de test est moins précis que l'ensemble de données d'apprentissage. Dans ce cas, cet écart entre la précision de l'entraînement et la précision du test représente un surapprentissage. Le contraire est le sous-ajustement. Si vous souhaitez en savoir plus sur ce sujet, je vous recommande Overfitting vs Underfitting :A Conceptual Explanation by Will Koehrsen.

À ce stade, nous pouvons faire des prédictions sur les images de notre ensemble de données d'entraînement.

predictions =model.predict(test_images)predictions[0]array([1.90860412e-08, 8.05085235e-11, 1.56402713e-08, 1.66699390e-10,7.86950158e-11, 4.33062996e-06, 2.4694 -08, 1.20656565e-02,3.80084719e-09, 9.87929940e-01], dtype=float32)

La sortie de model.predict est un tableau de 10 nombres avec la probabilité qu'une instance appartienne à chaque classe. Conserver les résultats dans la base de données MariaDB pour une analyse et un rapport plus poussés est une bonne idée. Vous trouverez ci-dessous un exemple d'itération sur le tableau de prédictions pour créer un tuple, puis l'insérer dans les prediction_results tableau.

sql ="INSERT INTO prédiction_results (img_idx, img_use, T_shirt_Top, Trouser, Pullover, Dress, Coat, Sandal, Shirt, Sneaker, Bag, Ankle_boot, label)VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);"i =0pour la ligne dans les prédictions :insert_tuple =(str(i), str(2), str (ligne[0]), chaîne(ligne[1]), chaîne(ligne[2]), chaîne(ligne[3]), chaîne(ligne[4]), chaîne(ligne[5]), chaîne(ligne [6]), str(ligne[7]), str(ligne[8]), str(ligne[9]), str(test_labels[i]))cur.execute(sql, insert_tuple)conn.commit() je +=1

Encore une fois, une simple instruction SQL peut être utilisée pour vérifier que les données ont été chargées.

sql ="SELECT T_shirt_Top, pantalon, pull, robe, manteau, sandale, chemise, baskets, sac, bottine, class_name as 'Test Label'FROM prediction_results JOIN categories ON label =class_idx WHERE img_idx =1"display( pd. read_sql(sql,conn) )

T_shirt_Top Pantalon Pull Robe Manteau Sandale Chemise Basket Sac Bottines Étiquette de test
0,00001 0.0 0.997912 0.0 0.001267 0.0 0.00081 0.0 0.0 0.0 Pull

Tracer des prédictions

Quelques fonctions de traçage pour afficher les prédictions sont définies ci-dessous (Fonctions graphiques).

Récupérons une nouvelle image de l'ensemble de test et affichons la classification du réseau de neurones en fonction de la probabilité de prédiction.

sql ="SELECT img_idx, étiquette FROM prédiction_results WHERE img_idx =1"cur.execute(sql)result =cur.fetchone()plt.figure(figsize=(6,3))plt.subplot(1,2, 1)plot_image(result[0], prédictions[result[0]], test_labels, test_images)plt.subplot(1,2,2)plot_value_array(result[0], prédictions[result[0]], test_labels)plt. montrer()


ci-dessus :image de l'ensemble de données fashion_mnist

Dans ce cas, le modèle a pu classer correctement l'image avec une précision de 100 %. Exécutons ensuite une requête pour récupérer les 15 premières images de l'ensemble de test et classons-les.

sql ="SELECT img_idx, label FROM prédiction_results LIMIT 15"num_rows =5num_cols =3plt.figure(figsize=(2*2*num_cols, 2*num_rows))cur.execute(sql)result =cur.fetchall() pour la ligne dans le résultat :plt.subplot(num_rows, 2*num_cols, 2*row[0]+1)plot_image(row[0], prédictions[row[0]], test_labels, test_images)plt.subplot(num_rows, 2 *num_cols, 2*row[0]+2)plot_value_array(row[0], prédictions[row[0]], test_labels)plt.tight_layout()plt.show()


ci-dessus :images de l'ensemble de données fashion_mnist

Comme vous pouvez le voir, il y aura des cas où le modèle peut être erroné, comme indiqué dans la dernière ligne, colonne de gauche. Dans ce cas, une basket a été classée comme une sandale (en rouge).

En résumé

Bien que l'intégration entre TensorFlow et MariaDB Server soit facile, les avantages de cette intégration sont substantiels :

  • L'utilisation de données relationnelles dans le machine learning peut réduire la complexité de la mise en œuvre. Les Data Scientists et les Data Engineers peuvent utiliser un langage commun pour effectuer des tâches de traitement et d'exploration de données.
  • L'efficacité acquise lors de l'accès, de la mise à jour, de l'insertion, de la manipulation et de la modification des données peut accélérer la mise sur le marché.
  • La possibilité de stocker les résultats du modèle dans la base de données permet aux utilisateurs finaux et aux analystes d'exécuter des requêtes et des rapports à l'aide d'outils de création de rapports conviviaux comme Tableau.

Licence MIT

L'ensemble de données Fashion MNIST (fashion_mnist) exploité par ce blog est sous licence MIT, Copyright © 2017 Zalando SE, https://tech.zalando.com

Le code source exploité par ce blog est adapté du tutoriel "Classification de base :classer les images de vêtements" qui est sous licence MIT, Copyright (c) 2017 François Chollet.

L'autorisation est accordée, gratuitement, à toute personne obtenant une copie de ce logiciel et des fichiers de documentation associés (le "Logiciel"), de traiter le Logiciel sans restriction, y compris, sans limitation, les droits d'utilisation, de copie, de modification, de fusion , publier, distribuer, sous-licencier et/ou vendre des copies du Logiciel, et permettre aux personnes à qui le Logiciel est fourni de le faire, sous réserve des conditions suivantes :

L'avis de droit d'auteur ci-dessus et cet avis d'autorisation doivent être inclus dans toutes les copies ou parties substantielles du Logiciel.

LE LOGICIEL EST FOURNI « EN L'ÉTAT », SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE, Y COMPRIS, MAIS SANS S'Y LIMITER, LES GARANTIES DE QUALITÉ MARCHANDE, D'ADÉQUATION À UN USAGE PARTICULIER ET D'ABSENCE DE CONTREFAÇON. EN AUCUN CAS LES AUTEURS OU LES DÉTENTEURS DU COPYRIGHT NE SERONT RESPONSABLES DE TOUTE RÉCLAMATION, DOMMAGE OU AUTRE RESPONSABILITÉ, QUE CE SOIT DANS UNE ACTION CONTRACTUELLE, DÉLICTUELLE OU AUTRE, DÉCOULANT DE, DE OU EN RELATION AVEC LE LOGICIEL OU L'UTILISATION OU D'AUTRES TRANSACTIONS DANS LE LOGICIEL.

Références

Convertir sa propre image en image du MNIST
matplotlib :tutoriel sur les images
5 façons dont l'IA transforme l'expérience client
La numérisation réinvente l'entreprise
Qu'est-ce que la classification des images ?
Introduction à Python Bibliothèque d'apprentissage profond TensorFlow

Fonctions graphiques

def plot_image(je, prédictions_array, true_label, img):predictions_array, true_label, img =prédictions_array, true_label[i], img[i]plt.grid(False)plt.xticks([])plt.yticks([ ])plt.imshow(img, cmap=plt.cm.binary)predicted_label =np.argmax(predictions_array)if predicted_label ==true_label:color ='blue'else:color ='red'plt.xlabel("{} { :2.0f}% ({})".format(class_names[predicted_label],100*np.max(predictions_array),class_names[true_label]),color=color)def plot_value_array(i, prédictions_array, true_label):predictions_array, true_label =prédictions_array, true_label[i]plt.grid(False)plt.xticks(range(10))plt.yticks([])thisplot =plt.bar(range(10), predicts_array, color="#777777")plt .ylim([0, 1])predicted_label =np.argmax(predictions_array)thisplot[predicted_label].set_color('red')thisplot[true_label].set_color('blue')