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)
-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
** 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
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.
** 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.
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.
** 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()
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.
Je vais expliquer le code. Malheureusement, la capacité à expliquer est faible.
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. La couche de mise en commun est la mise en commun maximale ** avec la zone de mise en commun ** 2 x 2.
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.
**
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
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.
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é
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))))
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