Batch-normaliseringslaget i Keras er ødelagt PlatoBlockchain Data Intelligence. Lodret søgning. Ai.

Batch-normaliseringslaget i Keras er brudt

OPDATERING: Desværre blev min Pull-Request til Keras, der ændrede adfærden for Batch Normalization-laget, ikke accepteret. Du kan læse detaljerne link.. For dem af jer, der er modige nok til at rode med tilpassede implementeringer, kan du finde koden i min gren. Jeg kan vedligeholde den og flette den sammen med den seneste stabile version af Keras (2.1.6, 2.2.2 , 2.2.4) så længe jeg bruger det, men ingen løfter.

De fleste mennesker, der arbejder i Deep Learning, har enten brugt eller hørt om Keras. For dem af jer, der ikke har, er det et fantastisk bibliotek, der abstraherer de underliggende Deep Learning-rammer såsom TensorFlow, Theano og CNTK og giver en API på højt niveau til træning af ANN'er. Den er nem at bruge, muliggør hurtig prototyping og har et venligt aktivt fællesskab. Jeg har brugt det flittigt og bidraget til projektet med jævne mellemrum i temmelig lang tid, og jeg anbefaler det bestemt til alle, der ønsker at arbejde med Deep Learning.

Selvom Keras gjorde mit liv lettere, er jeg mange gange blevet bidt af batchnormaliseringslagets mærkelige opførsel. Dens standardadfærd har ændret sig over tid, ikke desto mindre forårsager den stadig problemer for mange brugere, og som følge heraf er der flere relaterede åbne spørgsmål på Github. I dette blogindlæg vil jeg forsøge at bygge en sag for, hvorfor Keras' BatchNormalization-lag ikke spiller godt med Transfer Learning, jeg vil give koden, der løser problemet, og jeg vil give eksempler med resultaterne af patch.

På underafsnittene nedenfor giver jeg en introduktion til, hvordan Transfer Learning bruges i Deep Learning, hvad er Batch Normalization-laget, hvordan learning_phase fungerer, og hvordan Keras ændrede BN-adfærden over tid. Hvis du allerede kender disse, kan du roligt hoppe direkte til sektion 2.

1.1 Brug af Transfer Learning er afgørende for Deep Learning

En af grundene til, at Deep Learning tidligere blev kritiseret, er, at det kræver for meget data. Dette er ikke altid sandt; der er flere teknikker til at imødegå denne begrænsning, hvoraf en er Transfer Learning.

Antag, at du arbejder på et Computer Vision-program, og du vil bygge en klassificering, der adskiller katte fra hunde. Du behøver faktisk ikke millioner af katte-/hundebilleder for at træne modellen. I stedet kan du bruge en forudtrænet klassificering og finjustere de øverste foldninger med færre data. Ideen bag det er, at siden den fortrænede model var egnet til billeder, kan bundviklingerne genkende funktioner som linjer, kanter og andre nyttige mønstre, hvilket betyder, at du kan bruge dens vægte enten som gode initialiseringsværdier eller delvist genoptræne netværket med dine data .
Batch-normaliseringslaget i Keras er ødelagt PlatoBlockchain Data Intelligence. Lodret søgning. Ai.
Keras kommer med flere fortrænede modeller og brugervenlige eksempler på, hvordan man finjusterer modeller. Du kan læse mere på dokumentation.

1.2 Hvad er batchnormaliseringslaget?

Batch-normaliseringslaget blev introduceret i 2014 af Ioffe og Szegedy. Det løser problemet med forsvindende gradient ved at standardisere outputtet fra det forrige lag, det fremskynder træningen ved at reducere antallet af nødvendige iterationer, og det muliggør træning af dybere neurale netværk. At forklare præcis, hvordan det virker, ligger uden for dette indlægs rammer, men jeg opfordrer dig kraftigt til at læse originalt papir. En oversimplificeret forklaring er, at den omskalerer inputtet ved at trække dets middelværdi fra og ved at dividere med dets standardafvigelse; den kan også lære at fortryde transformationen, hvis det er nødvendigt.
Batch-normaliseringslaget i Keras er ødelagt PlatoBlockchain Data Intelligence. Lodret søgning. Ai.

1.3 Hvad er læringsfasen i Keras?

Nogle lag fungerer anderledes under trænings- og inferenstilstand. De mest bemærkelsesværdige eksempler er Batch Normalization og Dropout-lagene. I tilfælde af BN bruger vi under træning middelværdien og variansen af ​​minibatchen til at omskalere inputtet. På den anden side bruger vi under inferens det glidende gennemsnit og varians, der blev estimeret under træning.

Keras ved i hvilken tilstand den skal køre, fordi den har en indbygget mekanisme kaldet læringsfase. Indlæringsfasen styrer, om netværket er i tog- eller testtilstand. Hvis det ikke er manuelt indstillet af brugeren, kører netværket under fit() med learning_phase=1 (togtilstand). Mens vi producerer forudsigelser (for eksempel når vi kalder predict() & evaluate() metoderne eller ved valideringstrinnet af fit()), kører netværket med learning_phase=0 (testtilstand). Selvom det ikke anbefales, er brugeren også i stand til statisk at ændre learning_phase til en specifik værdi, men dette skal ske, før nogen model eller tensor tilføjes i grafen. Hvis indlæringsfasen er indstillet statisk, vil Keras være låst til den tilstand, som brugeren har valgt.

1.4 Hvordan implementerede Keras batchnormalisering over tid?

Keras har ændret adfærden for Batch Normalization flere gange, men den seneste væsentlige opdatering skete i Keras 2.1.3. Før v2.1.3, da BN-laget blev frosset (trænes = Falsk), blev det ved med at opdatere sine batch-statistikker, noget der forårsagede episk hovedpine for dets brugere.

Dette var ikke bare en mærkelig politik, det var faktisk forkert. Forestil dig, at der eksisterer et BN-lag mellem viklinger; hvis laget er frosset skal der ikke ske ændringer i det. Hvis vi opdaterer dens vægte delvist, og de næste lag også fryses, vil de aldrig få chancen for at tilpasse sig opdateringerne af mini-batch-statistikken, hvilket fører til højere fejl. Heldigvis starter fra version 2.1.3, når et BN-lag er frosset, opdaterer det ikke længere sine statistikker. Men er det nok? Ikke hvis du bruger Transfer Learning.

Nedenfor beskriver jeg præcist, hvad problemet er, og jeg skitserer den tekniske implementering for at løse det. Jeg giver også et par eksempler for at vise effekterne på modellens nøjagtighed før og efter patch anvendes.

2.1 Teknisk beskrivelse af problemet

Problemet med den nuværende implementering af Keras er, at når et BN-lag er frosset, fortsætter det med at bruge mini-batch-statistikken under træning. Jeg tror, ​​at en bedre tilgang, når BN er frosset, er at bruge den bevægelige middelværdi og varians, som den lærte under træningen. Hvorfor? Af samme grunde, hvorfor mini-batch-statistikken ikke bør opdateres, når laget er frosset: det kan føre til dårlige resultater, fordi de næste lag ikke trænes ordentligt.

Antag, at du bygger en Computer Vision-model, men at du ikke har nok data, så du beslutter dig for at bruge en af ​​de forudtrænede CNN'er fra Keras og finjustere den. Desværre får du ved at gøre det ingen garantier for, at middelværdien og variansen af ​​dit nye datasæt inde i BN-lagene vil ligne dem i det originale datasæt. Husk, at dit netværk i øjeblikket under træning altid vil bruge mini-batch-statistikken, enten er BN-laget frosset eller ej; også under inferens vil du bruge den tidligere lærte statistik over de frosne BN-lag. Som et resultat, hvis du finjusterer de øverste lag, vil deres vægt blive justeret til middelværdien/variansen af ny datasæt. Ikke desto mindre vil de under inferens modtage data, som er skaleret forskelligt fordi middelværdien/variansen af original datasæt vil blive brugt.
Batch-normaliseringslaget i Keras er ødelagt PlatoBlockchain Data Intelligence. Lodret søgning. Ai.
Ovenfor giver jeg en forenklet (og urealistisk) arkitektur til demonstrationsformål. Lad os antage, at vi finjusterer modellen fra Convolution k+1 op til toppen af ​​netværket (højre side), og vi holder frosset bunden (venstre side). Under træning vil alle BN-lag fra 1 til k bruge middelværdien/variansen af ​​dine træningsdata. Dette vil have negative virkninger på de frosne ReLU'er, hvis gennemsnittet og variansen på hver BN ikke er tæt på dem, der er lært under fortræning. Det vil også få resten af ​​netværket (fra CONV k+1 og senere) til at blive trænet med input, der har forskellige skalaer sammenlignet med, hvad der vil modtage under inferens. Under træning kan dit netværk tilpasse sig disse ændringer, ikke desto mindre i det øjeblik du skifter til forudsigelsestilstand, vil Keras bruge forskellige standardiseringsstatistikker, noget der vil fremskynde distributionen af ​​input fra de næste lag, hvilket fører til dårlige resultater.

2.2 Hvordan kan du opdage, om du er ramt?

En måde at detektere det på er at indstille indlæringsfasen for Keras statisk til 1 (togtilstand) og til 0 (testtilstand) og evaluere din model i hvert enkelt tilfælde. Hvis der er væsentlig forskel i nøjagtigheden på det samme datasæt, er du berørt af problemet. Det er værd at påpege, at på grund af den måde, learning_phase-mekanismen er implementeret i Keras, er det typisk ikke tilrådeligt at rode med den. Ændringer i læringsfasen vil ikke have nogen effekt på modeller, der allerede er kompileret og brugt; som du kan se i eksemplerne i de næste underafsnit, er den bedste måde at gøre dette på at starte med en ren session og ændre læringsfasen, før en tensor defineres i grafen.

En anden måde at opdage problemet på, mens du arbejder med binære klassifikatorer, er at kontrollere nøjagtigheden og AUC. Hvis nøjagtigheden er tæt på 50%, men AUC er tæt på 1 (og også du observerer forskelle mellem tog-/testtilstand på det samme datasæt), kan det være, at sandsynligheden er ude af skala på grund af BN-statistikken. Tilsvarende kan du til regression bruge MSE og Spearmans korrelation til at detektere det.

2.3 Hvordan kan vi rette det?

Jeg tror på, at problemet kan løses, hvis de frosne BN-lag faktisk netop er det: permanent låst i testtilstand. Implementeringsmæssigt skal flaget, der kan trænes, være en del af beregningsgrafen, og opførselen af ​​BN skal ikke kun afhænge af indlæringsfasen, men også af værdien af ​​den oplærbare egenskab. Du kan finde detaljerne om min implementering på Github.

Ved at anvende ovenstående rettelse vil det, når et BN-lag er frosset, ikke længere bruge mini-batch-statistikkerne, men i stedet bruge dem, der er lært under træningen. Som et resultat vil der ikke være nogen uoverensstemmelse mellem trænings- og testtilstande, hvilket fører til øget nøjagtighed. Når BN-laget ikke er frosset, vil det naturligvis fortsætte med at bruge mini-batch-statistikken under træning.

2.4 Vurdering af plastrets effekt

Selvom jeg skrev ovenstående implementering for nylig, er ideen bag den stærkt testet på problemer i den virkelige verden ved hjælp af forskellige løsninger, der har samme effekt. For eksempel kan uoverensstemmelsen mellem trænings- og testtilstande og undgås ved at opdele netværket i to dele (frosset og ufrosset) og udføre cache-træning (passere data gennem den frosne model én gang og derefter bruge dem til at træne det ufrosne netværk). Ikke desto mindre, fordi "tro mig, jeg har gjort det her før" typisk ikke har nogen vægt, giver jeg nedenfor et par eksempler, der viser virkningerne af den nye implementering i praksis.

Her er et par vigtige punkter om eksperimentet:

  1. Jeg vil bruge en lille mængde data til bevidst at overpasse modellen, og jeg vil træne og validere modellen på det samme datasæt. Ved at gøre det forventer jeg næsten perfekt nøjagtighed og identisk ydeevne på tog-/valideringsdatasættet.
  2. Hvis jeg under valideringen får væsentlig lavere nøjagtighed på det samme datasæt, vil jeg have en klar indikation af, at den nuværende BN-politik påvirker modellens ydeevne negativt under inferens.
  3. Enhver forbehandling vil finde sted uden for Generatorer. Dette er gjort for at omgå en fejl, der blev introduceret i v2.1.5 (i øjeblikket rettet på kommende v2.1.6 og seneste master).
  4. Vi vil tvinge Keras til at bruge forskellige læringsfaser under evaluering. Hvis vi opdager forskelle mellem den rapporterede nøjagtighed, vil vi vide, at vi er påvirket af den nuværende BN-politik.

Koden til 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)))

Lad os tjekke resultaterne 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 træning meget godt dataene og opnår på træningssættet næsten perfekt nøjagtighed. Stadig i slutningen af ​​hver iteration, mens vi evaluerer modellen på det samme datasæt, får vi betydelige forskelle i tab og nøjagtighed. Bemærk, at vi ikke burde få dette; vi har med vilje overfittet modellen på det specifikke datasæt, og trænings-/valideringsdatasættene er identiske.

Efter træningen er afsluttet, evaluerer vi modellen ved hjælp af 3 forskellige learning_phase-konfigurationer: Dynamisk, Statisk = 0 (testtilstand) og Statisk = 1 (træningstilstand). Som vi kan se, vil de første to konfigurationer give identiske resultater med hensyn til tab og nøjagtighed, og deres værdi matcher den rapporterede nøjagtighed af modellen på valideringssættet i den sidste iteration. Ikke desto mindre, når vi skifter til træningstilstand, observerer vi en massiv uoverensstemmelse (forbedring). Hvorfor er det det? Som vi sagde tidligere, er netværkets vægte indstillet i forventning om at modtage data skaleret med middelværdien/variansen af ​​træningsdataene. Desværre er disse statistikker anderledes end dem, der er gemt i BN-lagene. Da BN-lagene var frosset, blev disse statistikker aldrig opdateret. Denne uoverensstemmelse mellem værdierne af BN-statistikken fører til forringelse af nøjagtigheden under inferens.

Lad os se, hvad der sker, når vi anvender 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 fremmest observerer vi, at netværket konvergerer betydeligt hurtigere og opnår perfekt nøjagtighed. Vi ser også, at der ikke længere er uoverensstemmelse med hensyn til nøjagtighed, når vi skifter mellem forskellige læringsfaseværdier.

2.5 Hvordan fungerer patchen på et rigtigt datasæt?

Så hvordan fungerer patchen på et mere realistisk eksperiment? Lad os bruge Keras' præ-trænede ResNet50 (oprindeligt passet på imagenet), fjerne det øverste klassifikationslag og finjustere det med og uden patchen og sammenligne resultaterne. Til data vil vi bruge CIFAR10 (standard tog/test-split leveret af Keras), og vi vil ændre størrelsen på billederne til 224×224 for at gøre dem kompatible med ResNet50's inputstørrelse.

Vi vil lave 10 epoker for at træne det øverste klassifikationslag ved hjælp af RSMprop, og derefter vil vi gøre yderligere 5 for at finjustere alt efter det 139. lag ved hjælp af SGD(lr=1e-4, momentum=0.9). Uden patchen opnår vores model en nøjagtighed på 87.44%. Ved at bruge patchen får vi en nøjagtighed på 92.36%, næsten 5 point højere.

2.6 Skal vi anvende den samme rettelse på andre lag, såsom Dropout?

Batchnormalisering er ikke det eneste lag, der fungerer forskelligt mellem tog- og testtilstande. Frafald og dets varianter har også samme effekt. Skal vi anvende den samme politik på alle disse lag? Jeg tror ikke (selvom jeg ville elske at høre dine tanker om dette). Årsagen er, at Dropout bruges til at undgå overfitting, og dermed låse den permanent til forudsigelsestilstand under træning, ville dets formål omgås. Hvad synes du?

Jeg er overbevist om, at denne uoverensstemmelse skal løses i Keras. Jeg har set endnu mere dybtgående effekter (fra 100 % ned til 50 % nøjagtighed) i virkelige applikationer forårsaget af dette problem. jeg planlægger at sende allerede sendt en PR til Keras med rettelsen, og forhåbentlig bliver den accepteret.

Hvis du kunne lide dette blogindlæg, så brug et øjeblik på at dele det på Facebook eller Twitter. 🙂

Tidsstempel:

Mere fra Datumboks