Comment créer un classificateur d'image simple

La classification d'images est une application étonnante de l'apprentissage en profondeur. Nous pouvons entraîner un algorithme puissant pour modéliser un grand ensemble de données d'image. Ce modèle peut ensuite être utilisé pour classer un ensemble d'images similaire mais inconnu.

Il n'y a pas de limite aux applications de la classification d'images. Vous pouvez l'utiliser dans votre prochaine application ou vous pouvez l'utiliser pour résoudre un problème du monde réel. Tout dépend de vous. Mais pour quelqu'un qui est assez nouveau dans ce domaine, cela peut sembler très difficile au début. Comment dois-je récupérer mes données? Comment dois-je construire mon modèle? Quels outils dois-je utiliser?

Dans cet article, nous discuterons de tout cela - de la recherche d'un jeu de données à la formation de votre modèle. Je vais essayer de rendre les choses aussi simples que possible en évitant certains détails techniques ( PS: veuillez noter que cela ne signifie pas que ces détails ne sont pas importants. Je mentionnerai quelques ressources intéressantes auxquelles vous pouvez vous référer pour en savoir plus sur ces sujets ). Le but de cet article est d'expliquer le processus de base de construction d'un classificateur d'images et c'est ce sur quoi nous nous concentrerons plus ici.

Nous allons créer un classificateur d'image pour l'ensemble de données Fashion-MNIST. L'ensemble de données Fashion-MNIST est une collection d'images d'articles de Zalando. Il contient 60 000 images pour l'ensemble d'apprentissage et 10 000 images pour les données de l'ensemble de test ( nous aborderons les ensembles de données de test et d'entraînement avec l'ensemble de données de validation plus tard ). Ces images appartiennent aux étiquettes de 10 classes différentes.

Importation de bibliothèques

Notre objectif est de former un modèle d'apprentissage en profondeur capable de classer un ensemble d'images donné dans l'une de ces 10 classes. Maintenant que nous avons notre ensemble de données, nous devons passer aux outils dont nous avons besoin. Il existe de nombreuses bibliothèques et outils que vous pouvez choisir en fonction des exigences de votre propre projet. Pour celui-ci, je m'en tiendrai à ce qui suit:

  1. Numpy - bibliothèque Python pour le calcul numérique
  2. Pandas - Manipulation des données de la bibliothèque Python
  3. Matplotlib - Visualisation des données de la bibliothèque Python
  4. Keras - bibliothèque Python basée sur tensorflow pour la création de modèles d'apprentissage profond
  5. Jupyter - Je vais exécuter tout mon code sur les notebooks Jupyter. Vous pouvez l'installer via le lien. Vous pouvez également utiliser Google Colabs si vous avez besoin d'une meilleure puissance de calcul.

En plus de ces quatre, nous utiliserons également scikit-learn. Le but de ces bibliothèques deviendra plus clair une fois que nous plongerons dans le code.

D'accord! Nous avons nos outils et bibliothèques prêts. Nous devrions maintenant commencer à configurer notre code.

Commencez par importer toutes les bibliothèques mentionnées ci-dessus. En plus d'importer des bibliothèques, j'ai également importé des modules spécifiques de ces bibliothèques. Laissez-moi les parcourir un par un.

import numpy as np import pandas as pd import matplotlib.pyplot as plt import keras from sklearn.model_selection import train_test_split from keras.utils import to_categorical from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D from keras.layers import Dense, Dropout from keras.layers import Flatten, BatchNormalization

train_test_split: ce module divise l'ensemble de données d'entraînement en données d'apprentissage et de validation. La raison de cette scission est de vérifier si notre modèle est surajusté ou non. Nous utilisons un ensemble de données d'entraînement pour former notre modèle, puis nous comparerons la précision résultante à la précision de validation. Si la différence entre les deux quantités est significativement grande, alors notre modèle est probablement surajusté. Nous réitérerons tout au long de notre processus de création de modèles et apporterons les changements nécessaires en cours de route. Une fois que nous serons satisfaits de nos précisions de formation et de validation, nous ferons des prédictions finales sur nos données de test.

to_categorical: to_categorical est un utilitaire keras. Il est utilisé pour convertir les étiquettes catégorielles en encodages one-hot. Disons que nous avons trois étiquettes ("pommes", "oranges", "bananes"), puis un codage à chaud pour chacun d'entre eux serait [1, 0, 0] -> "pommes", [0, 1, 0] -> "oranges", [0, 0, 1] -> "bananes".

Le reste des modules Keras que nous avons importés sont des couches convolutives. Nous discuterons des couches convolutives lorsque nous commencerons à construire notre modèle. Nous allons également donner un rapide coup d'œil à ce que font chacune de ces couches.

Pré-traitement des données

Pour l'instant, nous allons nous concentrer sur l'obtention de nos données et leur analyse. Vous devez toujours vous rappeler l'importance du prétraitement et de l'analyse des données. Cela vous donne non seulement des informations sur les données, mais aide également à localiser les incohérences.

Une très légère variation des données peut parfois conduire à un résultat dévastateur pour votre modèle. Il est donc important de prétraiter vos données avant de les utiliser pour l'entraînement. Donc, dans cet esprit, commençons le prétraitement des données.

train_df = pd.read_csv('./fashion-mnist_train.csv') test_df = pd.read_csv('./fashion-mnist_test.csv')

Tout d'abord, importons notre ensemble de données ( voici le lien pour télécharger cet ensemble de données sur votre système ). Une fois que vous avez importé l'ensemble de données, exécutez la commande suivante.

train_df.head()

Cette commande vous montrera à quoi ressemblent vos données. La capture d'écran suivante montre la sortie de cette commande.

Nous pouvons voir comment nos données d'image sont stockées sous la forme de valeurs de pixels. Mais nous ne pouvons pas fournir de données à notre modèle dans ce format. Nous devrons donc le convertir en tableaux numpy.

train_data = np.array(train_df.iloc[:, 1:]) test_data = np.array(test_df.iloc[:, 1:])

Maintenant, il est temps d'obtenir nos étiquettes.

train_labels = to_categorical(train_df.iloc[:, 0]) test_labels = to_categorical(test_df.iloc[:, 0])

Ici, vous pouvez voir que nous avons utilisé to_categorical pour convertir nos données catégorielles en un encodage à chaud.

Nous allons maintenant remodeler les données et les convertir en type float32 afin que nous puissions les utiliser facilement.

rows, cols = 28, 28 train_data = train_data.reshape(train_data.shape[0], rows, cols, 1) test_data = test_data.reshape(test_data.shape[0], rows, cols, 1) train_data = train_data.astype('float32') test_data = test_data.astype('float32')

Nous avons presque fini. Finissons simplement le prétraitement de nos données en les normalisant. La normalisation des données d'image mappera toutes les valeurs de pixels de chaque image aux valeurs comprises entre 0 et 1. Cela nous aide à réduire les incohérences dans les données. Avant la normalisation, les données d'image peuvent avoir de grandes variations dans les valeurs de pixel qui peuvent conduire à un comportement inhabituel pendant le processus d'apprentissage.

train_data /= 255.0 test_data /= 255.0

Réseaux de neurones convolutifs

Ainsi, le prétraitement des données est effectué. Maintenant, nous pouvons commencer à construire notre modèle. Nous allons construire un réseau neuronal convolutif pour modéliser les données d'image. Les CNN sont des versions modifiées de réseaux de neurones réguliers. Ceux-ci sont modifiés spécifiquement pour les données d'image. Pour alimenter en images des réseaux de neurones réguliers, notre réseau aurait besoin d'un grand nombre de neurones d'entrée. Par exemple, juste pour une image 28x28, nous aurions besoin de 784 neurones d'entrée. Cela créerait un énorme désordre de paramètres d'entraînement.

Les CNN résolvent ce problème en supposant déjà que l'entrée va être une image. L'objectif principal des réseaux de neurones convolutifs est de tirer parti de la structure spatiale de l'image et d'en extraire des caractéristiques de haut niveau, puis de s'entraîner sur ces caractéristiques. Il le fait en effectuant une opération de convolution sur la matrice de valeurs de pixels.

The visualization above shows how convolution operation works. And the Conv2D layer we imported earlier does the same thing. The first matrix (from the left) in the demonstration is the input to the convolutional layer. Then another matrix called "filter" or "kernel" is multiplied (matrix multiplication) to each window of the input matrix. The output of this multiplication is the input to the next layer.

Other than convolutional layers, a typical CNN also has two other types of layers: 1) a  pooling layer, and 2) a fully connected layer.

Pooling layers are used to generalize the output of the convolutional layers. Along with generalizing, it also reduces the number of parameters in the model by down-sampling the output of the convolutional layer.

As we just learned, convolutional layers represent high level features from image data. Fully connected layers use these high level features to train the parameters and to learn to classify those images.

We will also use the Dropout, Batch-normalization and Flatten layers in addition to the layers mentioned above. Flatten layer converts the output of convolutional layers into a one dimensional feature vector. It is important to flatten the outputs because Dense (Fully connected) layers only accept a feature vector as input. Dropout and Batch-normalization layers are for preventing the model from overfitting.

train_x, val_x, train_y, val_y = train_test_split(train_data, train_labels, test_size=0.2) batch_size = 256 epochs = 5 input_shape = (rows, cols, 1)
def baseline_model(): model = Sequential() model.add(BatchNormalization(input_shape=input_shape)) model.add(Conv2D(32, (3, 3), padding="same", activation="relu")) model.add(MaxPooling2D(pool_size=(2, 2), strides=(2,2))) model.add(Dropout(0.25)) model.add(BatchNormalization()) model.add(Conv2D(32, (3, 3), padding="same", activation="relu")) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation="relu")) model.add(Dropout(0.5)) model.add(Dense(10, activation="softmax")) return model

The code that you see above is the code for our CNN model. You can structure these layers in many different ways to get good results. There are many popular CNN architectures which give state of the art results. Here, I have just created my own simple architecture for the purpose of this problem. Feel free to try your own and let me know what results you get :)

Training the model

Once you have created the model you can import it and then compile it by using the code below.

model = baseline_model() model.compile(loss='categorical_crossentropy', optimizer="sgd", metrics=['accuracy']) 

model.compile configures the learning process for our model. We have passed it three arguments. These arguments define the loss function for our model, optimizer and metrics.

history = model.fit(train_x, train_y, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(val_x, val_y)) 

And finally by running the code above you can train your model. I am training this model for just five epochs but you can increase the number of epochs. After your training process is completed you can make predictions on the test set by using the following code.

predictions= model.predict(test_data)

Conclusion

Congrats! You did it, you have taken your first step into the amazing world of computer vision.

You have created a your own image classifier. Even though this is a great achievement, we have just scratched the surface.

There is a lot you can do with CNNs. The applications are limitless. I hope that this article helped you to get an understanding of how the process of training these models works.

Working on other datasets on your own will help you understand this even better. I have also created a GitHub repository for the code I used in this article. So, if this article was useful for you please let me know.

If you have any questions or you want to share your own results or if you just want to say "hi", feel free to hit me up on twitter, and I'll try to do my best to help you. And finally Thanks a lot for reading this article!! :)