[PYTHON] Depuis qu'il y avait Doppelgenger, j'ai essayé de le distinguer avec l'intelligence artificielle (rires) (Partie 2)

salut! Je suis @eve_yk, un ingénieur Liaro. S'il vous plaît voir Partie 1 pour le début du sujet (pleurer) La dernière fois, nous avons collecté et traité des données pour former le classificateur. Cette fois, nous décrirons le modèle du classificateur et apprendrons et évaluerons réellement (identification du visage)!

3. Construisez un modèle du classificateur

Ensuite, décrivez le modèle du classificateur d'images de visage à entraîner dans Chainer. J'ai fait référence au code suivant (y compris la création de l'ensemble de données précédent). https://github.com/mitmul/chainer-cifar10

YTNet


class YTNet(chainer.Chain):

    def __init__(self):
        """
Définition du modèle
        """
        super(YTNet, self).__init__(
            conv1=L.Convolution2D(3, 32, 5, stride=1, pad=2),
            bn1  =L.BatchNormalization(32),
            conv2=L.Convolution2D(32, 32, 5, stride=1, pad=2),
            bn2  =L.BatchNormalization(32),
            conv3=L.Convolution2D(32, 64, 5, stride=1, pad=2),
            fc4=F.Linear(16384, 4096),
            fc5=F.Linear(4096, 2),
        )
        self.train = True

    def __call__(self, x, t):
    	"""
traitement avant
	    """
        h = F.max_pooling_2d(F.relu(self.conv1(x)), 3, stride=2)
        h = F.max_pooling_2d(F.relu(self.conv2(h)), 3, stride=2)
        h = F.relu(self.conv3(h))
        h = F.dropout(F.relu(self.fc4(h)), ratio=0.5, train=self.train)
        h = self.fc5(h)

        self.loss = F.softmax_cross_entropy(h, t)
        self.accuracy = F.accuracy(h, t)

        if self.train:
            return self.loss
        else:
            self.pred = F.softmax(h)
            return self.pred

4. Apprenez le modèle

En vous basant sur le code en 3., écrivez le code pour entraîner le modèle. Cette fois, la formation sera terminée relativement rapidement, mais lorsque vous essayez de travailler avec un plus grand ensemble de données, il est bon pour la santé mentale de montrer les progrès de la formation.

train.py


# -*- coding: utf-8 -*-

import argparse
import os
import six
import chainer
import chainer.functions as F
import chainer.links as L
import numpy as np
from chainer import optimizers
from chainer import cuda
from chainer import serializers
from chainer import Variable
from progressbar import ProgressBar


class YTNet(chainer.Chain):

    def __init__(self):
        """
Définition du modèle
        """
        super(YTNet, self).__init__(
            conv1=L.Convolution2D(3, 32, 5, stride=1, pad=2),
            bn1  =L.BatchNormalization(32),
            conv2=L.Convolution2D(32, 32, 5, stride=1, pad=2),
            bn2  =L.BatchNormalization(32),
            conv3=L.Convolution2D(32, 64, 5, stride=1, pad=2),
            fc4=F.Linear(16384, 4096),
            fc5=F.Linear(4096, 2),
        )
        self.train = True

    def __call__(self, x, t):
        """
traitement avant
        """
        h = F.max_pooling_2d(F.relu(self.conv1(x)), 3, stride=2)
        h = F.max_pooling_2d(F.relu(self.conv2(h)), 3, stride=2)
        h = F.relu(self.conv3(h))
        h = F.dropout(F.relu(self.fc4(h)), ratio=0.5, train=self.train)
        h = self.fc5(h)

        self.loss = F.softmax_cross_entropy(h, t)
        self.accuracy = F.accuracy(h, t)

        if self.train:
            return self.loss
        else:
            self.pred = F.softmax(h)
            return self.pred

def one_epoch(args, model, optimizer, data, label, epoch, train):
    """
1epoch formation ou traitement d'évaluation
    """
    model.train = train
    xp = cuda.cupy if args.gpu >= 0 else np

    sum_accuracy = 0
    sum_loss = 0

    p = ProgressBar(min_value=0, max_value=data.shape[0]) #Pour vérifier les progrès
    perm = np.random.permutation(data.shape[0])
    for i in xrange(0, data.shape[0], args.batchsize):
        p.update(i)
        
        #Créer un mini lot
        target = perm[i:i + args.batchsize]
        x = xp.array(data[target], dtype=xp.float32)
        t = xp.array(label[target], dtype=xp.int32)

        #Créer une variable
        volatile = 'off' if train else 'on'
        x = Variable(x, volatile=volatile)
        t = Variable(t, volatile=volatile)

        #Mise à jour des paramètres ou prédiction d'étiquettes
        if train:
            optimizer.update(model, x, t)
        else:
            pred = model(x, t).data
        
        sum_loss += float(model.loss.data) * t.data.shape[0]
        sum_accuracy += float(model.accuracy.data) * t.data.shape[0]

        del x, t

    print "" #Pour les sauts de ligne
    if train:
        print "train epoch " + str(epoch)
        print "   train loss : " + str(sum_loss / data.shape[0])
        print "   train acc  : " + str(sum_accuracy / data.shape[0])
    else:
        print "test epoch " + str(epoch)
        print "   test loss : " + str(sum_loss / data.shape[0])
        print "   test acc  : " + str(sum_accuracy / data.shape[0])

def load_dataset(datadir):
    """
Charger le jeu de données
    """
    train_data = np.load('%s/train_data.npy' % datadir)
    train_labels = np.load('%s/train_label.npy' % datadir)
    test_data = np.load('%s/test_data.npy' % datadir)
    test_labels = np.load('%s/test_label.npy' % datadir)

    return train_data, train_labels, test_data, test_labels

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("--gpu", type=int, default=-1)
    parser.add_argument("--batchsize", type=int, default=10)
    parser.add_argument('--data_dir', type=str, default='dataset')
    parser.add_argument('--output_dir', type=str, default='result')
    args = parser.parse_args()

    # model,Créer un optimiseur
    model = YTNet()
    optimizer = optimizers.Adam(alpha=0.00005)
    optimizer.setup(model)

    #Chargement de l'ensemble de données
    dataset = load_dataset(args.data_dir)
    tr_data, tr_labels, te_data, te_labels = dataset

    #Boucle principale
    for epoch in range(1, 20):
        #Entraînement
        one_epoch(args, model, optimizer, tr_data, tr_labels, epoch, True)
        #Évaluation
        one_epoch(args, model, optimizer, te_data, te_labels, epoch, False)

    #Enregistrer le modèle
    if not os.path.exists(args.output_dir):
        os.makedirs(args.output_dir)
    serializers.save_npz(args.output_dir + "YTNet.chainermodel", model)
    serializers.save_npz(args.output_dir + "YTNet.state", optimizer)

Après un entraînement d'environ 20 époques, la précision des données d'entraînement dépassait 99%.

5. Évaluer les performances

Enfin, nous évaluerons les performances. Testez avec les 10 images suivantes. Cinq d'entre eux sont @eve_yk et cinq sont Super Maradona Tanaka. Un exemple de visage peut être trouvé dans Article précédent, alors essayez de savoir si vous pouvez le deviner.

test.JPG

Je suis un peu inquiet, mais vous pouvez le voir à l'œil nu. C'est différent de la couleur des verres. La bonne réponse est eve_yk pour 1,2,4,7,10 et M. Tanaka pour 3,5,6,8,9.

Maintenant, qu'en est-il du CNN que vous avez appris cette fois? Testez avec le code ci-dessous.

test.py


# coding:utf-8

import os
import sys
import argparse
import glob
import cv2
import numpy as np
from chainer import Variable
from chainer import serializers
from train import YTNet

def transpose_opencv2chainer(x):
	"""
Conversion du format opencv npy au format chainer npy
		opencv  => (height, width, channel)
		chainer => (channel, height, width)
	"""
	return x.transpose(2,0,1)

file2labels = {"01.jpg ":"eve_yk", "02.jpg ":"eve_yk", "03.jpg ":"tanaka",
			   "04.jpg ":"eve_yk", "05.jpg ":"tanaka", "06.jpg ":"tanaka",
			   "07.jpg ":"eve_yk", "08.jpg ":"tanaka", "09.jpg ":"tanaka",
			   "10.jpg ":"eve_yk"}


if __name__ == "__main__":
	parser = argparse.ArgumentParser(description='Créer un ensemble de données pour CNN')
	parser.add_argument('--input_path',   required=True, type=str)
	parser.add_argument('--model_path',  required=True, type=str)
	args = parser.parse_args()

	#Obtenir la liste des fichiers jpg
	test_files  = glob.glob(args.input_path+"/*.jpg ")

	#Chargement du modèle
	model = YTNet()
	model = serializers.load_npz(args.model_path, , model)

	#Évaluer un par un
	collect_count = 0.0
        test_count = 0.0
	for file_path in test_files:
		image = cv2.imread(file_path)
		if image is None:
			#Échec de lecture
			continue
                test_count += 1.0

		#Obtenir le nom de fichier de la structure de répertoires
		file_name = file_path.split("/")[-1]
                print file_name+"("+file2labels[file_name]+") :",

		#Convertir au format de chaîne
		image = transpose_opencv2chainer(image)
		x = Variable(np.asarray([image], dtype=np.float32), volatile="on")
		t = Variable(np.asarray([[0]], dtype=np.int32), volatile="on")

		#Évaluation
		pred = model(x, t).data
		if int(pred) == 0: # tanaka
			print u"Résultat d'identification "tanaka""
			if file2labels[file_name] == u"tanaka":
				collect_count += 1.0
		else: # eve_yk
			print u"Résultat d'identification "eve_yk」"
			if file2labels[file_name] == u"eve_yk":
				collect_count += 1.0	

	print u"total:{}%".format(collect_count/test_count*100)

Le résultat est cette rue

python test.py --input_path test/ --model_path result/YTNet.chainermodel
08.jpg(tanaka) :Résultat d'identification "tanaka"
09.jpg(tanaka) :Résultat d'identification "eve_yk」
07.jpg(eve_yk) :Résultat d'identification "eve_yk」
01.jpg(eve_yk) :Résultat d'identification "eve_yk」
03.jpg(tanaka) :Résultat d'identification "tanaka"
06.jpg(tanaka) :Résultat d'identification "eve_yk」
02.jpg(eve_yk) :Résultat d'identification "eve_yk」
05.jpg(tanaka) :Résultat d'identification "tanaka"
04.jpg(eve_yk) :Résultat d'identification "eve_yk」
10.jpg(eve_yk) :Résultat d'identification "eve_yk」
total:8.0/10

J'ai confondu M. Tanaka de 6 et 9 avec eve_yk. S'agit-il d'une prédiction biaisée en raison de la différence de quantité de données d'entraînement? Cependant, j'ai le sentiment que l'image qui dérange l'œil humain est fausse. Après tout, il semble difficile de distinguer Doppelgenger avec un système à moitié fini.

en conclusion

J'ai créé un classificateur de visage qui identifie mon sosie. La précision est correcte. Je pense que c'était bien qu'il y ait eu de nombreux compromis tels que le nombre de données et le prétraitement. Il serait intéressant de travailler dur pour collecter des données et de classer un plus grand nombre de personnes, ou de travailler dur sur le prétraitement pour améliorer la précision!

Liaro et eve_yk soutiennent Super Maradona!

référence

https://github.com/mitmul/chainer-cifar10

Profil de l'artiste Yoshimoto Kogyo Co., Ltd. | Super Maradona

Recommended Posts

Depuis qu'il y avait Doppelgenger, j'ai essayé de le distinguer avec l'intelligence artificielle (rires) (Partie 2)
Depuis qu'il y avait Doppelgenger, j'ai essayé de le distinguer avec l'intelligence artificielle (rires) (Partie 1)
Un débutant a essayé de colorier un dessin au trait avec un chainer. J'ai pu le faire.
Un mémorandum lors de l'acquisition automatique avec du sélénium
Puisqu'il n'y a pas de description sur la façon de créer un environnement pour nnabla avec Docker, y compris le GPU, je l'ai essayé moi-même Partie 1
Quand j'ai essayé de créer un VPC avec AWS CDK mais que je n'ai pas pu le faire
Dans IPython, quand j'ai essayé de voir la valeur, c'était un générateur, donc je l'ai inventé quand j'étais frustré.
Je voulais utiliser la feuille de calcul Google avec AWS lambda, alors je l'ai essayé [Partie 2]
J'ai essayé d'implémenter une ligne moyenne mobile de volume avec Quantx
[IOS] Animation GIF avec Pythonista3. J'en étais accro.
J'ai essayé de créer automatiquement un rapport avec la chaîne de Markov
Quand j'ai essayé d'installer PIL et matplotlib dans un environnement virtualenv, j'en étais accro.
J'ai essayé de résoudre le problème d'optimisation des combinaisons avec Qiskit
J'ai créé un serveur avec socket Python et ssl et j'ai essayé d'y accéder depuis le navigateur
J'ai essayé de commencer avec Hy ・ Définir une classe
J'ai essayé de trier une colonne FizzBuzz aléatoire avec un tri à bulles.
J'ai essayé d'écrire dans un modèle de langage profondément appris
[5e] J'ai essayé de créer un certain outil de type Authenticator avec python
[2nd] J'ai essayé de créer un certain outil de type Authenticator avec python
[3ème] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de créer une liste de nombres premiers avec python
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
J'ai essayé de résumer ce qui était sorti avec Qiita avec Word cloud
Une note à laquelle j'étais accro lors de la création d'une table avec SQL Alchemy
J'ai essayé de créer une application de notification de publication à 2 canaux avec Python
J'ai essayé de créer des taureaux et des vaches avec un programme shell
J'ai essayé de créer une application todo en utilisant une bouteille avec python
[4th] J'ai essayé de créer un certain outil de type Authenticator avec python
[1er] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de faire une étrange citation pour Jojo avec LSTM
J'ai essayé de créer un mécanisme de contrôle exclusif avec Go
[Python] Quand j'ai essayé de créer un outil de décompression avec un fichier zip que je connaissais juste, j'étais accro à sys.exit ()
Comme c'est le 20e anniversaire de la formation, j'ai essayé de visualiser les paroles de Parfum avec Word Cloud
J'ai essayé de communiquer avec un serveur distant par communication Socket avec Python.
J'ai essayé de mettre en œuvre une blockchain qui fonctionne réellement avec environ 170 lignes
Lorsque j'ai essayé d'exécuter Python, j'ai été ignoré dans le Microsoft Store
J'ai essayé de créer un programme qui convertit les nombres hexadécimaux en nombres décimaux avec python
J'étais accro à la création d'un environnement Python venv avec VS Code
Une histoire à laquelle j'étais accro à essayer d'obtenir une URL de vidéo avec tweepy
J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Development] (2/3)
J'ai essayé de créer un LINE BOT "Sakurai-san" avec API Gateway + Lambda
J'ai écrit un diagramme de configuration du système avec des diagrammes sur Docker
Utilisez Python de Java avec Jython. J'étais aussi accro.
J'ai essayé de faire un signal avec Raspeye 4 (édition Python)
J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Execution] (3/3)
J'ai essayé d'envoyer un e-mail de fin d'inscription depuis Gmail avec django.
[Outlook] J'ai essayé de créer automatiquement un e-mail de rapport quotidien avec Python
J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Setup] (1/3)
J'ai essayé de créer un environnement de développement Mac Python avec pythonz + direnv
[Zaif] J'ai essayé de faciliter le commerce de devises virtuelles avec Python
J'ai essayé de créer un service de raccourcissement d'url sans serveur avec AWS CDK
J'étais accro à essayer Cython avec PyCharm, alors prenez note
J'ai essayé de créer un linebot (implémentation)
J'ai essayé de simuler combien il en coûterait pour composer un personnage très rare avec la gacha de Soshage