web-dev-qa-db-ja.com

ResNet:トレーニング中は100%の精度ですが、同じデータで33%の予測精度

機械学習とディープラーニングは初めてであり、学習目的でResnetを使用しようとしました。私は小さなデータ(3differentimages)をオーバーフィットして、ほぼ0の損失と1.0の精度を得ることができるかどうかを確認しようとしました。

問題は、trainingイメージ(つまり、トレーニングに使用される同じ3つのイメージ)の予測が正しくないことです。

トレーニング画像

image 1image 2image 3

画像ラベル

[1,0,0][0,1,0][0,0,1]

マイpython code

#loading 3 images and resizing them
imgs = np.array([np.array(Image.open("./Images/train/" + fname)
                          .resize((197, 197), Image.ANTIALIAS)) for fname in
                 os.listdir("./Images/train/")]).reshape(-1,197,197,1)
# creating labels
y = np.array([[1,0,0],[0,1,0],[0,0,1]])
# create resnet model
model = ResNet50(input_shape=(197, 197,1),classes=3,weights=None)

# compile & fit model
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['acc'])

model.fit(imgs,y,epochs=5,shuffle=True)

# predict on training data
print(model.predict(imgs))

モデルはデータをオーバーフィットします:

3/3 [==============================] - 22s - loss: 1.3229 - acc: 0.0000e+00
Epoch 2/5
3/3 [==============================] - 0s - loss: 0.1474 - acc: 1.0000
Epoch 3/5
3/3 [==============================] - 0s - loss: 0.0057 - acc: 1.0000
Epoch 4/5
3/3 [==============================] - 0s - loss: 0.0107 - acc: 1.0000
Epoch 5/5
3/3 [==============================] - 0s - loss: 1.3815e-04 - acc: 1.0000

しかし、予測は次のとおりです。

 [[  1.05677405e-08   9.99999642e-01   3.95520459e-07]
 [  1.11955103e-08   9.99999642e-01   4.14905685e-07]
 [  1.02637095e-07   9.99997497e-01   2.43751242e-06]]

つまり、すべての画像がlabel=[0,1,0]

どうして?そして、それはどのように起こりますか?

25
Dvir Samuel

これは、バッチ正規化レイヤーが原因です。

トレーニングフェーズでは、バッチはw.r.tで正規化されます。その平均と分散。ただし、テスト段階では、バッチはw.r.tで正規化されます。 移動平均以前に観測された平均と分散の。

BatchNormalizationレイヤーでは、デフォルトで_moving_mean_が0および_moving_variance_に初期化されるため、これは、観測されたバッチの数が少ない場合(例では5)の問題です。 1に初期化されます。

デフォルトのmomentumが0.99であることを考えると、移動平均を更新する必要があります収束する前に何度も 「実際の」平均と分散。

そのため、初期段階では予測が間違っていますが、1000エポック後には正しくなります。


BatchNormalizationレイヤーを強制的に「トレーニングモード」で動作させることで、それを確認できます。

トレーニング中、精度は1であり、損失はゼロに近いです。

_model.fit(imgs,y,epochs=5,shuffle=True)
Epoch 1/5
3/3 [==============================] - 19s 6s/step - loss: 1.4624 - acc: 0.3333
Epoch 2/5
3/3 [==============================] - 0s 63ms/step - loss: 0.6051 - acc: 0.6667
Epoch 3/5
3/3 [==============================] - 0s 57ms/step - loss: 0.2168 - acc: 1.0000
Epoch 4/5
3/3 [==============================] - 0s 56ms/step - loss: 1.1921e-07 - acc: 1.0000
Epoch 5/5
3/3 [==============================] - 0s 53ms/step - loss: 1.1921e-07 - acc: 1.0000
_

モデルを評価すると、5回の更新後も移動平均が初期値にかなり近いため、高損失と低精度が観察されます。

_model.evaluate(imgs,y)
3/3 [==============================] - 3s 890ms/step
[10.745396614074707, 0.3333333432674408]
_

ただし、「学習フェーズ」変数を手動で指定し、BatchNormalizationレイヤーに「実際の」バッチ平均と分散を使用させると、結果はfit()で観測されるものと同じになります。

_sample_weights = np.ones(3)
learning_phase = 1  # 1 means "training"
ins = [imgs, y, sample_weights, learning_phase]
model.test_function(ins)
[1.192093e-07, 1.0]
_

また、運動量をより小さな値に変更することで検証することもできます。

たとえば、_momentum=0.01_を_ResNet50_のすべてのバッチ標準レイヤーに追加すると、20エポック後の予測は次のようになります。

_model.predict(imgs)
array([[  1.00000000e+00,   1.34882026e-08,   3.92139575e-22],
       [  0.00000000e+00,   1.00000000e+00,   0.00000000e+00],
       [  8.70998792e-06,   5.31159838e-10,   9.99991298e-01]], dtype=float32)
_
16
Yu-Yang