[PYTHON] Créez un modèle de classification d'images de manière explosive avec Azure Custom Vision et implémentez-le avec Flask

Aperçu

Lors de la session d'étude, j'ai construit une application Web d'apprentissage supervisé en utilisant des données d'image en référence aux livres suivants.

Guide d'utilisation de l'apprentissage automatique pour apprendre dans la pratique

L'application créée est la suivante. URL:https://pokemonclassfication.herokuapp.com/

ポケモンアプリのサンプル.mov.gif

Lorsque vous téléchargez une image Pokémon, l'image est classée et les informations Pokémon estimées sont affichées. Nous exploitons la vision personnalisée d'Azure pour nos modèles analytiques et Flask pour notre infrastructure Web.

Cet article décrit principalement ce qui suit.

  1. Créez un script de collecte de données d'image avec Google Image Crawler
  2. Créez un modèle analytique avec Vison personnalisé
  3. Validation du modèle
  4. Mise en œuvre à l'aide de l'API Custom Vision

Pour une explication détaillée de l'implémentation de Flask, reportez-vous au livre " Guide pratique d'utilisation de l'apprentissage automatique "et" Référence officielle " Recommandé à lire.

Cliquez ici pour le code de l'application Web: Code de l'application de classification d'images Pokemon

1. Créez un script de collecte de données d'image avec Google Image Crawler

Un grand nombre d'images est nécessaire pour construire un modèle de classification d'images dans l'apprentissage supervisé. Après tout, collecter des images manuellement est une perte de travail, je souhaite donc l'automatiser dans une certaine mesure.

Le script de collection d'images utilise le package Python icrawler. Au lieu de simplement collecter, 20% des images collectées sont utilisées comme données de test, elles sont donc collectées dans des dossiers séparés. Le code utilisé est le suivant.

collect_img_poke.py


import os
import glob
import random
import shutil
from icrawler.builtin import GoogleImageCrawler

#Répertoire racine pour enregistrer les images
root_dir = 'pokemon/'
#Liste de mots clés de recherche d'images Pokemon
pokemonnames = ['Pikachu','Zenigame','Lézard humain','Fushigidane','Cavigon']

#Nombre de données d'image collectées
data_count = 100

for pokemonname in pokemonnames:
    crawler = GoogleImageCrawler(storage={'root_dir':root_dir + pokemonname + '/train'})
    
    filters = dict(
        size = 'large',
        type = 'photo'
    )
    
    #Exécution de l'exploration
    crawler.crawl(
        keyword=pokemonname,
        filters=filters,
        max_num=data_count
    )
    
    #Supprimer tous les fichiers si le répertoire de test de la dernière exécution existe
    
    if os.path.isdir(root_dir + pokemonname + '/test'):
        shutil.rmtree(root_dir + pokemonname + '/test')
    os.makedirs(root_dir + pokemonname + '/test')
    
    #Obtenez une liste des fichiers téléchargés
    filelist = glob.glob(root_dir + pokemonname + '/train/*')
    #Extraire 20% du nombre de téléchargements sous forme de données de test
    test_ratio = 0.2
    testfiles = random.sample(filelist, int(len(filelist) * test_ratio))
    
    for testfile in testfiles:
        shutil.move(testfile, root_dir + pokemonname + '/test/')

Ce qui précède est le Guide d'utilisation de l'apprentissage automatique pour apprendre dans la pratique C'est presque le même que le contenu décrit dans. Cependant, ce code seul ne fonctionnera pas à partir du 13 septembre 2020.

Il semble que la cause en soit que l'API de recherche d'images Google a changé. Voici une solution de contournement pour cela. Référence: Google Crawler is down # 65

Il semble que la méthode d'analyse de /icrawler/builtin/google.py devrait être modifiée comme suit. Le contenu commenté sera le contenu avant le changement.

def parse(self, response):
    soup = BeautifulSoup(
        response.content.decode('utf-8', 'ignore'), 'lxml')
    #image_divs = soup.find_all('script')
    image_divs = soup.find_all(name='script')
    for div in image_divs:
        #txt = div.text
        txt = str(div)
        #if not txt.startswith('AF_initDataCallback'):
        if 'AF_initDataCallback' not in txt:
            continue
        if 'ds:0' in txt or 'ds:1' not in txt:
            continue
        #txt = re.sub(r"^AF_initDataCallback\({.*key: 'ds:(\d)'.+data:function\(\){return (.+)}}\);?$",
        #             "\\2", txt, 0, re.DOTALL)
        #meta = json.loads(txt)
        #data = meta[31][0][12][2]
        #uris = [img[1][3][0] for img in data if img[0] == 1]
        
        uris = re.findall(r'http.*?\.(?:jpg|png|bmp)', txt)
        return [{'file_url': uri} for uri in uris]

Vous pouvez vérifier le répertoire dans lequel icrawler existe réellement par la méthode suivante.

>>import icrawler
>>icrawler.__path__
['/~~~~~~~~/python3.7/site-packages/icrawler']

Au fait, je pense qu'il a la hiérarchie suivante.

├── pokemon
│ ├── Pikachu
│   │   ├── test
│   │   └── train
│ ├── Lézard humain
│   │   ├── test
│   │   └── train
│ ├── Zenigame
│   │   ├── test
│   │   └── train
│ ├── Fushigidane
│   │   ├── test
│   │   └── train
│ └── Cavigon
│       ├── test
│       └── train
│
└── collect_img_poke.py

2. Créez un modèle analytique avec Vison personnalisé

Custom Vision est l'un des services Azure qui vous permet de créer des modèles d'analyse de classification d'images sans programmation. Une autre caractéristique est qu'il est facile de publier en tant qu'API. Pour en profiter, vous devez disposer d'un abonnement Azure. Vous pouvez l'utiliser gratuitement pendant un mois. Enregistrement Azure Portail de vision personnalisé

Reportez-vous à ce qui suit pour la procédure de création de Custom Vision avec GUI. Démarrage rapide: Comment créer un classificateur avec une vision personnalisée

Vous trouverez ci-dessous les étapes simples après la connexion au portail Custom Vision.

  1. Sélectionnez Nouveau projet pour créer votre premier projet. La boîte de dialogue Créer un nouveau projet s'affiche. Reportez-vous aux paramètres de la zone de texte et aux paramètres suivants pour les cases à cocher.

image.png

  1. Cliquez sur Ajouter une image. image.png

  2. Marquez l'image et téléchargez-la. Cette fois, je télécharge des images de Pikachu, Hitokage, Zenigame, Fushigidane et Kavigon.

image.png

  1. Cliquez sur Entraînement dans le coin supérieur droit, sélectionnez Entraînement rapide, puis cliquez sur Entraînement dans la fenêtre modale. image.png

L'application de classification d'images est construite selon la procédure ci-dessus. Les informations du modèle de construction sont les suivantes.

image.png

La raison pour laquelle la précision n'est pas bonne cette fois-ci est que les images collectées automatiquement sont téléchargées sans examen. Si vous souhaitez améliorer la précision, veuillez examiner les images collectées automatiquement. Peut-être que Pikachu et les gens qui font du cosplay sont mélangés.

  1. Cliquez simplement sur le bouton Publier en haut à gauche et ce modèle d'analyse sera publié sur le Web en tant qu'API. image.png

  2. Cliquez sur l'URL de prédiction pour obtenir des informations sur la connexion à l'API. image.png

Cette fois, afin de télécharger et d'utiliser l'image, nous utiliserons l'URL et la clé de prédiction décrites ci-dessous dans l'image.

La fonctionnalité d'Azure Custom Vision est que vous pouvez facilement créer un modèle de classification d'image par la procédure ci-dessus et le publier sur le Web en tant qu'API.

3. Validation du modèle

Laissez le modèle de construction analyser l'image téléchargée pour le test et vérifier le taux de précision. Créez les fichiers suivants dans la même hiérarchie que collect_img_poke.py. Exécutez le fichier après avoir défini l'URL publique et la clé du modèle créé.

predictions_poke_test.py


import glob
import requests
import json

base_url = '<API URL>'
prediction_key = '<Key>'

poke_root_dir = 'pokemon/'
#Liste des noms de Pokémon à vérifier
pokemonnames = ['Pikachu','Zenigame','Lézard humain','Fushigidane','Cavigon']

for pokename in pokemonnames:
    testfiles = glob.glob(poke_root_dir + pokename + '/test/*')
    data_count = len(testfiles)
    true_count = 0
    
    for testfile in testfiles:
        headers = {
            'Content-Type': 'application/json',    
            'Prediction-Key': prediction_key
        }
        
        params = {}
        predicts = {}
        data = open(testfile, 'rb').read()
        response = requests.post(base_url, headers=headers, params=params, data=data)
        results = json.loads(response.text)
        
        try:
            #Boucle par le nombre de balises dans le résultat de la prédiction
            for prediction in results['predictions']:
                #Stockez le Pokémon prédit en association avec sa probabilité
                predicts[prediction['tagName']] = prediction['probability']
            #Sélectionnez le Pokémon avec la probabilité la plus élevée comme résultat de prédiction
            prediction_result = max(predicts, key=predicts.get)
        
            #Augmentez le nombre de réponses correctes si les résultats de la prédiction correspondent
            if pokename == prediction_result:
                true_count += 1

        #Taille de l'image>À 6 Mo, serrez jusqu'à ce que vous obteniez une erreur dans la limite de Vision personnalisée.
        except KeyError:
            data_count -= 1
            continue
    
    #Calcul du taux de réponse correcte
    accuracy = (true_count / data_count) * 100
    print('Nom du Pokémon:' + pokename)
    print('Taux de réponse correct:' + str(accuracy) + '%')

C'est OK si le résultat suivant est sorti. La précision du modèle est faible, mais vous faites probablement un jugement approximatif en fonction de la couleur.

>>>python predictions_poke_test.py 
Nom du Pokémon:Pikachu
Taux de réponse correct:95.45454545454545%
Nom du Pokémon:Zenigame
Taux de réponse correct:95.23809523809523%
Nom du Pokémon:Lézard humain
Taux de réponse correct:81.81818181818183%
Nom du Pokémon:Fushigidane
Taux de réponse correct:85.0%
Nom du Pokémon:Cavigon
Taux de réponse correct:95.83333333333334%

4. Mise en œuvre à l'aide de l'API Custom Vision

Cette application est implémentée dans Flask. Le contour de l'application est présenté ci-dessous.

image.png

L'application Web vous permet d'analyser l'image téléchargée avec Custom Vision et d'obtenir le résultat de l'analyse. À partir du résultat de l'analyse, des informations détaillées dans la base de données sont acquises, et ces informations sont intégrées au HTML et affichées à l'écran. Ce modèle MTV est utilisé par Flask et Django. Pour plus d'informations sur Flask, reportez-vous au " Guide pratique d'utilisation de l'apprentissage automatique </ Vérifiez "a>" et " Référence officielle ". Ici, nous décrirons à partir de la coopération avec Cusom Vision correspondant à ② à sur la figure jusqu'à l'acquisition d'informations DB.

Cliquez ici pour le code complet: Code d'application de classification d'images Pokemon

Voici le code correspondant.

models.py


import flaski.database
import requests
import json
import os


base_url = '<API URL>'
prediction_key = '<Key>'
POKEMON_FOLDER =  './static/images/pokemon/'

#Seuil de probabilité de prédiction (pourcentage)
threshold = 60

#Obtenez des informations Pokemon de DB et retournez-les dans le type de dictionnaire
def get_pokemon_data(pokemonname):
    ses = flaski.database.db_session()
    pokemon = flaski.database.Pokemon
    pokemon_data = ses.query(pokemon).filter(pokemon.pokemon_name == pokemonname).first()

    pokemon_data_dict = {}
    if not pokemon_data is None:
        pokemon_data_dict['pokemon_name'] = pokemon_data.pokemon_name
        pokemon_data_dict['wiki_url']        = pokemon_data.wiki_url
        pokemon_data_dict['picture_path']    = os.path.join(POKEMON_FOLDER, pokemon_data.pokemon_name + '.png')

    return pokemon_data_dict

#Appeler l'API du modèle
def callAPI(uploadFile):
    #Exécution prédictive
    headers = {
        'Content-Type': 'application/json',
        'Prediction-Key': prediction_key
    }
    params = {}
    predicts = {}
    data = open(uploadFile, 'rb').read()
    response = requests.post(base_url, headers=headers, params=params, data=data)
    response_list = json.loads(response.text)
    result = []

    try:
        #Boucle par le nombre de balises dans le résultat de la prédiction
        for prediction in response_list['predictions']:
            if len(get_pokemon_data(prediction['tagName'])) != 0:
            #Adoptez-en un avec une probabilité supérieure au seuil
                if prediction['probability'] * 100 > threshold:
                    result.append(get_pokemon_data(prediction['tagName']))
        return result

    #Taille de l'image>S'il fait 6 Mo, serrez-le jusqu'à ce qu'une erreur se produise en raison de la limitation de Custom Vision.
    except KeyError:
        return result


L'API d'appel def (uploadFile) est le processus de téléchargement d'une image dans Custom Vision et d'acquisition de données, ce qui est presque le même que le contenu du script décrit dans 3. Vérification du modèle. La différence est que le seuil de probabilité de prédiction (pourcentage): seuil est défini de sorte que seules des informations plus précises puissent être obtenues. Dans le cas du code ci-dessus, nous obtenons des informations sur Pokemon avec un taux de précision de 60% ou plus.

def get_pokemon_data (pokemonname) est connecté à la table DB créée par Flask par le processus suivant. Ensuite, les informations d'un Pokémon spécifique sont acquises par le processus de filtrage.

ses = flaski.database.db_session()
pokemon_data = ses.query(pokemon).filter(pokemon.pokemon_name == pokemonname).first()

De cette façon, Flask facilite l'obtention d'informations sur la base de données sans utiliser SQL. Vous pouvez également créer des tables de base de données avec du code.

Le code ci-dessus est utilisé pour acquérir les résultats d'analyse de Custom Vision. Comme vous pouvez le voir, développer une application à l'aide de Custom Vision est très simple.

finalement

Azure Custom Vision était un excellent point de départ pour le développement d'applications d'apprentissage automatique, car il facilite la création de modèles de classification d'images. Malgré les explications détaillées dans les livres auxquels j'ai fait référence, la raison pour laquelle j'ai écrit l'article était que le livre a été publié l'année dernière et ne pouvait pas faire face à divers changements de spécifications (robot d'exploration, etc.). Par conséquent, cet article décrit le contenu nouvellement implémenté. Je ne parle pas beaucoup de l'implémentation de Flask car c'est compréhensible en lisant le livre.

J'espère que cet article vous donnera un aperçu détaillé de la création d'applications d'apprentissage automatique.

Recommended Posts

Créez un modèle de classification d'images de manière explosive avec Azure Custom Vision et implémentez-le avec Flask
J'ai fait un modèle de classification d'images et essayé de le déplacer sur mobile
POSTER l'image avec json et la recevoir avec flask
Prenez une image avec Pepper et affichez-la sur votre tablette
[Azure] Hit Custom Vision Service avec Python
Modèle Infer Custom Vision avec Raspeye
Implémenter un modèle avec état et comportement
Créez une application de composition d'images avec Flask + Pillow
Crop Numpy.ndarray et enregistrez-le en tant qu'image
Renvoyez les données d'image avec Flask of Python et dessinez-les dans l'élément canvas de HTML