Python: Application de la reconnaissance d'image à l'aide de CNN

Données volumineuses

ImageDataGenerator

La reconnaissance d'image nécessite un grand nombre de combinaisons de données d'image et de ses étiquettes (données d'enseignant).

Cependant, il n'est pas possible d'avoir un nombre suffisant de combinaisons d'images et d'étiquettes. Cela coûte souvent cher.

Par conséquent, en tant que technique utilisée lors de l'augmentation du nombre de données à une quantité suffisante

Il y a un remplissage d'image.

Gonfler une image n'a pas de sens simplement en copiant les données et en augmentant la quantité. Ainsi, par exemple, vous pouvez retourner ou déplacer l'image pour créer de nouvelles données.

image.png

Ici, nous utiliserons ImageDataGenerator de Keras pour le remplissage.

ImageDataGenerator a de nombreux arguments, et en les spécifiant de manière appropriée Vous pouvez facilement traiter les données.

Vous pouvez également combiner plusieurs processus pour générer une nouvelle image. Jetons un coup d'œil à certains arguments couramment utilisés dans ImageDataGenerator.

datagen = ImageDataGenerator(rotation_range=0.,
                            width_shift_range=0.,
                            height_shift_range=0.,
                            shear_range=0.,
                            zoom_range=0.,
                            channel_shift_range=0,
                            horizontal_flip=False,
                            vertical_flip=False)
rotation_range     :Plage de rotation à rotation aléatoire (unité: degré)
width_shift_range  :Mouvement parallèle aléatoire dans le sens horizontal, rapport à la largeur de l'image
height_shift_range :Mouvement parallèle aléatoire dans le sens vertical, rapport à la largeur verticale de l'image
shear_range        :Degré de cisaillement. L'augmentation de la taille donne à l'image un aspect plus écrasé ou étiré en diagonale (unité: degré)
zoom_range         :Vitesse à laquelle l'image est compressée et agrandie de manière aléatoire. Minimum 1-Comprimé à la plage de zoom, jusqu'à 1+zoom_Élargi à la gamme.
channel_shift_range:Si l'entrée est une image de canal RGB3, R,G,Ajoutez ou soustrayez une valeur aléatoire pour chaque B.(0~255)
horizontal_flip    :Si True est spécifié, il sera retourné horizontalement au hasard.
vertical_flip      :Si True est spécifié, il sera retourné verticalement au hasard.
flow
flow(x, y=None, batch_size=32, shuffle=True, seed=None, save_to_dir=None, save_prefix='', save_format='png', subset=None)
#Reçoit et étend des données numpy et un tableau d'étiquettes/Génère un lot de données normalisées.
argument
x:Les données,Doit être des données à 4 dimensions. Réglez le canal 1 pour les données en niveaux de gris et le canal 3 pour les données RVB.
y:étiquette
batch_size:Entier (par défaut:32). Spécifie la taille du lot de données.
shuffle  :Valeur de vérité (par défaut):Vrai). S'il faut mélanger les données.
save_to_dir:Aucun ou chaîne (par défaut: None).. Vous pouvez spécifier le répertoire dans lequel vous souhaitez enregistrer l'image étendue générée (utile pour visualiser ce que vous avez fait)
save_prefix:Chaîne (par défaut'').. Préfixe (défini) à donner au nom du fichier lors de l'enregistrement de l'image_to_Valide uniquement lorsqu'un argument est donné à dir)
save_format: "png"Ou"jpeg"(set_to_Valide uniquement lorsqu'un argument est donné à dir).. La valeur par défaut est"png"
Valeur de retour
x est le tableau Numpy de données d'image et y est le tableau Numpy de l'étiquette correspondante.(x, y)Est un itérateur généré à partir de

Si vous êtes intéressé, vous pouvez effectuer divers traitements avec d'autres arguments. Veuillez consulter le site officiel de Keras.

Normalisation

Diverses méthodes de normalisation

L'image ci-dessous est un exemple de normalisation. La normalisation est le processus de traitement selon les règles des données pour faciliter leur utilisation.

Dans l'exemple ci-dessus, la façon dont la lumière frappe est unifiée en effectuant une normalisation. Il supprime les différences entre les données qui ne sont pas directement liées à la formation. Cela peut grandement améliorer l'efficacité de l'apprentissage.

image.png

Le graphique ci-dessous est appelé "Normalisation des lots (BN)" dans la classification de cifar10. Cela montre que le taux de réponse correcte a augmenté de manière significative lors de la normalisation.

Ces dernières années, la normalisation est parfois moins nécessaire dans les modèles de réseaux de neurones profonds, Il ne fait aucun doute qu'il sera extrêmement utile lors de l'utilisation d'un modèle simple.

Il existe différentes méthodes de normalisation utilisées pour l'apprentissage en profondeur, et les plus typiques sont

Normalisation par lots(BN)
Analyse en composantes principales (ACP)
Décomposition de singularité (SVD)
Analyse des composants en phase zéro (ZCA)
Normalisation de la réponse locale (LRN)
Normalisation du contraste global (GCN)
Normalisation du contraste local (LCN)

Ces méthodes de normalisation peuvent être globalement divisées en «standardisation» et «blanchiment».
Nous examinerons chacun à partir de la prochaine session.

Standardisation

La normalisation est une méthode qui permet de rapprocher la distribution des données pour chaque entité en faisant en sorte que les caractéristiques individuelles aient une moyenne de 0 et une variance de 1.

L'image ci-dessous est dans l'ensemble de données CIFAR-10 À propos de chaque fonctionnalité (ici, 3 canaux de R, G, B) C'est une version standardisée. (Un peu plus de traitement a été ajouté pour le rendre plus facile à voir)

En normalisant, les nuances sont moyennées et il semble grisâtre. Au contraire, la couleur (R ou V ou B) qui n'était pas perceptible jusque-là Parce qu'il sera accentué (pondéré) au même niveau que les autres couleurs Cela facilite la recherche de fonctionnalités cachées.

image.png

Cliquez ici pour un exemple de mise en œuvre

import matplotlib.pyplot as plt
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator

(X_train, y_train), (X_test, y_test) = cifar10.load_data()

for i in range(10):
    plt.subplot(2, 5, i + 1)
    plt.imshow(X_train[i])
plt.suptitle('base images', fontsize=12)
plt.show()

#Génération de générateur
datagen = ImageDataGenerator(samplewise_center=True, samplewise_std_normalization=True)

#Standardisation
g = datagen.flow(X_train, y_train, shuffle=False)
X_batch, y_batch = g.next()

#Rend l'image générée plus facile à voir
X_batch *= 127.0 / max(abs(X_batch.min()), X_batch.max())
X_batch += 127.0
X_batch = X_batch.astype('uint8')

for i in range(10):
    plt.subplot(2, 5, i + 1)
    plt.imshow(X_batch[i])
plt.suptitle('standardization results', fontsize=12)
plt.show()

image.png

Blanchiment

Le blanchiment est le processus d'élimination de la corrélation entre les caractéristiques des données.

L'image ci-dessous est dans l'ensemble de données CIFAR-10 À propos de chaque fonctionnalité (ici, 3 canaux de R, G, B) Il est blanchi. (Un peu plus de traitement a été ajouté pour le rendre plus facile à voir)

En blanchissant, il semble globalement plus sombre et les bords sont accentués. En effet, le blanchiment a pour effet d'ignorer les nuances que l'on attend facilement des informations des pixels environnants.

En raison du blanchiment, ce n'est pas une surface ou un arrière-plan avec une petite quantité d'informations L'efficacité de l'apprentissage peut être améliorée en mettant l'accent sur les bords avec une grande quantité d'informations.

#Génération de générateur
datagen = ImageDataGenerator(featurewise_center=True, zca_whitening=True)

#Blanchiment
datagen.fit(X_train)
g = datagen.flow(X_train, y_train, shuffle=False)
X_batch, y_batch = g.next()

image.png

import matplotlib.pyplot as plt
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator

(X_train, y_train), (X_test, y_test) = cifar10.load_data()

#Cette fois, nous utiliserons 300 de toutes les données pour la formation et 100 pour les tests.
X_train = X_train[:300]
X_test = X_test[:100]
y_train = y_train[:300]
y_test = y_test[:100]

for i in range(10):
    plt.subplot(2, 5, i + 1)
    plt.imshow(X_train[i])
plt.suptitle('base images', fontsize=12)
plt.show()

#Génération de générateur
datagen = ImageDataGenerator(featurewise_center=True,zca_whitening=True)

#Blanchiment
datagen.fit(X_train)
g = datagen.flow(X_train, y_train, shuffle=False)
X_batch, y_batch = g.next()

#Rend l'image générée plus facile à voir
X_batch *= 127.0 / max(abs(X_batch.min()), abs(X_batch.max()))
X_batch += 127
X_batch = X_batch.astype('uint8')

for i in range(10):
    plt.subplot(2, 5, i + 1)
    plt.imshow(X_batch[i])
plt.suptitle('whitening results', fontsize=12)
plt.show()

image.png

Normalisation par lots

Dans l'apprentissage profond, la standardisation doit être effectuée pour chaque lot lors de l'apprentissage par mini-lots. C'est ce qu'on appelle la "normalisation par lots".

Dans Keras, comme indiqué ci-dessous, avec des couches entièrement connectées, des couches alambiquées, des fonctions d'activation, etc. De même, il peut être incorporé dans le modèle avec la méthode add of model.

model.add(BatchNormalization())

La normalisation par lots peut être appliquée non seulement comme prétraitement des données, mais également pour la sortie de couche intermédiaire. Surtout pour la sortie de fonctions dont la plage de valeurs de sortie n'est pas limitée, comme la fonction d'activation ReLU. La normalisation par lots peut être très efficace pour faciliter un apprentissage fluide.

import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist
from keras.layers import Activation, Conv2D, Dense, Flatten, MaxPooling2D, BatchNormalization
from keras.models import Sequential, load_model
from keras.utils.np_utils import to_categorical

(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = np.reshape(a=X_train, newshape=(-1,28,28,1))[:300]
X_test = np.reshape(a = X_test,newshape=(-1,28,28,1))[:300]
y_train = to_categorical(y_train)[:300]
y_test = to_categorical(y_test)[:300]

#Définition de model1 (modèle qui utilise la fonction sigmoïde pour la fonction d'activation)
model1 = Sequential()
model1.add(Conv2D(input_shape=(28, 28, 1), filters=32,
                 kernel_size=(2, 2), strides=(1, 1), padding="same"))
model1.add(MaxPooling2D(pool_size=(2, 2)))
model1.add(Conv2D(filters=32, kernel_size=(
    2, 2), strides=(1, 1), padding="same"))
model1.add(MaxPooling2D(pool_size=(2, 2)))
model1.add(Flatten())
model1.add(Dense(256))
model1.add(Activation('sigmoid'))
model1.add(Dense(128))
model1.add(Activation('sigmoid'))
model1.add(Dense(10))
model1.add(Activation('softmax'))


model1.compile(optimizer='sgd', loss='categorical_crossentropy',
              metrics=['accuracy'])
#Apprentissage
history = model1.fit(X_train, y_train, batch_size=32, epochs=3, validation_data=(X_test, y_test))

#Visualisation
plt.plot(history.history['acc'], label='acc', ls='-', marker='o')
plt.plot(history.history['val_acc'], label='val_acc', ls='-', marker='x')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.suptitle('model1', fontsize=12)
plt.show()


#Définition de model2 (modèle qui utilise ReLU pour la fonction d'activation)
model2 = Sequential()
model2.add(Conv2D(input_shape=(28, 28, 1), filters=32,
                 kernel_size=(2, 2), strides=(1, 1), padding="same"))
model2.add(MaxPooling2D(pool_size=(2, 2)))
model2.add(Conv2D(filters=32, kernel_size=(
    2, 2), strides=(1, 1), padding="same"))
model2.add(MaxPooling2D(pool_size=(2, 2)))
model2.add(Flatten())
model2.add(Dense(256))
model2.add(Activation('relu'))
#Ajout de la normalisation des lots ci-dessous
model2.add(BatchNormalization())
model2.add(Dense(128))
model2.add(Activation('relu'))
#Ajout de la normalisation des lots ci-dessous
model2.add(BatchNormalization())
model2.add(Dense(10))
model2.add(Activation('softmax'))


model2.compile(optimizer='sgd', loss='categorical_crossentropy',
              metrics=['accuracy'])
#Apprentissage
history = model2.fit(X_train, y_train, batch_size=32, epochs=3, validation_data=(X_test, y_test))

#Visualisation
plt.plot(history.history['acc'], label='acc', ls='-', marker='o')
plt.plot(history.history['val_acc'], label='val_acc', ls='-', marker='x')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.suptitle("model2", fontsize=12)
plt.show()

image.png

Apprentissage par transfert

Apprentissage par transfert

Il faut beaucoup de temps pour former un grand réseau de neurones et une grande quantité de données. Dans de tels cas, il est efficace d'utiliser un modèle qui a déjà été formé et publié avec une grande quantité de données. Pour entraîner un nouveau modèle à l'aide d'un modèle entraîné

C'est ce qu'on appelle «l'apprentissage par transfert».

Dans Keras, avec le modèle de classification d'images appris avec ImageNet (un énorme ensemble de données d'image composé de 1,2 million de feuilles et 1000 classes) Vous pouvez télécharger et utiliser ce poids.

Il existe plusieurs types de modèles publiés, mais ici nous utiliserons un modèle appelé VGG16 comme exemple.

image.png

Le modèle VGG est arrivé en deuxième position dans l'ILSVRC 2014, un concours de reconnaissance d'image à grande échelle. Il s'agit d'un modèle de réseau créé par l'équipe VGG (Visual Geometry Group) de l'Université d'Oxford.

Le pliage avec un petit filtre est répété 2 à 4 fois de suite, puis la mise en commun est répétée. La caractéristique est que la couche est assez profonde pour cette période.

Le modèle VGG a 16 couches de couches pondérées (couche de pliage et couche entièrement connectée) et 19 couches. Ils sont appelés respectivement VGG16 et VGG19.

VGG16 est un réseau neuronal avec 13 couches convolutives + 3 couches entièrement connectées = 16 couches.

Le modèle VGG original est un modèle de classification de 1000 classes, il y a donc 1000 unités de sortie. En utilisant la couche intermédiaire comme couche pour l'extraction d'entités sans utiliser la dernière couche entièrement connectée Il peut être utilisé pour l'apprentissage par transfert.

De plus, vous n'avez pas à vous soucier de la taille de l'image d'entrée.

En effet, le modèle VGG16 a une petite taille de noyau de couche de convolution de 3x3. De plus, padding = 'same', sauf si l'image d'entrée est extrêmement petite. En effet, un certain nombre de caractéristiques sont sécurisées à travers les 13 couches.

VGG16

Classifiez les ensembles de données cifar10 à l'aide de l'apprentissage par transfert dans Keras. Combinez le modèle VGG16 avec le modèle de type séquentiel que vous avez utilisé.

Commencez par créer un modèle de VGG.

from keras.applications.vgg16 import VGG16
#Les poids pré-appris dans ImageNet sont également chargés
input_tensor = Input(shape=(32, 32, 3))
vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)

input_tensor est un tenseur Keras facultatif (c'est-à-dire la sortie de layer.Input ()) à utiliser comme image d'entrée pour le modèle.

include_top indique s'il faut utiliser la dernière partie de couche entièrement connectée du modèle d'origine. En définissant ce paramètre sur False, seule la partie d'extraction d'entités par la couche de convolution du modèle d'origine est utilisée. Vous pouvez ajouter votre propre modèle aux couches suivantes.

Si imagenet est spécifié pour les poids, les poids appris par ImageNet seront utilisés, et si Aucun est spécifié, des poids aléatoires seront utilisés.

Pour ajouter une autre couche après la partie d'extraction d'entités, définissez à l'avance un modèle différent de VGG (top_model dans ce cas) et combinez-le comme suit.

top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='sigmoid'))
top_model.add(Dropout(0.5))
top_model.add(Dense(10, activation='softmax'))
model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))

Le poids de la partie d'extraction d'entités par vgg16 se réduira lors de sa mise à jour, donc corrigez-le comme suit.

#Jusqu'à la 20e couche du modèle est un modèle vgg
for layer in model.layers[:19]:
    layer.trainable = False

La compilation et l'apprentissage peuvent être effectués de la même manière, mais lors du transfert de l'apprentissage, il est préférable de sélectionner SGD comme fonction d'optimisation.

model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])

Cliquez ici pour un exemple de mise en œuvre

from keras import optimizers
from keras.applications.vgg16 import VGG16
from keras.datasets import cifar10
from keras.layers import Dense, Dropout, Flatten, Input
from keras.models import Model, Sequential
from keras.utils.np_utils import to_categorical
import matplotlib.pyplot as plt
import numpy as np

(X_train, y_train), (X_test, y_test) = cifar10.load_data()
X_train = X_train[:300]
X_test = X_test[:100]
y_train = to_categorical(y_train)[:300]
y_test = to_categorical(y_test)[:100]

#input_Définir le tenseur
input_tensor = Input(shape=(32, 32, 3))

vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)

top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='sigmoid'))
top_model.add(Dropout(0.5))
top_model.add(Dense(10, activation='softmax'))

#vgg16 et top_Veuillez concaténer les modèles
model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))

#Veuillez fixer le poids jusqu'à la 19e couche en utilisant l'instruction for
for layer in model.layers[:19]:
    layer.trainable = False

model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])


model.load_weights('param_vgg.hdf5')

model.fit(X_train, y_train, validation_data=(X_test, y_test), batch_size=32, epochs=1)

#Vous pouvez enregistrer les poids du modèle ci-dessous(Je ne peux pas faire ici)
# model.save_weights('param_vgg.hdf5')

#Évaluation de l'exactitude
scores = model.evaluate(X_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])

#Visualisation des données (10 premières feuilles de données de test)
for i in range(10):
    plt.subplot(2, 5, i+1)
    plt.imshow(X_test[i])
plt.suptitle("10 images of test data",fontsize=16)
plt.show()

#Prédiction (10 premières feuilles de données de test)
pred = np.argmax(model.predict(X_test[0:10]), axis=1)
print(pred)

model.summary()

Recommended Posts

Python: Application de la reconnaissance d'image à l'aide de CNN
Python: principes de base de la reconnaissance d'image à l'aide de CNN
Application de la reconnaissance d'image CNN2
Capture d'image de Firefox en utilisant Python
Reconnaissance d'image des fruits avec VGG16
Reconnaissance d'image à l'aide de chevaux et de cerfs CNN
Principes de base de la reconnaissance d'image CNN 1
Application de Python 3 vars
Reconnaissance d'accords à l'aide du chromagramme de la bibliothèque de python librosa
python: principes de base de l'utilisation de scikit-learn ①
Application de Python: Nettoyage des données Partie 3: Utilisation d'OpenCV et prétraitement des données d'image
J'ai essayé la reconnaissance de caractères manuscrits des caractères runiques avec CNN en utilisant Keras
[Python] Utilisation d'OpenCV avec Python (filtrage d'image)
Jugement de l'image rétroéclairée avec OpenCV
Authentification à l'aide de l'authentification des utilisateurs tweepy et de l'authentification d'application (Python)
Python: Application de l'apprentissage supervisé (retour)
[Python] Utilisation d'OpenCV avec Python (transformation d'image)
Suppression de la brume à l'aide de Python detailEnhanceFilter
python x tensoflow x reconnaissance de visage d'image
Implémentation des notifications de bureau à l'aide de Python
Implémentation de Light CNN (Python Keras)
Reconnaissance de caractères manuscrits à l'aide de KNN en Python
Essai de la reconnaissance vocale à l'aide d'Azure avec Python (entrée depuis le microphone)
Reconnaissance d'image
Bases du traitement d'images binarisées par Python
Collecte automatique des cours boursiers à l'aide de python
À propos de la création de l'interface graphique à l'aide de TKinter de Python
Estimation de catégorie à l'aide de l'API de reconnaissance d'image de docomo
Exemple d'application utilisant MongoDB de Spring Boot
Pratique d'utilisation de ceci en Python (mauvais)
Modèle de reconnaissance d'image utilisant l'apprentissage profond en 2016
Introduction facile de la reconnaissance vocale avec Python
[Python] Calcul de la similarité d'image (coefficient de dés)
Échelle de gris par matrice-Reinventor of Python image processing-
Traffic Safety-kun: Reconnaissance des panneaux de signalisation en Python
Dessin avec Matrix-Reinventor of Python Image Processing-
Étude sur Tokyo Rent en utilisant Python (3-1 sur 3)
Analyse d'image de microtomographie à rayons X par Python
Filtrage par convolution par matrice-Reinventor of Python image processing-
Analyse de la variation temporelle des trous noirs en utilisant Python
[Introduction à Udemy Python3 + Application] 26. Copie du dictionnaire
J'ai essayé la reconnaissance d'image de CIFAR-10 avec Keras-Learning-
Comment coder un drone en utilisant la reconnaissance d'image
[Python] J'ai essayé de juger l'image du membre du groupe d'idols en utilisant Keras
traitement d'image python
Programme de reconnaissance Nogizaka (utilisant Yolov5) Table des matières
J'ai essayé la reconnaissance d'image de CIFAR-10 avec la reconnaissance d'image Keras-
Apprentissage automatique: reconnaissance d'image de MNIST à l'aide de PCA et de Gaussian Native Bayes
[Introduction à Udemy Python3 + Application] 19. Copie de la liste
Obtenir l'URL de l'image à l'aide de l'API Flickr en Python
Commencez à utiliser Python
Introduction de la bibliothèque d'imagerie Python (PIL) à l'aide de HomeBrew
Encodage de caractères lors de l'utilisation du module csv de python 2.7.3
Les bases de Python ①
Bases de python ①
Traitement d'image? L'histoire du démarrage de Python pour