Batch Normalization-lagret i Keras är trasig PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Keras-normaliseringsskiktet i Keras är trasigt

UPDATE: Tyvärr accepterades inte min Pull-Request till Keras som ändrade beteendet hos Batch Normalization-lagret. Du kan läsa detaljerna här.. För dig som är modig nog att röra med anpassade implementationer kan du hitta koden i min gren. Jag kan behålla den och slå samman den med den senaste stabila versionen av Keras (2.1.6, 2.2.2 och 2.2.4) så länge jag använder det men inga löften.

De flesta som arbetar inom Deep Learning har antingen använt eller hört talas om Keras. För er som inte har det är det ett fantastiskt bibliotek som abstraherar de underliggande Deep Learning-ramarna som TensorFlow, Theano och CNTK och ger en API på hög nivå för utbildning av ANN. Den är lätt att använda, möjliggör snabb prototypning och har ett vänligt aktivt samhälle. Jag har använt det kraftigt och bidragit till projektet med jämna mellanrum en ganska lång tid och jag rekommenderar det definitivt till alla som vill arbeta med Deep Learning.

Trots att Keras underlättade mitt liv har jag gett många gånger bita av det udda beteendet hos Batch Normalization-lagret. Dess standardbeteende har förändrats över tid, ändå orsakar det fortfarande problem för många användare och som ett resultat finns det flera relaterade öppna frågor på Github. I det här blogginlägget kommer jag att försöka bygga ett fall för varför Keras 'BatchNormalization-lager inte spelar bra med Transfer Learning, jag ska tillhandahålla koden som löser problemet och jag kommer att ge exempel med resultaten från plåster.

I underavsnitten nedan ger jag en introduktion till hur Transfer Learning används i Deep Learning, vad är Batch Normalization-lagret, hur learningining_phase fungerar och hur Keras förändrade BN-beteende över tid. Om du redan vet dessa kan du säkert hoppa direkt till avsnitt 2.

1.1 Att använda Transfer Learning är avgörande för Deep Learning

En av anledningarna till att Deep Learning kritiserades tidigare är att det kräver för mycket data. Detta är inte alltid sant; Det finns flera tekniker för att hantera denna begränsning, varav en är Transfer Learning.

Antag att du arbetar med en datorvisionsapplikation och att du vill bygga en klassificering som skiljer katter från hundar. Du behöver faktiskt inte miljoner katt / hundbilder för att träna modellen. Istället kan du använda en förutbildad klassificerare och finjustera de översta vridningarna med mindre data. Tanken bakom det är att eftersom den förutbildade modellen passade på bilder kan bottenvolymerna känna igen funktioner som linjer, kanter och andra användbara mönster, vilket innebär att du kan använda vikterna antingen som bra initialiseringsvärden eller delvis omskolera nätverket med dina data .
Batch Normalization-lagret i Keras är trasig PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.
Keras kommer med flera förutbildade modeller och lättanvända exempel på hur man kan finjustera modeller. Du kan läsa mer om dokumentation.

1.2 Vad är Batch Normalization-lagret?

Batch Normalization-lagret introducerades 2014 av Ioffe och Szegedy. Den hanterar försvinnande gradientproblem genom att standardisera utgången från det föregående lagret, det påskyndar träningen genom att minska antalet nödvändiga iterationer och det möjliggör utbildning av djupare neurala nätverk. Att förklara exakt hur det fungerar ligger utanför detta inlägg, men jag uppmanar dig starkt att läsa originalpapper. En överförenklad förklaring är att den räknar om inmatningen genom att subtrahera dess medelvärde och genom att dela med sin standardavvikelse; det kan också lära sig att ångra omvandlingen vid behov.
Batch Normalization-lagret i Keras är trasig PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

1.3 Vad är inlärningsfasen i Keras?

Vissa lager fungerar annorlunda under träning och inferensläge. De mest anmärkningsvärda exemplen är Batch Normalization och Dropout-lagren. När det gäller BN använder vi under träningen medelvärdet och variansen för minipartiet för att omklassificera ingången. Å andra sidan, under inferensen använder vi det rörliga medelvärdet och variationen som uppskattades under träningen.

Keras vet i vilket läge som ska köras eftersom den har en inbyggd mekanism som heter inlärningsfas. Inlärningsfasen styr om nätverket är i tåg eller testläge. Om den inte ställs in manuellt av användaren, körs nätverket under learning () med learning_phase = 1 (tågläge). När vi producerar förutsägelser (till exempel när vi kallar metoderna förutsäga () och utvärdera () eller vid valideringssteget för passformen () körs nätverket med learning_phase = 0 (testläge). Även om det inte rekommenderas kan användaren också statiskt ändra inlärningsfasen till ett specifikt värde men detta måste ske innan någon modell eller tensor läggs till i diagrammet. Om inlärningsfasen är statiskt, kommer Keras att vara låst i vilket läge som användaren valt.

1.4 Hur implementerade Keras Batch Normalization över tid?

Keras har ändrat beteendet för Batch Normalization flera gånger men den senaste väsentliga uppdateringen hände i Keras 2.1.3. Före v2.1.3 när BN-lagret frystes (träningsbart = falskt) uppdaterade det sin batchstatistik, något som orsakade episk huvudvärk för sina användare.

Detta var inte bara en konstig politik, det var faktiskt fel. Föreställ dig att det finns ett BN-lager mellan invändningarna; Om lagret är fryst ska det inte hända några förändringar. Om vi ​​uppdaterar delvis vikterna och de nästa lagren fryses, kommer de aldrig att få chansen att anpassa sig till uppdateringarna av minisatsstatistiken vilket leder till högre fel. Tack och lov från version 2.1.3, när ett BN-lager fryses uppdaterar det inte längre sin statistik. Men räcker det? Inte om du använder Transfer Learning.

Nedan beskriver jag exakt vad som är problemet och jag skisserar det tekniska genomförandet för att lösa det. Jag ger också några exempel för att visa effekterna på modellens noggrannhet före och efter plåster tillämpas.

2.1 Teknisk beskrivning av problemet

Problemet med den nuvarande implementeringen av Keras är att när ett BN-lager fryses fortsätter det att använda minisatsstatistiken under träning. Jag tror att en bättre metod när BN är fryst är att använda det rörliga medelvärdet och variansen som den lärde sig under träningen. Varför? Av samma skäl varför minibatchstatistiken inte ska uppdateras när lagret är fryst: det kan leda till dåliga resultat eftersom nästa lager inte tränas ordentligt.

Antag att du bygger en datorvisionsmodell men du har inte tillräckligt med data, så du bestämmer dig för att använda en av de förutbildade CNN: erna för Keras och finjustera den. Genom att göra det får du tyvärr inga garantier för att medelvärdet och variansen för ditt nya datasätt i BN-lagren kommer att likna dem i det ursprungliga datasättet. Kom ihåg att för närvarande, under träningen, kommer ditt nätverk alltid att använda minisatsstatistiken antingen är BN-lagret fryst eller inte; även under inferensen kommer du att använda den tidigare lärda statistiken över de frysta BN-lagren. Som ett resultat, om du finjusterar topplagren, kommer deras vikter att justeras till medelvärdet / variansen för ny dataset. I slutändan kommer de dock att få data som skalas annorlunda eftersom medelvärdet / variansen för ursprungliga dataset kommer att användas.
Batch Normalization-lagret i Keras är trasig PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.
Ovanför tillhandahåller jag en förenklad (och orealistisk) arkitektur för demonstrationsändamål. Låt oss anta att vi finjusterar modellen från Convolution k + 1 upp till toppen av nätverket (höger sida) och att vi håller frusen ned (vänster sida). Under träningen kommer alla BN-lager från 1 till k att använda medel / variansen för dina träningsdata. Detta kommer att ha negativa effekter på de frysta ReLU: erna om medelvärdet och variansen för varje BN inte är nära de som lärt sig under förutbildningen. Det kommer också att göra att resten av nätverket (från CONV k + 1 och senare) tränas med ingångar som har olika skalor jämfört med vad som kommer att få under inferensen. Under träningen kan ditt nätverk anpassa sig till dessa förändringar, ändå när du byter till prediktionsläge kommer Keras att använda olika standardiseringsstatistik, något som kommer att snabba fördelningen av ingångarna i nästa lager som leder till dåliga resultat.

2.2 Hur kan du upptäcka om du drabbas?

Ett sätt att upptäcka det är att statiskt ställa inlärningsfasen för Keras till 1 (tågläge) och till 0 (testläge) och utvärdera din modell i båda fallen. Om det är betydande skillnad i noggrannhet på samma datasats påverkas du av problemet. Det är värt att påpeka att det på grund av hur lärande-fas-mekanismen implementeras i Keras, inte rekommenderas att orka med den. Ändringar av inlärningsfasen har ingen effekt på modeller som redan är kompilerade och används. Som du kan se på exemplen på nästa underavsnitt är det bästa sättet att göra detta att börja med en ren session och ändra inlärningsfasen innan någon tensor definieras i diagrammet.

Ett annat sätt att upptäcka problemet när du arbetar med binära klassificerare är att kontrollera noggrannheten och AUC. Om noggrannheten är nära 50% men AUC är nära 1 (och du observerar skillnader mellan tåg / testläge på samma datasats) kan det vara så att sannolikheterna är out-of-skala på grund av BN-statistiken. På samma sätt för regression kan du använda MSE och Spearmans korrelation för att upptäcka det.

2.3 Hur kan vi fixa det?

Jag tror att problemet kan åtgärdas om de frysta BN-lagren faktiskt är just det: permanent låst i testläge. Implementeringsmässigt måste den utbildningsbara flaggan vara en del av beräkningsgrafen och BN: s beteende behöver inte bara bero på inlärningsfasen utan också på värdet på den utbildningsbara egenskapen. Du kan hitta detaljerna om min implementering på Github.

Genom att tillämpa fixen ovan, när ett BN-lager är fryst, kommer det inte längre att använda minisatsstatistiken utan istället använda de som lärts under träningen. Som ett resultat kommer det inte att finnas någon skillnad mellan träning och testlägen vilket leder till ökad noggrannhet. Uppenbarligen när BN-lagret inte är fruset, kommer det att fortsätta använda minisatsstatistiken under träningen.

2.4 Utvärdera effekterna av lappen

Trots att jag skrev ovanstående implementering nyligen, testas tanken bakom den på verkliga problem med olika lösningar som har samma effekt. Till exempel avvikelsen mellan träning och testlägen och kan undvikas genom att dela upp nätverket i två delar (fryst och ofrossat) och utföra cachad träning (skicka data genom den frusna modellen en gång och sedan använda dem för att träna det ofrysta nätverket). Eftersom "lita på att jag har gjort det här tidigare" vanligtvis inte har någon vikt, ger jag nedan några exempel som visar effekterna av den nya implementeringen i praktiken.

Här är några viktiga punkter om experimentet:

  1. Jag kommer att använda en liten mängd data för att avsiktligt överdriva modellen och jag kommer att träna och validera modellen i samma dataset. Genom att göra det förväntar jag mig nästan perfekt noggrannhet och identisk prestanda på tåget / valideringsdatasetet.
  2. Om jag under valideringen får signifikant lägre noggrannhet på samma datasats kommer jag att ha en tydlig indikation på att den nuvarande BN-policyn påverkar modellens prestanda negativt under inferensen.
  3. Eventuell förbehandling sker utanför Generatorer. Detta görs för att hantera ett fel som introducerades i v2.1.5 (för närvarande fixat på kommande v2.1.6 och senaste master).
  4. Vi kommer att tvinga Keras att använda olika inlärningsfaser under utvärderingen. Om vi ​​ser skillnader mellan den rapporterade noggrannheten kommer vi att veta att vi påverkas av den nuvarande BN-policyn.

Koden för experimentet visas nedan:

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

Låt oss kolla resultaten 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 ovan lär modellen sig mycket bra data och uppnår på träningsuppsättningen nästan perfekt noggrannhet. Fortfarande i slutet av varje iteration, medan vi utvärderar modellen på samma datasats, får vi betydande skillnader i förlust och noggrannhet. Observera att vi inte borde få detta; Vi har avsiktligt övermonterat modellen på det specifika datasättet och utbildnings- / valideringsdatasätten är identiska.

Efter att träningen har slutförts utvärderar vi modellen med 3 olika konfigurationer för lärande_fas: Dynamisk, Statiskt = 0 (testläge) och Statiskt = 1 (träningsläge). Som vi kan se kommer de två första konfigurationerna att ge identiska resultat när det gäller förlust och noggrannhet och deras värde matchar den rapporterade noggrannheten för modellen på valideringsuppsättningen i den senaste iterationen. Ändå, när vi väl bytt till träningsläge, observerar vi en massiv avvikelse (förbättring). Varför det? Som vi sa tidigare är nätverkets vikter inställda och förväntar sig att få data skalade med medelvärdet / variansen för träningsdata. Tyvärr skiljer sig denna statistik från den som lagras i BN-lagren. Eftersom BN-lagren frystes uppdaterades aldrig denna statistik. Denna avvikelse mellan värdena i BN-statistiken leder till försämring av noggrannheten under inferens.

Låt oss se vad som händer när vi har använt plåster:

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 och främst observerar vi att nätverket konvergerar betydligt snabbare och uppnår perfekt noggrannhet. Vi ser också att det inte längre finns en skillnad i fråga om noggrannhet när vi växlar mellan olika inlärningsfasvärden.

2.5 Hur fungerar lappen på ett riktigt datasystem?

Så hur fungerar lappen på ett mer realistiskt experiment? Låt oss använda Keras förutbildade ResNet50 (ursprungligen passade på imagenet), ta bort det översta klassificeringsskiktet och finjustera det med och utan lappen och jämföra resultaten. För data använder vi CIFAR10 (standardtåget / testdelningen från Keras) och vi ändrar storleken på bilderna till 224 × 224 för att göra dem kompatibla med ResNet50: s ingångsstorlek.

Vi kommer att göra 10 epoker för att träna toppklassificeringsskiktet med hjälp av RSMprop och sedan kommer vi att göra ytterligare 5 för att finjustera allt efter det 139: e lagret med SGD (lr = 1e-4, momentum = 0.9). Utan lappen uppnår vår modell en noggrannhet på 87.44%. Med hjälp av lappen får vi en noggrannhet på 92.36%, nästan 5 poäng högre.

2.6 Ska vi tillämpa samma fix på andra lager som Dropout?

Batchnormalisering är inte det enda lagret som fungerar annorlunda mellan tåg- och testlägen. Dropout och dess varianter har också samma effekt. Ska vi tillämpa samma policy på alla dessa lager? Jag tror inte (även om jag gärna skulle vilja höra dina tankar om detta). Anledningen är att Dropout används för att undvika överanpassning, varigenom låsning av den permanent till förutsägelsemod under träning skulle besegra dess syfte. Vad tror du?

Jag tror starkt på att denna skillnad måste lösas i Keras. Jag har sett ännu djupare effekter (från 100% till 50% noggrannhet) i verkliga applikationer orsakade av detta problem. jag planerar att skicka skickade redan en PR till Keras med fixen och förhoppningsvis kommer det att accepteras.

Om du gillade den här blogginlägget, ta en stund för att dela den på Facebook eller Twitter. 🙂

Tidsstämpel:

Mer från Datumbox