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.
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.
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.
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.
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.
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()
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()
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()
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()
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.
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