[PYTHON] [TensorFlow] Ich habe versucht, KI in Fahrzeugeisen einzuführen

Einführung

Die Deep-Learning-Technologie ist mir vertraut geworden, und als ich gegoogelt habe, habe ich viele Beispiele gefunden, mit denen verschiedene Dinge im Bild erkannt werden. Die Ergebnisse sind leicht zu verstehen und es macht Spaß, sie zu sehen. Deshalb wollte ich mich beim Brauen auf etwas aufmerksam machen, aber da jeder es tut, um Tiere und Lieblingsschauspielerinnen zu erkennen, eine andere Geschichte Ich möchte es tun.

Also ** habe ich versucht, das im Eingabebild gezeigte Modell des Fahrzeugs durch Deep-Learning-Technologie zu erraten, wobei das Bild des Schienenfahrzeugs als Lerndaten verwendet wurde. ** Ich denke jedoch, dass das Levelgefühl ungefähr das gleiche ist wie das eines kleinen Kindes, das begonnen hat, sich für Züge zu interessieren.

↓ Wir möchten ein Bild eines solchen Fahrzeugs eingeben und es als "E231 Serie 500 Serie" erraten. E231系500番台(山手線)

Entwicklungsumgebung

Problemstellung

Lassen Sie uns ein Modell eines neuronalen Netzwerks lernen, das eine von fünf Optionen für ein bestimmtes ** Außenfoto eines Schienenfahrzeugs ** errät! Dieses Mal werden wir 5 Fahrzeugtypen in den Vororten von Tokio unter den Fahrzeugtypen von JR East ansprechen. Wenn Sie es sich ansehen, können Sie es leicht an der Farbe des Bandes erkennen, aber es kann für den Computer schwierig sein zu wissen, welches Teil das Fahrzeug ist.

Beispiel eines Fahrzeugbildes

Das Bild hier ist mein eigenes.

(1) Serie E231 Serie 500 (Yamate-Linie)

E231系500番台(山手線)

(2) Serie E233 Serie 0 (Chuo Line Rapid / Oume Line / Gokaichi Line)

E233系0番台(中央線快速・青梅線・五日市線)

(3) E233 Serie 1000 Serie (Keihin Tohoku / Negishi Line)

E233系1000番台(京浜東北・根岸線)

(4) E233-Serie 8000-Serie (Nanbu-Linie)

E233系8000番台(南武線)

(5) Serie E235 Serie 0 (neues Modell der Yamate-Linie)

E235系0番台(山手線)

Datensammlung

Ich habe auf diesen Artikel verwiesen. Bilderkennung "○○ Diskriminator" mit TensorFlow --Qiita

Laden Sie automatisch die Bilder herunter, die in der Google Bildsuche angezeigt werden.

pip install google_images_download
googleimagesdownload -k Yamate Line
googleimagesdownload -k Chuo Line Rapid
googleimagesdownload -k E235
:
:

Verwenden Sie von den gesammelten Bildern nur die Fotos, die das Äußere des Fahrzeugs zeigen. Die folgenden Bilder werden nicht verwendet.

Probieren Sie verschiedene Schlüsselwörter aus und sammeln Sie schließlich mehr als 100 Bilder pro Format. Dieses Mal gibt es 5 Typen für insgesamt 540 Blatt. Es scheint, dass die Anzahl überhaupt nicht ausreicht, aber selbst das ist ziemlich schwierig ... Selbst wenn Sie das Schlüsselwort ändern, wird nur das gleiche Bild getroffen.

Legen Sie als Nächstes die gesammelten Bilder in Ordnern für jede Klasse ab.

Bilder tatsächlich gesammelt

(1) Serie E231 Serie 500 (Yamate-Linie)

image.png

(2) Serie E233 Serie 0 (Chuo Line Rapid / Oume Line / Gokaichi Line)

image.png

(3) E233 Serie 1000 Serie (Keihin Tohoku / Negishi Line)

image.png

(4) E233-Serie 8000-Serie (Nanbu-Linie)

image.png

(5) E235 Serie 0 Serie (Yamate Linie)

image.png

Modell Trainingscode

Wenn das Bild fertig ist, ist es Zeit zu lernen. Grundsätzlich habe ich auf den Inhalt der folgenden Artikel verwiesen. Ich habe eine Gesichtserkennungs-KI durch Feinabstimmung von VGG16 mithilfe der GPU - Qiita erstellt

Jedes Format hat diesmal völlig unterschiedliche Farben (es gibt zwei Yamate-Linien, aber sie sehen sehr unterschiedlich aus). Ich denke, es ist eine einfachere Aufgabe als das Gesicht der Schauspielerin zu identifizieren, aber es sind immer noch nur etwa 500 Bilder. Dann wird es schwierig. Um mit dieser kleinen Datenmenge fertig zu werden, führen wir eine Feinabstimmung ** mit dem trainierten Modell von VGG16 durch. Das VGG16-Modell ist bei TensorFlow (Keras) erhältlich, ohne dass eine separate Paketinstallation erforderlich ist. Keras: Was sind VGG16 und VGG19? ?? --Qiita

VGG16 ist ein Modell, das 1000 Klassen von Bildklassifizierungen durchführt, die nichts mit Schienenfahrzeugen zu tun haben. Wenn man jedoch berücksichtigt, dass die erlernten Gewichte die Merkmalsgrößen ausdrücken, die für die Bildidentifizierung wirksam sind, gilt diese Aufgabe nur für die Schicht in der Nähe der Ausgabe. Es wird entsprechend ersetzt und gelernt. Es scheint möglich zu sein, das Identifikationsproblem zu lösen, das nichts mit den Trainingsdaten des ersten Modells zu tun hat. Oh geheimnisvoll. Die Eingabe ist ein Farbbild von 128 x 128 [^ 1], und nach Durchlaufen des VGG16-Modells werden 256 Einheiten der vollständig verbundenen Ebene, Dropout und 5 Einheiten der vollständig verbundenen Ebene (Ausgabeebene) angehängt. Es werden nur die Gewichte der diesmal hinzugefügten vollständig verbundenen Schicht und der Teil von Conv2D-Conv2D-Conv2D trainiert, der der Ausgangsschicht von VGG16 am nächsten liegt, und die verbleibenden Conv2D-Schichten werden nicht aus den gelernten Parametern verschoben.

[^ 1]: Wie im Originalartikel war 150x150 in Ordnung, aber wenn VGG16 übergeben wird, wird die Bildgröße in vertikaler und horizontaler Richtung jeweils 1/32, also habe ich irgendwie darüber nachgedacht, ein Vielfaches von 32 zu machen. Dem 224x224, der für das ursprüngliche VGG16-Lernen verwendet wurde, ging der Speicher aus (wahrscheinlich, weil TensorFlow unter Windows 10 nicht gut funktionierte und unter Linux auf einer virtuellen Maschine ausgeführt wurde).

Das Eingabebild wird zum Lernen verwendet, indem Schwankungen wie Vergrößerung / Verkleinerung und Links / Rechts-Inversion mit "ImageDataGenerator" angegeben werden, wie sie an verschiedenen Stellen eingeführt wurden. Das Originalbild ist ungefähr 500, aber ** jede Epoche gibt eine andere Schwankung, so dass es scheint, dass die Daten aufgeblasen sind **. Python - Über Keras Image Data Generator | teratail

train.py


import tensorflow as tf
from tensorflow.keras.layers import Dense, Input, Flatten, Dropout
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
from tensorflow.keras.models import Model
from tensorflow.keras.applications import VGG16
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt

#Lerneinstellungen
batch_size = 32
epochs = 30
#Funktionseinstellung
#Ordnet Klassen dem Namen des Unterordners zu
classes = ["E231-yamanote", "E233-chuo", "E233-keihintohoku", "E233-nanbu", "E235-yamanote"]
num_classes = len(classes)
img_width, img_height = 128, 128
feature_dim = (img_width, img_height, 3)
#Dateipfad
data_dir = "./images"

# ===Bildvorbereitung===
datagen = ImageDataGenerator(
    rescale=1.0 / 255, #Jeder Pixelwert ist[0, 1]Konvertieren und handhaben
    zoom_range=0.2,
    horizontal_flip=True,
    validation_split=0.1
)
train_generator = datagen.flow_from_directory(
    data_dir,
    subset="training",
    target_size=(img_width, img_height),
    color_mode="rgb",
    classes=classes,
    class_mode="categorical",
    batch_size=batch_size,
    shuffle=True)
validation_generator = datagen.flow_from_directory(
    data_dir,
    subset="validation",
    target_size=(img_width, img_height),
    color_mode="rgb",
    classes=classes,
    class_mode="categorical",
    batch_size=batch_size)

#Holen Sie sich die Anzahl der Bilder und berechnen Sie die Anzahl der Mini-Batches von 1 Epoche
num_train_samples = train_generator.n
num_validation_samples = validation_generator.n
steps_per_epoch_train = (num_train_samples-1) // batch_size + 1
steps_per_epoch_validation  = (num_validation_samples-1) // batch_size + 1

# ===Modelldefinition===
#Trainieren Sie basierend auf dem trainierten VGG16-Modell, indem Sie nur die Ausgabeschicht ändern
# block4_Trainieren Sie die Parameter nicht bis zum Pool
vgg16 = VGG16(include_top=False, weights="imagenet", input_shape=feature_dim)
for layer in vgg16.layers[:15]:
    layer.trainable = False

#Erstellen Sie dieses Modell
layer_input = Input(shape=feature_dim)
layer_vgg16 = vgg16(layer_input)
layer_flat = Flatten()(layer_vgg16)
layer_fc = Dense(256, activation="relu")(layer_flat)
layer_dropout = Dropout(0.5)(layer_fc)
layer_output = Dense(num_classes, activation="softmax")(layer_dropout)
model = Model(layer_input, layer_output)
model.summary()
model.compile(loss="categorical_crossentropy",
              optimizer=SGD(lr=1e-3, momentum=0.9),
              metrics=["accuracy"])

# ===Lernen===
cp_cb = ModelCheckpoint(
    filepath="weights.{epoch:02d}-{loss:.4f}-{val_loss:.4f}.hdf5",
    monitor="val_loss",
    verbose=1,
    mode="auto")
reduce_lr_cb = ReduceLROnPlateau(
    monitor="val_loss",
    factor=0.5,
    patience=1,
    verbose=1)
history = model.fit(
    train_generator,
    steps_per_epoch=steps_per_epoch_train,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=steps_per_epoch_validation,
    callbacks=[cp_cb, reduce_lr_cb])

# ===Übergangsausgabe der richtigen Antwortrate===
plt.plot(range(1, len(history.history["accuracy"]) + 1),
         history.history["accuracy"],
         label="acc", ls="-", marker="o")
plt.plot(range(1, len(history.history["val_accuracy"]) + 1),
         history.history["val_accuracy"],
         label="val_acc", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.savefig("accuracy.png ")
plt.show()

Übergang des Lernens

Nach 30 Epochen sieht der Übergang der richtigen Antwortrate in den Trainingsdaten und Verifizierungsdaten so aus. Ich habe trainiert, indem ich die CPU auf einem Notebook ohne GPU gedreht habe (bei vollem Betrieb mit 4 Kernen), aber da 1 Epoche ungefähr 1 Minute dauerte, dauerte es insgesamt ungefähr 30 Minuten. accuracy.png Die korrekte Antwortrate der Verifizierungsdaten wurde in etwa 10 Epochen gestoppt, aber die korrekte Antwortrate für 5-Choice-Fragen hat 94% erreicht. Sie haben trotz der geringen Datenmenge Ihr Bestes gegeben!

Die Funktion "ModelCheckpoint" speichert das Modell automatisch am Ende jeder Epoche. Dieses Mal hatte das Modell `weight.17-0.1049-0.1158.hdf5`` aus der 17. Epoche den geringsten Verlust an Validierungsdaten, daher werden wir dies zur Identifizierung verwenden.

import numpy as np
print(np.argmin(history.history["val_loss"]) + 1)
#17 (Kann sich jedes Mal ändern)

wichtiger Punkt

Ich habe Optimizer auf "SGD" gesetzt, aber wenn ich es auf "Adam" usw. setze, konvergiert es nicht gut. Dies ist wahrscheinlich auf die Feinabstimmung zurückzuführen. Einzelheiten finden Sie im folgenden Artikel. [\ TensorFlow ] Optimizer hat auch Weight --Qiita

Identifizieren Sie das Fahrzeug

Lassen Sie uns tatsächlich jedes der am Anfang aufgelisteten Bilder identifizieren.

predict.py


import sys

def usage():
    print("Usage: {0} <input_filename>".format(sys.argv[0]), file=sys.stderr)
    exit(1)

# ===Ruft den Dateinamen des Eingabebildes aus dem Argument ab===
if len(sys.argv) != 2:
    usage()
input_filename = sys.argv[1]

import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing import image
 
#Funktionseinstellung
classes = ["E231-yamanote", "E233-chuo", "E233-keihintohoku", "E233-nanbu", "E235-yamanote"]
num_classes = len(classes)
img_width, img_height = 128, 128
feature_dim = (img_width, img_height, 3)

# ===Modell laden===
model = tf.keras.models.load_model("weights.17-0.1049-0.1158.hdf5")

# ===Eingabebild laden===
img = image.load_img(input_filename, target_size=(img_height, img_width))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
#Der Wertebereich ist der gleiche wie beim Lernen[0, 1]Konvertieren zu
x = x / 255.0
#Fahrzeugtyp vorhersagen
pred = model.predict(x)[0]
#Ergebnisse anzeigen
for cls, prob in zip(classes, pred):
    print("{0:18}{1:8.4f}%".format(cls, prob * 100.0))

Eingabe- / Ausgabebeispiel

Wenn Sie dem Befehlszeilenargument predigen.py den Namen der Bilddatei geben, wird das Identifikationsergebnis ausgegeben.

python3 predict.py filename.jpg

Alle hier vorgestellten Eingabebeispiele sind Ihre eigenen. Obwohl ein Teil des Bildes für die Veröffentlichung hier verarbeitet wird, wird es wie zum Zeitpunkt des tatsächlichen Lernens und Identifizierens eingegeben.

(1) Serie E231 Serie 500 (Yamate-Linie)

E231系500番台(山手線)
E231-yamanote      99.9974%
E233-chuo           0.0000%
E233-keihintohoku   0.0000%
E233-nanbu          0.0004%
E235-yamanote       0.0021%

Es ist die richtige Antwort ohne Beschwerden.

(2) Serie E233 Serie 0 (Chuo Line Rapid / Oume Line / Gokaichi Line)

E233系0番台(中央線快速・青梅線・五日市線)
E231-yamanote       0.0023%
E233-chuo          97.3950%
E233-keihintohoku   0.0101%
E233-nanbu          2.5918%
E235-yamanote       0.0009%

Das ist überhaupt kein Problem.

(3) E233 Serie 1000 Serie (Keihin Tohoku / Negishi Line)

E233系1000番台(京浜東北・根岸線) Es ist ein Bild, das für die Maschine schwer zu identifizieren scheint, da es den Namen der Station und die Personen zeigt.
E231-yamanote       2.0006%
E233-chuo           0.9536%
E233-keihintohoku  34.9607%
E233-nanbu          6.5641%
E235-yamanote      55.5209%

Die Wahrscheinlichkeit der Yamate Line E235-Serie hat zugenommen. Die Bedingungen sind schlecht und das Bild ist von der Seite, ist es also unvermeidlich?

Der Grund, warum dieses Bild von der Seite ist, ist übrigens, dass ich kein Bild des Keihin Tohoku Line-Zugs von vorne von mir genommen habe ... (Schweiß)

(4) E233-Serie 8000-Serie (Nanbu-Linie)

E233系8000番台(南武線)
E231-yamanote       0.1619%
E233-chuo           7.9535%
E233-keihintohoku   0.0309%
E233-nanbu         91.7263%
E235-yamanote       0.1273%

Ich habe der richtigen Nanbu-Linie eine hohe Wahrscheinlichkeit gegeben, aber es scheint, dass ich mit der Chuo-Linie schnell ein wenig verloren war. Die Form ist jedoch fast gleich und nur in verschiedenen Farben, aber in diesem Fall kann sie mit der Keihin Tohoku-Linie verwechseln.

(5) E235 Serie 0 Serie (Yamate Linie)

E235系0番台(山手線)
E231-yamanote       0.0204%
E233-chuo           0.0000%
E233-keihintohoku   0.0027%
E233-nanbu          0.0002%
E235-yamanote      99.9767%

Dies ist kein Problem.

Andere

E233系1000番台(京浜東北・根岸線)をE235系0番台(山手線)に間違えた
E231-yamanote       0.2417%
E233-chuo           0.0204%
E233-keihintohoku   2.1286%
E233-nanbu          0.0338%
E235-yamanote      97.5755%

Eigentlich ist die dritte die richtige Antwort, aber es scheint, dass ich dachte, es sei ein neues Modell der Yamate-Linie. Warum. .. ..

E233系0番台(中央線快速)をE235系0番台(山手線)に間違えた
E231-yamanote      47.2513%
E233-chuo           0.0898%
E233-keihintohoku   0.4680%
E233-nanbu          6.5922%
E235-yamanote      45.5986%

Die zweite ist die richtige Antwort, aber aus irgendeinem Grund werde ich die Yamate-Linie empfehlen. Gibt es eine Theorie, dass E235 einfach für Bilder von der Seite empfohlen wird? Der Grund, warum die Wahrscheinlichkeit der Nanbu-Linie etwas höher ist, ist, dass sie auf das gelbe Zeichen ganz rechts reagiert (ich weiß nicht, ob es tatsächlich so ist).

Zusammenfassung

Ich habe versucht, ein Modell zu lernen, das 5 Fahrzeugtypen anhand von etwa 500 Bildern von Eisenbahnfahrzeugen identifiziert, die mit der Google-Bildsuche erfasst wurden. Indem ein Teil des trainierten Modells (VGG16) umgeleitet und erlernt wird, scheint ein Modell erstellt worden zu sein, das auch auf einem PC ohne GPU in etwa 30 Minuten angemessen identifiziert werden kann. Es gibt einige Muster, die Fehler machen, aber ich denke, er war ein guter Kämpfer für die Menge an Rechenressourcen und Daten. Es war überraschend einfach zu machen und es hat Spaß gemacht.

Wenn Sie es ernsthaft tun, müssen Sie Bilddaten aus verschiedenen Richtungen sammeln, und ich denke, es ist notwendig, den Teil des Fahrzeugs auszuschneiden. Wenn Sie das Gesicht identifizieren möchten, können Sie das Gesicht sofort mit OpenCV usw. ausschneiden. Bei einem Fahrzeug handelt es sich jedoch wahrscheinlich um die Annotation zur Objekterkennung.

Recommended Posts

[TensorFlow] Ich habe versucht, KI in Fahrzeugeisen einzuführen
Ich habe versucht, Pylint vorzustellen
Ich habe versucht, Autoencoder mit TensorFlow zu implementieren
Ich habe versucht, AutoEncoder mit TensorFlow zu visualisieren
Ich habe versucht, Text mit TensorFlow zu klassifizieren
Ich habe versucht, KI für Smash Bra zu machen
Ich habe ein ○ ✕ Spiel mit TensorFlow gemacht
Ich habe versucht, TensorFlow auszuführen
Als ich versuchte, Python3 in Atom einzuführen, blieb ich stecken
Ich habe versucht, Grad-CAM mit Keras und Tensorflow zu implementieren
Ich habe versucht, die alternative Klasse mit Tensorflow zu finden
Ich habe versucht, PredNet zu lernen
Ich habe versucht, SVM zu organisieren.
Ich habe versucht, PCANet zu implementieren
Ich habe versucht, Linux wieder einzuführen
Ich habe versucht, SparseMatrix zusammenzufassen
Ich habe versucht, Magenta / TensorFlow zu verwenden
jupyter ich habe es berührt
Ich habe versucht, StarGAN (1) zu implementieren.
Ich habe versucht, das Blockdiagramm-Generierungswerkzeug blockdiag einzuführen
Ich habe versucht, den für TensorFlow geschriebenen Code nach Theano zu portieren
Ich habe versucht, mit TensorFlow den Durchschnitt mehrerer Spalten zu ermitteln
Ich habe versucht, Deep VQE zu implementieren
Ich habe das TensorFlow-Tutorial als erstes ausprobiert
Ich habe versucht, eine Quip-API zu erstellen
Ich habe versucht, Othello AI mit Tensorflow zu machen, ohne die Theorie des maschinellen Lernens zu verstehen ~ Einführung ~
Ich habe das 2. TensorFlow-Tutorial ausprobiert
Ich habe versucht, eine kontroverse Validierung zu implementieren
Ich habe versucht, Pytorchs Datensatz zu erklären
Ich habe Watson Voice Authentication (Speech to Text) ausprobiert.
TensorFlow Tutorial Ich habe CNN 4th ausprobiert
Ich habe Teslas API berührt
Fortsetzung: Ich habe versucht, das Blockdiagramm-Generierungswerkzeug blockdiag einzuführen
Ich habe versucht, mich über MCMC zu organisieren.
Ich habe versucht, Realness GAN zu implementieren
Ich habe versucht, den Ball zu bewegen
Ich habe versucht, die Höhen und Tiefen des Schlusskurses des Aktienkurses von Guru Navi mit TensorFlow vorherzusagen (Fortschritt)
Ich habe versucht, den Abschnitt zu schätzen.
Ich habe versucht, Othello AI mit Tensorflow zu erstellen, ohne die Theorie des maschinellen Lernens zu verstehen ~ Implementierung ~
Ich habe versucht, Othello AI mit Tensorflow zu erstellen, ohne die Theorie des maschinellen Lernens zu verstehen ~ Battle Edition ~
Ich habe versucht, das Gesichtsbild mit sparse_image_warp von TensorFlow Addons zu transformieren
Ich habe versucht, eine Gesichtsdiagnose-KI für professionelle Golferinnen zu erstellen ②
Ich überarbeitete "Ich habe versucht, Othello AI zu machen, als Programmieranfänger Python studierten"
Ich habe versucht, einen Linebot zu erstellen (Implementierung)
TensorFlow Tutorial Ich habe MNIST 3rd ausprobiert
Ich habe versucht, die Behandlung von Python-Ausnahmen zusammenzufassen
Ich habe versucht, PLSA in Python zu implementieren
Ich habe versucht, Azure Speech to Text zu verwenden.
Ich habe versucht, den Befehl umask zusammenzufassen
Ich habe versucht, Permutation in Python zu implementieren
Ich habe versucht, einen Linebot zu erstellen (Vorbereitung)
Ich versuchte das Weckwort zu erkennen
Ich habe versucht, mit Hy anzufangen
Ich habe versucht, ○ ✕ mit TensorFlow zu spielen
Ich habe versucht, PLSA in Python 2 zu implementieren
Python3-Standardeingabe habe ich versucht zusammenzufassen
Ich habe versucht, die grafische Modellierung zusammenzufassen.