[PYTHON] Bildklassifizierung mit selbst erstelltem neuronalen Netzwerk von Keras und PyTorch

Einführung

PyTorch-Praxis. Dies ist der Inhalt bis zum letzten Mal ↓ Implementierung einer einfachen Regressionsanalyse mit Keras Weinklassifizierung nach Keras Machine Sommelier von Keras- Datensatzvorbereitung für PyTorch

Problemstellung

fig1_a1_hook.png fig1_b1_spanner.png
fig1-a2-hook.gif fig1-b2-spanner.gif
Figure 1-a. Hook Wrench Figure 1-b. Spanner Wrench

Netzwerkstruktur

Das selbst erstellte NN wird in diesem Artikel MyNet genannt. Es ist ein Netzwerk, das aus einer Eingabeschicht (28 * 28 * 3 Knoten), einer Zwischenschicht (200 Knoten) und einer Ausgabeschicht (2 Ausgänge) besteht. Dieses Mal haben wir es möglich gemacht, 3 RGB-Kanäle zu berücksichtigen. Das konzeptionelle Diagramm der Struktur ist Abbildung 2.

fig2_network.png
Figure 2.Konzeptdiagramm von MyNet

In der mittleren Ebene wird ReLU als Aktivierungsfunktion und Dropout ebenfalls angewendet. Wenden Sie die Softmax-Funktion als Aktivierungsfunktion in der Ausgabeebene an und geben Sie sie für jede Klasse aus (2). Bekommen

Ein kurzes Glossar über Netzwerke

fig2_NN_terms.png
Figure 3.Konzeptionelles Diagramm von Begriffen und Lernen beim maschinellen Lernen

・ ** Neuronen, Knoten </ font> ** Der Teil, der ein Eingangssignal empfängt und etwas ausgibt. Wie in Abbildung 3 gezeigt, wird der abgerundete Teil als Neuron (Knoten) bezeichnet. Er wandelt eine Funktion in ein Eingangssignal um und gibt ein Ausgangssignal aus.

・ ** Aktivierungsfunktion </ font> **: ReLU, Softmax Eine Funktion, die jedes Neuron (Knoten) transformiert, wenn es eine Ausgabe von einer Eingabe empfängt. So etwas wie $ f_ {()} $ ist in der Abbildung dargestellt.

Klicken Sie hier, um eine Beschreibung der Aktivierungsfunktion zu erhalten In der Abbildung ist die Softmax-Funktion als Beispiel dargestellt. Die Softmax-Funktion wird in der letzten Schicht verwendet, und die Summe der Ausgaben, die jeder Klasse entsprechen, ist 1 (dies kann als Klassenwahrscheinlichkeit angesehen werden). Die Aktivierungsfunktion wird verwendet, um das Phänomen nachzuahmen, dass das Gehirn Feuer synchronisiert, wenn es einen bestimmten Schwellenwert überschreitet. Indem die Aktivierungsfunktion zu einer nichtlinearen Funktion gemacht wird, hat sich die Erkennungsgenauigkeit bei der Bilderkennung dramatisch verbessert. Neben Softmax gibt es ReLU, Sigmaid usw., die je nach Situation ordnungsgemäß verwendet werden müssen, aber nacheinander erscheinen neue. * Nichtlinear bedeutet, dass es nicht mit einer einzelnen geraden Linie geschrieben werden kann, und die lineare Funktion ist eine Funktion, die mit einer einzelnen geraden Linie geschrieben werden kann.
fig4_a.png fig4_b.png fig4_c.png
Figure 4-a.Softmax-Funktion Figure 4-b. ReLU Figure 4-c.Sigmaid-Funktion

・ ** Verlustfunktion </ font> **: kategoriale Kreuzentropie Der Verlustwert ist der Fehler zwischen dem vom neuronalen Netzwerk vorhergesagten Wert und der richtigen Antwort, und die Funktion zum Auffinden des Fehlers ist die Verlustfunktion. Wie in der Abbildung gezeigt, ist es eine Funktion, die den Fehler aus der Ausgabe des Modells und dem richtigen Antwortetikett berechnet.

Klicken Sie hier, um eine Beschreibung der Verlustfunktion zu erhalten In der Abbildung ist die Kreuzentropie als Beispiel dargestellt. Kreuzentropie wird bei Klassifizierungsaufgaben verwendet. Die Formel für die Kreuzentropie lautet wie folgt. $$E=-\sum_{k=1}^{K} t_{n k} \log y_{n k}$$ $ n $ ist die Probennummer, $ K $ ist die Anzahl der Klassen, $ y_ {nk} $ ist die Ausgabe der $ n $ Probenklasse $ k $, $ t_ {nk} $ ist die $ n $ Probenklasse $ k $ Richtiges Antwortetikett

・ ** Optimierungsfunktion </ font> **: SGD Die Optimierungsfunktion ist eine Funktion, die das Gewicht so ändert, dass der Wert der Verlustfunktion abnimmt. Berechnen Sie wie in der Abbildung gezeigt den Gradienten aus Fehler und Gewicht und passen Sie das Gewicht an.

Klicken Sie hier, um eine Beschreibung der Optimierungsfunktion zu erhalten Ein Optimierungsalgorithmus ist geeigneter als eine Funktion, und SGD ist in der Abbildung als Beispiel dargestellt. SGD (Probabilistic Gradient Descent Method) aktualisiert die Gewichte beim Mini-Batch-Lernen wiederholt nach und nach. Die folgende Abbildung ist eine konzeptionelle Animation der Gewichtsaktualisierung von SGD und wird als $ w ← w ± εΔE $ aktualisiert. Darüber hinaus gibt es Optimierungsfunktionen wie Adam und RMSprop. ![SGD.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282390/657e4792-2b07-2462-deab-c0bc7cb500ee.gif)

・ ** Keras ** Eine in Python geschriebene übergeordnete neuronale Netzwerkbibliothek, die auf TensorFlow, CNTK oder Theano ausgeführt werden kann.

・ ** PyTorch ** It’s a Python-based scientific computing package targeted at two sets of audiences: ・ Ein Ersatz für NumPy, um die Leistung von GPUs zu nutzen ・ Eine Deep-Learning-Forschungsplattform, die maximale Flexibilität und Geschwindigkeit bietet

Implementierung in Keras

Siehe GitHub für das gesamte Programm. Das Folgende ist eine Extraktion des MyNet-Teils.

Implementiert in Keras
# Build a model
from keras.applications.mobilenet import MobileNet
from keras.applications.resnet50 import ResNet50
from keras.layers.pooling import GlobalAveragePooling2D
from keras.layers.core import Dense, Dropout, Flatten
from keras.models import Model, load_model, Sequential
from keras.optimizers import Adam, RMSprop, SGD

base_model = Sequential()
top_model = Sequential()

INPUT_SHAPE = (img_size[0], img_size[1], 3)
neuron_total = 500

elif type_backbone == "MyNet":
    INPUT_SHAPE = (img_size[0], img_size[1], 3)
    base_model.add(Dense(neuron_total, activation='relu',
                         input_shape=(INPUT_SHAPE[0]*INPUT_SHAPE[1]*INPUT_SHAPE[2],)))
    base_model.add(Dropout(0.5))
    top_model.add(Dense(nb_classes, activation='softmax', 
                  input_shape=base_model.output_shape[1:]))

# Concatenate base_model(backbone) with top model
model = Model(input=base_model.input, output=top_model(base_model.output))

print("{}Schicht".format(len(model.layers)))

# Compile the model
model.compile(
    optimizer = SGD(lr=0.001),
    loss = 'categorical_crossentropy',
    metrics = ["accuracy"]
)

model.summary()

Implementierung in PyTorch

Siehe GitHub für das gesamte Programm. Das Folgende ist eine Extraktion des MyNet-Teils.

PyTorch-Implementierung
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F
import torchvision.models
from torchsummary import summary

neuron_total = 200
INPUT_SHAPE = (img_size[0], img_size[1], 3)
print(INPUT_SHAPE)
print(nb_classes)

# Create my model
class MyNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.l1 = nn.Linear(INPUT_SHAPE[0]*INPUT_SHAPE[1]*INPUT_SHAPE[2], neuron_total)# Input Layer to Intermediate modules
        self.dropout1 = torch.nn.Dropout2d(p=0.5)
        self.l2 = nn.Linear(neuron_total, 2) #Intermediate modules to Output Layer

    def forward(self, x):#Vorwärtsausbreitung
        x = x.view(-1, INPUT_SHAPE[0]*INPUT_SHAPE[1]*INPUT_SHAPE[2] ) # x.view : Transform a tensor shape. If the first argument is "-1", automatically adjust to the second argument.
        x = self.l1(x)
        x = self.dropout1(x)
        x = self.l2(x)
        return x

if type_backbone == "ResNet50":
    model = Resnet()
elif type_backbone == "Mobilenet":
    model = Mobilenet()
elif type_backbone == "MyNet":
    model = MyNet()
model = model.to(device)
# Show the model 
summary(model, ( 3, img_size[1], img_size[0]))#channel, w, h

Vergleich der beiden in der Programmierung

Vergleich der Datensatzvorbereitung

Wie in Vorbereiten eines Datensatzes für PyTorch erwähnt, wird zunächst gesagt, dass Keras das Numpy-Format verwendet und PyTorch die Formate DataLoader und Tensor verwendet. Der Punkt ist anders.

Modellbauvergleich

In Bezug auf die Erstellung eines Modells passt Keras die Form automatisch an, wenn Ebenen mit Dense usw. verbunden werden. PyTorch muss dies jedoch klarstellen. Zum Beispiel, wenn Sie in Abbildung 2 einige mittlere Ebenen hinzufügen.

base_model = Sequential()
top_model = Sequential()
INPUT_SHAPE = (img_size[0], img_size[1], 3)
base_model.add(Dense(neuron_total, activation='relu',
                         input_shape=(INPUT_SHAPE[0]*INPUT_SHAPE[1]*INPUT_SHAPE[2],)))
base_model.add(Dense(neuron_total, activation='relu'))
base_model.add(Dense(neuron_total, activation='relu'))
base_model.add(Dropout(0.5))
top_model.add(Dense(nb_classes, activation='softmax', 
                  input_shape=base_model.output_shape[1:]))

# Concatenate base_model(backbone) with top model
model = Model(input=base_model.input, output=top_model(base_model.output))

In PyTorch

class MyNet2(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(INPUT_SHAPE[0]*INPUT_SHAPE[1]*INPUT_SHAPE[2], neuron_total)# Input Layer to Intermediate modules
        self.fc2 = nn.Linear(neuron_total, int(neuron_total/2)) #Intermediate modules to Output Layer
        self.dropout1 = torch.nn.Dropout2d(p=0.5)
        self.fc3 = nn.Linear(int(neuron_total/2), 2)

    def forward(self, x):#Vorwärtsausbreitung
        x = x.view(-1, INPUT_SHAPE[0]*INPUT_SHAPE[1]*INPUT_SHAPE[2] ) # x.view : Transform a tensor shape. If the first argument is "-1", automatically adjust to the second argument.
        x = self.fc1(x)
        x = self.fc2(x)
        x = F.relu(x)
        x = self.dropout1(x)
        x = self.fc3(x)
        return x

In PyTorch wird die Anzahl der Knoten sowohl für die Eingabe als auch für die Ausgabe angegeben.

Dropout-Vergleich

Ich fürchte, ich weiß nicht viel darüber, aber Keras sollte die Dropout-Anwendung nicht zwischen Lernen und Evaluieren wechseln müssen. In PyTorch wird Dropout von model.eval () deaktiviert. Wenn Sie also das Testbild laden, wird deutlich, dass es sich nicht im Lernmodus befindet.

param = torch.load(weights_folder_path + "/" + best_weights_path)
model.load_state_dict(param, strict=False)
model.eval()
# ~ Inference

Vergleich von model_summary (Anzahl der Parameter)

Wie Sie sehen können, stimmte die Anzahl der Parameter genau überein.

fig_modelsummary.png
Figure 5.Keras nach Modellzusammenfassung(links)Und PyTorch(richtig)Vergleich

Vergleich der GPU-Nutzung

Es ist eine kleine Geschichte, aber in Keras müssen Sie die Beschreibung nicht ändern, wenn Sie eine GPU verwenden, sondern im Fall von PyTorch

#image, label = Variable(image), Variable(label)
image, label = Variable(image).cuda(), Variable(label).cuda()

Es muss umgeschrieben werden als.

Vergleich der Lernschleife

In Keras wird durch Schreiben wie model.fit die Lernbewertungsschleife für die Anzahl der Epochen wiederholt. In PyTorch wird die Anzahl der Epochen wie folgt in einer for-Schleife wiederholt.

def train(epoch):
    #~Abkürzung
def validation():
    #~Abkürzung
for epoch in range(1, total_epochs + 1):
    train(epoch)
    validation()

Ausgangsvergleich

Außerdem verwendet PyTorch standardmäßig log_softmax, sodass die Gesamtklassenwahrscheinlichkeit nicht 1 beträgt (geben Sie softmax an oder konvertieren Sie es selbst).

Vergleich von beiden während des Lernens

Als ich zuerst den Betriebsstatus des PCs mit dem Task-Manager überprüfte, gab es die folgenden Unterschiede.

fig4_tm.png
Figure 6. Kera(links)Und PyTorch(richtig)Leistung des Task-Managers während jedes Lernens (pro 10 Epochen)

Die Speichernutzung war auf der PyTorch-Seite gering. Da Keras Datensätze in Listen und Numpy-Arrays enthält (in diesem Programm), verbraucht es zwangsläufig Speicher. Die GPU-Auslastung war auch auf der PyTorch-Seite gering.

Vergleichen Sie als Nächstes die Lernausführungsgeschwindigkeit jedes Netzwerks von Keras und PyTorch. Die folgende Tabelle fasst die Zeit (en) zusammen, die für 40 Epochen erforderlich sind, wenn über ein Netzwerk trainiert wird.

Keras PyTorch
ResNet 3520 s 3640 s
Mobilenet 1600 s 1760 s
MyNet 40 s 680 s

Keras setzt verbose = 1 in model.fit, daher betrachte ich den Wert von Sekunden, der ohne Erlaubnis ausgegeben wurde. Es ist genau, aus der Zeit pro Schritt zu berechnen, aber es ist ärgerlich, so dass es ein ungefährer Wert ist. Aus der obigen Tabelle geht hervor, dass PyTorch etwas langsamer ist (ungefähr 3 Sekunden langsamer in 1 Epoche). Besonders MyNet ist ziemlich langsam. PyTorch ist jedoch energieeffizienter (?). Ich wollte, dass PyTorch schneller ist, aber ich denke, der Code ist schlecht. Ich bin der Meinung, dass PyTorch besser ist, um Energie bei fast gleicher Geschwindigkeit zu sparen.

Vergleich der Ergebnisse

Inferenzergebnisse von ResNet, Mobilenet, MyNet in Keras

Die geschätzten Ergebnisse von Verlust, Genauigkeit und Testbildern der trainierten Ergebnisse sind unten zusammengefasst. Die Lernkurve ist schrecklich, aber die Ergebnisse sind vernünftig.

fig5_Keras_l_a.png
Figure 7.Verlust und Genauigkeit (Keras) für Epochen des Lernens
fig6_a.png
Figure 8-a.Geschätztes Ergebnis von ResNet50(Keras)
fig6_b.png
Figure 8-b.Erraten Sie die Ergebnisse von Mobilenet v1(Keras)
fig6_c.png
Figure 8-c.Erraten Sie die Ergebnisse von MyNet(Keras)

ResNet, Mobilenet, MyNet raten zu PyTorch

Die geschätzten Ergebnisse von Verlust, Genauigkeit und Testbildern der trainierten Ergebnisse sind unten zusammengefasst. Ähnlich wie bei Keras wird das Ergebnis in der Falte angezeigt.

** Klicken Sie hier, um eine Zusammenfassung der Lernraten mit PyTorch zu erhalten **
fig9_l_a.png
Figure 9.Verlust und Genauigkeit (PyTorch) für Epochen des Lernens
fig10_a.png
Figure 10-a.Geschätztes Ergebnis von ResNet50 (PyTorch)
fig10_b.png
Figure 10-b.Vermutungsergebnis von Mobilenet v1 (PyTorch)
fig10_c.png
Figure 10-c.Erraten Sie die Ergebnisse von MyNet (PyTorch)

Basierend auf den Ergebnissen von Keras und PyTorch

Beide sind in der Regel gleich (weil ich versucht habe, fast gleich zu lernen).

Sowohl Keras als auch PyTorch können nach ResNet und Mobilenet klassifiziert werden, nicht jedoch nach MyNet auf MNIST-Ebene. Es scheint jedoch, dass das Lernen mit ResNet und Mobilenet nicht gut läuft, um zu sehen, wie der Verlust sinkt. Dieses Mal ähnelt das Testbild den Trainingsdaten, daher denke ich, dass es die richtige Antwort war. Bei Klassifizierungsproblemen, die so ähnlich sind wie Haken- und Schraubenschlüssel, scheint die Anzahl der Daten mit etwa 60 Blatt gering zu sein. Darüber hinaus bin ich der Meinung, dass selbst wenn alle Daten verfügbar sind, sie nicht klassifiziert werden können.

Übrigens ist das Ergebnis des Trainings des Knotens der mittleren Schicht mit 500 und der Anzahl des Lernens mit 100 Epochen in MyNet wie folgt.

fig_mynet100.png
Figure 11.Das Ergebnis des Trainings des Mittelschichtknotens mit 500 und der Anzahl des Lernens mit 100 Epochen mit MyNet

Der Verlustwert der Validierung wird nicht verringert. Vielleicht ist es ein Problem, das nicht nur durch ein nicht tiefes neuronales Netz kategorisiert werden kann. Es muss festgelegt werden, ob die Anzahl der Schichten erhöht oder CNN (Convolutional Neural Network) verwendet werden soll.

Bonus

Wir werden die Logos der beiden Unternehmen für das Herstellerlogo klassifizieren, das im vorherigen Sommelier für Werkzeugmaschinen angezeigt wurde. Es gibt Unterschiede in der Form, aber kann es als neuronales Netz klassifiziert werden? Ich werde es auf MyNet versuchen. Zum Lernen und Bewerten habe ich das online gesammelte Makino Milling Co., Ltd.-Logo und das Okuma-Logo verwendet, und für den Test habe ich mein eigenes handgeschriebenes Logo verwendet. Die, die ich selbst geschrieben habe.

makino_logo_test1.png Okuma_logo_test1.png
Figure 12-a.Handgeschriebenes Makino Milling Logo Figure 12-b.Handbemaltes Okuma-Logo

Der Übergang von Verlust und Genauigkeit ist wie folgt.

graph_loss.png graph_acc.png
Figure 13-a.Verlustübergang in Bezug auf die Epoche Figure 13-b.Übergang der Genauigkeit in Bezug auf die Epoche

Möglicherweise lernen Sie besser als Haken- und Schraubenschlüssel. Ich denke es sieht so aus:

2figure.png 4figure.png
Figure 14-a.Makino Milling Logo erraten Ergebnis Figure 14-b.Okuma Logo erraten Ergebnis

Dieses Ergebnis ist sehr gut kategorisiert. Es scheint möglich zu sein, auch ein neuronales Netzwerk zu klassifizieren, das nicht tief ist, wenn es einen Formunterschied wie ein Logo gibt.

Zusammenfassung

  • Hakenschlüssel und Schraubenschlüssel können nicht durch ein einfaches neuronales Netz klassifiziert werden
  • Wenn es sich um ein Unternehmenslogo handelt, kann es auch dann klassifiziert werden, wenn es nicht tief ist

Ausführungsumgebung Umgebung

  • Windows10
  • CPU:Core i7-7700HQ
  • Memory: 16GB
  • Graphic board: GTX1060 6GB
  • Strage: NVMe M.2 SSD 1TB
  • CUDA 9.0.176
  • cuDNN 7.0.5
  • Wenn Sie CUDA oder cuDNN nicht installiert haben, müssen Sie eine Umgebung erstellen.
  • Keras==2.1.5
  • tensorflow-gpu==1.11.0
  • torch==1.1.0
  • scikit-learn==0.19.1
  • scipy==1.4.1

Referenz

https://keras.io/ja/ https://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html https://qiita.com/sheep96/items/0c2c8216d566f58882aa https://rightcode.co.jp/blog/information-technology/pytorch-mnist-learning https://water2litter.net/rum/post/pytorch_tutorial_classifier/ https://qiita.com/jyori112/items/aad5703c1537c0139edb https://pystyle.info/pytorch-cnn-based-classification-model-with-fashion-mnist/ https://pytorch.org/docs/stable/torchvision/models.html https://qiita.com/perrying/items/857df46bb6cdc3047bd8 https://qiita.com/sakaia/items/5e8375d82db197222669 https://discuss.pytorch.org/t/low-accuracy-when-loading-the-model-and-testing/44991/5

Recommended Posts