Ich habe Deep Learning studiert und versucht, eine Ausgabe zu machen, einschließlich der Etablierung von Wissen, also habe ich es als Artikel geschrieben. Der vollständige Code ist auf GitHub aufgeführt. Dieses Mal haben wir VGG16, das für CNN-Modelle bekannt ist, mithilfe von Keras, einem Deep-Learning-Framework, das das Erstellen von Modellen erleichtert, implementiert und Bilder von CIFAR10 identifiziert.
Google Colaboratory
import
import numpy as np
import sys
%matplotlib inline
import matplotlib.pyplot as plt
import keras
from keras.datasets import cifar10
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten, BatchNormalization
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
Importieren Sie zunächst die erforderlichen Bibliotheken. Keras (Offizielles Dokument) ist ein High-Level-Deep-Learning-Framework mit TensorFlow usw. als Back-End, mit dem sich komplexe Modelle einfach entwerfen und erweitern lassen. ..
Außerdem ist CIFAR10 ein Farbbilddatensatz der Universität von Toronto, der Flugzeuge, Autos, Vögel, Katzen, Hirsche usw. umfasst. 10 Arten von Bildern von Hunden, Fröschen, Pferden, Schiffen und Lastwagen werden in 32 x 32 Pixel gespeichert. CIFAR10 wird standardmäßig im Paket keras.data bereitgestellt, ähnlich wie MNIST für handgeschriebene numerische Daten.
datasets
'''Datensatz laden'''
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
'''Festlegen der Stapelgröße, Anzahl der Klassen, Anzahl der Epochen'''
batch_size=64
num_classes=10
epochs=20
'''one-heiße Vektorisierung'''
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
'''Formanzeige'''
print("x_train : ", x_train.shape)
print("y_train : ", y_train.shape)
print("x_test : ", x_test.shape)
print("y_test : ", y_test.shape)
Laden Sie als Nächstes die Trainingsdaten und Testdaten mit load_data (). Die Chargengröße und die Anzahl der Epochen sind oben definiert. Außerdem werden die Etikettendaten in einen One-Hot-Vektor konvertiert (ein Vektor, in dem nur eine Komponente 1 und die anderen alle 0 sind), damit sie von Softmax verarbeitet werden können. Diese Formen sehen folgendermaßen aus:
Ausgabeergebnis
x_train : (50000, 32, 32, 3)
y_train : (50000, 10)
x_test : (10000, 32, 32, 3)
y_test : (10000, 10)
Die Anzahl der Trainingsdaten beträgt 50.000 und die Anzahl der Testdaten beträgt 10000.
Nun machen wir das VGG16-Modell. Die VGG-Serie wird in diesem Artikel ausführlich erläutert. Grob zusammengefasst ist VGG16 ein vom VGG-Team erstelltes CNN-Modell, das um Objekterkennung und Bildklassifizierung konkurriert ILSVRC (IMAGENET Large Scale Visulal Recognition). Ist es wie ein Modell, das in der Herausforderung einen hohen Rang hat? Aufgrund seines relativ einfachen Designs und seiner hohen Leistung wird es häufig in der Einführung von Deep Learning erwähnt. Der Ursprung von 16 scheint darin zu liegen, dass es insgesamt aus 16 Schichten besteht. Die Struktur von VGG16 ist in der folgenden Abbildung dargestellt. (Zitiert aus Originalartikel. VGG16 ist Modell D.)
Es gibt 13 Faltungsschichten mit einer Filtergröße von 3x3 und 3 vollständig verbundene Schichten. Ich habe versucht, VGG16 unter Bezugnahme auf die obige Abbildung zu implementieren.
VGG16
'''VGG16'''
input_shape=x_train.shape[1:]
model = Sequential()
model.add(Conv2D(filters=64, kernel_size=(3,3), strides=(1,1), padding='same', input_shape=input_shape, name='block1_conv1'))
model.add(BatchNormalization(name='bn1'))
model.add(Activation('relu'))
model.add(Conv2D(filters=64, kernel_size=(3,3), strides=(1,1), padding='same', name='block1_conv2'))
model.add(BatchNormalization(name='bn2'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same', name='block1_pool'))
model.add(Conv2D(filters=128, kernel_size=(3,3), strides=(1,1), padding='same', name='block2_conv1'))
model.add(BatchNormalization(name='bn3'))
model.add(Activation('relu'))
model.add(Conv2D(filters=128, kernel_size=(3,3), strides=(1,1), padding='same', name='block2_conv2'))
model.add(BatchNormalization(name='bn4'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same', name='block2_pool'))
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), padding='same', name='block3_conv1'))
model.add(BatchNormalization(name='bn5'))
model.add(Activation('relu'))
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), padding='same', name='block3_conv2'))
model.add(BatchNormalization(name='bn6'))
model.add(Activation('relu'))
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), padding='same', name='block3_conv3'))
model.add(BatchNormalization(name='bn7'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same', name='block3_pool'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), padding='same', name='block4_conv1'))
model.add(BatchNormalization(name='bn8'))
model.add(Activation('relu'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), padding='same', name='block4_conv2'))
model.add(BatchNormalization(name='bn9'))
model.add(Activation('relu'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), padding='same', name='block4_conv3'))
model.add(BatchNormalization(name='bn10'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same', name='block4_pool'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), padding='same', name='block5_conv1'))
model.add(BatchNormalization(name='bn11'))
model.add(Activation('relu'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), padding='same', name='block5_conv2'))
model.add(BatchNormalization(name='bn12'))
model.add(Activation('relu'))
model.add(Conv2D(filters=512, kernel_size=(3,3), strides=(1,1), padding='same', name='block5_conv3'))
model.add(BatchNormalization(name='bn13'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='same', name='block5_pool'))
model.add(Flatten(name='flatten'))
model.add(Dense(units=4096, activation='relu', name='fc1'))
model.add(Dense(units=4096, activation='relu', name='fc2'))
model.add(Dense(units=num_classes, activation='softmax', name='predictions'))
model.summary()
Es gibt zwei Arten von Keras-Modellkonstruktionsmethoden, das sequentielle Modell und das funktionale API-Modell, aber dieses Mal habe ich das einfachere sequentielle Modell verwendet. Modelle werden in Serie erstellt, indem sie wie oben beschrieben zum Modell hinzugefügt werden. Bitte beachten Sie, dass das VGG-Modell ursprünglich für ILSVRC vorgesehen ist, sodass die Eingabegröße und die Ausgabegröße nicht mit diesen Daten übereinstimmen. Daher wird die Eingabe- / Ausgabegröße wie folgt geändert. Dieses Mal verwende ich das viel einfachere CIFAR10, sodass Sie möglicherweise kein so komplexes Modell verwenden müssen.
Vorher ändern | Nach der veränderung | |
---|---|---|
Eingabegröße | 224×224 | 32×32 |
Ausgabegröße | 1000 | 10 |
Außerdem wird die Chargennormalisierung derzeit als Methode verwendet, um ein Überlernen der Trainingsdaten zu verhindern. Sie wird jedoch nicht verwendet, da diese Methode bei der Ankündigung der VGG nicht festgelegt wurde. Diesmal habe ich das auch übernommen. Das Ausgabeergebnis des Modells ist wie folgt.
Ausgabeergebnis
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
block1_conv1 (Conv2D) (None, 32, 32, 64) 1792
_________________________________________________________________
bn1 (BatchNormalization) (None, 32, 32, 64) 256
_________________________________________________________________
activation_1 (Activation) (None, 32, 32, 64) 0
_________________________________________________________________
block1_conv2 (Conv2D) (None, 32, 32, 64) 36928
_________________________________________________________________
bn2 (BatchNormalization) (None, 32, 32, 64) 256
_________________________________________________________________
activation_2 (Activation) (None, 32, 32, 64) 0
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 16, 16, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 16, 16, 128) 73856
_________________________________________________________________
bn3 (BatchNormalization) (None, 16, 16, 128) 512
_________________________________________________________________
activation_3 (Activation) (None, 16, 16, 128) 0
_________________________________________________________________
block2_conv2 (Conv2D) (None, 16, 16, 128) 147584
_________________________________________________________________
bn4 (BatchNormalization) (None, 16, 16, 128) 512
_________________________________________________________________
activation_4 (Activation) (None, 16, 16, 128) 0
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 8, 8, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 8, 8, 256) 295168
_________________________________________________________________
bn5 (BatchNormalization) (None, 8, 8, 256) 1024
_________________________________________________________________
activation_5 (Activation) (None, 8, 8, 256) 0
_________________________________________________________________
block3_conv2 (Conv2D) (None, 8, 8, 256) 590080
_________________________________________________________________
bn6 (BatchNormalization) (None, 8, 8, 256) 1024
_________________________________________________________________
activation_6 (Activation) (None, 8, 8, 256) 0
_________________________________________________________________
block3_conv3 (Conv2D) (None, 8, 8, 256) 590080
_________________________________________________________________
bn7 (BatchNormalization) (None, 8, 8, 256) 1024
_________________________________________________________________
activation_7 (Activation) (None, 8, 8, 256) 0
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 4, 4, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 4, 4, 512) 1180160
_________________________________________________________________
bn8 (BatchNormalization) (None, 4, 4, 512) 2048
_________________________________________________________________
activation_8 (Activation) (None, 4, 4, 512) 0
_________________________________________________________________
block4_conv2 (Conv2D) (None, 4, 4, 512) 2359808
_________________________________________________________________
bn9 (BatchNormalization) (None, 4, 4, 512) 2048
_________________________________________________________________
activation_9 (Activation) (None, 4, 4, 512) 0
_________________________________________________________________
block4_conv3 (Conv2D) (None, 4, 4, 512) 2359808
_________________________________________________________________
bn10 (BatchNormalization) (None, 4, 4, 512) 2048
_________________________________________________________________
activation_10 (Activation) (None, 4, 4, 512) 0
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 2, 2, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 2, 2, 512) 2359808
_________________________________________________________________
bn11 (BatchNormalization) (None, 2, 2, 512) 2048
_________________________________________________________________
activation_11 (Activation) (None, 2, 2, 512) 0
_________________________________________________________________
block5_conv2 (Conv2D) (None, 2, 2, 512) 2359808
_________________________________________________________________
bn12 (BatchNormalization) (None, 2, 2, 512) 2048
_________________________________________________________________
activation_12 (Activation) (None, 2, 2, 512) 0
_________________________________________________________________
block5_conv3 (Conv2D) (None, 2, 2, 512) 2359808
_________________________________________________________________
bn13 (BatchNormalization) (None, 2, 2, 512) 2048
_________________________________________________________________
activation_13 (Activation) (None, 2, 2, 512) 0
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 1, 1, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 512) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 2101248
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
_________________________________________________________________
predictions (Dense) (None, 10) 40970
=================================================================
Total params: 33,655,114
Trainable params: 33,646,666
Non-trainable params: 8,448
_________________________________________________________________
Wir werden das erstellte Modell lernen.
Lernen
'''Optimierungsdefinition'''
optimizer=keras.optimizers.adam()
model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
'''Datennormalisierung'''
x_train=x_train.astype('float32')
x_train/=255
x_test=x_test.astype('float32')
x_test/=255
'''fit'''
history=model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test))
Die verwendete Optimierungsmethode war die häufig verwendete Adam. Da der Hyperparameter diesmal nicht eingestellt ist, wird der Parameter auf den Standardwert gesetzt. Die Verlustfunktion ist eine kategoriale Kreuzentropie, die in dem durch Gleichung (1) ausgedrückten Mehrklassenklassifizierungsproblem verwendet wird.
Die zu optimierende Metrik ist die richtige Antwortrate. (Angegeben durch Metriken) Stellen Sie diese nach model.compile ein. Schließlich können Sie die Bilddaten normalisieren und mit model.fit trainieren. Protokollieren Sie das Lernen in der Geschichte. Mit den obigen Einstellungen sind die Lernergebnisse wie folgt.
Ausführungsergebnis
Train on 50000 samples, validate on 10000 samples
Epoch 1/20
50000/50000 [==============================] - 38s 755us/step - loss: 2.0505 - acc: 0.1912 - val_loss: 2.1730 - val_acc: 0.2345
Epoch 2/20
50000/50000 [==============================] - 33s 667us/step - loss: 1.5810 - acc: 0.3763 - val_loss: 1.8167 - val_acc: 0.3522
Epoch 3/20
50000/50000 [==============================] - 33s 663us/step - loss: 1.2352 - acc: 0.5354 - val_loss: 1.4491 - val_acc: 0.5108
Epoch 4/20
50000/50000 [==============================] - 34s 674us/step - loss: 0.9415 - acc: 0.6714 - val_loss: 1.1408 - val_acc: 0.6202
Epoch 5/20
50000/50000 [==============================] - 34s 670us/step - loss: 0.7780 - acc: 0.7347 - val_loss: 0.8930 - val_acc: 0.6974
Epoch 6/20
50000/50000 [==============================] - 34s 675us/step - loss: 0.6525 - acc: 0.7803 - val_loss: 0.9603 - val_acc: 0.6942
Epoch 7/20
50000/50000 [==============================] - 34s 673us/step - loss: 0.5637 - acc: 0.8129 - val_loss: 0.9188 - val_acc: 0.7184
Epoch 8/20
50000/50000 [==============================] - 34s 679us/step - loss: 0.4869 - acc: 0.8405 - val_loss: 1.0963 - val_acc: 0.7069
Epoch 9/20
50000/50000 [==============================] - 34s 677us/step - loss: 0.4268 - acc: 0.8594 - val_loss: 0.6283 - val_acc: 0.8064
Epoch 10/20
50000/50000 [==============================] - 33s 668us/step - loss: 0.3710 - acc: 0.8785 - val_loss: 0.6944 - val_acc: 0.7826
Epoch 11/20
50000/50000 [==============================] - 34s 670us/step - loss: 0.3498 - acc: 0.8871 - val_loss: 0.6534 - val_acc: 0.8024
Epoch 12/20
50000/50000 [==============================] - 33s 663us/step - loss: 0.2751 - acc: 0.9113 - val_loss: 0.6253 - val_acc: 0.8163
Epoch 13/20
50000/50000 [==============================] - 34s 670us/step - loss: 0.2388 - acc: 0.9225 - val_loss: 1.1404 - val_acc: 0.7384
Epoch 14/20
50000/50000 [==============================] - 33s 667us/step - loss: 0.2127 - acc: 0.9323 - val_loss: 0.9577 - val_acc: 0.7503
Epoch 15/20
50000/50000 [==============================] - 33s 667us/step - loss: 0.1790 - acc: 0.9421 - val_loss: 0.7820 - val_acc: 0.7915
Epoch 16/20
50000/50000 [==============================] - 33s 666us/step - loss: 0.1559 - acc: 0.9509 - val_loss: 0.7138 - val_acc: 0.8223
Epoch 17/20
50000/50000 [==============================] - 34s 671us/step - loss: 0.1361 - acc: 0.9570 - val_loss: 0.8909 - val_acc: 0.7814
Epoch 18/20
50000/50000 [==============================] - 33s 669us/step - loss: 0.1272 - acc: 0.9606 - val_loss: 0.7006 - val_acc: 0.8246
Epoch 19/20
50000/50000 [==============================] - 33s 666us/step - loss: 0.1130 - acc: 0.9647 - val_loss: 0.7523 - val_acc: 0.8177
Epoch 20/20
50000/50000 [==============================] - 34s 671us/step - loss: 0.0986 - acc: 0.9689 - val_loss: 0.7233 - val_acc: 0.8350
Nach Abschluss von 20 Epochen betrug die korrekte Antwortrate für Trainingsdaten etwa 97% und für Testdaten etwa 84%. Zeichnen wir den Verlust und die richtige Antwortrate für jede Epoche.
Diagrammplot
'''Visualisierung der Ergebnisse'''
plt.figure(figsize=(10,7))
plt.plot(history.history['acc'], color='b', linewidth=3)
plt.plot(history.history['val_acc'], color='r', linewidth=3)
plt.tick_params(labelsize=18)
plt.ylabel('acuuracy', fontsize=20)
plt.xlabel('epoch', fontsize=20)
plt.legend(['training', 'test'], loc='best', fontsize=20)
plt.figure(figsize=(10,7))
plt.plot(history.history['loss'], color='b', linewidth=3)
plt.plot(history.history['val_loss'], color='r', linewidth=3)
plt.tick_params(labelsize=18)
plt.ylabel('loss', fontsize=20)
plt.xlabel('epoch', fontsize=20)
plt.legend(['training', 'test'], loc='best', fontsize=20)
plt.show()
Der Übergang der richtigen Antwortrate ist in der folgenden Abbildung dargestellt.
Der Übergang der Verlustfunktion ist in der folgenden Abbildung dargestellt.
Hmm ... Der Verlust von Testdaten ist ab der 4. Epoche instabil geworden. Ich habe Batch-Normalisierung durchgeführt, aber es sieht nach Übertarinierung aus.
Dieses Training nimmt nicht viel Zeit in Anspruch, aber Sie können das Modell, das Sie lange trainiert haben, wiederverwenden, indem Sie es speichern. Speichern Sie das Modell und die Gewichte wie unten gezeigt.
Modell speichern
'''Datenspeicher'''
model.save('cifar10-CNN.h5')
model.save_weights('cifar10-CNN-weights.h5')
Dieses Mal habe ich als Tutorial Keras verwendet, um das Bild von CIFAR10 mit dem berühmten VGG16-Modell zu identifizieren. Da VGG16 ursprünglich ein Modell für die Klassifizierung von 1000 Klassen war, habe ich die Eingabe- / Ausgabegröße geändert und die Chargennormalisierung verwendet, aber ich habe sie übertrainiert. Die Eingabe- / Ausgabegröße ist möglicherweise zu klein. Darüber hinaus können als Verbesserungsmethoden die Implementierung der Dropout- und L2-Regularisierung und die Optimierung von Optimierungsmethoden in Betracht gezogen werden.
Für die Implementierung dieses Codes habe ich auf die folgenden Bücher verwiesen.
Recommended Posts