10

写真から数値予測を行うために、Keras でモデルを作成しようとしています。私のモデルにはdensenet121畳み込みベースがあり、その上にいくつかの追加レイヤーがあります。最後の 2 つのレイヤーを除くすべてのレイヤーが に設定されlayer.trainable = Falseます。回帰タスクであるため、私の損失は平均二乗誤差です。トレーニング中は が得られloss: ~3ますが、データのまったく同じバッチでの評価は次のようになりますloss: ~30

model.fit(x=dat[0],y=dat[1],batch_size=32)

エポック 1/1 32/32 [============================] - 0s 11ms/ステップ - 損失: 2.5571

model.evaluate(x=dat[0],y=dat[1])

32/32 [============================] - 2s 59ms/ステップ 29.276123046875

トレーニングと評価の間、まったく同じ 32 枚の写真をフィードします。また、予測値を使用して損失を計算しy_pred=model.predict(dat[0])、numpy を使用して平均二乗誤差を構築しました。結果は、評価から得たものと同じでした (つまり、29.276123...)。

この動作はBatchNormalization、畳み込みベースのレイヤーが原因である可能性があるという提案がありました ( github での議論)。もちろん、BatchNormalization私のモデルのすべてのレイヤーlayer.trainable=Falseも同様に設定されています。誰かがこの問題に遭遇し、解決策を見つけたのではないでしょうか?

4

2 に答える 2

2

しかし、ドロップアウト層は通常逆の効果を生み出し、評価の損失をトレーニング中の損失よりも少なくします。

必ずしも!ドロップアウト層では一部のニューロンがドロップされますが、ドロップアウト率に応じて出力が縮小されることに注意してください。推論時間 (つまり、テスト時間) では、ドロップアウトは完全に削除され、モデルを 1 エポックだけトレーニングしたことを考えると、見た動作が発生する可能性があります。モデルを 1 つのエポックだけトレーニングしているため、ニューロンの一部のみがドロップアウト層にドロップされていますが、それらはすべて推論時に存在することを忘れないでください。

より多くのエポックでモデルのトレーニングを続けると、(同じデータに対する)トレーニングの損失とテストの損失がほぼ同じになると予想される場合があります。

自分で実験してみてくださいtrainable。Dropout レイヤーのパラメーターを に設定して、Falseこれが発生するかどうかを確認してください。


1 エポックのトレーニングの後、トレーニングの損失が同じデータ バッチの評価の損失と等しくないことを見て、(私がそうであったように) 混乱するかもしれません。Dropoutこれは、またはBatchNormalizationレイヤーのあるモデルに固有のものではありません。次の例を検討してください。

from keras import layers, models
import numpy as np

model = models.Sequential()
model.add(layers.Dense(1000, activation='relu', input_dim=100))
model.add(layers.Dense(1))

model.compile(loss='mse', optimizer='adam')
x = np.random.rand(32, 100)
y = np.random.rand(32, 1)

print("Training:")
model.fit(x, y, batch_size=32, epochs=1)

print("\nEvaluation:")
loss = model.evaluate(x, y)
print(loss)

出力:

Training:
Epoch 1/1
32/32 [==============================] - 0s 7ms/step - loss: 0.1520

Evaluation:
32/32 [==============================] - 0s 2ms/step
0.7577340602874756

では、同じデータに対して計算された場合、損失が異なるのはなぜ0.1520 != 0.7577ですか。

これを尋ねると、それはあなたが私のように十分な注意を払っていないからです。それ0.1520は、モデルのパラメーターを更新する前 (つまり、バックワード パスまたはバックプロパゲーションを行う前) の損失です。モデルの重み0.7577が更新された後の損失です。使用されるデータが同じであっても、それらの損失値を計算するときのモデルの状態は同じではありません (別の質問: 逆伝播後に損失が増加したのはなぜですか?それは単に、1 つのエポックに対してのみトレーニングしたためです。したがって、重みの更新はまだ十分に安定していません)。

これを確認するために、検証データと同じデータ バッチを使用することもできます。

model.fit(x, y, batch_size=32, epochs=1, validation_data=(x,y))

上記の変更された行で上記のコードを実行すると、次のような出力が得られます (明らかに、正確な値は異なる場合があります)。

Training:
Train on 32 samples, validate on 32 samples
Epoch 1/1
32/32 [==============================] - 0s 15ms/step - loss: 0.1273 - val_loss: 0.5344

Evaluation:
32/32 [==============================] - 0s 89us/step
0.5344240665435791

検証損失と評価損失がまったく同じであることがわかります。これは、検証がエポックの終わり (つまり、モデルの重みが既に更新されているとき) に実行されるためです。

于 2018-07-01T13:37:22.063 に答える