Tensorflow API の公式ドキュメントでは、tf.lays.conv2d
と tf.layers.dense
のパラメータ kernel_initializer
のデフォルトは None
であるとされています。
しかし、layers tutorial (https://www.tensorflow.org/tutorials/layers) を読むと、このパラメータがコードに設定されていないことに気づきました。例えば
# Convolutional Layer #1
conv1 = tf.layers.conv2d(
inputs=input_layer,
filters=32,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
チュートリアルのサンプルコードは何のエラーもなく実行されるので、デフォルトの kernel_initializer
は None
ではないのだと思います。では、どのイニシャライザが使われているのでしょうか?
別のコードでは、conv2dとdenseレイヤーの kernel_initializer
を設定しませんでしたが、すべてうまくいきました。しかし、kernel_initializer
に tf.truncated_normal_initializer(stddev=0.1, dtype=tf.float32)
をセットしようとすると、NaNエラーが発生しました。どうなっているのでしょうか?どなたか教えてください。
いい質問ですねー。調べるのはなかなかコツがいりますね!
tf.lays.conv2d
にはドキュメントがありません。variable_scope.get_variable
を呼び出していることがわかります。コードでは
self.kernel = vs.get_variable('kernel',
shape=kernel_shape,
initializer=self.kernel_initializer,
regularizer=self.kernel_regularizer,
trainable=True,
dtype=self.dtype)
次のステップ: イニシャライザが None のとき、変数スコープはどうなっているか
ここにはこう書いてあります。
initializer が None(デフォルト) の場合、コンストラクタで渡されたデフォルトのイニシャライザが使われます。 が使用されます。もし、これも
Noneならば、新しい glorot_uniform_initializer
を使用します。
つまり答えは、glorot_uniform_initializer
を使うということです。
完全を期すために、このイニシャライザーの定義を示します。
Glorot uniform initializer, Xavier uniform initializerとも呼ばれます。
これは、一様分布から [-limit, limit] の範囲内でサンプルを取得します。
ここで, limit
は sqrt(6 / (fan_in + fan_out))
です.
ここで、 fan_in
はウェイトテンソルの入力ユニット数
であり、fan_out
はウェイトテンソルの出力ユニット数である。
参考:http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf
編集:これは私がコードとドキュメントで見つけたものです。おそらく、重みに対してevalを実行することで、初期化がこのように見えることを確認することができるだろう