[PYTHON] (Deep learning) J'ai collecté des images de l'API Flickr et essayé de discriminer en transférant l'apprentissage avec VGG16

introduction

** ~~ L'article a été révisé (10 mars 2020) ~~ ** ** A corrigé l'article (4 mai 2020) **

Cet article résume les éléments suivants:

Au fait, puisque je suis un débutant en apprentissage automatique, j'utilise peut-être des expressions inappropriées. Dans ce cas, nous vous prions de nous excuser pour la gêne occasionnée, mais nous vous serions reconnaissants de bien vouloir nous le signaler.

L'environnement d'exécution est le suivant.

Les URL auxquelles j'ai fait référence sont répertoriées ci-dessous. https://qiita.com/ayumiya/items/e1e87df54c41519be6b4

Collectez des images

Cette fois, j'ai utilisé l'API flickr pour collecter un grand nombre d'images. À ce sujet, nous avons collecté des images en enregistrant flickr, en émettant une API, une clé secrète, etc. en référence à l'URL suivante. http://ykubot.com/2017/11/05/flickr-api/

Concernant la collection, j'ai pu collecter automatiquement des images en exécutant le programme suivant sur python. Le temps nécessaire pour collecter 300 feuilles était d'environ 5 minutes dans ce cas.

Vous trouverez ci-dessous le texte intégral du programme.

collection.py



import os
import time
import traceback
 
import flickrapi
from urllib.request import urlretrieve
 
import sys
from retry import retry
flickr_api_key = "xxxx" #Entrez la clé API émise ici
secret_key = "xxxx" #Entrez la CLE SECRET émise ici
 
keyword = sys.argv[1]
 
 
@retry()
def get_photos(url, filepath):
    urlretrieve(url, filepath)
    time.sleep(1)
 
 
if __name__ == '__main__':
 
    flicker = flickrapi.FlickrAPI(flickr_api_key, secret_key, format='parsed-json')
    response = flicker.photos.search(
        text='child',#Entrez le mot que vous souhaitez rechercher
        per_page=300,#Spécifiez le nombre de feuilles que vous souhaitez collecter
        media='photos',
        sort='relevance',
        safe_search=1,
        extras='url_q,license'
    )
    photos = response['photos']
 
    try:
        if not os.path.exists('./image-data/' + 'child'):
            os.mkdir('./image-data/' +'child')
 
        for photo in photos['photo']:
            url_q = photo['url_q']
            filepath = './image-data/' + 'child' + '/' + photo['id'] + '.jpg'
            get_photos(url_q, filepath)
 
    except Exception as e:
        traceback.print_exc()

Cette fois, nous avons collecté 300 de ces images pour reconnaître «enfant: enfant» et «vieil homme: aîné». Comme je l'expliquerai plus tard, on estime que le mot de recherche aîné n'a pas eu un taux de reconnaissance élevé car des images de plantes, de jeunes femmes, etc. ont été collectées ainsi que des personnes âgées.

Créer un programme de reconnaissance d'image

L'article suivant décrit le programme de reconnaissance d'image. Je vais affiner les points sur lesquels je suis tombé par hasard et les points à noter de l'ensemble du tableau, puis écrire le programme complet.

Bibliothèques, modules, etc. importés

child.py



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

Précautions lors de la création d'une fonction de modèle

child.py



model = Model(input=vgg16.input, output=top_model(vgg16.output))

À l'origine, l'environnement de spécification installait tensorflow et le citait comme la bibliothèque keras. Exemple: from tensorflow.keras.utils import to_categorical

Si vous procédez tel quel, en définissant cette fonction de modèle,

('Keyword argument not understood:', 'input')

Une erreur est survenue.

Il semble que cela se produit lorsque la version de keras est ancienne, J'ai également mis à jour Keras lui-même, mais l'erreur a continué à apparaître. Par conséquent, lorsque j'ai essayé d'écrire pour lire keras lui-même, cela a été résolu.

Ce résumé d'erreur et la mise à jour de keras lui-même https://sugiyamayoshiaki.jp/%E3%80%90%E3%82%A8%E3%83%A9%E3%83%BC%E3%80%91typeerror-keyword-argument-not-understood-data_format/

Vue d'ensemble du modèle VGG16

Le modèle utilisé cette fois est un modèle entraîné basé sur un perceptron multicouche appelé VGG16.

URL:https://arxiv.org/pdf/1409.1556.pdf Auteur: Karen Simonyan & Andrew Zisserman Visual Geometry Group, Department of Engineering Science, University of Oxford

002.jpeg

L'image ci-dessus ** image D ** est le modèle traité cette fois. C'est un réseau de neurones avec 13 couches convolutives ** avec une taille de noyau de ** 3 dimensions et 3 couches entièrement connectées. C'est l'algorithme annoncé en 2015, mais avant cela, la taille du noyau était très grande, comme 9 ou 11 dimensions, il y avait donc un problème que le taux de discrimination était faible alors que la charge de calcul était élevée. Par conséquent, VGG16 est une méthode qui résout ce problème en réduisant la taille du noyau à 3 et en rendant les couches plus profondes (13 couches).   En outre, le but de ce modèle est que vous pouvez vous référer à un modèle pondéré qui a subi une grande quantité de formation à la reconnaissance d'image sur un site d'images appelé ImageNet. Il peut être identifié comme 1000 types d'articles. Par conséquent, il existe deux façons de l'utiliser.

La première consiste à utiliser le modèle pondéré qui a été formé pour trouver le plus proche de 1000 types. La deuxième méthode consiste à utiliser le modèle lui-même pour un nouvel apprentissage sans utiliser de poids. Cette fois, j'aimerais utiliser cette deuxième méthode pour distinguer les enfants des personnes âgées.

Jetons un coup d'œil au contenu de ce modèle.

child.py


model.summary()

production


_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 224, 224, 3)       0
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312
_________________________________________________________________
predictions (Dense)          (None, 1000)              4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________


En regardant la ** forme de sortie **, c'est (Aucun, 244, 244, 3). Cela représente ** (nombre d'échantillons, résolution verticale, résolution horizontale, nombre de canaux (≈ RVB pour la couleur du numéro de dimension)) **. En regardant cette valeur, nous pouvons voir que le nombre de dimensions est passé de 64 à 128 à 256 à 512 après avoir traversé la couche de convolution.

Modifié pour l'apprentissage par transfert

child.py



input_tensor = Input(shape=(50, 50, 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='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(2, activation='softmax'))

Ajoutez après la couche VGG16 pour diviser en deux types, enfants et personnes âgées.

https://qiita.com/MuAuan/items/86a56637a1ebf455e180

Créer une fonction pour déterminer s'il s'agit d'un enfant ou d'un vieil homme

child.py



def child(img):
    img = cv2.resize(img, (50, 50))
    pred = np.argmax(model.predict(np.array([img])))
    if pred == 0:
        return 'C'est un enfant'
    else:
        return 'C'est un vieil homme'

En conséquence, le taux de réponse correcte n'était pas très bon. En effet, si vous recherchez un vieil homme (ancien) sur flickr, vous trouverez des photos de personnes non âgées, donc je pense que l'apprentissage ne se passe pas bien. L'image ci-dessous est un exemple.

003.png

en conclusion

Lors de l'utilisation d'un modèle déjà entraîné tel que VGG16, il est efficace d'utiliser un ensemble de données qui peut faire bon usage du contenu entraîné.

J'espère que vous pourrez l'utiliser en chevauchant fermement les épaules de vos ancêtres.

Le programme complet est stocké ci-dessous. https://github.com/Fumio-eisan/vgg16_child20200310

Recommended Posts

(Deep learning) J'ai collecté des images de l'API Flickr et essayé de discriminer en transférant l'apprentissage avec VGG16
Deep Learning from scratch La théorie et la mise en œuvre de l'apprentissage profond appris avec Python Chapitre 3
[Partie 4] Utilisez le Deep Learning pour prévoir la météo à partir d'images météorologiques
[Partie 1] Utilisez le Deep Learning pour prévoir la météo à partir d'images météorologiques
[Partie 3] Utilisez le Deep Learning pour prévoir la météo à partir d'images météorologiques
Reconnaissez votre patron avec Deep Learning et masquez l'écran
[Partie 2] Utilisez le Deep Learning pour prévoir la météo à partir d'images météorologiques
Procédure de génération et d'enregistrement d'un modèle d'apprentissage par machine learning, en faisant un serveur API et en communiquant avec JSON depuis un navigateur
Utilisez l'API Flickr de Python
J'ai essayé de refactoriser le code du modèle publié dans "Obtenir des images de l'API Flickr avec Python" (Partie 2)
Réaliser la construction d'environnement pour "Deep Learning from scratch" avec docker et Vagrant
Traitement de la voix par apprentissage profond: identifions qui est l'acteur vocal à partir de la voix
Préparez l'environnement pour le livre O'Reilly "Deep Learning from scratch" avec apt-get (Debian 8)
Essayez Fine Tuning (apprentissage par transfert), qui est le courant dominant avec des images avec keras, avec apprentissage des données
Déterminez s'il s'agit de mon enfant à partir de l'image du chien Shiba par apprentissage profond (4) Visualisation par Grad-CAM et Grad-CAM guidé
L'histoire de l'apprentissage profond avec TPU
Chainer et deep learning appris par approximation de fonction
99,78% de précision avec apprentissage en profondeur en reconnaissant les hiragana manuscrits
Apprentissage parallèle du deep learning par Keras et Kubernetes
Extraire des images et des tableaux de pdf avec python pour réduire la charge de reporting
Obtenez des données de Poloniex, un bureau de change virtuel, via l'API et utilisez le Deep Learning pour prédire le prix du lendemain.