[PYTHON] Kategorisieren Sie Gesichtsbilder von Anime-Charakteren mit Chainer

In diesem Artikel erkläre ich Folgendes, indem ich die Schritte zur Feinabstimmung eines Illustration2Vec-Modells mithilfe des Animeface-Zeichendatensatzes befolge und ein Modell trainiere, das 146 verschiedene Zeichengesichtsbilder mit einer Genauigkeit von 90% oder besser klassifizieren kann. Ich werde.

Mit Chainer

Die verwendete Umgebung ist wie folgt.

Die verwendete Bibliothek ist wie folgt.

--Chainer> = 2.0.1 (Es wurde bestätigt, dass es mit der neuesten Version 4.1.0 funktioniert.) --CuPy> = 1.0.1 (Es wurde bestätigt, dass es mit der neuesten Version 4.1.0 funktioniert.)

Chainer ist abwärtskompatibel

Um den Inhalt grob zusammenzufassen

** Die Methode zur Beschaffung eines Datensatzes, der in Chainer nicht im Voraus von außen vorbereitet wurde ** und zur Verwendung des in Chainer beschriebenen Netzwerks wird anhand eines konkreten Beispiels gezeigt. Die grundlegenden Schritte entsprechen fast dem in Chainer v4: Tutorial für Anfänger beschriebenen Kapitel zum Erweitern der CIFAR10-Dataset-Klasse.

Dieses Mal werde ich erklären, wie vorab trainierte Netzwerkgewichte als Anfangswerte unter Verwendung eines Datensatzes von Domänen verwendet werden, die den Zieldaten ähnlich sind. Wenn Sie ein Netzwerk optimieren möchten, das in Form des Caffe-Modells .caffe verteilt ist, können Sie fast das gleiche Verfahren wie in diesem Artikel anwenden.

Dieser Artikel ist eine Markdown-Ausgabe von ursprünglich in Jupyter-Notizbuch geschrieben.

1. Datensatz herunterladen

Laden Sie zunächst den Datensatz herunter. Diesmal die Miniaturansicht des Anime-Charakters, der von Nagadomi, dem Großmeister von Kaggle, unter [hier] verteilt wurde (http://www.nurs.or.jp/~nagadomi/animeface-character-dataset/) Verwenden Sie einen Datensatz.

%%bash
if [ ! -d animeface-character-dataset ]; then
    curl -L -O http://www.nurs.or.jp/~nagadomi/animeface-character-dataset/data/animeface-character-dataset.zip
    unzip animeface-character-dataset.zip
    rm -rf animeface-character-dataset.zip
fi

Geben Sie die Bibliothek ein, die mit pip verwendet werden soll. ** Der Teil cupy-cuda90 basiert auf der CUDA-Version Ihrer Umgebung, cupy-cuda80 (für CUDA8.0-Umgebung), cupy-cuda90 (für CUDA9.0-Umgebung), cupy- Wählen Sie die entsprechende aus cuda91 (für CUDA 9.1-Umgebung). ) **

%%bash
pip install chainer
pip install cupy-cuda80 # or cupy-cuda90 or cupy-cuda91
pip install Pillow
pip install tqdm

2. Überprüfen Sie die Problemeinstellungen

Dieses Mal wird unter Verwendung der Gesichtsbilder verschiedener Zeichen, die im Animeface-Zeichendatensatz enthalten sind, bei der Eingabe eines unbekannten Zeichengesichtsbildes ausgegeben, welches Gesicht des Zeichens in der bekannten Klassenliste zu sein scheint. Ich möchte ein Netzwerk trainieren, das dies tut.

Zu diesem Zeitpunkt wurde anstelle eines Trainings mit zufällig initialisierten Parametern eine Methode zur Feinabstimmung mit dem Zieldatensatz basierend auf einem Modell durchgeführt, das im Voraus mit Daten ähnlicher Domänen trainiert wurde ** Ich werde versuchen.

Der Datensatz, der dieses Mal zum Lernen verwendet wird, ist ein Datensatz, der viele Bilder enthält, wie unten gezeigt, und jedes Zeichen wird im Voraus in Ordner unterteilt. Daher wird es auch diesmal ein orthodoxes Bildklassifizierungsproblem sein.

Entsprechend extrahierte Datenprobe

000_hatsune_miku 002_suzumiya_haruhi 007_nagato_yuki 012_asahina_mikuru
face_128_326_108.png face_1000_266_119.png face_83_270_92.png face_121_433_128.png

3. Erstellen eines Dataset-Objekts

Hier erfahren Sie, wie Sie ein Dataset-Objekt mit einer Klasse namens "LabeledImageDataset" erstellen, die häufig bei Bildklassifizierungsproblemen verwendet wird. Bereiten Sie sich zunächst mit Standard-Python-Funktionen vor.

Rufen Sie zunächst die Liste der Pfade zur Bilddatei ab. Die Bilddateien sind in Verzeichnisse für jedes Zeichen unter "Animeface-Character-Dataset / Thumb" unterteilt. Wenn sich im folgenden Code eine Datei mit dem Namen "Ignorieren" im Ordner befindet, wird das Bild in diesem Ordner ignoriert.

import os
import glob
from itertools import chain

#Bildordner
IMG_DIR = 'animeface-character-dataset/thumb'

#Ordner für jedes Zeichen
dnames = glob.glob('{}/*'.format(IMG_DIR))

#Liste der Bilddateipfade
fnames = [glob.glob('{}/*.png'.format(d)) for d in dnames
          if not os.path.exists('{}/ignore'.format(d))]
fnames = list(chain.from_iterable(fnames))

Als Nächstes stellt im Bilddateipfad der Teil des Verzeichnisnamens, der das Bild enthält, den Zeichennamen dar. Verwenden Sie ihn daher, um eine ID zu erstellen, die für jedes Zeichen für jedes Bild eindeutig ist.

#Geben Sie jedem eine eindeutige ID aus dem Ordnernamen
labels = [os.path.basename(os.path.dirname(fn)) for fn in fnames]
dnames = [os.path.basename(d) for d in dnames
          if not os.path.exists('{}/ignore'.format(d))]
labels = [dnames.index(l) for l in labels]

Jetzt erstellen wir das Basisdatensatzobjekt. Es ist einfach, eine Liste von Tupeln mit dem Dateipfad und seinen Beschriftungen an LabeledImageDataset zu übergeben. Dies ist ein Iterator, der ein Taple wie "(img, label)" zurückgibt.

from chainer.datasets import LabeledImageDataset

#Datensatzerstellung
d = LabeledImageDataset(list(zip(fnames, labels)))

Als nächstes verwenden wir eine praktische Funktion namens "Transform Dataset", die von Chainer bereitgestellt wird. Dies ist eine Wrapper-Klasse, die ein Dataset-Objekt und eine Funktion verwendet, die die Konvertierung in die einzelnen Daten darstellt. Auf diese Weise können Sie Teile für die Datenerweiterung, Vorverarbeitung usw. außerhalb der Dataset-Klasse vorbereiten.

from chainer.datasets import TransformDataset
from PIL import Image

width, height = 160, 160

#Bildgrößenänderungsfunktion
def resize(img):
    img = Image.fromarray(img.transpose(1, 2, 0))
    img = img.resize((width, height), Image.BICUBIC)
    return np.asarray(img).transpose(2, 0, 1)

#Konvertierung in die einzelnen Daten
def transform(inputs):
    img, label = inputs
    img = img[:3, ...]
    img = resize(img.astype(np.uint8))
    img = img - mean[:, None, None]
    img = img.astype(np.float32)
    #Nach dem Zufallsprinzip nach links und rechts drehen
    if np.random.rand() > 0.5:
        img = img[..., ::-1]
    return img, label

#Erstellen Sie einen Datensatz mit Konvertierung
td = TransformDataset(d, transform)

Auf diese Weise können Sie ein Dataset-Objekt erstellen, das ein Taple wie "(img, label)" empfängt, das vom "LabeledImageDataset" -Objekt "d" zurückgegeben wird, es durch die "transform" -Funktion leitet und dann zurückgibt. Ich tat.

Teilen wir dies nun in zwei Teildatensätze auf, einen für das Training und einen für die Validierung. Dieses Mal werden wir 80% des gesamten Datensatzes für das Training und die restlichen 20% für die Validierung verwenden. Mit split_dataset_random werden die Daten im Dataset einmal gemischt und dann in den angegebenen Pausen aufgeteilt.

from chainer import datasets

train, valid = datasets.split_dataset_random(td, int(len(d) * 0.8), seed=0)

Die Dataset-Partitionierung bietet auch mehrere andere Funktionen, z. B. "get_cross_validation_datasets_random", die mehrere verschiedene Trainings- und Validierungs-Dataset-Paare zum Kreuztest zurückgeben. Schau dir das an. : SubDataset

Übrigens ist der bei der Konvertierung verwendete Mittelwert das Durchschnittsbild der Bilder, die in dem diesmal verwendeten Trainingsdatensatz enthalten sind. Berechnen wir das.

import matplotlib.pyplot as plt
import numpy as np
from tqdm import tqdm_notebook

#Berechnen Sie, ob das durchschnittliche Bild nicht berechnet wurde
if not os.path.exists('image_mean.npy'):
    #Ich möchte den Durchschnitt mit einer Version des Trainingsdatensatzes berechnen, die die Konvertierung nicht beißt
    t, _ = datasets.split_dataset_random(d, int(len(d) * 0.8), seed=0)

    mean = np.zeros((3, height, width))
    for img, _ in tqdm_notebook(t, desc='Calc mean'):
        img = resize(img[:3].astype(np.uint8))
        mean += img
    mean = mean / float(len(d))
    np.save('image_mean', mean)
else:
    mean = np.load('image_mean.npy')

Lassen Sie uns das durchschnittliche Bild anzeigen, das als Test berechnet wurde.

#Anzeige des Durchschnittsbildes
%matplotlib inline
plt.imshow(mean.transpose(1, 2, 0) / 255)
plt.show()

png

Es ist irgendwie beängstigend ...

Beim Subtrahieren des Durchschnitts von jedem Bild wird der Durchschnitt für jedes Pixel verwendet. Berechnen Sie daher den durchschnittlichen Pixelwert (RGB) dieses Durchschnittsbilds.

mean = mean.mean(axis=(1, 2))

4. Modelldefinition und Vorbereitung der Feinabstimmung

Als nächstes definieren wir das zu trainierende Modell. Hier basiert auf dem in Illustration2Vec verwendeten Netzwerk, das die Tag-Vorhersage und Merkmalsextraktion mit einem Modell durchführt, das unter Verwendung vieler 2D-Illustrationsbilder gelernt wurde, dem letzten Bei dem neuen Modell werden zwei Ebenen entfernt und zwei zufällig initialisierte, vollständig verbundene Ebenen hinzugefügt.

Zum Zeitpunkt des Lernens wird nach dem Initialisieren des Teils der dritten Schicht und darunter aus der Ausgabe mit dem vorab trainierten Gewicht von Illustration2Vec das Gewicht dieses Teils festgelegt. Das heißt, ** trainiere nur die zwei neu hinzugefügten vollständig verbundenen Ebenen. ** **.

Laden Sie zunächst die trainierten Parameter des verteilten Illustration2Vec-Modells herunter.

%%bash
if [ ! -f illust2vec_ver200.caffemodel ]; then
    curl -L -O https://github.com/rezoo/illustration2vec/releases/download/v2.0.0/illust2vec_ver200.caffemodel
fi

Dieser trainierte Parameter wird in Form eines Caffe-Modells bereitgestellt, aber Chainer kann das trainierte Caffe-Modell sehr einfach laden (CaffeFunction). /reference/generated/chainer.links.caffe.CaffeFunction.html#chainer.links.caffe.CaffeFunction)), mit dem wir die Parameter und die Modellstruktur laden. Das Laden dauert jedoch einige Zeit. Speichern Sie daher das "Chain" -Objekt, das Sie nach dem Laden in eine Datei mit dem Python-Standard "pickle" erhalten. Dies beschleunigt das Laden ab dem nächsten Mal.

Der tatsächliche Netzwerkcode sieht folgendermaßen aus:

import dill

import chainer
import chainer.links as L
import chainer.functions as F

from chainer import Chain
from chainer.links.caffe import CaffeFunction
from chainer import serializers

class Illust2Vec(Chain):

    CAFFEMODEL_FN = 'illust2vec_ver200.caffemodel'

    def __init__(self, n_classes, unchain=True):
        w = chainer.initializers.HeNormal()        
        model = CaffeFunction(self.CAFFEMODEL_FN)  #Laden und speichern Sie das Caffe-Modell. (Es braucht Zeit)
        del model.encode1  #Löschen Sie nicht benötigte Ebenen, um Speicherplatz zu sparen.
        del model.encode2
        del model.forwards['encode1']
        del model.forwards['encode2']
        model.layers = model.layers[:-2]
        
        super(Illust2Vec, self).__init__()
        with self.init_scope():
            self.trunk = model  #Nehmen Sie das ursprüngliche Illust2Vec-Modell als Kofferraum in dieses Modell auf.
            self.fc7 = L.Linear(None, 4096, initialW=w)
            self.bn7 = L.BatchNormalization(4096)
            self.fc8 = L.Linear(4096, n_classes, initialW=w)
            
    def __call__(self, x):
        h = self.trunk({'data': x}, ['conv6_3'])[0]  #Original Illust2Vec Modell conv6_Nehmen Sie die Ausgabe von 3.
        h.unchain_backward()
        h = F.dropout(F.relu(self.bn7(self.fc7(h))))  #Die folgenden Ebenen sind neu hinzugefügte Ebenen.
        return self.fc8(h)

n_classes = len(dnames)
model = Illust2Vec(n_classes)
model = L.Classifier(model)
/home/mitmul/chainer/chainer/links/caffe/caffe_function.py:165: UserWarning: Skip the layer "encode1neuron", since CaffeFunction does notsupport Sigmoid layer
  'support %s layer' % (layer.name, layer.type))
/home/mitmul/chainer/chainer/links/caffe/caffe_function.py:165: UserWarning: Skip the layer "loss", since CaffeFunction does notsupport SigmoidCrossEntropyLoss layer
  'support %s layer' % (layer.name, layer.type))

Die Beschreibung "h.unchain_backward ()" ist im Teil von "call" erschienen. unchain_backward wird von einer Zwischenausgabe Variable usw. im Netzwerk aufgerufen und trennt alle Netzwerkknoten vor diesem Punkt. Daher wird der Fehler während des Trainings nicht an die Schichten übertragen, bevor dies aufgerufen wird, und infolgedessen werden die Parameter nicht aktualisiert.

Wie oben erwähnt

Zum Zeitpunkt des Lernens wird nach dem Initialisieren des Teils der dritten Schicht und darunter aus der Ausgabe mit dem vorab trainierten Gewicht von Illustration2Vec das Gewicht dieses Teils festgelegt.

Der Code dafür ist "h.unchain_backward ()".

Weitere Informationen dazu finden Sie in diesem Artikel, in dem erläutert wird, wie Chainers Autograd mit Define-by-Run funktioniert. : 1-Datei-Chainer erstellen

5. Lernen

Lassen Sie uns nun mit diesem Datensatz und Modell trainieren. Laden Sie zunächst die erforderlichen Module.

from chainer import iterators
from chainer import training
from chainer import optimizers
from chainer.training import extensions
from chainer.training import triggers
from chainer.dataset import concat_examples

Als nächstes stellen Sie die Lernparameter ein. Diesmal

Wird besorgt.

batchsize = 64
gpu_id = 0
initial_lr = 0.01
lr_drop_epoch = 10
lr_drop_ratio = 0.1
train_epoch = 20

Unten finden Sie den Code zum Lernen.

train_iter = iterators.MultiprocessIterator(train, batchsize)
valid_iter = iterators.MultiprocessIterator(
    valid, batchsize, repeat=False, shuffle=False)

optimizer = optimizers.MomentumSGD(lr=initial_lr)
optimizer.setup(model)
optimizer.add_hook(chainer.optimizer.WeightDecay(0.0001))

updater = training.StandardUpdater(
    train_iter, optimizer, device=gpu_id)

trainer = training.Trainer(updater, (train_epoch, 'epoch'), out='AnimeFace-result')
trainer.extend(extensions.LogReport())
trainer.extend(extensions.observe_lr())

#Wert, den Sie in die Standardausgabe schreiben möchten
trainer.extend(extensions.PrintReport(
    ['epoch',
     'main/loss',
     'main/accuracy',
     'val/main/loss',
     'val/main/accuracy',
     'elapsed_time',
     'lr']))

#Die Verlustdarstellung speicherte automatisch jede Epoche
trainer.extend(extensions.PlotReport(
        ['main/loss',
         'val/main/loss'],
        'epoch', file_name='loss.png'))

#Genauigkeitsdiagramme werden auch automatisch in jeder Epoche gespeichert
trainer.extend(extensions.PlotReport(
        ['main/accuracy',
         'val/main/accuracy'],
        'epoch', file_name='accuracy.png'))

#Erweiterung, die validiert wird, indem die Train-Eigenschaft des Modells auf False gesetzt wird
trainer.extend(extensions.Evaluator(valid_iter, model, device=gpu_id), name='val')

#Lr-Lernrate für jede angegebene Epoche_drop_Verdoppeln Sie das Verhältnis
trainer.extend(
    extensions.ExponentialShift('lr', lr_drop_ratio),
    trigger=(lr_drop_epoch, 'epoch'))

trainer.run()
epoch       main/loss   main/accuracy  val/main/loss  val/main/accuracy  elapsed_time  lr        
1           1.58266     0.621792       0.623695       0.831607           29.4045       0.01        
2           0.579938    0.835989       0.54294        0.85179            56.3893       0.01        
3           0.421797    0.877897       0.476766       0.876872           83.9976       0.01        
4           0.3099      0.909251       0.438246       0.879637           113.476       0.01        
5           0.244549    0.928394       0.427892       0.884571           142.931       0.01        
6           0.198274    0.938638       0.41589        0.893617           172.42        0.01        
7           0.171127    0.946709       0.432277       0.89115            201.868       0.01        
8           0.146401    0.953125       0.394634       0.902549           231.333       0.01        
9           0.12377     0.964404       0.409338       0.894667           260.8         0.01        
10          0.109239    0.967198       0.400371       0.907746           290.29        0.01        
11          0.0948708   0.971337       0.378603       0.908831           319.742       0.001       
12          0.0709512   0.98065        0.380891       0.90786            349.242       0.001       
13          0.0699093   0.981892       0.384257       0.90457            379.944       0.001       
14          0.0645318   0.982099       0.370053       0.908008           410.963       0.001       
15          0.0619039   0.983547       0.379178       0.908008           441.941       0.001       
16          0.0596897   0.983646       0.375837       0.911709           472.832       0.001       
17          0.0579783   0.984789       0.379593       0.908008           503.836       0.001       
18          0.0611943   0.982202       0.378177       0.90842            534.86        0.001       
19          0.061885    0.98303        0.373961       0.90569            565.831       0.001       
20          0.0548781   0.986341       0.3698         0.910624           596.847       0.001       

Das Lernen war in weniger als 6 Minuten abgeschlossen. Der Fortschritt der Standardausgabe war wie oben. Am Ende können Sie eine Genauigkeit von mehr als 90% für den Verifizierungsdatensatz erhalten. Lassen Sie uns nun die Verlustkurve und die Genauigkeitskurve im Lernprozess anzeigen, der als Bilddatei gespeichert ist.

from IPython.display import Image
Image(filename='AnimeFace-result/loss.png')

output_35_0.png

Image(filename='AnimeFace-result/accuracy.png')

output_36_0.png

Ich fühle, dass es sicher konvergiert hat.

Nehmen wir zum Schluss einige Bilder aus dem Validierungsdatensatz und sehen uns die einzelnen Klassifizierungsergebnisse an.

%matplotlib inline
import matplotlib.pyplot as plt

from PIL import Image
from chainer import cuda

chainer.config.train = False
for _ in range(10):
    x, t = valid[np.random.randint(len(valid))]
    x = cuda.to_gpu(x)
    y = F.softmax(model.predictor(x[None, ...]))
    
    pred = os.path.basename(dnames[int(y.data.argmax())])
    label = os.path.basename(dnames[t])
    
    print('pred:', pred, 'label:', label, pred == label)

    x = cuda.to_cpu(x)
    x += mean[:, None, None]
    x = x / 256
    x = np.clip(x, 0, 1)
    plt.imshow(x.transpose(1, 2, 0))
    plt.show()
pred: 097_kamikita_komari label: 097_kamikita_komari True

output_38_1.png

pred: 127_setsuna_f_seiei label: 127_setsuna_f_seiei True

output_38_3.png

pred: 171_ikari_shinji label: 171_ikari_shinji True

output_38_5.png

pred: 042_tsukimura_mayu label: 042_tsukimura_mayu True

output_38_7.png

pred: 001_kinomoto_sakura label: 001_kinomoto_sakura True

output_38_9.png

pred: 090_minase_iori label: 090_minase_iori True

output_38_11.png

pred: 132_minamoto_chizuru label: 132_minamoto_chizuru True

output_38_13.png

pred: 106_nia label: 106_nia True

output_38_15.png

pred: 174_hayama_mizuki label: 174_hayama_mizuki True

output_38_17.png

pred: 184_suzumiya_akane label: 184_suzumiya_akane True

output_38_19.png

Als ich 10 Bilder zufällig ausgewählt habe, konnte ich alle diese Bilder richtig beantworten.

Speichern Sie zum Schluss vorerst einen Schnappschuss, da er eines Tages für etwas verwendet werden kann.

from chainer import serializers

serializers.save_npz('animeface.model', model)

6. Bonus 1: So schreiben Sie eine Datensatzklasse in vollem Umfang

Um eine Dataset-Klasse vollständig zu schreiben, können Sie eine eigene Klasse vorbereiten, die die Klasse "chainer.dataset.DatasetMixin" erbt. Die Klasse muss eine __len__ und eine get_example Methode haben. Zum Beispiel:

class MyDataset(chainer.dataset.DatasetMixin):
    
    def __init__(self, image_paths, labels):
        self.image_paths = image_paths
        self.labels = labels
        
    def __len__(self):
        return len(self.image_paths)
    
    def get_example(self, i):
        img = Image.open(self.image_paths[i])
        img = np.asarray(img, dtype=np.float32)
        img = img.transpose(2, 0, 1)
        label = self.labels[i]
        return img, label

Dies erfolgt durch Übergeben einer Liste von Bilddateipfaden und einer Liste von Beschriftungen, die in der entsprechenden Reihenfolge angeordnet sind, an den Konstruktor. Wenn Sie mit dem Accessor [] einen Index angeben, wird das Bild aus dem entsprechenden Pfad gelesen und mit der Beschriftung angeordnet. Es ist eine Dataset-Klasse, die einen Taple zurückgibt. Sie können es beispielsweise wie folgt verwenden.

image_files = ['images/hoge_0_1.png', 'images/hoge_5_1.png', 'images/hoge_2_1.png', 'images/hoge_3_1.png', ...]
labels = [0, 5, 2, 3, ...]

dataset = MyDataset(image_files, labels)

img, label = dataset[2]

#=> 'images/hoge_2_1.png'Die gelesenen Bilddaten und ihre Beschriftung (in diesem Fall 2) werden zurückgegeben.

Dieses Objekt kann unverändert an Iterator übergeben und für das Training mit Trainer verwendet werden. Mit anderen Worten

train_iter = iterators.MultiprocessIterator(dataset, batchsize=128)

Sie können einen solchen Iterator erstellen, ihn mit dem Optimierer an den Updater übergeben und den Updater an den Trainer übergeben, um mit dem Trainer zu lernen.

7. Bonus 2: So erstellen Sie das einfachste Datensatzobjekt

Tatsächlich ist der Datensatz zur Verwendung mit Chainers Trainer ** nur eine Python-Liste OK **. Dies bedeutet, dass, wenn die Länge mit "len ()" ermittelt werden kann und das Element mit dem Accessor "[]" abgerufen werden kann, ** alle als Datensatzobjekt ** behandelt werden können. Zum Beispiel

data_list = [(x1, t1), (x2, t2), ...]

Sie können dies an Iterator übergeben, indem Sie eine Liste von Tupeln wie "(Daten, Beschriftung)" erstellen.

train_iter = iterators.MultiprocessIterator(data_list, batchsize=128)

Der Nachteil dieses Ansatzes besteht jedoch darin, dass der gesamte Datensatz vor dem Training im Speicher gespeichert werden muss. Um dies zu verhindern, [ImageDataset](http://docs.chainer.org/en/stable/reference/generated/chainer.datasets.ImageDataset.html#chainer.datasets.ImageDataset] und [TupleDataset](http: // So kombinieren Sie docs.chainer.org/en/stable/reference/generated/chainer.datasets.TupleDataset.html#chainer.datasets.TupleDataset) und LabaledImageDataset. Es gibt Klassen wie reference / generate / chainer.datasets.LabeledImageDataset.html # chainer.datasets.LabeledImageDataset). Weitere Informationen finden Sie im Dokument. http://docs.chainer.org/en/stable/reference/datasets.html#general-datasets

Recommended Posts

Kategorisieren Sie Gesichtsbilder von Anime-Charakteren mit Chainer
Gesichtserkennung von Anime-Charakteren mit Keras
Erste Anime-Gesichtserkennung mit Chainer
Anime-Gesichtserkennung mit OpenCV
Multi-Class Multi-Label-Klassifizierung von Bildern mit Pytorch
Lernen Sie mit Chainer, monochrome Bilder einzufärben
Klassifizieren Sie Anime-Gesichter mit tiefem Lernen mit Chainer
Gesichtserkennung durch Sammeln von Bildern von Angers.
Transkription von Bildern mit der Vision API von GCP
[python, openCV] base64 Gesichtserkennung in Bildern
Zählen Sie die Anzahl der Zeichen mit Echo
Speichern Sie automatisch Bilder Ihrer Lieblingsfiguren aus der Google Bildsuche mit Python
Mischen Sie Hunderttausende von Bildern gleichmäßig mit Tensorflow.
Laden Sie das Kaffeemodell mit Chainer und klassifizieren Sie die Bilder
Leistungsvergleich des Gesichtsdetektors mit Python + OpenCV
Wavelet-Konvertierung von Bildern mit PyWavelets und OpenCV
Seq2Seq (1) mit Chainer
Zeigen Sie eingebettete Bilder von MP3 und Flac mit Mutagen an
Versuchen Sie, die Bildkonvertierung mit OpenCV mit Python zu projizieren
Versuchen wir nun die Gesichtserkennung mit Chainer (Vorhersagephase).
Erstellen Sie einen Stapel von Bildern und blasen Sie sie mit ImageDataGenerator auf
Ich habe versucht, das Bild mit Python + OpenCV "morphologisch zu konvertieren"
Versuchen wir nun die Gesichtserkennung mit Chainer (Lernphase)