私のモデルは、複数の BN レイヤーと DO レイヤーを持つ CNN ベースのモデルです。もともと、次のように誤って model.train() をループの外側に置きました。
model.train()
for e in range(num_epochs):
# train model
model.eval()
# eval model
記録のために、上記のコードは適切にトレーニングされ、検証セットで適切に実行されました。
[CV:02][E:001][I:320/320] avg. Loss: 0.460897, avg. Acc: 0.742746, test. acc: 0.708046(max: 0.708046)
[CV:02][E:002][I:320/320] avg. Loss: 0.389883, avg. Acc: 0.798791, test. acc: 0.823563(max: 0.823563)
[CV:02][E:003][I:320/320] avg. Loss: 0.319034, avg. Acc: 0.825559, test. acc: 0.834914(max: 0.834914)
[CV:02][E:004][I:320/320] avg. Loss: 0.301322, avg. Acc: 0.834254, test. acc: 0.834052(max: 0.834914)
[CV:02][E:005][I:320/320] avg. Loss: 0.292184, avg. Acc: 0.839575, test. acc: 0.835201(max: 0.835201)
[CV:02][E:006][I:320/320] avg. Loss: 0.285467, avg. Acc: 0.842266, test. acc: 0.837931(max: 0.837931)
[CV:02][E:007][I:320/320] avg. Loss: 0.279607, avg. Acc: 0.844917, test. acc: 0.829885(max: 0.837931)
[CV:02][E:008][I:320/320] avg. Loss: 0.275252, avg. Acc: 0.846443, test. acc: 0.827874(max: 0.837931)
[CV:02][E:009][I:320/320] avg. Loss: 0.270719, avg. Acc: 0.848150, test. acc: 0.822989(max: 0.837931)
しかし、コードを見直しているうちに、上記のコードは最初の繰り返しの後に BN レイヤーと DO レイヤーをオフにしてしまうため、間違いを犯したことに気付きました。
そこで、次の行を移動しました: model.train() ループ内:
for e in range(num_epochs):
model.train()
#train model
model.eval()
#eval model
この時点で、モデルの学習は比較的不十分でした (次の出力でわかるように、モデルのオーバーフィットのように見えました)。トレーニングの精度は高くなりましたが、検証セットの精度が大幅に低下しました (BN と DO の通常の効果を考慮すると、この時点で奇妙になり始めていました)。
[CV:02][E:001][I:320/320] avg. Loss: 0.416946, avg. Acc: 0.750477, test. acc: 0.689080(max: 0.689080)
[CV:02][E:002][I:320/320] avg. Loss: 0.329121, avg. Acc: 0.798992, test. acc: 0.690948(max: 0.690948)
[CV:02][E:003][I:320/320] avg. Loss: 0.305688, avg. Acc: 0.829053, test. acc: 0.719540(max: 0.719540)
[CV:02][E:004][I:320/320] avg. Loss: 0.290048, avg. Acc: 0.840539, test. acc: 0.741954(max: 0.741954)
[CV:02][E:005][I:320/320] avg. Loss: 0.279873, avg. Acc: 0.848872, test. acc: 0.745833(max: 0.745833)
[CV:02][E:006][I:320/320] avg. Loss: 0.270934, avg. Acc: 0.854274, test. acc: 0.742960(max: 0.745833)
[CV:02][E:007][I:320/320] avg. Loss: 0.263515, avg. Acc: 0.856945, test. acc: 0.741667(max: 0.745833)
[CV:02][E:008][I:320/320] avg. Loss: 0.256854, avg. Acc: 0.858672, test. acc: 0.734483(max: 0.745833)
[CV:02][E:009][I:320/320] avg. Loss: 0.252013, avg. Acc: 0.861363, test. acc: 0.723707(max: 0.745833)
[CV:02][E:010][I:320/320] avg. Loss: 0.245525, avg. Acc: 0.865519, test. acc: 0.711494(max: 0.745833)
そこで、「BN レイヤーと DO レイヤーが私のモデルに悪影響を及ぼしていると思います」と考えたので、それらを削除しました。ただし、モデルは BN 層と DO 層を削除してもうまく機能しませんでした (実際、モデルは何も学習していないようです)。
[CV:02][E:001][I:320/320] avg. Loss: 0.552687, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:002][I:320/320] avg. Loss: 0.506234, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:003][I:320/320] avg. Loss: 0.503373, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:004][I:320/320] avg. Loss: 0.502966, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:005][I:320/320] avg. Loss: 0.502870, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:006][I:320/320] avg. Loss: 0.502832, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:007][I:320/320] avg. Loss: 0.502800, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:008][I:320/320] avg. Loss: 0.502765, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
この時点で私は非常に混乱しました。さらに進んで、別の実験を行いました。BN レイヤーと DO レイヤーをモデルに戻し、次のことをテストしました。
for e in range(num_epochs):
model.eval()
# train model
# eval model
それはうまくいきませんでした:
[CV:02][E:001][I:320/320] avg. Loss: 0.562196, avg. Acc: 0.744774, test. acc: 0.689080(max: 0.689080)
[CV:02][E:002][I:320/320] avg. Loss: 0.506071, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:003][I:320/320] avg. Loss: 0.503234, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:004][I:320/320] avg. Loss: 0.502916, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:005][I:320/320] avg. Loss: 0.502859, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
[CV:02][E:006][I:320/320] avg. Loss: 0.502838, avg. Acc: 0.749071, test. acc: 0.689080(max: 0.689080)
上記の実験を複数回実行しましたが、結果は上に投稿した結果と大きくかけ離れていませんでした。(私が扱っているデータは非常に単純です)。
要約すると、このモデルは非常に特殊な設定で最適に機能します。
- モデルにバッチ正規化とドロップアウトが追加されました。(これはいい)。
- 最初のエポックのみ model.train() をオンにしてモデルをトレーニングします。(奇妙な.. 3と組み合わせて)
- 残りの反復では、model.eval() をオンにしてモデルをトレーニングします。(これもおかしい)
正直なところ、上記のようにトレーニング手順を設定することはありませんでしたが (誰もそうしないと思います)、何らかの理由でうまく機能します。誰かが似たようなことを経験したことがありますか? または、モデルがこのように動作する理由を教えていただければ幸いです!!
前もって感謝します!!