CIFAR-10 Nie można uzyskać dokładności powyżej 60%, Keras z backendem Tensorflow [zamknięte]


11

Trening po 15 epokach w zestawie danych CIFAR-10 wydaje się sprawiać, że utrata walidacji nie maleje, pozostając na poziomie około 1,4 (z 60% dokładnością walidacji). Przetasowałem zestaw treningowy, podzieliłem go na 255 i zaimportowałem jako float32. Wypróbowałem wiele architektur, zarówno z opuszczaniem warstw Conv2D, jak i bez nich, i wydaje się, że nic nie działa. Ta sama architektura osiąga 99,7% dokładności na zestawach testowych dla MNIST. Zobacz architekturę poniżej:

(Uwaga: Próbowałem zwiększać porzucanie i zwiększać / zmniejszać szybkość uczenia się optymalizatora Adama, aby zapobiec nadmiernemu dopasowaniu, wszystko to zapobiega nadmiernemu dopasowaniu, ale zarówno zestaw treningowy, jak i testowy mają teraz podobną niską dokładność około 60%).

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)

Wyniki:

    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)

Aktualizacja: dalsze testy, w tym BatchNormalizacja zarówno z MaxNorm, jak i bez niego -

img

Nowa architektura:

    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'))

Odpowiedzi:


8

Zauważ, że MNIST jest znacznie prostszym zestawem problemów niż CIFAR-10 i możesz uzyskać 98% z całkowicie połączonej (niekonwolucyjnej) sieci NNet z bardzo niewielkimi trudnościami. Bardzo prosty CNN z tylko jedną lub dwiema warstwami splotowymi może również osiągnąć ten sam poziom dokładności.

Nie jestem pewien co do architektury NNet, ale mogę uzyskać 78% dokładność testowania na CIFAR-10 z następującą architekturą (która jest stosunkowo prostsza i ma mniejszą wagę). Nie była wymagana specjalna inicjalizacja ani trzymanie za ręce, przy użyciu waniliowych ustawień domyślnych i optymalizatora Adama:

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'])

Ta architektura jest dość prosta i luźno oparta na https://arxiv.org/pdf/1412.6806.pdf .

Trenowanie tego modelu w ten sposób:

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!!!')

Daje to, co, jak widzisz, dochodzi do prawie 77% w 25. epoce i mniej więcej spłaszcza się stamtąd (ale ma wystarczającą regularyzację od porzucenia, aby zapobiec degradacji z powodu nadmiernego dopasowania, przynajmniej w stosunku do testowanej liczby iteracji) .

Trenuj na 50000 próbkach, sprawdzaj na 10000 próbkach
Epoka 1/50
50000/50000 [==============================] - 19s 390us / krok - strata: 1.6058 - acc: 0.4150 - val_loss: 1.5285 - val_acc: 0.4669
Epoka 2/50
50000/50000 [======================= =======] - 191 371us / krok - strata: 1,2563 - acc: 0,5477 - val_loss: 1.1447 - val_acc: 0,5901
Epoch
3/50 50000/50000 [============= =================] - 19s 373us / step - strata: 1,0784 - acc: 0,6163 - val_loss: 1,1577 - val_acc: 0,6002
...
Epoch 25/50
50000/50000 [ ==============================] - 19s 374us / step - loss: 0.3188 - acc: 0.8857 - val_loss: 0.7493 - val_acc : 0,7680
...
Epoka 50/50
50000/50000 [==============================] - 193 373us / krok - strata: 0,1928 - acc: 0,9329 - val_loss : 0,8718 - val_acc: 0,7751
Gotowe !!!

Oto jeszcze prostsza i znacznie mniejsza architektura, która może szybko osiągnąć 70% przy użyciu tego samego schematu szkolenia (bez norm BatchNormalization lub puli warstw):

# 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'])

Warto zauważyć, że architektury, które osiągają najlepszą opublikowaną dokładność na CIFAR-10 (obecnie w zakresie 90-96%) są generalnie bardziej skomplikowane i trenowanie na sprzęcie GPU zajmuje wiele godzin. Ale udało mi się dotrzeć do zakresu 70–80% z dość prostymi architekturami, które trenują w kilka minut, co polecam przed pójściem do najlepiej opublikowanych wyników, które zwykle wymagają bardziej skomplikowanych architektur, dłuższych okresów szkolenia, czasami specjalne schematy trzymania / szkolenia lub zwiększania danych oraz godziny pociągu.

AKTUALIZACJA:

Na podstawie zaktualizowanych wykresów w pytaniu najbardziej oczywistym przedstawionym problemem jest nadmierne dopasowanie. Dowodem na to jest rozbieżność danych z testu pociągu po około 15 epoce, która wykazuje niewystarczającą regularyzację dla tej architektury, dla tego zestawu danych. Jest mało prawdopodobne, aby uzyskać poprawę dzięki dostrajaniu jakichkolwiek innych hiperparametrów (strategie normalizacji, wskaźniki uczenia się itp.), Chyba że rozwiązano problem nadmiernego dopasowania.

Przy korzystaniu z sieci Nets zalecam:

  1. Zacznij od architektur, które naśladują lub replikują te, o których wiadomo, że dają dobre wyniki
  2. Sprawdź wydajność swojego zestawu danych, zwracając szczególną uwagę na nadmierne dopasowanie do sieci (czego dowodem są znaczne rozbieżności błędów w testach pociągu)
  3. Dodaj dodatkową regularyzację (zwiększ odsetek rezygnacji), gdy zaobserwowane zostanie nadmierne dopasowanie (szukasz „wystarczającej ilości”, aby zapobiec nadmiernemu dopasowaniu - zbyt duże spowoduje niedopasowanie)
  4. Eksperymentuj ze strukturą, podejściami szkoleniowymi i hiperparametrami, aby znaleźć sposoby poprawy

Recepty dotyczące tych ostatnich są w rzeczywistości dość trudne, ponieważ nie ma teoretycznych podstaw do interakcji między strukturą, szkoleniem lub hiperparametrami, aby uzyskać wydajność na danym zestawie danych. Dowody na to, że podejścia stosowane przez publikowane architektury osiągające podobnie wysoki poziom wydajności w zestawach danych testów porównawczych są bardzo różne.

Stwierdzono, że Batchnormalizacja znacznie poprawia niektóre architektury, ale inne mogą sobie z tym poradzić całkiem dobrze (lub są obojętne na jego obecność). Jedyne prawdziwe wskazówki, które można tu podać, to wypróbowanie i sprawdzenie, czy to pomoże.

Ogólnie rzecz biorąc, należy unikać precyzyjnego dostosowywania wskaźników uczenia się, chyba że jesteś zaawansowanym praktykiem z głębokim zrozumieniem ConvNets i odpowiednią umiejętnością czytania liści herbaty w odniesieniu do przyrostowej wydajności między epokami podczas treningu. Indywidualne stawki uczenia się i inne schematy szkoleń specjalistycznych mogą w niektórych przypadkach pomóc sieciom poruszać się po lokalnych minimach i znaleźć lepsze ogólne rozwiązania, ale jeśli nie masz dużo czasu i wiedzy, aby zdiagnozować zachowanie zbieżności sieci, nie jest to dobre miejsce na początek. Większość z nas powinna używać takiego optymalizatora jak Adam, który w zdecydowanej większości przewyższy nowatorskie próby ręcznego dostosowania wskaźników uczenia się.

Powiększanie danych za pomocą wstępnego przetwarzania obrazu może czasem przynieść znaczną poprawę wydajności (ogólnie, im bardziej zróżnicowane dane wejściowe, tym lepszy model uogólni - przetwarzanie wstępne danych wprowadza zmiany w przestrzeni wejściowej, co może poprawić dokładność poza próbą i możepozwolić sobie na zmniejszenie wymagań regularyzacji - hipotetycznie, przy nieskończonych danych treningowych wcale nie potrzebowalibyśmy żadnej regularyzacji, ale w przestrzeni przetwarzania obrazu raczej nie podejdziemy do tej asymptoty). Może to jednak znacznie wydłużyć czas szkolenia i spowolnić tempo konwergencji, a także wprowadza cały inny zestaw hiperparametrów związanych z technikami permutacji obrazu wejściowego (obracanie, kadrowanie, skalowanie, szum itp.). Ponieważ ta ścieżka może wydłużyć czas szkolenia i wymagać dodatkowych eksperymentów w celu dostrojenia wyników, pewną ogólną radą byłoby dążenie do uzyskania najlepszej dokładności w sieci bez augmentacji, a następnie sprawdzenie, czy niektóre skromne augmentacje przyniosą poprawę. Jeśli tak, może uzasadniać dalsze eksperymenty.

W przypadku wszystkich eksperymentów z tuningiem należy zwracać uwagę na zmiany w zachowaniu nadmiernie i niedopasowanym. Zmiana architektury sieci, schematów szkolenia lub hiperparametrów może wymagać dodatkowego dostrojenia regularyzacji porzucania. Zdolność do łatwego stwierdzenia nadmiernego i niedopasowanego zachowania na podstawie wydajności pociągu / testu jest prawdopodobnie najważniejszą podstawową umiejętnością w pracy z sieciami sieciowymi, a wraz z doświadczeniem staje się bardziej intuicyjna.

To jest świeca, którą kierują się wszystkie twoje wysiłki. Świeca może jedynie słabo oświetlić ścieżkę, ale bez niej potkniesz się w ciemności. Jeśli twoja sieć jest źle przeregulowana lub niedopasowana, należy to rozwiązać przed próbą przypadkowych permutacji struktury sieci lub hiperparametrów.

Stosunkowo proste architektury z waniliowymi schematami szkolenia zawartymi w tej odpowiedzi pokazują rzeczywistość pracy z architekturami NNET nad trudnymi problemami, takimi jak klasyfikacja obrazów: osiągnięcie „całkiem dobrego” wyniku opartego na podejściach, o których wiadomo, że działają dobrze, nie jest trudne, ale stopniowa poprawa jest coraz bardziej kosztowny. Osiągnięcie najlepiej opublikowanych wyników za pomocą eksperymentów będzie przekraczać możliwości wielu osób (choć czas i wysiłek są wystarczające), aby postępować zgodnie z przepisami książek kucharskich opublikowanych metod w celu powtórzenia ich wyników, ale nawet nie jest to niemożliwe oznacza trywialny). Osiąganie stopniowej poprawy od „całkiem dobrego” punktu początkowego może być bardzo czasochłonnym procesem prób i błędów, a wiele eksperymentów nie przyniesie żadnej znaczącej poprawy.

Nie ma to na celu zniechęcenia nikogo do próby uczenia się, ale jedynie wyjaśnienie, że do opanowania (stale rozszerzanego) zestawu narzędzi w torbie sztuczek NNet wymagana jest znaczna inwestycja, a usprawnienia w drodze prób i błędów mogą wymagać dziesiątki (lub setki) eksperymentów w ciągu dni lub tygodni szkolenia poświęconego GPU.

Czas, umiejętności i zasoby (dedykowany procesor graficzny) potrzebne do trenowania sieci do bardzo wysokich poziomów wydajności częściowo wyjaśniają popularność wstępnie przeszkolonych sieci.


1
Architektury sieci neuronowej nie mają żadnych warstw puli? czy to nie tworzy niemożliwej do zarządzania liczby parametrów?
Spandyie

2
Pooling - pfft! Przereklamowany. Wykorzystuje to podejście w pełni splotowe, które używa kroczenia do zdziesiątkowania zamiast łączenia - zobacz opis w połączonym dokumencie. Kroczenie splotowe może uzyskać taki sam efekt „lejekowania” jak łączenie przy użyciu nieco innych środków. To, że oba działają, po prostu pokazuje, że nie ma zbyt wielu solidnych podstaw teoretycznych, aby stać na stanowisku, dlaczego którekolwiek z tych rzeczy działa.
T3am5hark

6

Patrząc na wartości utraty i dokładności w próbie i poza próbą, twój model jest obecnie niedopasowany, ale monotonicznie się poprawia. Innymi słowy, wydaje się, że uruchomienie tego dla większej liczby epok spowodowałoby wyższą wydajność predykcyjną / mniejszą utratę entropii.

Używasz wysoce uregulowanej (usuwanej warstwy) architektury, co nie jest złe. Nie jest jednak zaskakujące, że trening trwa znacznie dłużej niż bez jakiejkolwiek regulacji. Ze względu na zanikające warstwy jest mało prawdopodobne, abyś (zasadniczo) przeszedł się.

Rzeczy, które możesz spróbować przyspieszyć naukę:

ja. podkręć tempo uczenia się: np. zacznij od małego, podnieś go na środku, a pod koniec opuść ponownie.

ii. dodaj normę wsadową : w powyższej architekturze możesz uwzględnić normę wsadową zarówno w blokach splotowych, jak i gęstych warstwach. Zwykle warstwa normy wsadowej jest dodawana po aktywacji nieliniowej, ale przed usunięciem. Nie jestem pewien, jak dobrze gra norma wsadowa z maxnorm. Dla twoich gęstych warstw, spróbowałbym batch-norm + dropuout z / bez maxnorm. Mam wrażenie, że nie potrzebujesz maxnorm, jeśli zastosujesz normalizację partii.

iii. zwiększyć rozmiar partii: nie jestem pewien, jaki jest twój rozmiar partii i czy posiadasz kartę graficzną. Jeśli masz procesor graficzny, prawdopodobnie powinieneś spróbować zmaksymalizować wielkość partii w wielokrotnościach 32.

Wreszcie, aby upewnić się, że Twoje dane są `` możliwe do nauczenia się '' / nie są uszkodzone (np. Nieświadomie nie zastosowałeś transformacji w celu wypaczenia), odrzuciłbym całą regularyzację z twojej architektury, przeprowadziłem szkolenie i zobaczyłem, że możesz dopasować się do zestawu treningowego . Jeśli potrafisz nauczyć się danych treningowych, reszta jest ćwiczeniem uogólniającym. Jeśli nie możesz dopasować się do danych treningowych nawet bez regularyzacji, najprawdopodobniej twój model potrzebuje większej pojemności (głębsza i szersza architektura).


Dziękuję uprzejmie za radę! Miałeś rację co do tego, że MaxNorm nieco ingeruje. Niemniej jednak, nawet po dodaniu warstw BatchNormalization (zobacz aktualizację) i usunięciu / włączeniu MaxNorm, dokładność jest nadal niska. Nie ma również miejsca żadna rozbudowa. Mam procesor graficzny i próbowałem trenować z 64 128 256 i 512 partiami, ale zauważono niewielką różnicę. Jeśli chodzi o szybkość uczenia się, korzystam z optymalizatora Adama i pomyślałem, że mniej więcej powinno to pozostać w spokoju? Niemniej jednak próbowałem LR przy 0,05, 0,001, 0,0005 i zauważyłem, że domyślnie 0,001 wydaje się nadal najlepszy. Jakieś pomysły?
10.04.17

Jestem również w stanie dobrze się dopasować. Starałem się jak najlepiej skopiować architekturę w dokumentach, które wydają się być w stanie osiągnąć 80% ++ dokładność z MNIST10. Kiedy zostawiam trening modelowy na dłuższe epoki, wydaje się, że strata teraz wzrasta (ponad 20 epok).
10.04.17

Modyfikacja komentarza - po zmianach w modelu wykresy wskazują teraz, że znacznie przewyższa dane (w oparciu o rozbieżność błędu sprawdzania poprawności po ~ 15 epokach)
T3am5hark

W rzeczywistości kwestionuję użyteczność oferowanych tu porad, szczególnie dla nowych lekarzy. To wszystko, co możesz zrobić, jasne, ale dla osób, które są nowicjuszami w CNN i nie mają intuicji ani nie rozumieją, jak te rzeczy działają, jest o wiele za dużo pokręteł i dźwigni, aby je modyfikować bez żadnych nakazowych wskazówek innych niż próba ślepa i błąd, który raczej nie przyniesie pozytywnych rezultatów. Lepiej byłoby zacząć od prostszych architektur, które są w stanie uzyskać dobrą (nie najlepiej opublikowaną) wydajność przy minimalnym marszczeniu, a następnie zbadać możliwości poprawy. Moje dwa centy.
T3am5hark

Aby dalej opracowywać - nie baw się stawkami nauki, użyj Adama. Pokonuje ręczne dostosowywanie wskaźników uczenia się przez 99,99% czasu. Ponadto - stwierdzenie, że „jest mało prawdopodobne, że kiedykolwiek się dopasujesz” jest po prostu błędne (na co wskazują kolejne grafiki, które teraz wykazują znaczące przeinaczenie) i nie ma żadnego powodu, aby plakat zakładał, że ... nic nie mówi a priori dla danej architektury, czy dany współczynnik rezygnacji będzie wystarczająco regulowany, aby zapobiec nadmiernemu dopasowaniu.
T3am5hark

1

Dałem temu dziś szansę i konsekwentnie byłem w stanie trafić blisko 75-80% dokładności testu.

Historia treningu

  • Łączna liczba użytych parametrów wyniosła: 183,242

  • Możesz zrobić to lepiej, dodając może kilka dodatkowych warstw, ale nie musisz być nadmierny. Bardziej złożone sieci nie zawsze dają lepsze wyniki.

Propozycje

Sugeruję ci, abyś utrzymywał prostą architekturę. Postępuj zgodnie z Razor Razor , proste jest lepsze.

  • Skaluj swoje dane

  • Nie używaj losowego ziarna

  • Użyj odpowiedniego optymalizatora; Użyłem Adadelty, tak jak pochodzi z Keras.

  • CNN nie muszą być zawiłe; nie komplikuj

  • Głębsze, chudsze sieci czasami działają lepiej niż szersze

  • Użyj regularyzacji (np. Dropout)

Poniżej znajduje się mój kod (za pomocą 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.