CIFAR-10 Kann nicht mehr als 60% Genauigkeit erreichen, Keras mit Tensorflow-Backend [geschlossen]


11

Das Training nach 15 Epochen mit dem CIFAR-10-Datensatz scheint den Validierungsverlust nicht mehr zu verringern und liegt bei 1,4 (mit einer Validierungsgenauigkeit von 60%). Ich habe das Trainingsset gemischt, durch 255 geteilt und als float32 importiert. Ich habe zahlreiche Architekturen ausprobiert, sowohl mit als auch ohne Ausfall in den Conv2D-Ebenen, und nichts scheint zu funktionieren. Dieselbe Architektur erreicht eine Genauigkeit von 99,7% bei Testsätzen für MNIST. Bitte beachten Sie die Architektur unten:

(Hinweis: Ich habe versucht, die Ausfallrate zu erhöhen und die Lernrate des Adam-Optimierers zu erhöhen / zu verringern, um eine Überanpassung zu verhindern. Dies verhindert lediglich eine Überanpassung, wobei jedoch sowohl das Training als auch der Testsatz jetzt eine ähnlich niedrige Genauigkeit von etwa 60% aufweisen.)

with tf.device('/gpu:0'):
    tf.placeholder(tf.float32, shape=(None, 20, 64))
    #placeholder initialized (pick /cpu:0 or /gpu:0)
    seed = 6
    np.random.seed(seed)
    modelnn = Sequential()
    neurons = x_train_reduced.shape[1:]

    modelnn.add(Convolution2D(32, 3, 3, input_shape=neurons, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(32, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Dropout(0.2))
    modelnn.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Dropout(0.2))
    modelnn.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Dropout(0.2))
    #modelnn.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
    #modelnn.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
    #modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Flatten())
    #modelnn.add(Dropout(0.5))
    modelnn.add(Dense(1024, activation='relu', W_constraint=maxnorm(3)))
    modelnn.add(Dropout(0.5))
    modelnn.add(Dense(512, activation='relu', W_constraint=maxnorm(3)))
    modelnn.add(Dropout(0.5))
    modelnn.add(Dense(10, activation='softmax'))
    modelnn.compile(loss='categorical_crossentropy', optimizer=optimizer_input, metrics=['accuracy'])
    y_train = to_categorical(y_train)
    modelnn.fit(x_train_reduced, y_train, nb_epoch=nb_epoch_count, shuffle=True, batch_size=bsize,
                           validation_split=0.1)

Ergebnisse:

    44100/44100 [==============================] - 22s - loss: 2.1453 - acc: 0.2010 - val_loss: 1.9812 - val_acc: 0.2959
    Epoch 2/50
    44100/44100 [==============================] - 24s - loss: 1.9486 - acc: 0.3089 - val_loss: 1.8685 - val_acc: 0.3567
    Epoch 3/50
    44100/44100 [==============================] - 18s - loss: 1.8599 - acc: 0.3575 - val_loss: 1.7822 - val_acc: 0.3982
    Epoch 4/50
    44100/44100 [==============================] - 18s - loss: 1.7925 - acc: 0.3933 - val_loss: 1.7272 - val_acc: 0.4229
    Epoch 5/50
    44100/44100 [==============================] - 18s - loss: 1.7425 - acc: 0.4195 - val_loss: 1.6806 - val_acc: 0.4459
    Epoch 6/50
    44100/44100 [==============================] - 18s - loss: 1.6998 - acc: 0.4440 - val_loss: 1.6436 - val_acc: 0.4682
    Epoch 7/50
    44100/44100 [==============================] - 18s - loss: 1.6636 - acc: 0.4603 - val_loss: 1.6156 - val_acc: 0.4837
    Epoch 8/50
    44100/44100 [==============================] - 18s - loss: 1.6333 - acc: 0.4781 - val_loss: 1.6351 - val_acc: 0.4776
    Epoch 9/50
    44100/44100 [==============================] - 18s - loss: 1.6086 - acc: 0.4898 - val_loss: 1.5732 - val_acc: 0.5063
    Epoch 10/50
    44100/44100 [==============================] - 18s - loss: 1.5776 - acc: 0.5065 - val_loss: 1.5411 - val_acc: 0.5227
    Epoch 11/50
    44100/44100 [==============================] - 18s - loss: 1.5585 - acc: 0.5145 - val_loss: 1.5485 - val_acc: 0.5212
    Epoch 12/50
    44100/44100 [==============================] - 18s - loss: 1.5321 - acc: 0.5288 - val_loss: 1.5354 - val_acc: 0.5316
    Epoch 13/50
    44100/44100 [==============================] - 18s - loss: 1.5082 - acc: 0.5402 - val_loss: 1.5022 - val_acc: 0.5427
    Epoch 14/50
    44100/44100 [==============================] - 18s - loss: 1.4945 - acc: 0.5438 - val_loss: 1.4916 - val_acc: 0.5490
    Epoch 15/50
    44100/44100 [==============================] - 192s - loss: 1.4762 - acc: 0.5535 - val_loss: 1.5159 - val_acc: 0.5394
    Epoch 16/50
    44100/44100 [==============================] - 18s - loss: 1.4577 - acc: 0.5620 - val_loss: 1.5389 - val_acc: 0.5257
    Epoch 17/50
    44100/44100 [==============================] - 18s - loss: 1.4425 - acc: 0.5671 - val_loss: 1.4590 - val_acc: 0.5667
    Epoch 18/50
    44100/44100 [==============================] - 18s - loss: 1.4258 - acc: 0.5766 - val_loss: 1.4552 - val_acc: 0.5763
    Epoch 19/50
    44100/44100 [==============================] - 18s - loss: 1.4113 - acc: 0.5805 - val_loss: 1.4439 - val_acc: 0.5767
    Epoch 20/50
    44100/44100 [==============================] - 18s - loss: 1.3971 - acc: 0.5879 - val_loss: 1.4473 - val_acc: 0.5769
    Epoch 21/50
    44100/44100 [==============================] - 18s - loss: 1.3850 - acc: 0.5919 - val_loss: 1.4251 - val_acc: 0.5871
    Epoch 22/50
    44100/44100 [==============================] - 18s - loss: 1.3668 - acc: 0.6006 - val_loss: 1.4203 - val_acc: 0.5910
    Epoch 23/50
    44100/44100 [==============================] - 18s - loss: 1.3549 - acc: 0.6051 - val_loss: 1.4207 - val_acc: 0.5939
    Epoch 24/50
    44100/44100 [==============================] - 18s - loss: 1.3373 - acc: 0.6111 - val_loss: 1.4516 - val_acc: 0.5784
    Epoch 25/50
    44100/44100 [==============================] - 18s - loss: 1.3285 - acc: 0.6149 - val_loss: 1.4146 - val_acc: 0.5922
    Epoch 26/50
    44100/44100 [==============================] - 18s - loss: 1.3134 - acc: 0.6205 - val_loss: 1.4090 - val_acc: 0.6024
    Epoch 27/50
    44100/44100 [==============================] - 18s - loss: 1.3043 - acc: 0.6239 - val_loss: 1.4307 - val_acc: 0.5959
    Epoch 28/50
    44100/44100 [==============================] - 18s - loss: 1.2862 - acc: 0.6297 - val_loss: 1.4241 - val_acc: 0.5978
    Epoch 29/50
    44100/44100 [==============================] - 18s - loss: 1.2706 - acc: 0.6340 - val_loss: 1.4046 - val_acc: 0.6067
    Epoch 30/50
    44100/44100 [==============================] - 18s - loss: 1.2634 - acc: 0.6405 - val_loss: 1.4120 - val_acc: 0.6037
    Epoch 31/50
    44100/44100 [==============================] - 18s - loss: 1.2473 - acc: 0.6446 - val_loss: 1.4067 - val_acc: 0.6045
    Epoch 32/50
    44100/44100 [==============================] - 18s - loss: 1.2411 - acc: 0.6471 - val_loss: 1.4083 - val_acc: 0.6098
    Epoch 33/50
    44100/44100 [==============================] - 18s - loss: 1.2241 - acc: 0.6498 - val_loss: 1.4091 - val_acc: 0.6076
    Epoch 34/50
    44100/44100 [==============================] - 18s - loss: 1.2121 - acc: 0.6541 - val_loss: 1.4209 - val_acc: 0.6127
    Epoch 35/50
    44100/44100 [==============================] - 18s - loss: 1.1995 - acc: 0.6582 - val_loss: 1.4230 - val_acc: 0.6131
    Epoch 36/50
    44100/44100 [==============================] - 18s - loss: 1.1884 - acc: 0.6622 - val_loss: 1.4024 - val_acc: 0.6124
    Epoch 37/50
    44100/44100 [==============================] - 18s - loss: 1.1778 - acc: 0.6657 - val_loss: 1.4328 - val_acc: 0.6080
    Epoch 38/50
    44100/44100 [==============================] - 18s - loss: 1.1612 - acc: 0.6683 - val_loss: 1.4246 - val_acc: 0.6159
    Epoch 39/50
    44100/44100 [==============================] - 18s - loss: 1.1466 - acc: 0.6735 - val_loss: 1.4282 - val_acc: 0.6122
    Epoch 40/50
    44100/44100 [==============================] - 18s - loss: 1.1325 - acc: 0.6783 - val_loss: 1.4311 - val_acc: 0.6157
    Epoch 41/50
    44100/44100 [==============================] - 18s - loss: 1.1213 - acc: 0.6806 - val_loss: 1.4647 - val_acc: 0.6047
    Epoch 42/50
    44100/44100 [==============================] - 18s - loss: 1.1064 - acc: 0.6842 - val_loss: 1.4631 - val_acc: 0.6047
    Epoch 43/50
    44100/44100 [==============================] - 18s - loss: 1.0967 - acc: 0.6870 - val_loss: 1.4535 - val_acc: 0.6106
    Epoch 44/50
    44100/44100 [==============================] - 18s - loss: 1.0822 - acc: 0.6893 - val_loss: 1.4532 - val_acc: 0.6149
    Epoch 45/50
    44100/44100 [==============================] - 18s - loss: 1.0659 - acc: 0.6941 - val_loss: 1.4691 - val_acc: 0.6108
    Epoch 46/50
    44100/44100 [==============================] - 18s - loss: 1.0610 - acc: 0.6956 - val_loss: 1.4751 - val_acc: 0.6106
    Epoch 47/50
    44100/44100 [==============================] - 18s - loss: 1.0397 - acc: 0.6981 - val_loss: 1.4857 - val_acc: 0.6041
    Epoch 48/50
    44100/44100 [==============================] - 18s - loss: 1.0208 - acc: 0.7039 - val_loss: 1.4901 - val_acc: 0.6106
    Epoch 49/50
    44100/44100 [==============================] - 18s - loss: 1.0187 - acc: 0.7036 - val_loss: 1.4994 - val_acc: 0.6106
    Epoch 50/50
    44100/44100 [==============================] - 18s - loss: 1.0024 - acc: 0.7070 - val_loss: 1.5078 - val_acc: 0.6039
    Time: 1109.7512991428375
    Neural Network now trained from dimensions (49000, 3, 32, 32)

Update: Weitere Tests einschließlich BatchNormalization mit und ohne MaxNorm -

img

Neue Architektur:

    modelnn.add(Convolution2D(32, 3, 3, input_shape=neurons, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(32, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(BatchNormalization())
    modelnn.add(Dropout(0.2))
    modelnn.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(BatchNormalization())
    modelnn.add(Dropout(0.2))
    modelnn.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(BatchNormalization())
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Dropout(0.2))
    # modelnn.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
    # modelnn.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
    # modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Flatten())
    modelnn.add(Dense(1024, activation='relu', W_constraint=maxnorm(3)))
    modelnn.add(BatchNormalization())
    modelnn.add(Dropout(0.5))
    modelnn.add(Dense(512, activation='relu', W_constraint=maxnorm(3)))
    modelnn.add(BatchNormalization())
    modelnn.add(Dropout(0.5))
    modelnn.add(Dense(10, activation='softmax'))

Antworten:


8

Beachten Sie, dass MNIST ein viel einfacheres Problem ist als CIFAR-10, und Sie können 98% von einem vollständig verbundenen (nicht faltungsorientierten) NNet mit sehr geringen Schwierigkeiten erhalten. Ein sehr einfaches CNN mit nur einer oder zwei Faltungsschichten kann ebenfalls die gleiche Genauigkeit erreichen.

Ich bin mir über Ihre NNet-Architektur nicht sicher, aber ich kann Sie mit der folgenden Architektur (die vergleichsweise einfacher ist und weniger Gewichte hat) auf 78% Testgenauigkeit auf CIFAR-10 bringen. Unter Verwendung der Vanille-Standardeinstellungen und des Adam-Optimierers war keine spezielle Initialisierung oder Handhaltung erforderlich:

model = Sequential()
model.add(Conv2D(input_shape=trainX[0,:,:,:].shape, filters=96, kernel_size=(3,3)))
model.add(Activation('relu'))
model.add(Conv2D(filters=96, kernel_size=(3,3), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Conv2D(filters=192, kernel_size=(3,3)))
model.add(Activation('relu'))
model.add(Conv2D(filters=192, kernel_size=(3,3), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(BatchNormalization())
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dense(n_classes, activation="softmax"))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Diese Architektur ist ziemlich einfach und basiert lose auf https://arxiv.org/pdf/1412.6806.pdf .

Trainieren Sie dieses Modell folgendermaßen:

n_epochs = 25
batch_size = 256
callbacks_list = None
H = model.fit(trainX, trainY, validation_data=(testX, testY), 
              epochs=n_epochs, batch_size=batch_size, callbacks=callbacks_list)
print('Done!!!')

Gibt Folgendes an, von dem Sie sehen können, dass es bis zur 25. Epoche fast 77% erreicht und sich von dort aus mehr oder weniger abflacht (es hat jedoch genügend Regularisierung durch Dropout, um zu verhindern, dass es sich aufgrund von Überanpassung verschlechtert, zumindest über die getestete Anzahl von Iterationen hinaus). .

Trainieren Sie mit 50000 Proben, validieren Sie mit 10000 Proben
Epoche 1/50
50000/50000 [==============================] - 19s 390us / Schritt - Verlust: 1.6058 - acc: 0.4150 - val_loss: 1.5285 - val_acc: 0.4669
Epoche 2/50
50000/50000 [======================== =======] - 19s 371us / Schritt - Verlust: 1,2563 - acc: 0,5477 - val_loss: 1,1447 - val_acc: 0,5901
Epoche 3/50
50000/50000 [============= =================] - 19s 373us / step - loss: 1.0784 - acc: 0.6163 - val_loss: 1.1577 - val_acc: 0.6002
...
Epoche 25/50
50000/50000 [ =============================] - 19s 374us / step - loss: 0.3188 - acc: 0.8857 - val_loss: 0.7493 - val_acc : 0,7680
...
Epoche 50/50
50000/50000 [=============================] - 19s 373us / step - loss: 0.1928 - acc: 0.9329 - val_loss : 0.8718 - val_acc: 0.7751
Fertig !!!

Hier ist eine noch einfachere und viel kleinere Architektur, die mit demselben Trainingsprogramm (keine BatchNormalization- oder Pooling-Ebenen) ziemlich schnell zu 70% gelangen kann:

# CNN architecture with Keras
model = Sequential()
model.add(Conv2D(input_shape=trainX[0,:,:,:].shape, filters=32, 
                 use_bias=True, kernel_size=(3,3)))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Conv2D(filters=64, use_bias=False, kernel_size=(5,5), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.3))
model.add(Dense(n_classes, activation="softmax"))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=    ['accuracy'])

Es ist erwähnenswert, dass die Architekturen, die auf CIFAR-10 die derzeit am besten veröffentlichte Genauigkeit erreichen (derzeit im Bereich von 90 bis 96%), im Allgemeinen komplizierter sind und viele Stunden benötigen, um auf GPU-Hardware zu trainieren. Aber ich konnte mit relativ einfachen Architekturen, die in wenigen Minuten trainiert werden, den Bereich von 70-80% erreichen. Dies würde ich empfehlen, bevor ich die am besten veröffentlichten Ergebnisse erzielte, die normalerweise kompliziertere Architekturen und längere Einarbeitungszeiträume erfordern. manchmal spezielle Handhalte- / Trainingspläne oder Datenerweiterungen und Stunden Zugzeit.

AKTUALISIEREN:

Basierend auf den aktualisierten Darstellungen in der Frage ist das offensichtlichste Problem, das gezeigt wird, die Überanpassung. Dies wird durch die Divergenz der Zugtestdaten nach etwa der 15. Epoche belegt, die eine unzureichende Regularisierung für diese Architektur für diesen Datensatz zeigt. Es ist unwahrscheinlich, dass Sie durch die Einstellung anderer Hyperparameter (Normalisierungsstrategien, Lernraten usw.) eine Verbesserung erzielen, wenn die Überanpassung nicht behoben wird.

Bei der Verwendung von NNets empfehle ich Folgendes:

  1. Beginnen Sie mit Architekturen, die diejenigen nachahmen oder replizieren, von denen bekannt ist, dass sie gute Ergebnisse erzielen
  2. Überprüfen Sie die Leistung Ihres Datensatzes mit besonderem Augenmerk auf eine Überanpassung im Netzwerk (was durch eine signifikante Divergenz der Zugtestfehler belegt wird).
  3. Fügen Sie eine zusätzliche Regularisierung hinzu (erhöhen Sie die Abbrecherquote), wenn eine Überanpassung beobachtet wird (Sie suchen nach "gerade genug", um eine Überanpassung zu verhindern - zu viel führt zu einer Unteranpassung).
  4. Experimentieren Sie mit Struktur, Trainingsansätzen und Hyperparametern, um Verbesserungsmöglichkeiten zu finden

Vorschriften in Bezug auf Letzteres sind eigentlich ziemlich schwer zu bekommen, da es wenig theoretische Grundlagen dafür gibt, wie Struktur, Training oder Hyperparameter interagieren, um die Leistung eines bestimmten Datensatzes zu erzielen. Dass die Ansätze veröffentlichter Architekturen, die bei Benchmark-Datensätzen ein ähnlich hohes Leistungsniveau erreichen, so unterschiedlich sind, ist ein Beweis dafür.

Es wurde festgestellt, dass die Batchnormalisierung einige Architekturen erheblich verbessert, andere jedoch ohne sie gut auskommen können (oder deren Vorhandensein gleichgültig sind). Die einzige wirkliche Anleitung, die Sie hier geben können, besteht darin, es auszuprobieren und zu prüfen, ob es hilft.

Eine Feinabstimmung der Lernraten sollte im Allgemeinen vermieden werden, es sei denn, Sie sind ein fortgeschrittener Praktiker mit einem tiefen Verständnis von ConvNets und der entsprechenden Fähigkeit, die Teeblätter im Hinblick auf die inkrementelle Leistung zwischen den Epochen während des Trainings zu lesen. Angepasste Lernraten und andere spezielle Trainingsprogramme können in einigen Fällen dazu beitragen, dass Netzwerke in lokalen Minima navigieren und bessere Gesamtlösungen finden. Wenn Sie jedoch nicht viel Zeit und das Know-how haben, um das Konvergenzverhalten des Netzwerks zu diagnostizieren, ist dies nicht der Fall Ein guter Anfang. Die meisten von uns sollten einen Optimierer wie Adam verwenden, der in den allermeisten Fällen unerfahrene Versuche mit handabgestimmten Lernraten übertrifft.

Die Datenerweiterung durch Bildvorverarbeitung kann manchmal zu erheblichen Leistungsverbesserungen führen (im Allgemeinen wird das Modell umso besser verallgemeinert, je vielfältiger die Eingabedaten sind. Durch die Datenvorverarbeitung wird der Eingaberaum um Variationen erweitert, wodurch die Genauigkeit außerhalb der Stichprobe verbessert werden kannReduzieren Sie die Anforderungen an die Regularisierung - hypothetisch, mit unendlichen Trainingsdaten würden wir überhaupt keine Regularisierung benötigen, aber im Bildverarbeitungsraum ist es unwahrscheinlich, dass wir uns dieser Asymptote nähern. Dies kann jedoch die Trainingszeit erheblich verlängern und die Konvergenzraten verlangsamen, und führt eine ganze Reihe anderer Hyperparameter ein, die sich auf Eingangsbildpermutationstechniken beziehen (Rotation, Zuschneiden, Skalieren, Rauschen usw. usw.). Da dieser Pfad die Trainingszeiten verlängern kann und zusätzliche Experimente erforderlich sind, um die Ergebnisse zu optimieren, sollten Sie zunächst die beste Genauigkeit in Ihrem Netzwerk anstreben, ohne zuerst eine Erweiterung vorzunehmen, und dann prüfen, ob eine bescheidene Erweiterung zu einer Verbesserung führt. In diesem Fall sind möglicherweise weitere Experimente erforderlich.

Bei allen Tuning-Experimenten müssen Sie auf Änderungen des Über- und Unteranpassungsverhaltens achten. Das Ändern der Netzwerkarchitektur, des Trainingsplans oder der Hyperparameter erfordert möglicherweise eine zusätzliche Optimierung der Dropout-Regularisierung. Die Fähigkeit, das Über- und Unteranpassungsverhalten anhand der Zug- / Testleistung leicht festzustellen, ist wohl die wichtigste Grundkompetenz bei der Arbeit mit NNets, und dies wird mit der Erfahrung intuitiver.

Dies ist die Kerze, von der alle Ihre Bemühungen geleitet werden. Die Kerze kann den Weg nur schwach beleuchten, aber ohne sie stolpern Sie im Dunkeln herum. Wenn Ihr Netzwerk stark über- oder unterpassend ist, sollte dies behoben werden, bevor Sie zufällige Permutationen der Netzwerkstruktur oder der Hyperparameter versuchen.

Die in dieser Antwort enthaltenen vergleichsweise einfachen Architekturen mit Vanille-Trainingsprogrammen zeigen, dass die Arbeit mit NNET-Architekturen bei schwierigen Problemen wie der Bildklassifizierung Realität ist: Es ist nicht schwierig, ein "ziemlich gutes" Ergebnis zu erzielen, das auf Ansätzen basiert, von denen bekannt ist, dass sie gut funktionieren, sondern eine schrittweise Verbesserung wird immer teurer. Das Erreichen der am besten veröffentlichten Ergebnisse durch Experimente wird über die Fähigkeiten oder die Zeitverfügbarkeit vieler hinausgehen (obwohl es mit genügend Zeit und Mühe möglich ist, die Kochbuchrezepte der veröffentlichten Ansätze zu befolgen, um ihre Ergebnisse zu replizieren - aber selbst dies ist keineswegs der Fall bedeutet trivial). Das Erreichen einer inkrementellen Verbesserung von einem "ziemlich guten" Ausgangspunkt aus kann ein sehr zeitaufwändiger Prozess des Versuchs und Irrtums sein, und viele Experimente werden keine signifikante Verbesserung ergeben.

Dies soll niemanden davon abhalten, zu lernen, sondern nur klarstellen, dass eine erhebliche Investition erforderlich ist, um das (ständig wachsende) Toolset in der NNet-Trickkiste zu beherrschen, und Verbesserungen durch Ausprobieren erforderlich machen können Dutzende (oder Hunderte) von Experimenten über Tage oder Wochen des dedizierten GPU-Trainings.

Die Zeit, die Fähigkeiten und die Ressourcen (dedizierte GPU), die erforderlich sind, um Netzwerke auf ein sehr hohes Leistungsniveau zu trainieren, erklären teilweise die Beliebtheit vorab trainierter Netzwerke.


1
Ihre neuronalen Netzwerkarchitekturen haben keine Pooling-Schichten? schafft das nicht eine unüberschaubare Anzahl von Parametern?
Spandyie

2
Pooling - pfft! Überbewertet. Hierbei wird ein All-Convolutional-Ansatz verwendet, bei dem das Dezimieren und nicht das Pooling verwendet wird. Eine Beschreibung finden Sie im verknüpften Dokument. Faltungsschritte können den gleichen "Trichtereffekt" erzielen wie Pooling mit leicht unterschiedlichen Mitteln. Dass beide arbeiten, zeigt einfach, dass es nicht viele feste theoretische Grundlagen gibt, auf denen man stehen kann, warum all diese Dinge funktionieren.
T3am5hark

6

Betrachtet man Ihre Verlust- und Genauigkeitswerte innerhalb und außerhalb der Stichprobe, so ist Ihr Modell derzeit unterausgestattet, verbessert sich jedoch monoton. Mit anderen Worten, es scheint, als würde dies für mehr Epochen zu einer höheren Vorhersageleistung / weniger Entropieverlust führen.

Sie verwenden eine stark regulierte Architektur (Drop-Out-Layer), was nicht schlecht ist. Es ist jedoch auch nicht verwunderlich, dass das Training viel länger dauert als ohne Regularisierung. Aufgrund der Ausfallschichten ist es unwahrscheinlich, dass Sie (erheblich) überanpassen.

Dinge, die Sie versuchen können, um das Lernen zu beschleunigen:

ich. Passen Sie die Lernrate an: Beginnen Sie z. B. mit einer kleinen, wandern Sie sie in der Mitte nach oben und senken Sie sie gegen Ende wieder ab.

ii. Batch- Normalisierung hinzufügen : In der obigen Architektur können Sie Batch-Norm sowohl in Ihre Faltungsblöcke als auch in dichte Schichten aufnehmen. Normalerweise wird die Batch-Norm-Schicht nach der nichtlinearen Aktivierung, jedoch vor dem Ausfall hinzugefügt. Ich bin mir nicht sicher, wie gut Batch-Norm mit Maxnorm spielt. Für Ihre dichten Schichten würde ich Batch-Norm + Dropuout mit / ohne Maxnorm versuchen. Ich habe das Gefühl, Sie brauchen kein Maxnorm, wenn Sie die Chargennormalisierung anwenden.

iii. Stapelgröße erhöhen: Ich bin nicht sicher, wie groß Ihr Stapel ist und ob Sie eine GPU besitzen. Wenn Sie eine GPU haben, sollten Sie wahrscheinlich versuchen, Ihre Stapelgröße in Multiplikativen von 32 zu maximieren.

Um sicherzustellen, dass Ihre Daten "lernbar" / nicht beschädigt sind (z. B. wenn Sie nicht unfreiwillig eine Transformation angewendet haben, um sie zu verzerren), würde ich alle Regularisierungen aus Ihrer Architektur entfernen, Schulungen durchführen und sicherstellen, dass Sie sich an das Trainingsset anpassen können . Wenn Sie Trainingsdaten erfolgreich lernen können, ist der Rest eine Generalisierungsübung. Wenn Sie sich auch ohne Regularisierung nicht übermäßig an Trainingsdaten anpassen können, benötigt Ihr Modell höchstwahrscheinlich mehr Kapazität (tiefere und umfassendere Architektur).


Vielen Dank für den Rat! Sie hatten Recht damit, dass MaxNorm sich leicht einmischte. Trotzdem ist die Genauigkeit auch nach dem Hinzufügen der BatchNormalization-Ebenen (siehe Update) und dem Entfernen / Einschließen von MaxNorm immer noch gering. Es findet auch keine Augmentation statt. Ich habe eine GPU und habe versucht, mit 64.128.256 und 512 Chargen zu trainieren, aber es wird kaum ein Unterschied festgestellt. In Bezug auf die Lernrate verwende ich den Adam-Optimierer und dachte, dies sollte mehr oder weniger in Ruhe gelassen werden? Trotzdem habe ich LR bei 0,05, 0,001, 0,0005 ausprobiert und festgestellt, dass der Standardwert 0,001 immer noch am besten ist. Irgendwelche Ideen?
user4779

Auch ich kann gut überpassen. Ich habe mein Bestes versucht, um die Architektur in den Papieren zu kopieren, die mit MNIST10 eine Genauigkeit von 80% ++ erreichen können. Wenn ich das Modelltraining für längere Epochen verlasse, scheint der Verlust jetzt zuzunehmen (mehr als 20 Epochen oder so).
user4779

Änderungskommentar - Nach den Änderungen am Modell zeigen die Grafiken nun an, dass die Daten erheblich überpasst werden (basierend auf der Divergenz des Validierungsfehlers nach ~ 15 Epochen)
T3am5hark

Ich bestreite tatsächlich die Nützlichkeit der hier angebotenen Ratschläge, insbesondere für neue Praktizierende. Dies sind alles Dinge, die Sie tun können, aber für Leute, die CNNs noch nicht kennen und nicht die Intuition oder das Verständnis dafür haben, wie diese Dinge funktionieren, sind es viel zu viele Knöpfe und Hebel, um sie ohne andere vorgeschriebene Anweisungen als Blindversuche zu optimieren und Fehler, die wahrscheinlich keine positiven Ergebnisse liefern. Besser wäre es, zuerst mit einfacheren Architekturen zu beginnen, die mit minimalem Twiddling eine gute (nicht am besten veröffentlichte) Leistung erzielen können, und dann von dort aus Verbesserungsmöglichkeiten zu erkunden. Meine zwei Cent.
T3am5hark

Verwenden Sie Adam, um weiter zu arbeiten - spielen Sie nicht mit Lernraten. In 99,99% der Fälle wird es die Handabstimmung der Lernraten übertreffen. Auch - die Aussage, dass es "unwahrscheinlich ist, dass Sie jemals überanpassen", ist einfach falsch (wie aus den nachfolgenden Grafiken hervorgeht, die jetzt eine signifikante Überanpassung zeigen), und es gibt keinen guten Grund für das Poster anzunehmen, dass ... Für eine bestimmte Architektur gibt es a priori nichts zu sagen, ob eine bestimmte Abbrecherquote ausreichend reguliert wird, um eine Überanpassung zu verhindern.
T3am5hark

1

Ich habe dies heute ausprobiert und konnte durchweg eine Testgenauigkeit von fast 75-80% erreichen.

Trainingshistorie

  • Die Gesamtzahl der verwendeten Parameter war: 183,242

  • Sie können es besser machen, indem Sie vielleicht ein paar weitere Ebenen hinzufügen, aber Sie müssen nicht übermäßig sein. Komplexere Netzwerke führen nicht immer zu besseren Ergebnissen.

Vorschläge

Mein Vorschlag an Sie ist, dass Sie Ihre Architektur einfach halten. Folgen Sie Occams Rasiermesser , einfach ist besser.

  • Skalieren Sie Ihre Daten

  • Verwenden Sie keinen zufälligen Samen

  • Verwenden Sie einen geeigneten Optimierer. Ich habe Adadelta wie von Keras verwendet.

  • CNNs müssen nicht verschlungen werden. halte es einfach

  • Tiefere, dünnere Netzwerke funktionieren manchmal besser als breitere

  • Regularisierung verwenden (zB Dropout)

Unten ist mein Code (mit Keras)

# Define the model
model = Sequential()
model.add(Convolution2D(64, (4, 4), padding='same', input_shape=(3, 32, 32)))
model.add(MaxPooling2D(pool_size=(2, 2), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Convolution2D(64, (2, 2), padding='same'))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Convolution2D(32, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Convolution2D(32, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=2))
model.add(Dropout(0.15))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(64))
model.add(Activation('tanh'))
model.add(Dropout(0.25))
model.add(Dense(num_classes, activation='softmax'))
# Compile the model
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.