- 2018 年 4 月 17 日
- ヴァシリス・ヴリニオティス
- 。 30コメント
更新:残念ながら、バッチ正規化レイヤーの動作を変更するKerasへの私のプルリクエストは受け入れられませんでした。 詳細をご覧いただけます こちら。 カスタム実装をいじるのに十分勇敢なあなたのために、あなたはコードを見つけることができます 私の支店。 私はそれを維持し、Kerasの最新の安定バージョンとマージするかもしれません(2.1.6, 2.2.2 & 2.2.4)私がそれを使う限り、約束はしません。
ディープラーニングで働くほとんどの人は、 ケラス。 まだお持ちでない方は、TensorFlow、Theano、CNTKなどの基盤となるディープラーニングフレームワークを抽象化し、 高レベルAPI ANNのトレーニング用。 使いやすく、迅速なプロトタイピングが可能で、フレンドリーなアクティブコミュニティがあります。 私はこれを頻繁に使用しており、かなり長い間定期的にプロジェクトに貢献してきました。ディープラーニングに取り組みたい人にはぜひお勧めします。
Kerasによって私の生活は楽になりましたが、バッチ正規化レイヤーの奇妙な動作に何度も噛まれました。 そのデフォルトの動作は時間とともに変化しましたが、それでもなお多くのユーザーに問題を引き起こし、その結果、いくつかの関連するものがあります 未解決の問題 Githubで。 このブログ投稿では、KerasのBatchNormalizationレイヤーがTransfer Learningでうまく機能しない場合の事例を構築しようと思います。問題を修正するコードを提供し、結果の例を示します patch.
以下のサブセクションでは、深層学習で転移学習がどのように使用されるか、バッチ正規化レイヤーとは何か、learninging_phaseがどのように機能するか、Kerasが時間とともにBNの動作をどのように変化させたかについて紹介します。 これらをすでに知っている場合は、セクション2に直接安全にジャンプできます。
1.1深層学習には転移学習の使用が重要です
過去にディープラーニングが批判された理由のXNUMXつは、必要なデータが多すぎることです。 これは常に正しいとは限りません。 この制限に対処する方法はいくつかありますが、そのXNUMXつが転移学習です。
コンピュータービジョンアプリケーションで作業していて、猫と犬を区別する分類器を作成するとします。 モデルをトレーニングするために、実際には何百万もの猫/犬の画像は必要ありません。 代わりに、事前トレーニング済みの分類子を使用して、少ないデータで上位の畳み込みを微調整できます。 その背後にある考え方は、事前トレーニング済みモデルが画像に適合していたため、下部の畳み込みはライン、エッジ、その他の有用なパターンなどの機能を認識できるため、その重みを適切な初期値として使用するか、データでネットワークを部分的に再トレーニングできるということです。
Kerasには、いくつかの事前トレーニング済みモデルと、モデルの微調整方法に関する使いやすいサンプルが付属しています。 詳細については、 ドキュメント.
1.2バッチ正規化レイヤーとは何ですか?
バッチ正規化レイヤーは、2014年にIoffeとSzegedyによって導入されました。 これは、前の層の出力を標準化することによって消失勾配の問題に対処し、必要な反復回数を減らすことでトレーニングを高速化し、より深いニューラルネットワークのトレーニングを可能にします。 それがどのように機能するかを正確に説明することはこの投稿の範囲を超えていますが、私はあなたに 原紙。 単純化しすぎた説明は、平均を差し引いて標準偏差で割ることによって入力を再スケーリングすることです。 また、必要に応じて変換を元に戻す方法も学習できます。
1.3 Kerasのlearning_phaseとは何ですか?
一部のレイヤーは、トレーニングモードと推論モードで動作が異なります。 最も注目すべき例は、バッチ正規化レイヤーとドロップアウトレイヤーです。 BNの場合、トレーニング中に、ミニバッチの平均と分散を使用して入力を再スケーリングします。 一方、推論時には、トレーニング中に推定された移動平均と分散を使用します。
Kerasは組み込みのメカニズムと呼ばれるため、どのモードで実行するかを知っています。 Learning_phase。 学習フェーズでは、ネットワークがトレインモードかテストモードかを制御します。 ユーザーが手動で設定しない場合、fit()の間、ネットワークはlearning_phase = 1(トレインモード)で実行されます。 予測を生成している間(たとえば、predict()およびevaluate()メソッドを呼び出すとき、またはfit()の検証ステップで)、ネットワークはlearning_phase = 0(テストモード)で実行されます。 推奨されていませんが、ユーザーはlearning_phaseを特定の値に静的に変更することもできますが、これは、モデルまたはテンソルがグラフに追加される前に行う必要があります。 Learning_phaseが静的に設定されている場合、Kerasはユーザーが選択したモードにロックされます。
1.4 Kerasはどのようにしてバッチ正規化を実装しましたか?
Kerasはバッチ正規化の動作を数回変更しましたが、最新の重要な更新はKeras 2.1.3で行われました。 v2.1.3より前は、BNレイヤーがフリーズしたとき(trainable = False)、バッチ統計を更新し続けました。これは、ユーザーに重大な問題を引き起こしたものです。
これは単なる奇妙な政策ではなく、実際には間違っていました。 畳み込みの間にBNレイヤーが存在すると想像してください。 レイヤーがフリーズしている場合、変更は発生しません。 ウェイトを部分的に更新し、次のレイヤーもフリーズしている場合、それらはミニバッチ統計の更新に調整する機会を得ることはなく、エラーが高くなります。 ありがたいことに、バージョン2.1.3以降、BNレイヤーがフリーズすると、統計が更新されなくなりました。 しかし、それで十分ですか? 転移学習を使用している場合はできません。
以下では、何が問題であるかを正確に説明し、それを解決するための技術的な実装を概説します。 また、モデルの精度への影響を前後に示すいくつかの例を示します。 patch 適用される。
2.1問題の技術的説明
Kerasの現在の実装の問題は、BNレイヤーがフリーズしている場合、トレーニング中にミニバッチ統計を引き続き使用することです。 BNがフリーズしているときのより良いアプローチは、トレーニング中に学習した移動平均と分散を使用することです。 どうして? レイヤーがフリーズしたときにミニバッチ統計を更新してはならないのと同じ理由で、次のレイヤーが適切にトレーニングされていないため、結果が悪くなる可能性があります。
コンピュータービジョンモデルを構築しているが、十分なデータがないため、Kerasの事前トレーニング済みのCNNのXNUMXつを使用して微調整することにしたとします。 残念ながら、そうすることで、BNレイヤー内の新しいデータセットの平均と分散が元のデータセットのものと同様になるという保証はありません。 現時点では、トレーニング中に、BNレイヤーがフリーズしているかどうかにかかわらず、ネットワークは常にミニバッチ統計を使用することに注意してください。 また、推論時には、以前に学習した凍結BN層の統計を使用します。 その結果、最上位のレイヤーを微調整すると、それらの重みは平均値/分散に調整されます。 新製品 データセット。 それにもかかわらず、推論の間、彼らはスケーリングされたデータを受け取ります 異なって の平均/分散 オリジナル データセットが使用されます。
上記では、デモンストレーション用に単純化された(そして非現実的な)アーキテクチャーを提供しています。 ネットワークの上部(右側)までモデルをたたみ込みk + 1からモデルまで微調整し、下部(左側)を固定したと仮定します。 トレーニング中、1からkまでのすべてのBNレイヤーは、トレーニングデータの平均/分散を使用します。 これは、各BNの平均と分散が事前トレーニング中に学習したものに近くない場合、凍結されたReLUに悪影響を及ぼします。 また、ネットワークの残りの部分(CONV k + 1以降)は、推論中に受信するものと比較して異なるスケールを持つ入力でトレーニングされます。 トレーニング中、ネットワークはこれらの変更に適応できますが、予測モードに切り替えると、Kerasは異なる標準化統計を使用します。これにより、次のレイヤーの入力の分布が速くなり、結果が悪くなります。
2.2影響を受けているかどうかをどのように検出できますか?
これを検出する1つの方法は、Kerasの学習フェーズを0(トレーニングモード)およびXNUMX(テストモード)に静的に設定し、それぞれのケースでモデルを評価することです。 同じデータセットで精度に大きな違いがある場合は、問題の影響を受けています。 Kerasでlearning_phaseメカニズムが実装されている方法のため、通常、それをいじることはお勧めしません。 learning_phaseの変更は、すでにコンパイルおよび使用されているモデルには影響しません。 次のサブセクションの例でわかるように、これを行う最良の方法は、クリーンなセッションから開始して、グラフでテンソルが定義される前にlearning_phaseを変更することです。
バイナリ分類子を使用しているときに問題を検出する別の方法は、精度とAUCを確認することです。 精度が50%に近いが、AUCが1に近い場合(および同じデータセットでトレーニングモードとテストモードの違いが見られる場合)、BN統計により確率がスケール外である可能性があります。 同様に、回帰の場合、MSEとSpearmanの相関を使用してそれを検出できます。
2.3どうすれば修正できますか?
フリーズしたBNレイヤーが実際にテストモードで永久にロックされている場合、問題は修正できると思います。 実装に関しては、トレーニング可能なフラグは計算グラフの一部である必要があり、BNの動作はlearning_phaseだけでなく、トレーニング可能なプロパティの値にも依存する必要があります。 あなたは私の実装の詳細を見つけることができます githubの.
上記の修正を適用することにより、BNレイヤーがフリーズすると、ミニバッチ統計情報は使用されなくなり、代わりにトレーニング中に学習された統計情報が使用されます。 その結果、トレーニングモードとテストモードの間に差異がなくなり、精度が向上します。 BNレイヤーがフリーズしていない場合は、トレーニング中にミニバッチ統計を引き続き使用します。
2.4パッチの効果の評価
最近、上記の実装を作成しましたが、その背後にあるアイデアは、同じ効果を持つさまざまな回避策を使用して、実際の問題について徹底的にテストされています。 たとえば、トレーニングモードとテストモードの不一致は、ネットワークをXNUMXつの部分(凍結と非凍結)に分割し、キャッシュされたトレーニングを実行することで(凍結モデルに一度データを渡してから、凍結されていないネットワークのトレーニングに使用することで)回避できます。 それでも、「私がこれまでにやったことがある」を信頼することは一般的に重要ではないため、以下では、実際の新しい実装の効果を示すいくつかの例を示します。
実験に関する重要な点をいくつか次に示します。
- 少量のデータを使用してモデルを意図的に過剰適合させ、同じデータセットでモデルをトレーニングして検証します。 そうすることで、train / validationデータセットでほぼ完全な精度と同じパフォーマンスが期待できます。
- 検証中に同じデータセットで精度が大幅に低下した場合、現在のBNポリシーが推論中のモデルのパフォーマンスに悪影響を及ぼしていることを明確に示します。
- 前処理はすべてジェネレータの外部で行われます。 これは、v2.1.5で導入されたバグ(現在、次のv2.1.6および最新のマスターで修正されています)を回避するために行われます。
- 評価中にKerasに異なる学習フェーズを使用するように強制します。 報告された精度の違いを見つけた場合、現在のBNポリシーの影響を受けていることがわかります。
実験のコードを以下に示します。
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)))
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]
上記のように、トレーニング中にモデルはデータを非常によく学習し、トレーニングセットでほぼ完全な精度で達成します。 それでも、各反復の最後に、同じデータセットでモデルを評価しているときに、損失と精度に大きな違いが生じます。 これを取得すべきではないことに注意してください。 特定のデータセットとトレーニング/検証データセットのモデルを意図的にオーバーフィットしました。
トレーニングが完了したら、動的、静的= 3(テストモード)、静的= 0(トレーニングモード)の1つの異なるlearning_phase構成を使用してモデルを評価します。 ご覧のとおり、最初のXNUMXつの構成では、損失と精度の点で同じ結果が得られ、それらの値は、最後の反復で設定された検証でモデルの報告された精度と一致します。 それでも、トレーニングモードに切り替えると、大きな不一致(改善)が見られます。 なんでそれ? 前に述べたように、ネットワークの重みは、トレーニングデータの平均/分散でスケーリングされたデータを受信することを期待して調整されます。 残念ながら、これらの統計はBNレイヤーに保存されている統計とは異なります。 BNレイヤーが凍結されたため、これらの統計は更新されませんでした。 BN統計の値間のこの不一致は、推論中の精度の低下につながります。
適用したらどうなるか見てみましょう 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]
まず、ネットワークの収束が大幅に速くなり、完全な精度が得られることがわかります。 また、異なるlearning_phase値を切り替えると、精度の点で矛盾がなくなっていることもわかります。
2.5パッチは実際のデータセットでどのように機能しますか?
それでは、パッチはより現実的な実験でどのように機能しますか? Kerasの事前トレーニング済みのResNet50(元はimagenetに適合)を使用して、最上位の分類レイヤーを削除し、パッチありとパッチなしで微調整し、結果を比較してみましょう。 データについては、CIFAR10(Kerasが提供する標準の列車/テスト分割)を使用し、画像を224×224にサイズ変更して、ResNet50の入力サイズと互換性があるようにします。
RSMpropを使用して最上位の分類層をトレーニングするために10エポックを実行し、次にSGD(lr = 5e-139、momentum = 1)を使用して4番目の層以降のすべてを微調整するためにさらに0.9つのエポックを実行します。 パッチがないと、モデルの精度は87.44%になります。 パッチを使用すると、精度が92.36%になり、ほぼ5ポイント高くなります。
2.6ドロップアウトなどの他のレイヤーにも同じ修正を適用する必要がありますか?
バッチ正規化は、トレーニングモードとテストモードで動作が異なる唯一のレイヤーではありません。 ドロップアウトとそのバリアントも同じ効果があります。 これらすべてのレイヤーに同じポリシーを適用する必要がありますか? 私はそうは思いません(これについてのあなたの考えを聞きたいと思っていても)。 その理由は、ドロップアウトが過剰適合を回避するために使用されているため、トレーニング中にドロップアウトを予測モードに永続的にロックすると、その目的が損なわれるためです。 どう思いますか?
この矛盾はKerasで解決する必要があると強く信じています。 この問題が原因の実際のアプリケーションでは、さらに大きな影響(100%から50%の精度まで)が見られます。 私 送る予定 すでに送った PR Kerasに修正を加えて、うまくいけば受け入れられます。
このブログ投稿が気に入ったら、少し時間をかけてFacebookまたはTwitterで共有してください。 🙂