現在、研究などでtensorflow を使ってDNNを組んでいるのだが、出力が全部同じになる問題が発生し、その原因などを追求してみた。
状況だが、具体的には、多クラス分類において、最終出力層の出力がバッチ全体で同じような出力になってしまうのだ。
こんな感じ
$ output = [0 0 0 0 0 0 0 0 0 0 0 0]
true_label = [1 6 5 7 10 11 10 15 3 2 1 4]
例としては、15クラス分類を行うDNNがあったとして、出力が全て同じになってしまっている。
重み:wの初期値などはランダムに設定されるため、毎回出力が0だけ、というわけではなく、1のときもあれば14のときもある。
原因として色々探ってみたが、最も大きく響く2つの要因があった。が、その前に、根本的に学習が進んでないだけかもしれないということもある。
私の場合、最初のほうはずっと同じ出力だったが、学習がある程度進むと出力にバリエーションが出てき始めた、ということもあるので、学習の経過を根気よく見守るのも大事かも。(だが、学習が遅いときは学習係数を見直したほうがいい)
では、原因について。
1つ目
学習率が最適ではない
上の学習率とは、基本的には最適化アルゴリズム(optimizer)に与える学習率のことである。
私の場合は、Adamを使用しているが、こちらの場合はαの値が大きすぎたりすると例の症状が起きたりする。色々なNNを作ったが、1.0e-3 ~ 1.0e-5 くらいで調整してみるのも一つの手かもしれない。
次に、2つ目
重みwの設定が最適でない
これはどういうことかというと、tensorflow チュートリアルなどでは、wの初期値は
tf.random_normal()
などで生成することになるが、ここで与えた乱数の分布などが正規分布のままだとNNにとっては良くないそうだ。
具体的に解説してくれているページがあったので参照してほしい。
ざっくりいうと、重みの初期値の設定を疎かにすると、学習に大きく影響を及ぼすから、ちゃんとパラメータを調節しよう、という話だ。
teratailには初期値の分布に関しての質問があった(参照ページ:重みづけを一様分布で行い、バイアスづけを正規分布で行う理由がわからない)
補足:上記のページの回答からも重みの初期化のページに飛べるよ
tensorflow で実際に初期値を色々いじってみたりするのも解決策かもしれない。
ちなみに、私は
w = 0.9*tf.Variable(tf.truncated_normal([3, 5, 1, conv1_features], stddev=0.1), dtype=tf.float32)
みたいな感じで、変数の最初に係数を設けたりした。(コードの中身については省略)
まとめると、ハイパラメータの設定が最適でないとNNは動かない。
DNNは奥が深いなと感じる今日この頃…
ではでは。
コメント