[PYTHON] Maintenant, essayons la reconnaissance faciale avec Chainer (phase d'apprentissage)

Aperçu

La fin du développement de Chainer a été annoncée et la reconnaissance faciale est pleine de sentiments. Je vais l'épeler ici comme un mémorandum.

Cette série sera envoyée en deux parties. Cette fois, je vais vous expliquer comment mettre en œuvre la phase d'apprentissage (apprentissage des images faciales). La prochaine fois, j'expliquerai l'implémentation de Prediction Phase (reconnaissance faciale à l'aide d'une caméra).

De plus, comme j'étais un débutant en ML et un lycéen à l'époque, il peut y avoir des erreurs dans les informations ou il peut y avoir un bug dans le programme. S'il y a une telle chose, je vous serais reconnaissant de bien vouloir le signaler dans les commentaires. (Date de création de l'article: 2020/2/9)

environnement

-Software- Windows 10 Home Anaconda3 64-bit(Python3.7) Spyder -Library- Chainer 7.0.0 -Hardware- CPU: Intel core i9 9900K GPU: NVIDIA GeForce GTX1080ti RAM: 16GB 3200MHz

référence

** Livres ** CQ Publishing Deep Learning à partir de l'arithmétique et de la framboise ([Page Amazon](https://www.amazon.co.jp/%E7%AE%97%E6%95%B0-%E3%83%A9%E3%82%BA%E3%83%91% E3% 82% A4% E3% 81% 8B% E3% 82% 89% E5% A7% 8B% E3% 82% 81% E3% 82% 8B-% E3% 83% 87% E3% 82% A3% E3 % 83% BC% E3% 83% 97% E3% 83% BB% E3% 83% A9% E3% 83% BC% E3% 83% 8B% E3% 83% B3% E3% 82% B0-% E3% 83% 9C% E3% 83% BC% E3% 83% 89% E3% 83% BB% E3% 82% B3% E3% 83% B3% E3% 83% 94% E3% 83% A5% E3% 83% BC% E3% 82% BF% E3% 83% BB% E3% 82% B7% E3% 83% AA% E3% 83% BC% E3% 82% BA-% E7% 89% A7% E9% 87% 8E / dp / 4789847063))) site Référence de l'API Chainer

programme

Pour le moment, je le posterai sur Github. https://github.com/himazin331/Face-Recognition-Chainer- Le référentiel contient une phase d'apprentissage, une phase de prédiction, un programme de traitement de données et Haar-Cascade.

supposition

** Anaconda3 doit être installé ** pour le fonctionnement du programme. Veuillez vous référer à ce qui suit pour savoir comment télécharger et installer Anaconda3. Site de téléchargement d'Anaconda3 Méthode d'installation Anaconda3 (Windows)

Aussi, si vous aimez le ici publié par mon ami, veuillez vous y référer.

Après avoir installé Anaconda3, à l'invite Anaconda3 pip install chainer Veuillez entrer et installer Chainer.

À propos des données d'entraînement

Dans ce programme, ** les données d'entraînement sont une image en échelle de gris et un fichier JPEG 32x32px ** Il est mis en œuvre sur place. Veuillez utiliser ici pour le traitement des données.

Code source

** Veuillez noter que le code est sale ... **

face_recog_train_CH.py



import argparse as arg
import os
import sys

import chainer
import chainer.functions as F
import chainer.links as L 
from chainer import training
from chainer.training import extensions

#Définition de CNN
class CNN(chainer.Chain):
    
    #Définition de chaque couche
    def __init__(self, n_out):
        super(CNN, self).__init__(
            #Définition de la couche de convolution
            conv1 = L.Convolution2D(1, 16, 5, 1, 0),  # 1st
            conv2 = L.Convolution2D(16, 32, 5, 1, 0), # 2nd
            conv3 = L.Convolution2D(32, 64, 5, 1, 0), # 3rd

            #Connexion linéaire de tous les neurones
            link = L.Linear(None, 1024), #Couche entièrement connectée
            link_class = L.Linear(None, n_out), #Couche entièrement connectée pour la classification(n_out:Nombre de cours)
        )
        
    #Propagation vers l'avant
    def __call__(self, x):
        
        #Couche pliante->Fonction ReLU->Couche de pooling maximale
        h1 = F.max_pooling_2d(F.relu(self.conv1(x)), ksize=2)   # 1st
        h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), ksize=2)  # 2nd
        h3 = F.relu(self.conv3(h2))  # 3rd
        
        #Couche entièrement connectée->Fonction ReLU
        h4 = F.relu(self.link(h3))
        
        #Retour de valeur prédite
        return self.link_class(h4) #Couche entièrement connectée pour la classification
 
# Trainer
class trainer(object):
    
    #Construction de modèles,Configuration de la méthode d'optimisation
    def __init__(self):
        
        #Construction de modèles
        self.model = L.Classifier(CNN(2))
        
        #Optimisation de la configuration de la méthode
        self.optimizer = chainer.optimizers.Adam() #Algorithme d'Adam
        self.optimizer.setup(self.model) #Définir le modèle dans l'optimiseur
        
    #Apprentissage
    def train(self, train_set, batch_size, epoch, gpu, out_path):

        #Correspondant au traitement GPU
        if gpu >= 0:
            chainer.cuda.get_device(gpu).use() #Obtenir un objet appareil
            self.model.to_gpu()  #Copiez le contenu de l'instance sur le GPU
        
        #Créer un itérateur de jeu de données(Définition du traitement itératif des données d'entraînement,Mélangez chaque boucle)
        train_iter = chainer.iterators.SerialIterator(train_set, batch_size)

        #Créer un programme de mise à jour
        updater = training.StandardUpdater(train_iter, self.optimizer, device=gpu)
        #Créer un formateur
        trainer = training.Trainer(updater, (epoch, 'epoch'), out=out_path)

        #paramètres d'extension
        #Schématisation du flux de traitement
        trainer.extend(extensions.dump_graph('main/loss'))
        #Rédiger un instantané pour chaque apprentissage
        trainer.extend(extensions.snapshot(), trigger=(epoch, 'epoch'))
        # log(Format JSON)l'écriture
        trainer.extend(extensions.LogReport())
        #Tracez la valeur de la perte sur le graphique
        trainer.extend(
                extensions.PlotReport('main/loss', 'epoch', file_name='loss.png'))
        #Tracer la précision de la prédiction sur un graphique
        trainer.extend(
                extensions.PlotReport('main/accuracy', 'epoch', file_name='accuracy.png'))
        #«Nombre d’apprentissage» pour chaque apprentissage,Valeur de la perte,Précision de la prédiction,Sortie "temps écoulé"
        trainer.extend(extensions.PrintReport(
                ['epoch', 'main/loss', 'main/accuracy', 'elapsed_time']))
        #Affichage de la barre de progression
        trainer.extend(extensions.ProgressBar())

        #Commencer à apprendre
        trainer.run()

        print("___Training finished\n\n")
        
        #Rendre le modèle compatible avec le processeur
        self.model.to_cpu()
    
        #Enregistrer les paramètres
        print("___Saving parameter...")
        param_name = os.path.join(out_path, "face_recog.model") #Destination de sauvegarde des paramètres appris
        chainer.serializers.save_npz(param_name, self.model) #Ecrire les paramètres entraînés au format NPZ
        print("___Successfully completed\n\n")
    
#Création de l'ensemble de données
def create_dataset(data_dir):
    
    print("\n___Creating a dataset...")
    
    cnt = 0
    prc = ['/', '-', '\\', '|']
    
    #Nombre de jeux d'images
    print("Number of Rough-Dataset: {}".format(len(os.listdir(data_dir))))
    #Nombre de données d'image
    for c in os.listdir(data_dir):
        d = os.path.join(data_dir, c)
        print("Number of image in a directory \"{}\": {}".format(c, len(os.listdir(d))))
    
    train = []  #Ensemble de données temporaire
    label = 0
    
    #Création de jeux de données temporaires
    for c in os.listdir(data_dir):
        
        print('\nclass: {}, class id: {}'.format(c, label))   #Sortie du nom de classe et de l'ID de classe
       
        d = os.path.join(data_dir, c)    #Combiner le nom du dossier et le nom du dossier de classe
        imgs = os.listdir(d)    #Obtenez tous les fichiers image
        
        #Lecture seule des fichiers image au format JPEG
        for i in [f for f in imgs if ('jpg'or'JPG' in f)]:        
            
            #Via le fichier cache
            if i == 'Thumbs.db':
                continue
            
            train.append([os.path.join(d, i), label])   #Après avoir combiné le chemin du dossier de classe et le nom du fichier image, enregistrez-le dans la liste

            cnt += 1
            
            print("\r   Loading a images and labels...{}    ({} / {})".format(prc[cnt%4], cnt, len(os.listdir(d))), end='')
            
        print("\r   Loading a images and labels...Done    ({} / {})".format(cnt, len(os.listdir(d))), end='')
        
        label += 1
        cnt = 0

    train_set = chainer.datasets.LabeledImageDataset(train, '.')    #Base de données
    
    print("\n___Successfully completed\n")
    
    return train_set
    
def main():

    #Options de ligne de commande
    parser = arg.ArgumentParser(description='Face Recognition train Program(Chainer)')
    parser.add_argument('--data_dir', '-d', type=str, default=None,
                        help='Spécifier le chemin du dossier(Erreur lorsque non spécifié)')
    parser.add_argument('--out', '-o', type=str, 
                        default=os.path.dirname(os.path.abspath(__file__))+'/result'.replace('/', os.sep),
                        help='Spécifiez la destination de sauvegarde des paramètres(Valeur par défaut./result)')
    parser.add_argument('--batch_size', '-b', type=int, default=32,
                        help='Spécifier la taille du mini lot(Valeur par défaut 32)')
    parser.add_argument('--epoch', '-e', type=int, default=15,
                        help='Spécifier le nombre d'apprentissage(Valeur par défaut 15)')
    parser.add_argument('--gpu', '-g', type=int, default=-1,
                        help='Spécification de l'ID GPU(Les valeurs négatives indiquent le traitement du processeur,Valeur par défaut-1)')
    args = parser.parse_args()

    #Dossier non spécifié->exception
    if args.data_dir == None:
        print("\nException: Folder not specified.\n")
        sys.exit()
    #Lors de la spécification d'un dossier qui n'existe pas->exception
    if os.path.exists(args.data_dir) != True:
        print("\nException: Folder {} is not found.\n".format(args.data_dir))
        sys.exit()

    #Réglage de la sortie des informations
    print("=== Setting information ===")
    print("# Images folder: {}".format(os.path.abspath(args.data_dir)))
    print("# Output folder: {}".format(args.out))
    print("# Minibatch-size: {}".format(args.batch_size))
    print("# Epoch: {}".format(args.epoch))
    print("===========================")

    #Création de l'ensemble de données
    train_set = create_dataset(args.data_dir)

    #Commencer à apprendre
    print("___Start training...")
    Trainer = trainer()
    Trainer.train(train_set, args.batch_size, args.epoch, args.gpu, args.out)
   
if __name__ == '__main__':
    main()

Résultat d'exécution

image.png

image.png Après l'exécution, le fichier ci-dessus sera généré dans la destination de sauvegarde.

commander python face_recog_train_CH.py -d <dossier> -e <nombre d'apprentissage> -b <taille du lot> (-o <save> -g <ID GPU>) Le fichier est enregistré dans «. / Result» par défaut.

La description

Je vais expliquer le code. Malheureusement, la capacité à expliquer est faible.

Modèle de réseau

Le modèle de réseau cette fois est un réseau de neurones convolutifs (CNN). Le modèle de réseau est défini dans la classe CNN.

Classe CNN


#Définition de CNN
class CNN(chainer.Chain):
    
    #Définition de chaque couche
    def __init__(self, n_out):
        super(CNN, self).__init__(
            #Définition de la couche convolutive
            conv1 = L.Convolution2D(1, 16, 5, 1, 0),  # 1st
            conv2 = L.Convolution2D(16, 32, 5, 1, 0), # 2nd
            conv3 = L.Convolution2D(32, 64, 5, 1, 0), # 3rd

            #Connexion linéaire de tous les neurones
            link = L.Linear(None, 1024), #Couche entièrement connectée
            link_class = L.Linear(None, n_out), #Couche entièrement connectée pour la classification(n_out:Nombre de cours)
        )
        
    #Propagation vers l'avant
    def __call__(self, x):
        
        #Couche pliante->Fonction ReLU->Couche de pooling maximale
        h1 = F.max_pooling_2d(F.relu(self.conv1(x)), ksize=2)   # 1st
        h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), ksize=2)  # 2nd
        h3 = F.relu(self.conv3(h2))  # 3rd
        
        #Couche entièrement connectée->Fonction ReLU
        h4 = F.relu(self.link(h3))
        
        #Retour de valeur prédite
        return self.link_class(h4) #Couche entièrement connectée pour la classification

Nous transmettons chainer.Chain comme argument à la classe CNN. chainer.Chain est une classe spécifique à Chainer et constitue le cœur du réseau. Appelez la méthode d'instance «init» lors de la création d'une instance, et appelez la méthode d'instance de la superclasse «chainer.Chain» pour définir la couche de convolution et la couche entièrement connectée.

Les hyperparamètres de la couche de convolution dans ce programme sont indiqués dans le tableau ci-dessous.

Canal d'entrée Canal de sortie Taille du filtre Largeur de foulée Largeur de rembourrage
1st 1 16 5 1 0
2nd 16 32 5 1 0
3rd 32 64 5 1 0

Puisqu'on suppose que les données d'apprentissage sont une image en échelle de gris, le nombre de canaux d'entrée de la première couche de convolution est fixé à 1. S'il s'agit d'une image RVB, ce sera 3. "Largeur de remplissage 0" signifie qu'aucun processus de remplissage n'est effectué.

Les hyperparamètres de la couche entièrement connectée sont indiqués dans le tableau ci-dessous.

Nombre de dimensions d'entrée Nombre de dimensions de sortie
Couche entièrement connectée None 1024
Pour la classification None 2

Si vous spécifiez «Aucun» pour le nombre de dimensions d'entrée, le nombre de dimensions des données d'entrée sera appliqué automatiquement.

Cette fois, je vais faire ** 2 classification de classe **, donc j'ai mis le nombre de dimensions de sortie de la couche entièrement connectée pour ** classification de classe à 2 **. Lors de la création d'une instance de la classe CNN, en entrant une valeur numérique dans l'argument, la classification de classe correspondra à cette valeur numérique. (Dans le code, n_out signifie quelle classe classer.)

L'autre méthode, «call», est utilisée pour la propagation vers l'avant. La structure générale est illustrée dans la figure ci-dessous. image.png La couche de mise en commun est la mise en commun maximale ** avec la zone de mise en commun ** 2 x 2.


Création de l'ensemble de données

Tout d'abord, il y a quelques points à noter à propos de l'ensemble de données, donc je vais d'abord expliquer la fonction qui crée l'ensemble de données. L'ensemble de données est créé avec la fonction crate_dataset.

create_fonction d'ensemble de données


#Création de l'ensemble de données
def create_dataset(data_dir):
    
    print("\n___Creating a dataset...")
    
    cnt = 0
    prc = ['/', '-', '\\', '|']
    
    #Nombre de jeux d'images
    print("Number of Rough-Dataset: {}".format(len(os.listdir(data_dir))))
    #Nombre de données d'image
    for c in os.listdir(data_dir):
        d = os.path.join(data_dir, c)
        print("Number of image in a directory \"{}\": {}".format(c, len(os.listdir(d))))
    
    train = []  #Ensemble de données temporaire
    label = 0
    
    #Création de jeux de données temporaires
    for c in os.listdir(data_dir):
        
        print('\nclass: {}, class id: {}'.format(c, label))   #Sortie du nom de classe et de l'ID de classe
       
        d = os.path.join(data_dir, c)    #Combiner le nom du dossier et le nom du dossier de classe
        imgs = os.listdir(d)    #Obtenez tous les fichiers image
        
        #Lecture seule des fichiers image au format JPEG
        for i in [f for f in imgs if ('jpg'or'JPG' in f)]:        
            
            #Via le fichier cache
            if i == 'Thumbs.db':
                continue
            
            train.append([os.path.join(d, i), label])   #Après avoir combiné le chemin du dossier de classe et le nom du fichier image, enregistrez-le dans la liste

            cnt += 1
            
            print("\r   Loading a images and labels...{}    ({} / {})".format(prc[cnt%4], cnt, len(os.listdir(d))), end='')
            
        print("\r   Loading a images and labels...Done    ({} / {})".format(cnt, len(os.listdir(d))), end='')
        
        label += 1
        cnt = 0

    train_set = chainer.datasets.LabeledImageDataset(train, '.')    #Base de données
    
    print("\n___Successfully completed\n")
    
    return train_set

L'ensemble de données dans le problème de classification nécessite des données d'entraînement et des étiquettes correctes.

Dans ce cas, ** les données d'entraînement sont une image de visage et l'étiquette de réponse correcte est la valeur numérique correspondant à ce visage **. Par exemple, lorsqu'il y a des classes incorrectes et correctes "0" pour toutes les étiquettes des données d'entraînement dans la classe de réponse incorrecte Les étiquettes des données d'apprentissage dans la classe de réponse correcte sont définies collectivement sur "1". En raison de sa nature, vous devez faire attention à la structure du dossier.

** ** dataset.png

Comme ci-dessus, dans un dossier (train_data) Créez un dossier (faux, vrai) pour chaque classe et mettez-y les données d'image. En faisant cela, l'étiquette de réponse correcte des données d'apprentissage contenues dans false devient 0, et l'étiquette de réponse correcte contenue dans true devient 1. Dans cet exemple, l'option de commande -d spécifie train_data.

Après avoir fait quelque chose comme les notes dans le code Enfin, dans le code ci-dessous, une liste de données d'entraînement et d'étiquettes, Créez-le formellement en tant qu'ensemble de données.

    train_set = chainer.datasets.LabeledImageDataset(train, '.')    #Base de données

Apprentissage

Configurez et apprenez avant de faire du machine learning dans la classe de formateur.

classe de formateur(Méthode d'instance)


# Trainer
class trainer(object):
    
    #Construction de modèles,Configuration de la méthode d'optimisation
    def __init__(self):
        
        #Construction de modèles
        self.model = L.Classifier(CNN(2))
        
        #Optimisation de la configuration de la méthode
        self.optimizer = chainer.optimizers.Adam() #Algorithme d'Adam
        self.optimizer.setup(self.model) #Définir le modèle dans l'optimiseur

Appelez la méthode d'instance «init» lors de la création d'une instance pour déterminer l'algorithme de construction et d'optimisation du modèle de réseau. Avec self.model = L.Classifier (CNN (2)), ** classez dans n'importe quel nombre de classes en mettant une valeur arbitraire entre parenthèses de ** CNN (2) **.

Après construction, la méthode Chainer.links appelée L.Classifier () donne les fonctions d'activation et de perte. La fonction d'activation est ici une fonction d'activation utilisée au moment de la sortie, telle que la fonction softmax. La fonction d'activation est définie sur la fonction softmax et la fonction de perte est définie sur l'erreur d'entropie croisée ** par défaut, donc dans le cas d'un problème de classification, il n'y a pas de problème à simplement encapsuler le modèle de réseau.

Ensuite, après avoir créé une instance de l'algorithme d'optimisation ** Adam ** avec self.optimizer = chainer.optimizers.Adam (), Appliquez le modèle de réseau avec self.optimizer.setup (self.model).


Dans la méthode train de la classe trainer, Nous allons créer un itérateur d'ensemble de données (Iterator), un programme de mise à jour et un formateur, et continuerons la formation.

classe de formateur(méthode de train)


    #Apprentissage
    def train(self, train_set, batch_size, epoch, gpu, out_path):

        #Correspondant au traitement GPU
        if gpu >= 0:
            chainer.cuda.get_device(gpu).use() #Obtenir un objet appareil
            self.model.to_gpu()   #Copiez le contenu de l'instance sur le GPU

        #Créer un itérateur de jeu de données(Définition du traitement itératif des données d'entraînement,Mélangez chaque boucle)
        train_iter = chainer.iterators.SerialIterator(train_set, batch_size)

        #Créer un programme de mise à jour
        updater = training.StandardUpdater(train_iter, self.optimizer, device=gpu)
        #Créer un formateur
        trainer = training.Trainer(updater, (epoch, 'epoch'), out=out_path)

        #paramètres d'extension
        #Schématisation du flux de traitement
        trainer.extend(extensions.dump_graph('main/loss'))
        #Rédiger un instantané pour chaque apprentissage
        trainer.extend(extensions.snapshot(), trigger=(epoch, 'epoch'))
        # log(Format JSON)l'écriture
        trainer.extend(extensions.LogReport())
        #Tracez la valeur de la perte sur le graphique
        trainer.extend(
                extensions.PlotReport('main/loss', 'epoch', file_name='loss.png'))
        #Tracer la précision de la prédiction sur un graphique
        trainer.extend(
                extensions.PlotReport('main/accuracy', 'epoch', file_name='accuracy.png'))
        #«Nombre d’apprentissage» pour chaque apprentissage,Valeur de la perte,Précision de la prédiction,Sortie "temps écoulé"
        trainer.extend(extensions.PrintReport(
                ['epoch', 'main/loss', 'main/accuracy', 'elapsed_time']))
        #Affichage de la barre de progression
        trainer.extend(extensions.ProgressBar())

        #Commencer à apprendre
        trainer.run()

        print("___Training finished\n\n")

        #Rendre le modèle compatible avec le processeur
        self.model.to_cpu()

        #Enregistrer les paramètres
        print("___Saving parameter...")
        param_name = os.path.join(out_path, "face_recog.model") #Destination de sauvegarde des paramètres appris
        chainer.serializers.save_npz(param_name, self.model) #Ecrire les paramètres entraînés au format NPZ
        print("___Successfully completed\n\n")

Le code ci-dessous ** crée un itérateur d'ensemble de données **.

        #Créer un itérateur de jeu de données(Définition du traitement itératif des données d'entraînement,Mélangez chaque boucle)
        train_iter = chainer.iterators.SerialIterator(train_set, batch_size)

Il ** crée des mélanges et des mini-lots de commandes de données **. Spécifiez l'ensemble de données cible (train_set) et la taille du mini-lot ( batch_size) comme arguments.


Ensuite, ** créez un programme de mise à jour **.

        #Créer un programme de mise à jour
        updater = training.StandardUpdater(train_iter, self.optimizer, device=gpu)

ʻUpdater ** met à jour les paramètres **. En tant qu'arguments, spécifiez l'itérateur de l'ensemble de données (train_iter), l'algorithme d'optimisation ( self.optimizer) et l'ID GPU si nécessaire. L'algorithme d'optimisation est self.optimizer.setup (), qui applique l'algorithme d'optimisation au modèle de réseau. Même si vous spécifiez directement chainer.optimizers.Adam ()`, cela ne fonctionnera pas.


Ensuite, créez un ** formateur **.

        #Créer un formateur
        trainer = training.Trainer(updater, (epoch, 'epoch'), out=out_path)

trainer ** implémente une boucle d'apprentissage **. Nous définirons quels déclencheurs (conditions) pour mettre fin à l'apprentissage. Habituellement déclenché par le nombre d'époques ou d'itérations d'apprentissage.

Dans ce cas, ** le nombre d'apprentissage ʻepoch est défini comme déclencheur **. En tant qu'arguments, mise à jour (ʻupdater) et déclencheur d'arrêt ((epoch, 'epoch')) En outre, spécifiez la destination d'enregistrement du fichier créé par l'extension.


Ensuite, c'est enfin apprendre! Ajoutons une extension pratique avant. Le chainer a une extension appelée ** Trainer Extension **.

        #paramètres d'extension
        #Schématisation du flux de traitement
        trainer.extend(extensions.dump_graph('main/loss'))
        #Rédiger un instantané pour chaque apprentissage
        trainer.extend(extensions.snapshot(), trigger=(epoch, 'epoch'))
        # log(Format JSON)l'écriture
        trainer.extend(extensions.LogReport())
        #Tracez la valeur de la perte sur le graphique
        trainer.extend(
                extensions.PlotReport('main/loss', 'epoch', file_name='loss.png'))
        #Tracer la précision de la prédiction sur un graphique
        trainer.extend(
                extensions.PlotReport('main/accuracy', 'epoch', file_name='accuracy.png'))
        #«Nombre d’apprentissage» pour chaque apprentissage,Valeur de la perte,Précision de la prédiction,Sortie "temps écoulé"
        trainer.extend(extensions.PrintReport(
                ['epoch', 'main/loss', 'main/accuracy', 'elapsed_time']))
        #Affichage de la barre de progression
        trainer.extend(extensions.ProgressBar())

ici, -Une fonction qui écrit les données d'entrée et le flux de paramètres dans le fichier DOT suivant ・ Une fonction qui capture des informations telles que les paramètres à la fin de l'apprentissage (Vous pouvez redémarrer l'apprentissage à partir du milieu en utilisant un instantané) -Une fonction qui écrit l'historique des valeurs de perte et la précision des prédictions lors de l'apprentissage au format JSON. -Une fonction qui trace la valeur de la perte et la précision de la prédiction sur un graphique et l'exporte au format PNG. -Une fonction pour afficher le nombre d'apprentissage, la valeur de la perte, la précision de la prédiction et le temps écoulé pour chaque apprentissage ・ Fonction pour afficher la barre de progression Est donnée. Il existe également d'autres extensions. Référence de l'extension du formateur De plus, le fichier DOT et le fichier PNG générés sont générés dans la destination de sauvegarde spécifiée par training.Trainer ().


Après avoir ajouté la fonction d'extension, l'apprentissage est enfin lancé.

        #Commencer à apprendre
        trainer.run()

Avec cette seule ligne, tout commence (?) Attendons que l'apprentissage soit terminé.

Après l'apprentissage, enregistrez les paramètres.

        #Enregistrer les paramètres
        print("___Saving parameter...")
        param_name = os.path.join(out_path, "face_recog.model") #Destination de sauvegarde des paramètres appris
        chainer.serializers.save_npz(param_name, self.model) #Ecrire les paramètres entraînés au format NPZ
        print("___Successfully completed\n\n")

Dans chainer.serializers.save_npz (), définissez le paramètre de destination de sauvegarde (param_name) et le modèle de réseau ( self.model). Si spécifié, les paramètres seront enregistrés au format NPZ. Ce paramètre est utilisé pour reconnaître réellement le visage.

fonction principale

La fonction principale est omise car il n'y a pas de place pour l'expliquer.

fonction principale


def main():

    #Options de ligne de commande
    parser = arg.ArgumentParser(description='Face Recognition train Program(Chainer)')
    parser.add_argument('--data_dir', '-d', type=str, default=None,
                        help='Spécifier le chemin du dossier(Erreur lorsque non spécifié)')
    parser.add_argument('--out', '-o', type=str, 
                        default=os.path.dirname(os.path.abspath(__file__))+'/result'.replace('/', os.sep),
                        help='Spécifiez la destination de sauvegarde des paramètres(Valeur par défaut./result)')
    parser.add_argument('--batch_size', '-b', type=int, default=32,
                        help='Spécifier la taille du mini lot(Valeur par défaut 32)')
    parser.add_argument('--epoch', '-e', type=int, default=15,
                        help='Spécifier le nombre d'apprentissage(Valeur par défaut 15)')
    parser.add_argument('--gpu', '-g', type=int, default=-1,
                        help='Spécification de l'ID GPU(Les valeurs négatives indiquent le traitement du processeur,Valeur par défaut-1)')
    args = parser.parse_args()

    #Dossier non spécifié->exception
    if args.data_dir == None:
        print("\nException: Folder not specified.\n")
        sys.exit()
    #Lors de la spécification d'un dossier qui n'existe pas->exception
    if os.path.exists(args.data_dir) != True:
        print("\nException: Folder {} is not found.\n".format(args.data_dir))
        sys.exit()

    #Réglage de la sortie des informations
    print("=== Setting information ===")
    print("# Images folder: {}".format(os.path.abspath(args.data_dir)))
    print("# Output folder: {}".format(args.out))
    print("# Minibatch-size: {}".format(args.batch_size))
    print("# Epoch: {}".format(args.epoch))
    print("===========================")

    #Création de l'ensemble de données
    train_set = create_dataset(args.data_dir)

    #Commencer à apprendre
    print("___Start training...")
    Trainer = trainer()
    Trainer.train(train_set, args.batch_size, args.epoch, args.gpu, args.out)
   
if __name__ == '__main__':
    main()

** À propos du traitement GPU ** J'ai construit l'environnement pour qu'il puisse être traité par GPU, donc Le traitement suivant est décrit. Peu importe qu'il soit là ou non, et il n'a pas besoin d'être traité par le GPU. Cependant, contrairement à Tensorflow, Chainer a un long temps d'apprentissage, nous vous recommandons donc de traiter avec GPU si possible. .. (En fonction de l'environnement et du problème à résoudre) J'omettrai la construction de l'environnement de traitement GPU.

        if gpu >= 0:
            chainer.cuda.get_device(gpu).use() #Obtenir un objet appareil
            self.model.to_gpu()  #Copier les données d'entrée sur le périphérique spécifié

Mise en garde

Dans le processus ci-dessous, nous compterons le nombre de données d'entraînement, ** Une feuille supplémentaire peut être ajoutée **. C'est parce qu'il inclut un cache de vignettes appelé Thumbs.db. ~~ C'est ennuyeux, donc ~~ Je ne prends pas cela en considération lors du comptage. Cependant, il n'y a pas de problème car il est traité de manière à être transmis lors de la création du jeu de données.

    for c in os.listdir(data_dir):
        d = os.path.join(data_dir, c)
        print("Number of image in a directory \"{}\": {}".format(c, len(os.listdir(d))))

en conclusion

J'ai posté sur Qiita pour la première fois cette fois, mais je suis inquiet car il y a beaucoup de points de malaise ... Comme mentionné dans l'aperçu, veuillez commenter s'il y a quelque chose qui ne va pas. corriger.

La prochaine fois, car c'est la phase de prédiction, j'utiliserai l'appareil photo pour reconnaître le visage ... Je ne peux pas montrer mon visage, alors je prévois d'utiliser l'image du visage d'une personnalité publique à la place.

En plus de Chainer, vous pouvez implémenter un programme de reconnaissance faciale avec Tensorflow (tf.keras), essayer de visualiser des filtres et des cartes de caractéristiques, etc. J'ai essayé diverses choses telles que l'utilisation du cadre d'optimisation des hyper paramètres "Optuna", donc j'espère pouvoir publier dans le futur. (Bien que ce soit sous la forme d'un mémorandum)

Recommended Posts

Maintenant, essayons la reconnaissance faciale avec Chainer (phase d'apprentissage)
Essayez la reconnaissance faciale avec Python
Essayez la reconnaissance faciale avec python + OpenCV
Première reconnaissance faciale d'anime avec Chainer
Essayez l'apprentissage de la représentation commune avec le chainer
Essayez avec Chainer Deep Q Learning - Lancement
[Python3] [Ubuntu16] [Docker] Essayez la reconnaissance faciale avec OpenFace
Reconnaissance faciale avec Edison
Essai de reconnaissance faciale facile avec Jetson Nano et caméra Web
Reconnaissance faciale avec OpenCV de Python
Essayez d'implémenter RBM avec chainer.
Reconnaissance faciale par Amazon Rekognition
Essayez le Deep Learning avec FPGA
Reconnaissance faciale / coupe avec OpenCV
Essayez le machine learning à la légère avec Kaggle
Déplaçons word2vec avec Chainer et voyons la progression de l'apprentissage
Renforcer l'apprentissage 13 Essayez Mountain_car avec ChainerRL.
Essayez l'apprentissage en profondeur avec TensorFlow Partie 2
Essayez de prédire les courses de chevaux avec Chainer
[Chainer] Apprentissage de XOR avec perceptron multicouche
SVM essayant l'apprentissage automatique avec scikit-learn
Renforcer l'apprentissage 8 Essayez d'utiliser l'interface utilisateur de Chainer
Reconnaissance faciale avec caméra avec opencv3 + python2.7
Introduction au Deep Learning (2) - Essayez votre propre régression non linéaire avec Chainer-
J'ai essayé la reconnaissance faciale avec OpenCV
Classez les visages d'anime avec l'apprentissage en profondeur avec Chainer
Essayez les prévisions de prix Bitcoin avec Deep Learning
Essayons gRPC avec Go et Docker
Reconnaissance faciale des personnages d'anime avec Keras
Essayez l'apprentissage profond de la génomique avec Kipoi
[python, openCV] base64 Reconnaissance faciale dans les images
API de reconnaissance faciale sans serveur conçue avec Python
Renforcer l'apprentissage 11 Essayez OpenAI acrobot avec ChainerRL.
Catégoriser les images de visage de personnages d'anime avec Chainer
Essayez de monter votre visage avec le test AB
Reconnaissance d'image avec le modèle Caffe Chainer Yo!