Hallo! Ich bin @eve_yk, ein Liaro-Ingenieur. Den Anfang der Angelegenheit finden Sie in Teil 1 (Weinen). Beim letzten Mal haben wir Daten gesammelt und verarbeitet, um den Klassifikator zu trainieren. Dieses Mal werden wir das Modell des Klassifikators beschreiben und tatsächlich lernen und bewerten (Gesichtsidentifikation)!
Beschreiben Sie als Nächstes das Modell des Gesichtsbildklassifikators, der in [Chainer] trainiert werden soll (http://chainer.org/). Ich habe auf den folgenden Code verwiesen (einschließlich der vorherigen Datensatzerstellung). https://github.com/mitmul/chainer-cifar10
YTNet
class YTNet(chainer.Chain):
def __init__(self):
"""
Modelldefinition
"""
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):
"""
Vorwärtsverarbeitung
"""
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
Schreiben Sie den Code basierend auf dem Code in 3., um das Modell zu trainieren. Dieses Mal ist das Training relativ schnell beendet, aber wenn Sie versuchen, mit einem größeren Datensatz zu arbeiten, ist es für die psychische Gesundheit gut, den Fortschritt des Trainings zu zeigen.
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):
"""
Modelldefinition
"""
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):
"""
Vorwärtsverarbeitung
"""
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 Training oder Evaluierungsverarbeitung
"""
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]) #Zur Überprüfung des Fortschritts
perm = np.random.permutation(data.shape[0])
for i in xrange(0, data.shape[0], args.batchsize):
p.update(i)
#Erstellen Sie eine Mini-Charge
target = perm[i:i + args.batchsize]
x = xp.array(data[target], dtype=xp.float32)
t = xp.array(label[target], dtype=xp.int32)
#Variable erstellen
volatile = 'off' if train else 'on'
x = Variable(x, volatile=volatile)
t = Variable(t, volatile=volatile)
#Parameteraktualisierung oder Etikettenvorhersage
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 "" #Für Zeilenumbrüche
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):
"""
Laden Sie den Datensatz
"""
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,Optimierer erstellen
model = YTNet()
optimizer = optimizers.Adam(alpha=0.00005)
optimizer.setup(model)
#Datensatz laden
dataset = load_dataset(args.data_dir)
tr_data, tr_labels, te_data, te_labels = dataset
#Hauptschleife
for epoch in range(1, 20):
#Ausbildung
one_epoch(args, model, optimizer, tr_data, tr_labels, epoch, True)
#Auswertung
one_epoch(args, model, optimizer, te_data, te_labels, epoch, False)
#Modell speichern
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)
Nach dem Training in etwa 20 Epochen lag die Genauigkeit der Trainingsdaten über 99%.
Schließlich werden wir die Leistung bewerten. Testen Sie mit den folgenden 10 Bildern. Fünf von ihnen sind @eve_yk und fünf sind Super Maradona Tanaka. Ein Beispiel für das Gesicht finden Sie im Vorherigen Artikel. Versuchen Sie also zu erraten, ob Sie es erraten können.
Ich bin ein wenig besorgt, aber Sie können es mit dem menschlichen Auge sehen. Es unterscheidet sich von der Farbe der Brille. Die richtige Antwort lautet eve_yk für 1,2,4,7,10 und Mr. Tanaka für 3,5,6,8,9.
Was ist nun mit dem CNN, das Sie dieses Mal gelernt haben? Testen Sie mit dem folgenden Code.
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):
"""
Konvertieren Sie vom opencv npy-Format in das chainer npy-Format
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='Erstellen Sie einen Datensatz für CNN')
parser.add_argument('--input_path', required=True, type=str)
parser.add_argument('--model_path', required=True, type=str)
args = parser.parse_args()
#Holen Sie sich die JPG-Dateiliste
test_files = glob.glob(args.input_path+"/*.jpg ")
#Modell laden
model = YTNet()
model = serializers.load_npz(args.model_path, , model)
#Bewerten Sie eins nach dem anderen
collect_count = 0.0
test_count = 0.0
for file_path in test_files:
image = cv2.imread(file_path)
if image is None:
#Lesefehler
continue
test_count += 1.0
#Holen Sie sich den Dateinamen aus der Verzeichnisstruktur
file_name = file_path.split("/")[-1]
print file_name+"("+file2labels[file_name]+") :",
#In Chainer-Format konvertieren
image = transpose_opencv2chainer(image)
x = Variable(np.asarray([image], dtype=np.float32), volatile="on")
t = Variable(np.asarray([[0]], dtype=np.int32), volatile="on")
#Auswertung
pred = model(x, t).data
if int(pred) == 0: # tanaka
print u"Identifikationsergebnis "tanaka""
if file2labels[file_name] == u"tanaka":
collect_count += 1.0
else: # eve_yk
print u"Identifikationsergebnis "Vorabend_yk」"
if file2labels[file_name] == u"eve_yk":
collect_count += 1.0
print u"total:{}%".format(collect_count/test_count*100)
Das Ergebnis ist diese Straße
python test.py --input_path test/ --model_path result/YTNet.chainermodel
08.jpg(tanaka) :Identifikationsergebnis "tanaka"
09.jpg(tanaka) :Identifikationsergebnis "Vorabend_yk」
07.jpg(eve_yk) :Identifikationsergebnis "Vorabend_yk」
01.jpg(eve_yk) :Identifikationsergebnis "Vorabend_yk」
03.jpg(tanaka) :Identifikationsergebnis "tanaka"
06.jpg(tanaka) :Identifikationsergebnis "Vorabend_yk」
02.jpg(eve_yk) :Identifikationsergebnis "Vorabend_yk」
05.jpg(tanaka) :Identifikationsergebnis "tanaka"
04.jpg(eve_yk) :Identifikationsergebnis "Vorabend_yk」
10.jpg(eve_yk) :Identifikationsergebnis "Vorabend_yk」
total:8.0/10
Ich habe Mr. Tanaka von 6 und 9 mit eve_yk verwechselt. Handelt es sich um eine voreingenommene Vorhersage aufgrund der unterschiedlichen Menge an Trainingsdaten? Ich habe jedoch das Gefühl, dass das für das menschliche Auge störende Bild falsch ist. Schließlich scheint es schwierig zu sein, Doppelgenger von einem halbfertigen System zu unterscheiden.
Ich habe einen Gesichtsklassifikator erstellt, der mein Aussehen identifiziert. Die Genauigkeit ist in Ordnung. Ich finde es gut, dass es viele Kompromisse wie Datenanzahl und Vorverarbeitung gab. Es wäre interessant, hart zu arbeiten, um Daten zu sammeln und eine größere Anzahl von Personen zu klassifizieren, oder hart an der Vorverarbeitung zu arbeiten, um die Genauigkeit zu verbessern!
Liaro und eve_yk machen sich für Super Maradona stark!
https://github.com/mitmul/chainer-cifar10
Yoshimoto Kogyo Co., Ltd. Entertainer-Profil | Super Maradona