Lorsque je faisais du machine learning pour la première fois, je m'intéressais à la reconnaissance d'image et j'ai décidé de l'essayer, mais je me demandais quelle approche adopter. Par conséquent, il y avait un cours appelé "Reconnaissance d'image à l'aide de CNN" par Aidemy, alors je l'ai suivi et j'ai décidé de faire CNN.
La première chose à laquelle j'ai pensé a été le classement des chevaux de course car j'aime les courses de chevaux. Pensant comme [cheval de course = cheval sur lequel monte un cavalier], j'ai pensé à faire quelque chose qui puisse être reconnu comme un [cheval], que ce soit un cheval de course ou un cheval nu.
** La classification est le cheval et le cerf. ** ** La raison est que j'ai également utilisé l'ensemble de données CIFAR-10 dans le processus de collecte d'images de chevaux, mais il y avait un cerf dans le CIFAR-10. Je voulais essayer quelque chose de similaire à un animal, donc c'était juste.
Ce qui suit a été utilisé pour la collecte d'images.
Recherche mot "cheval de course" "Cheval de course" "Cheval de course" environ 1400 feuilles Recherche mot "cerf" environ 800
L'ensemble de données est parfaitement traité, nous traiterons donc les images que nous avons récupérées sur le Web.
Utilisez le hachage d'image (phash) pour extraire les images en double. Détecter les dossiers avec la même image dans ImageHash J'ai utilisé le code cité et édité ici.
from PIL import Image, ImageFile
import imagehash
import os
#Ne sautez pas les grandes images
ImageFile.LOAD_TRUNCATED_IMAGES = True
#phash Affiche la différence entre les valeurs de hachage de deux images
def image_hash(img, otherimg):
#Spécifiez le phash
hash = imagehash.phash ( Image.open ( img ) )
other_hash = imagehash.phash ( Image.open ( otherimg ) )
return hash - other_hash
#Détecter la plus petite taille d'image
def minhash(img, otherimg):
# (largeur,la taille)Taple
hash_size = Image.open ( img ).size
otherhash_size = Image.open ( otherimg ).size
if hash_size == otherhash_size:
return 0
if hash_size < otherhash_size:
return 1
#Enregistrez le répertoire contenant les images que vous souhaitez rechercher dans le chemin suivant
default_dir = 'Chemin où le répertoire contenant les images est enregistré'
#Obtenez le répertoire contenant les images que vous souhaitez rechercher
img_dir = os.listdir ( default_dir )
#Obtenez le chemin contenant l'image que vous souhaitez rechercher
img_dir_path = os.path.join ( default_dir, img_dir[0] )
#Obtenez une liste d'images
img_list = os.listdir ( img_dir_path )
#S'il y a deux images ou plus, récupérez le chemin de l'image et listez-la
img_path = [os.path.join ( img_dir_path, i ) for i in img_list
if len ( os.path.join ( img_dir_path, i ) ) > 2]
#Obtenir le nombre d'images dans un dossier
img_list_count = len ( img_list )
i = 0
delete_list = []
# image_hash(),minhash()Comparez les images par dossier avec
while i < img_list_count:
#le progrès
print ( 'Fonctionnement: ', str ( i + 1 ) + '/' + str ( img_list_count ) )
# i +Ne comparez pas la même image avec celle de la deuxième comparaison avec 1
for j in range ( i + 1, img_list_count ):
#Si la différence entre les valeurs de hachage est de 10 ou moins, elle est reconnue comme la même image.
if image_hash ( img_path[i], img_path[j] ) < 10:
print ( img_path[i] + ' | vs | ' + img_path[j] )
#Si la taille de l'image est la même, supprimez un chemin_Stocker dans la liste
if minhash ( img_path[i], img_path[j] ) == 0:
if not img_path[j] in delete_list:
delete_list.append ( img_path[i] )
#Supprimer le chemin avec la plus petite taille d'image_Stocker dans la liste
if minhash ( img_path[i], img_path[j] ) == 1:
delete_list.append ( img_path[i] )
j += 1
i += 1
#Affichez le chemin de l'image que vous souhaitez supprimer
print ( delete_list )
#Pour ouvrir l'image que vous souhaitez supprimer
# def open_folder(path):
# subprocess.run ( 'explorer {}'.format ( path ) )
#
# for i in range ( len ( delete_list ) ):
# open_folder ( delete_list[i] )
#Si vous souhaitez continuer la suppression
# for i in delete_list:
# try:
# os.remove( i )
# except OSError :
# pass
Comparez la similitude d'image entre ORB et Perceptual Hash en utilisant python
Calculer la similitude d'image à l'aide de Perceptual Hash
J'ai supprimé manuellement les images que je pensais ne pas pouvoir être utilisées pour l'apprentissage.
Veuillez vous reporter ici pour la conversion au format RVB. Images de prétraitement pour l'apprentissage automatique
De cette manière, l'image traitée est prête.
Utilisez l'image plus CIFAR-10 pour l'image ci-dessus.
459 photos récupérées par l'API Horse Folder, dossier de cerfs API + CIFAR-10 1138 feuilles Est gonflé avec ImageDataGenerator.
Vous pouvez entraîner le modèle tel quel en utilisant fit_generator () et flow (), mais cette fois c'est juste pour un simple remplissage.
Enregistrez donc l'image générée sur votre lecteur.
from keras.preprocessing.image import ImageDataGenerator
import os
datagen = ImageDataGenerator(rotation_range=20, #Plage de rotation à rotation aléatoire (unité: degré)
width_shift_range=0.2, #Mouvement parallèle aléatoire dans le sens horizontal, rapport à la largeur de l'image
height_shift_range=0.2, #Mouvement parallèle aléatoire dans la direction verticale, rapport à la largeur verticale de l'image
shear_range=0.2, #Degré de cisaillement. L'augmentation de la taille donne à l'image un aspect plus écrasé ou étiré en diagonale (unité: degré)
zoom_range=0.2, #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
horizontal_flip=True) #Retourner horizontalement au hasard
root_dir = './data/padding' #Chemin avec le dossier d'image que vous souhaitez gonfler
targetsize = (128, 128) #Taille de traitement
save_dir = os.listdir(root_dir) #Nom du dossier pour enregistrer l'image gonflée
save_path = os.path.join('./data/save', save_dir[0]) #Où enregistrer l'image gonflée
increase = len(os.listdir(os.path.join(root_dir, save_dir[0]))) #Nombre d'images dans le dossier d'images que vous souhaitez gonfler
increase_count = 1 #Gonflez ce nombre de motifs par feuille(increase✕increase_Les images augmentent du nombre de comptage)
#Créer si le répertoire de destination n'existe pas
if not os.path.exists(save_path):
os.makedirs(save_path)
# flow_from_directory()Image avec laquelle vous voulez gonfler(dossier)Et traiter et enregistrer l'image gonflée en même temps
ffd = datagen.flow_from_directory(
directory=root_dir,
target_size=targetsize,
color_mode='rgb',
batch_size=increase,
save_to_dir=save_path)
[next(ffd) for i in range(increase_count)]
dossier cheval 2000 feuilles 2000 dossiers de cerfs Est prêt.
Images d'entraînement Keras-Augmenter avec Keras ImageDataGenerator Modifiez Keras CNN pour comprendre ImageDataGenerator classifier_from_little_data_script_1.py [Comment gonfler les images d'entraînement avec Keras ImageDataGenerator](https://intellectual-curiosity.tokyo/2019/07/03/keras%E3%81%AEimagedatagenerator%E3%81%A7%E5%AD%A6% E7% BF% 92% E7% 94% A8% E7% 94% BB% E5% 83% 8F% E3% 82% 92% E6% B0% B4% E5% A2% 97% E3% 81% 97% E3% 81% 99% E3% 82% 8B% E6% 96% B9% E6% B3% 95 /) Image Preprocessing
L'importation jusqu'à "Représentation graphique des résultats" est la suivante
#Code pour exécuter plaidML avec Karas
import plaidml.keras
plaidml.keras.install_backend()
from sklearn.model_selection import train_test_split
from keras.callbacks import ModelCheckpoint
from keras.layers import Conv2D, MaxPooling2D, Dense, Dropout, Flatten
from keras.models import Sequential
from keras.utils import np_utils
from keras import optimizers
from keras.preprocessing.image import img_to_array, load_img
import keras
import glob
import numpy as np
import matplotlib.pyplot as plt
#Chemin du répertoire d'image
root_dir = './data/'
#Nom du répertoire d'images
baka = ['horse', 'deer']
X = [] #Liste qui stocke les données 2D des images
y = [] #étiquette(Bonne réponse)Liste pour stocker des informations sur
for label, img_title in enumerate(baka):
file_dir = root_dir + img_title
img_file = glob.glob(file_dir + '/*')
for i in img_file:
img = img_to_array(load_img(i, target_size=(128, 128)))
X.append(img)
y.append(label)
#Liste en 4 dimensions de tableaux Numpy(*, 244, 224, 3)
X = np.asarray(X)
y = np.asarray(y)
#Convertir les valeurs de pixel de 0 à 1
X = X.astype('float32') / 255.0
#Étiquette un-Convertir en étiquette à chaud
y = np_utils.to_categorical(y, 2)
#Divisez les données
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=0)
xy = (X_train, X_test, y_train, y_test)
# .Économisez avec npy
np.save('./npy/train.npy', xy)
#Données d'image pour l'apprentissage(Rangée (hauteur),Largeur de colonne),Couleur (3))Confirmation de(Entrée de la couche d'entrée_Identique à la forme)
print('3D:', X_train.shape[1:])
Cette partie est un essai et une erreur Utilisez ModelCheckpoint dans les rappels de model.fit () pour enregistrer le modèle pour chaque époque. Enfin, l'ensemble du modèle lorsque val_loss est la valeur minimale reste au format hdf5. Les modèles et graphiques sont ** ceux avec le taux de précision le plus élevé dans le test final. ** **
#Couche d'entrée,Couche cachée(Fonction d'activation:relu)
model.add ( Conv2D ( 32, (3, 3), activation='relu', padding='same', input_shape=X_train.shape[1:] ) )
model.add ( MaxPooling2D ( pool_size=(2, 2) ) )
model.add ( Conv2D ( 32, (3, 3), activation='relu', padding='same' ) )
model.add ( MaxPooling2D ( pool_size=(2, 2) ) )
model.add ( Conv2D ( 64, (3, 3), activation='relu' ) )
model.add ( MaxPooling2D ( pool_size=(2, 2) ) )
model.add ( Conv2D ( 128, (3, 3), activation='relu' ) )
model.add ( MaxPooling2D ( pool_size=(2, 2) ) )
model.add ( Flatten () )
model.add ( Dense ( 512, activation='relu' ) )
model.add ( Dropout ( 0.5 ) )
#Couche de sortie(Classement 2 classes)(Fonction d'activation:softmax)
model.add ( Dense ( 2, activation='softmax' ) )
#Compiler (taux d'apprentissage:1e-3, fonction de perte: catégorique_crossentropy, algorithme d'optimisation: RMSprop, fonction d'évaluation: précision(Taux de réponse correct))
rms = optimizers.RMSprop ( lr=1e-3 )
model.compile ( loss='categorical_crossentropy',
optimizer=rms,
metrics=['accuracy'] )
#Époque du modèle d'apprentissage
epoch = 50
#Chemin pour enregistrer le modèle
fpath = f'./model/model.{epoch:02d}-.h5'
#Vérifiez si vous souhaitez enregistrer le modèle pour chaque époque
mc = ModelCheckpoint (
filepath=fpath,
monitor='val_loss', #Que vérifier la note
verbose=1,
save_best_only=True, # val_Le dernier modèle optimal de perte n'est pas écrasé
save_weights_only=False, #Si False, enregistrez le modèle entier
mode='min', #La cible du contrôle est val_Puisqu'il s'agit d'une perte, spécifiez le minimum
period=1 ) #Intervalle d'époque à vérifier
#Apprenez avec le modèle construit
history = model.fit (
X_train,
y_train,
batch_size=64,
epochs=epoch,
callbacks=[mc],
validation_data=(X_test, y_test) )
Le nombre affiché dans le graphique n'est pas le nombre dans model.h5, mais le nombre de la dernière époque.
#Visualisation
fig = plt.figure(figsize=(18, 6)) #Création de fenêtres
#Graphique du taux de réponse correct
plt.subplot(1, 2, 1) #Afficher deux côte à côte sur le côté droit
plt.plot(history.history['acc'], label='acc', ls='-', marker='o') #Exactitude des données d'entraînement
plt.plot(history.history['val_acc'], label='val_acc', ls='-', marker='x') #Exactitude des données d'entraînement
plt.title(f'Training and validation accuracy \n val_acc {score[1]:.4f}') #Titre
plt.xlabel('epoch') #Axe horizontal
plt.ylabel('accuracy') #Axe vertical
plt.legend(['acc', 'val_acc']) #Guide d'utilisation
plt.grid(color='gray', alpha=0.2) #Affichage de grille
#Graphique de perte
plt.subplot(1, 2, 2) #Afficher deux côte à côte sur le côté gauche
plt.plot(
history.history['loss'], label='loss', ls='-', marker='o') #Perte de données d'entraînement
plt.plot(history.history['val_loss'], label='val_loss', ls='-', marker='x') #Perte de données d'entraînement
plt.title(f'Training and validation loss \n val_loss {score[0]:.4f}')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['loss', 'val_loss'])
plt.grid(color='gray', alpha=0.2)
#sauvegarder
plt.savefig('1.png')
plt.show()
Modèle enregistré
Epoch 15/50 ・ ・ ・ ・ ・ ・ 3200/3200 [==============================] - 122s 38ms/step - loss: 0.1067 - acc: 0.9625 - val_loss: 0.1872 - val_acc: 0.9363
Parce que le graphique n'est pas stable Epoch15 a atteint la valeur minimale val_loss. val_loss: 0.1872 - val_acc: 0.9363
Il est possible que le taux d'apprentissage soit élevé et que le nombre de données soit petit. En outre, la seconde moitié est en surapprentissage.
Les améliorations basées sur cela sont décrites dans «** Essayé **» à la fin de cet article. En conséquence, cela n'a pas fonctionné ...
Préparez une image complètement différente et distinguez-la avec le modèle enregistré.
#Code pour exécuter plaidML avec Karas
import plaidml.keras
plaidml.keras.install_backend()
from keras.preprocessing.image import img_to_array, load_img
from keras.models import load_model
import numpy as np
import glob
#Chemin des données du modèle
hdf_path = './model/model.20-val_loss 0.2648 - val_acc 0.8793.h5'
#Chargement du modèle
model = load_model(hdf_path)
#Répertoire contenant les images à tester
img_path = './baka/'
#Obtenez 14 images
img_list = glob.glob(img_path + '*')
size = (128, 128, 3)
for index, i in enumerate(img_list):
#Redimensionner et charger des images et les organiser
test_img = img_to_array(load_img(i, target_size=size))
# 0~Plage à 1
test_img = test_img / 255
#Dans un tableau à 4 dimensions
test_img = test_img[np.newaxis, ...]
#Prévoir
pre = model.predict(test_img)
if np.max(pre[0]) == pre[0, 0]:
print(f'{img_list[index]} -> {pre}Est un cheval')
if np.max(pre[0]) == pre[0, 1]:
print(f'{img_list[index]} -> {pre}Cerf')
Un nombre élevé sur le côté gauche du tableau est un cheval, et un nombre élevé sur le côté droit est un cerf.
deer1.jpg-> [[0.08649362 0.9135064]] est un cerf deer2.jpg-> [[5.096481e-06 9.999949e-01]] est un cerf deer3.jpg-> [[0.01137464 0.9886254]] est un cerf deer4.jpg-> [[0.04577665 0.9542234]] est un cerf deer5.jpg-> [[1.0562457e-07 9.9999988e-01]] est un cerf deer6.jpg-> [[0.10744881 0.89255124]] est un cerf deer7.jpg-> [[0.5856648 0.41433516]] est un cheval horse1.jpg-> [[0.00249346 0.99750656]] est un cerf horse10.jpg-> [[0.6968936 0.30310643]] est un cheval horse2.jpg-> [[0.90138936 0.09861059]] est un cheval horse3.jpg-> [[9.9987268e-01 1.2731158e-04]] est un cheval horse4.jpg-> [[9.9999964e-01 4.1403896e-07]] est un cheval horse5.jpg-> [[9.999294e-01 7.052123e-05]] est un cheval horse6.jpg-> [[9.9999738e-01 2.6105645e-06]] est un cheval horse7.jpg-> [[0.93193245 0.06806755]] est un cheval horse8.jpg-> [[0.01251398 0.987486]] est un cerf horse9.jpg-> [[0.00848716 0.99151284]] est un cerf
Le taux de réponse correcte était de 76,47%.
Quant au jugement du cheval de course, qui était le but principal, horse10.jpg a été jugé comme [cheval], mais horse8.jpg et horse9.jpg ont été jugés comme [cerf].
J'ai réalisé que je n'avais pas encore suffisamment étudié, que ce soit la cause du jeu de données, la taille des données ou autre chose.
Voici quelques-unes des choses que j'ai essayées.
Modifier l'ensemble de données
dossier cheval → 2295 feuilles dossier cerf → 2295 feuilles Et bien que je n'ai pas changé la couche, j'ai baissé le taux d'apprentissage à 1e-4.
Epoch 27/30 ・ ・ ・ ・ ・ ・ 3672/3672 [==============================] - 139s 38ms/step - loss: 0.1167 - acc: 0.9570 - val_loss: 0.1760 - val_acc: 0.9227
Le graphique n'est pas stable résultats de test
Incorrect deer1.jpg-> [[0.5788138 0.42118627]] est un cheval deer5.jpg-> [[0.5183205 0.48167947]] est un cheval horse8.jpg-> [[0.0699899 0.93001]] est un cerf Bonne réponse horse9.jpg-> [[0.612066 0.38793397]] est un cheval horse10.jpg-> [[0.7463752 0.2536248]] est un cheval
Le taux de réponse correcte a chuté de 70,59%.
Cette fois, le taux d'apprentissage a été encore réduit à 1e-5 et la taille du lot a été fixée à 32. Je n'ai pas changé les couches. Le graphique est devenu stable. Cependant, le taux de réponse correcte au test était de 47,06%, ce qui était considérablement inférieur.
J'ai essayé beaucoup d'autres choses avec l'ensemble de données ci-dessus, mais je n'ai pas obtenu les résultats escomptés, alors j'ai à nouveau changé l'ensemble de données.
dossier cheval → 2276 feuilles dossier cerf → 2276 feuilles
Également réduit le nombre de couches
#Couche d'entrée,Couche cachée(Fonction d'activation:relu)
model.add ( Conv2D ( 32, (3, 3), activation='relu', padding='same', input_shape=X_train.shape[1:] ) )
model.add ( MaxPooling2D ( pool_size=(2, 2) ) )
model.add ( Conv2D ( 32, (3, 3), activation='relu', padding='same' ) )
model.add ( MaxPooling2D ( pool_size=(2, 2) ) )
model.add ( Conv2D ( 64, (3, 3), activation='relu' ) )
model.add ( MaxPooling2D ( pool_size=(2, 2) ) )
model.add ( Flatten () )
model.add ( Dense ( 64, activation='relu' ) )
model.add ( Dropout ( 0.5 ) )
#Couche de sortie(Classement 2 classes)(Fonction d'activation:softmax)
model.add ( Dense ( 2, activation='softmax' ) )
Compiler (taux d'apprentissage: 1e-4, fonction de perte: catégorical_crossentropy, algorithme d'optimisation: RMSprop, fonction d'évaluation: précision (taux de réponse correct)) Epoques = 20, taille du lot batch_size = 32
Epoch 18/20 3641/3641 [==============================] - 131s 36msstep - loss 0.2647 - acc 0.8846 - val_loss 0.2948 - val_acc 0.8716
Le graphique a tendance à être un peu stable, mais le taux de réponse correcte du test était de 64,71%.
J'ai essayé diverses choses, y compris la fonction sigmoïde, deer1.jpg a une forte probabilité d'être jugé comme un cheval. De plus, l'image avant du cheval de course de horse8.jpg et horse9.jpg est plus susceptible d'être considérée comme un cerf. Les données sont peut-être insuffisantes.
Il existe encore différentes techniques pour augmenter le taux de précision, mais je voudrais terminer ici une fois et relever le défi à nouveau. Atténuation du taux d'apprentissage, apprentissage d'ensemble, apprentissage par transfert, EfficientNet, etc.
Je n'ai pas obtenu les résultats souhaités, mais j'ai pu essayer la reconnaissance d'image à l'aide de CNN.
Classification en 2 types (classes) par Keras Quelle méthode d'optimisation montre les meilleures performances pour apprendre CNN J'ai en fait fabriqué et publié une IA qui détermine si le chocolat que j'ai reçu le jour de la Saint-Valentin est mon préféré (2019) Méthode d'opération lors de la gestion d'un tableau d'images, etc. Identification d'amis avec TensorFlow + Keras - Partie 2: Apprendre avec un simple CNN Connaissances de base d'apprentissage en profondeur pour les super débutants Facile à créer CNN avec Keras Une machine qui ne peut pas distinguer une belle femme n'est qu'une machine: génération de jeux de données pour l'apprentissage automatique par Python Création d'une IA de discrimination de groupe de pente par reconnaissance d'image Créez une IA qui vous permet de choisir Ayataka par reconnaissance d'image Ajustez les hyper paramètres dans MNIST pour voir le graphique de perte / précision CNN avec Keras Enregistrez le meilleur modèle (Comment utiliser ModelCheckpoint) L'histoire de l'utilisation de l'apprentissage en profondeur pour créer un programme de discrimination des actrices qui vous ressemble Implémentation DNN dans Keras Chargez un modèle entraîné avec KERAS et identifiez une image
Recommended Posts