機械学習とディープラーニングは初めてであり、学習目的でResnetを使用しようとしました。私は小さなデータ(3differentimages)をオーバーフィットして、ほぼ0の損失と1.0の精度を得ることができるかどうかを確認しようとしました。
問題は、trainingイメージ(つまり、トレーニングに使用される同じ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]
どうして?そして、それはどのように起こりますか?
これは、バッチ正規化レイヤーが原因です。
トレーニングフェーズでは、バッチは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)
_