Batch Normalization-laget til Keras er ødelagt PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Batch Normalization-laget til Keras er ødelagt

OPPDATERING: Pull-Request til Keras som endret oppførselen til Batch Normalization-laget ble dessverre ikke akseptert. Du kan lese detaljene her.. For de av dere som er modige nok til å rote med tilpassede implementeringer, kan du finne koden i grenen min. Jeg kan vedlikeholde den og slå den sammen med den siste stabile versjonen av Keras (2.1.6, 2.2.2 og 2.2.4) så lenge jeg bruker det, men ingen løfter.

De fleste som jobber med dyp læring har enten brukt eller hørt om Keras. For de av dere som ikke har det, er det et flott bibliotek som trekker ut de underliggende Deep Learning-rammene som TensorFlow, Theano og CNTK og gir en API på høyt nivå for opplæring av ANN-er. Den er enkel å bruke, muliggjør rask prototyping og har et vennlig aktivt fellesskap. Jeg har brukt det tungt og bidratt til prosjektet med jevne mellomrom i ganske lang tid, og jeg vil absolutt anbefale det til alle som ønsker å jobbe med Deep Learning.

Selv om Keras gjorde livet mitt lettere, har jeg ganske mange ganger blitt bitt av den merkelige oppførselen til Batch Normalization-laget. Standardatferden har endret seg over tid, men det forårsaker fortsatt problemer for mange brukere, og som et resultat er det flere relaterte åpne problemer på Github. I dette blogginnlegget vil jeg prøve å bygge en sak for hvorfor Keras 'BatchNormalization-lag ikke spiller bra med Transfer Learning, jeg vil gi koden som løser problemet, og jeg vil gi eksempler med resultatene av patch.

På underavsnittene nedenfor gir jeg en introduksjon om hvordan Transfer Learning brukes i Deep Learning, hva er Batch Normalization-laget, hvordan learningining_phase fungerer og hvordan Keras endret BN-oppførselen over tid. Hvis du allerede vet disse, kan du trygt hoppe direkte til seksjon 2.

1.1 Å bruke Transfer Learning er avgjørende for Deep Learning

En av grunnene til at Deep Learning tidligere ble kritisert, er at det krever for mye data. Dette stemmer ikke alltid; det er flere teknikker for å takle denne begrensningen, hvorav en er Transfer Learning.

Anta at du jobber med et Computer Vision-program, og at du vil bygge en klassifisering som skiller katter fra hunder. Du trenger faktisk ikke millioner av katt- / hundebilder for å trene modellen. I stedet kan du bruke en forhåndstrent klassifisering og finjustere toppkonvolusjonene med mindre data. Tanken bak er at siden den pre-trente modellen passet på bilder, kan bunnkonvolusjonene gjenkjenne funksjoner som linjer, kanter og andre nyttige mønstre, noe som betyr at du kan bruke vektene enten som gode initialiseringsverdier eller delvis omskole nettverket med dataene dine. .
Batch Normalization-laget til Keras er ødelagt PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Keras kommer med flere forhåndstrente modeller og brukervennlige eksempler på hvordan du finjusterer modeller. Du kan lese mer på dokumentasjon.

1.2 Hva er Batch Normalization-laget?

Batch Normalization-laget ble introdusert i 2014 av Ioffe og Szegedy. Den adresserer det forsvinnende gradientproblemet ved å standardisere utdataene fra forrige lag, det øker opplæringen ved å redusere antall nødvendige iterasjoner og muliggjør opplæring av dypere nevrale nettverk. Å forklare nøyaktig hvordan det fungerer ligger utenfor omfanget av dette innlegget, men jeg oppfordrer deg sterkt til å lese originalpapir. En forenklet forklaring er at den omskalerer inngangen ved å trekke gjennomsnittet og dele det med standardavviket; det kan også lære å angre transformasjonen om nødvendig.
Batch Normalization-laget til Keras er ødelagt PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

1.3 Hva er læringsfasen i Keras?

Noen lag fungerer forskjellig under trening og inferensmodus. De mest bemerkelsesverdige eksemplene er Batch Normalization og Dropout-lagene. Når det gjelder BN, bruker vi under trening gjennomsnittet og variansen til minibatchet for å skalere inngangen. På den annen side bruker vi glidende gjennomsnitt og varians som ble estimert under trening under inferens.

Keras vet i hvilken modus å kjøre fordi den har en innebygd mekanisme som kalles læringsfase. Læringsfasen styrer om nettverket er i tog eller testmodus. Hvis det ikke er manuelt innstilt av brukeren, kjører nettverket under tilpasning () med learning_phase = 1 (togmodus). Mens vi produserer spådommer (for eksempel når vi kaller forutsi () og vurder () -metodene eller ved valideringstrinnet for tilpasningen (), kjører nettverket med learning_phase = 0 (testmodus). Selv om det ikke anbefales, kan brukeren også statisk endre læringsfasen til en bestemt verdi, men dette må skje før noen modell eller tensor legges til i grafen. Hvis læringsfasen er angitt statisk, blir Keras låst i hvilken modus brukeren valgte.

1.4 Hvordan implementerte Keras Batch Normalization over tid?

Keras har endret oppførselen til Batch Normalization flere ganger, men den siste viktige oppdateringen skjedde i Keras 2.1.3. Før v2.1.3 da BN-laget var frossent (trenbart = usant), fortsatte det å oppdatere batchstatistikken, noe som forårsaket episk hodepine for brukerne.

Dette var ikke bare en merkelig policy, den var faktisk feil. Tenk deg at det eksisterer et BN-lag mellom viklingene; hvis laget er frossent, skal det ikke skje noen endringer. Hvis vi delvis oppdaterer vektene, og de neste lagene også er frossen, vil de aldri få sjansen til å tilpasse seg oppdateringene av minibatchstatistikken, noe som fører til høyere feil. Heldigvis starter fra versjon 2.1.3, når et BN-lag er frosset, oppdaterer det ikke lenger statistikken. Men er det nok? Ikke hvis du bruker Transfer Learning.

Nedenfor beskriver jeg nøyaktig hva som er problemet, og jeg skisserer den tekniske implementeringen for å løse det. Jeg gir også noen eksempler for å vise effekten på modellens nøyaktighet før og etter patch blir brukt.

2.1 Teknisk beskrivelse av problemet

Problemet med den nåværende implementeringen av Keras er at når et BN-lag fryses, fortsetter det å bruke minibatchstatistikken under trening. Jeg tror at en bedre tilnærming når BN er frossen er å bruke det bevegelige gjennomsnittet og variansen det lærte under trening. Hvorfor? Av samme grunner til at mini-batch-statistikken ikke skal oppdateres når laget er frossent: det kan føre til dårlige resultater fordi de neste lagene ikke blir trent riktig.

Anta at du bygger en datamaskinvisjonsmodell, men at du ikke har nok data, så du bestemmer deg for å bruke en av de forhåndstrente CNN-ene til Keras og finjustere den. Dessverre får du ingen garantier for at gjennomsnittet og variansen til det nye datasettet ditt i BN-lagene vil være lik de i det opprinnelige datasettet. Husk at nettverket ditt for øyeblikket alltid vil bruke minibatchstatistikken under trening, enten BN-laget er frossent eller ikke; også under inferens vil du bruke den tidligere innlærte statistikken for de frosne BN-lagene. Som et resultat, hvis du finjusterer topplagene, vil vektene deres bli justert til gjennomsnittet / variansen til nytt datasett. Likevel vil de under inferens motta data som er skalert annerledes fordi gjennomsnittet / variansen til original datasettet vil bli brukt.
Batch Normalization-laget til Keras er ødelagt PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Ovenfor gir jeg en forenklet (og urealistisk) arkitektur for demonstrasjonsformål. La oss anta at vi finjusterer modellen fra Convolution k + 1 opp til toppen av nettverket (høyre side), og vi holder frossen bunnen (venstre side). Under trening vil alle BN-lag fra 1 til k bruke gjennomsnittet / variansen til treningsdataene dine. Dette vil ha negative effekter på de frosne reLUene hvis gjennomsnittet og variansen for hver BN ikke er nær de som ble lært under trening. Det vil også føre til at resten av nettverket (fra CONV k + 1 og senere) blir trent med innganger som har forskjellige skalaer sammenlignet med hva som vil mottas under inferens. Under trening kan nettverket tilpasse seg disse endringene, men i det øyeblikket du bytter til prediksjonsmodus, vil Keras bruke annen standardiseringsstatistikk, noe som vil raskt distribuere inngangen til de neste lagene, noe som fører til dårlige resultater.

2.2 Hvordan kan du oppdage om du er berørt?

En måte å oppdage det på er å sette læringsfasen til Keras statisk til 1 (togmodus) og til 0 (testmodus) og evaluere modellen din i hvert tilfelle. Hvis det er betydelig forskjell i nøyaktighet på samme datasett, blir du påvirket av problemet. Det er verdt å påpeke at på grunn av måten learning_phase-mekanismen er implementert i Keras, anbefales det vanligvis ikke å rote med den. Endringer i læringsfasen vil ikke ha noen innvirkning på modeller som allerede er samlet og brukt; Som du kan se på eksemplene på de neste underavsnittene, er den beste måten å gjøre dette på å starte med en ren økt og endre læringsfasen før noen tensor er definert i grafen.

En annen måte å oppdage problemet mens du arbeider med binære klassifikatorer, er å kontrollere nøyaktigheten og AUC. Hvis nøyaktigheten er nær 50%, men AUC er nær 1 (og du også observerer forskjeller mellom tog / testmodus på samme datasett), kan det være at sannsynlighetene er utenfor skalaen på grunn av BN-statistikken. På samme måte kan du for regresjon bruke MSE og Spearmans korrelasjon for å oppdage det.

2.3 Hvordan kan vi fikse det?

Jeg tror at problemet kan løses hvis de frosne BN-lagene faktisk bare er det: permanent låst i testmodus. Implementeringsmessig må det opplærbare flagget være en del av beregningsgrafen, og oppførselen til BN må ikke bare avhenge av læringsfasen, men også av verdien av den opplærbare eiendommen. Du finner detaljene i implementeringen min på Github.

Ved å bruke den ovennevnte løsningen, når et BN-lag er frosset, vil det ikke lenger bruke minibatchstatistikken, men i stedet bruke de som er lært under trening. Som et resultat vil det ikke være noen avvik mellom trening og testmodus som fører til økt nøyaktighet. Åpenbart når BN-laget ikke er frossent, vil det fortsette å bruke minibatchstatistikken under trening.

2.4 Vurdering av effekten av lappen

Selv om jeg nylig skrev den ovennevnte implementeringen, blir ideen bak den testet tungt på virkelige problemer ved hjelp av forskjellige løsninger som har samme effekt. For eksempel kan avviket mellom opplærings- og testmodus unngås ved å dele nettverket i to deler (frossent og ufrosset) og utføre hurtigbufret opplæring (sende data gjennom den frosne modellen en gang og deretter bruke dem til å trene det ufrosne nettverket). Likevel, fordi "stol på meg at jeg har gjort dette før" vanligvis ikke har noen vekt, nedenfor gir jeg noen eksempler som viser effekten av den nye implementeringen i praksis.

Her er noen viktige punkter om eksperimentet:

  1. Jeg vil bruke en liten mengde data for å overfylte modellen med vilje, og jeg vil trene og validere modellen på samme datasett. Ved å gjøre dette forventer jeg nesten perfekt nøyaktighet og identisk ytelse på toget / valideringsdatasettet.
  2. Hvis jeg under validering får betydelig lavere nøyaktighet på samme datasett, vil jeg ha en klar indikasjon på at gjeldende BN-policy påvirker ytelsen til modellen negativt under inferens.
  3. Forbehandling vil foregå utenfor generatorene. Dette gjøres for å omgå en feil som ble introdusert i v2.1.5 (foreløpig løst på kommende v2.1.6 og siste master).
  4. Vi vil tvinge Keras til å bruke forskjellige læringsfaser under evaluering. Hvis vi ser forskjeller mellom rapportert nøyaktighet, vil vi vite at vi blir påvirket av gjeldende BN-policy.

Koden for eksperimentet er vist nedenfor:

import numpy as np
from keras.datasets import cifar10
from scipy.misc import imresize

from keras.preprocessing.image import ImageDataGenerator
from keras.applications.resnet50 import ResNet50, preprocess_input
from keras.models import Model, load_model
from keras.layers import Dense, Flatten
from keras import backend as K


seed = 42
epochs = 10
records_per_class = 100

# We take only 2 classes from CIFAR10 and a very small sample to intentionally overfit the model.
# We will also use the same data for train/test and expect that Keras will give the same accuracy.
(x, y), _ = cifar10.load_data()

def filter_resize(category):
   # We do the preprocessing here instead in the Generator to get around a bug on Keras 2.1.5.
   return [preprocess_input(imresize(img, (224,224)).astype('float')) for img in x[y.flatten()==category][:records_per_class]]

x = np.stack(filter_resize(3)+filter_resize(5))
records_per_class = x.shape[0] // 2
y = np.array([[1,0]]*records_per_class + [[0,1]]*records_per_class)


# We will use a pre-trained model and finetune the top layers.
np.random.seed(seed)
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
l = Flatten()(base_model.output)
predictions = Dense(2, activation='softmax')(l)
model = Model(inputs=base_model.input, outputs=predictions)

for layer in model.layers[:140]:
   layer.trainable = False

for layer in model.layers[140:]:
   layer.trainable = True

model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(ImageDataGenerator().flow(x, y, seed=42), epochs=epochs, validation_data=ImageDataGenerator().flow(x, y, seed=42))

# Store the model on disk
model.save('tmp.h5')


# In every test we will clear the session and reload the model to force Learning_Phase values to change.
print('DYNAMIC LEARNING_PHASE')
K.clear_session()
model = load_model('tmp.h5')
# This accuracy should match exactly the one of the validation set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 0')
K.clear_session()
K.set_learning_phase(0)
model = load_model('tmp.h5')
# Again the accuracy should match the above.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 1')
K.clear_session()
K.set_learning_phase(1)
model = load_model('tmp.h5')
# The accuracy will be close to the one of the training set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))

La oss sjekke resultatene på Keras v2.1.5:

Epoch 1/10
1/7 [===>..........................] - ETA: 25s - loss: 0.8751 - acc: 0.5312
2/7 [=======>......................] - ETA: 11s - loss: 0.8594 - acc: 0.4531
3/7 [===========>..................] - ETA: 7s - loss: 0.8398 - acc: 0.4688 
4/7 [================>.............] - ETA: 4s - loss: 0.8467 - acc: 0.4844
5/7 [====================>.........] - ETA: 2s - loss: 0.7904 - acc: 0.5437
6/7 [========================>.....] - ETA: 1s - loss: 0.7593 - acc: 0.5625
7/7 [==============================] - 12s 2s/step - loss: 0.7536 - acc: 0.5744 - val_loss: 0.6526 - val_acc: 0.6650

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.3881 - acc: 0.8125
2/7 [=======>......................] - ETA: 3s - loss: 0.3945 - acc: 0.7812
3/7 [===========>..................] - ETA: 2s - loss: 0.3956 - acc: 0.8229
4/7 [================>.............] - ETA: 1s - loss: 0.4223 - acc: 0.8047
5/7 [====================>.........] - ETA: 1s - loss: 0.4483 - acc: 0.7812
6/7 [========================>.....] - ETA: 0s - loss: 0.4325 - acc: 0.7917
7/7 [==============================] - 8s 1s/step - loss: 0.4095 - acc: 0.8089 - val_loss: 0.4722 - val_acc: 0.7700

Epoch 3/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2246 - acc: 0.9375
2/7 [=======>......................] - ETA: 3s - loss: 0.2167 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.2260 - acc: 0.9479
4/7 [================>.............] - ETA: 2s - loss: 0.2179 - acc: 0.9375
5/7 [====================>.........] - ETA: 1s - loss: 0.2356 - acc: 0.9313
6/7 [========================>.....] - ETA: 0s - loss: 0.2392 - acc: 0.9427
7/7 [==============================] - 8s 1s/step - loss: 0.2288 - acc: 0.9456 - val_loss: 0.4282 - val_acc: 0.7800

Epoch 4/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2183 - acc: 0.9688
2/7 [=======>......................] - ETA: 3s - loss: 0.1899 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1887 - acc: 0.9792
4/7 [================>.............] - ETA: 1s - loss: 0.1995 - acc: 0.9531
5/7 [====================>.........] - ETA: 1s - loss: 0.1932 - acc: 0.9625
6/7 [========================>.....] - ETA: 0s - loss: 0.1819 - acc: 0.9688
7/7 [==============================] - 8s 1s/step - loss: 0.1743 - acc: 0.9747 - val_loss: 0.3778 - val_acc: 0.8400

Epoch 5/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0973 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0828 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0851 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0897 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0928 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0936 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.1337 - acc: 0.9838 - val_loss: 0.3916 - val_acc: 0.8100

Epoch 6/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0747 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0852 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0812 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0831 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0779 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0766 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0813 - acc: 1.0000 - val_loss: 0.3637 - val_acc: 0.8550

Epoch 7/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2478 - acc: 0.8750
2/7 [=======>......................] - ETA: 2s - loss: 0.1966 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.1528 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.1300 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.1193 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.1196 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.1084 - acc: 0.9838 - val_loss: 0.3546 - val_acc: 0.8600

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0539 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0900 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0815 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0740 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0700 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0701 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0695 - acc: 1.0000 - val_loss: 0.3269 - val_acc: 0.8600

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0306 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0377 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0898 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.0773 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0742 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0708 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0659 - acc: 0.9838 - val_loss: 0.3604 - val_acc: 0.8600

Epoch 10/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0354 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0381 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0354 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0828 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0791 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0794 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0704 - acc: 0.9838 - val_loss: 0.3615 - val_acc: 0.8600

DYNAMIC LEARNING_PHASE
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 0
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 1
[0.025861846953630446, 1.0]

Som vi kan se ovenfor, lærer modellen under trening veldig godt dataene og oppnår på treningssettet nesten perfekt nøyaktighet. Fortsatt på slutten av hver iterasjon, mens vi vurderer modellen på samme datasett, får vi betydelige forskjeller i tap og nøyaktighet. Merk at vi ikke skal få dette; vi har forsettlig overmontert modellen på det spesifikke datasettet, og opplærings- / valideringsdatasettene er identiske.

Etter at opplæringen er fullført, vurderer vi modellen ved hjelp av 3 forskjellige læringsfasekonfigurasjoner: Dynamisk, Static = 0 (testmodus) og Static = 1 (treningsmodus). Som vi kan se vil de to første konfigurasjonene gi identiske resultater når det gjelder tap og nøyaktighet, og verdien deres samsvarer med rapportert nøyaktighet av modellen på valideringssettet i den siste iterasjonen. Når vi bytter til treningsmodus, observerer vi likevel et massivt avvik (forbedring). Hvorfor det? Som vi sa tidligere, er vektene i nettverket innstilt og forventer å motta data skalert med gjennomsnittet / variansen til treningsdataene. Dessverre er denne statistikken forskjellig fra den som er lagret i BN-lagene. Siden BN-lagene var frosset, ble denne statistikken aldri oppdatert. Dette avviket mellom BNI-statistikkens verdier fører til forverring av nøyaktigheten under inferens.

La oss se hva som skjer når vi bruker patch:

Epoch 1/10
1/7 [===>..........................] - ETA: 26s - loss: 0.9992 - acc: 0.4375
2/7 [=======>......................] - ETA: 12s - loss: 1.0534 - acc: 0.4375
3/7 [===========>..................] - ETA: 7s - loss: 1.0592 - acc: 0.4479 
4/7 [================>.............] - ETA: 4s - loss: 0.9618 - acc: 0.5000
5/7 [====================>.........] - ETA: 2s - loss: 0.8933 - acc: 0.5250
6/7 [========================>.....] - ETA: 1s - loss: 0.8638 - acc: 0.5417
7/7 [==============================] - 13s 2s/step - loss: 0.8357 - acc: 0.5570 - val_loss: 0.2414 - val_acc: 0.9450

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2331 - acc: 0.9688
2/7 [=======>......................] - ETA: 2s - loss: 0.3308 - acc: 0.8594
3/7 [===========>..................] - ETA: 2s - loss: 0.3986 - acc: 0.8125
4/7 [================>.............] - ETA: 1s - loss: 0.3721 - acc: 0.8281
5/7 [====================>.........] - ETA: 1s - loss: 0.3449 - acc: 0.8438
6/7 [========================>.....] - ETA: 0s - loss: 0.3168 - acc: 0.8646
7/7 [==============================] - 9s 1s/step - loss: 0.3165 - acc: 0.8633 - val_loss: 0.1167 - val_acc: 0.9950

Epoch 3/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2457 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.2592 - acc: 0.9688
3/7 [===========>..................] - ETA: 2s - loss: 0.2173 - acc: 0.9688
4/7 [================>.............] - ETA: 1s - loss: 0.2122 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.2003 - acc: 0.9688
6/7 [========================>.....] - ETA: 0s - loss: 0.1896 - acc: 0.9740
7/7 [==============================] - 9s 1s/step - loss: 0.1835 - acc: 0.9773 - val_loss: 0.0678 - val_acc: 1.0000

Epoch 4/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2051 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1652 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1423 - acc: 0.9896
4/7 [================>.............] - ETA: 1s - loss: 0.1289 - acc: 0.9922
5/7 [====================>.........] - ETA: 1s - loss: 0.1225 - acc: 0.9938
6/7 [========================>.....] - ETA: 0s - loss: 0.1149 - acc: 0.9948
7/7 [==============================] - 9s 1s/step - loss: 0.1060 - acc: 0.9955 - val_loss: 0.0455 - val_acc: 1.0000

Epoch 5/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0769 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0846 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0797 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0736 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0914 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0858 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0808 - acc: 1.0000 - val_loss: 0.0346 - val_acc: 1.0000

Epoch 6/10
1/7 [===>..........................] - ETA: 1s - loss: 0.1267 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1039 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0893 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0780 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0758 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0789 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0738 - acc: 1.0000 - val_loss: 0.0248 - val_acc: 1.0000

Epoch 7/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0344 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0385 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0467 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0445 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0446 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0429 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0421 - acc: 1.0000 - val_loss: 0.0202 - val_acc: 1.0000

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0319 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0300 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0320 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0307 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0303 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0291 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0358 - acc: 1.0000 - val_loss: 0.0167 - val_acc: 1.0000

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0246 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0255 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0258 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0250 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0252 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0260 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0327 - acc: 1.0000 - val_loss: 0.0143 - val_acc: 1.0000

Epoch 10/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0251 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0228 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0217 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0249 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0244 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0239 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0290 - acc: 1.0000 - val_loss: 0.0127 - val_acc: 1.0000

DYNAMIC LEARNING_PHASE
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 0
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 1
[0.01744014158844948, 1.0]

Først og fremst observerer vi at nettverket konvergerer betydelig raskere og oppnår perfekt nøyaktighet. Vi ser også at det ikke lenger er avvik når det gjelder nøyaktighet når vi bytter mellom forskjellige læringsfaseverdier.

2.5 Hvordan fungerer oppdateringen på et ekte datasett?

Så hvordan fungerer plasteret på et mer realistisk eksperiment? La oss bruke Keras 'forhåndstrente ResNet50 (opprinnelig plassert på imagenet), fjerne det øverste klassifiseringslaget og finjustere det med og uten plasteret og sammenligne resultatene. For data, vil vi bruke CIFAR10 (standard tog / test split gitt av Keras), og vi vil endre størrelsen på bildene til 224 × 224 for å gjøre dem kompatible med ResNet50s inngangsstørrelse.

Vi vil gjøre 10 epoker for å trene det øverste klassifiseringslaget ved hjelp av RSMprop, og deretter vil vi gjøre ytterligere 5 for å finjustere alt etter det 139. laget ved hjelp av SGD (lr = 1e-4, momentum = 0.9). Uten lappen oppnår modellen vår en nøyaktighet på 87.44%. Ved hjelp av lappen får vi en nøyaktighet på 92.36%, nesten 5 poeng høyere.

2.6 Bør vi bruke den samme løsningen på andre lag som Dropout?

Batch Normalization er ikke det eneste laget som fungerer forskjellig mellom tog- og testmodus. Frafall og dets varianter har også samme effekt. Bør vi bruke samme policy på alle disse lagene? Jeg tror ikke (selv om jeg gjerne vil høre tankene dine om dette). Årsaken er at Dropout brukes til å unngå overmontering, og dermed vil det låse det permanent i prediksjonsmodus under trening. Hva tror du?

Jeg tror sterkt at dette avviket må løses i Keras. Jeg har sett enda dypere effekter (fra 100% ned til 50% nøyaktighet) i virkelige applikasjoner forårsaket av dette problemet. Jeg planlegger å sende allerede sendt en PR til Keras med løsningen og forhåpentligvis blir den akseptert.

Hvis du likte dette blogginnlegget, vennligst bruk et øyeblikk til å dele det på Facebook eller Twitter. 🙂

Tidstempel:

Mer fra Datoboks