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.
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.
Das Bild hier ist mein eigenes.
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.
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()
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. 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)
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
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))
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.
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.
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.
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ß)
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.
E231-yamanote 0.0204%
E233-chuo 0.0000%
E233-keihintohoku 0.0027%
E233-nanbu 0.0002%
E235-yamanote 99.9767%
Dies ist kein Problem.
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. .. ..
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).
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