CaffeネットワークをTensorFlowに移植していますが、xavierの初期化が行われていないようです。私は使ってtruncated_normal
いますが、これは訓練を非常に難しくしているようです。
回答:
でTensorflow 2.0、さらに双方tf.contrib.*
とtf.get_variable()
非推奨されています。Xavierの初期化を行うには、次のように切り替える必要があります。
init = tf.initializers.GlorotUniform()
var = tf.Variable(init(shape=shape))
# or a oneliner with a little confusing brackets
var = tf.Variable(tf.initializers.GlorotUniform()(shape=shape))
GlorotユニフォームとXavierユニフォームは、同じ初期化タイプの2つの異なる名前です。Kerasの有無にかかわらずTF2.0で初期化を使用する方法について詳しく知りたい場合は、ドキュメントを参照してください。
バージョン0.8以降、Xavierイニシャライザーがあります。ドキュメントについては、こちらを参照してください。
次のようなものを使用できます。
W = tf.get_variable("W", shape=[784, 256],
initializer=tf.contrib.layers.xavier_initializer())
get_variable
与えるのではなく、イニシャライザに与えることでこれを行うことを知っていますか?以前は持っていてtf.truncated_normal(shape=[dims[l-1],dims[l]], mean=mu[l], stddev=std[l], dtype=tf.float64)
、そこで形状を指定しましたが、今ではあなたの提案が私のコードを台無しにしてしまいます。何か提案はありますか?
tf.Variable(...)
持ち、使用するラッパーを自分で作成するだけですtf.get_variable(...)
XavierとYoshuaの方法tf.Variable
を使用して初期化を定義する方法に関する別の例を追加するだけです。
graph = tf.Graph()
with graph.as_default():
...
initializer = tf.contrib.layers.xavier_initializer()
w1 = tf.Variable(initializer(w1_shape))
b1 = tf.Variable(initializer(b1_shape))
...
これによりnan
、RELUで複数のレイヤーを使用する場合、数値が不安定になるため、損失関数に値を設定できなくなりました。
@ Aleph7、Xavier / Glorotの初期化は、ニューロンの着信接続の数(fan_in)、発信接続の数(fan_out)、および活性化関数の種類(sigmoidまたはtanh)によって異なります。これを参照してください:http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf
さて、あなたの質問に。これは私がTensorFlowでそれを行う方法です:
(fan_in, fan_out) = ...
low = -4*np.sqrt(6.0/(fan_in + fan_out)) # use 4 for sigmoid, 1 for tanh activation
high = 4*np.sqrt(6.0/(fan_in + fan_out))
return tf.Variable(tf.random_uniform(shape, minval=low, maxval=high, dtype=tf.float32))
他の回答で提案されている正規分布ではなく、一様分布からサンプリングする必要があることに注意してください。
ちなみに、私は昨日、Xavier初期化も使用するTensorFlowを使用して別の何かについて投稿しました。興味がある場合は、エンドツーエンドの例を含むPythonノートブックもあります:https://github.com/delip/blog-stuff/blob/master/tensorflow_ufp.ipynb
tensorflow
と呼ばれる優れたラッパーprettytensor
は、ソースコードに実装を提供します(ここから直接コピーされます)。
def xavier_init(n_inputs, n_outputs, uniform=True):
"""Set the parameter initialization using the method described.
This method is designed to keep the scale of the gradients roughly the same
in all layers.
Xavier Glorot and Yoshua Bengio (2010):
Understanding the difficulty of training deep feedforward neural
networks. International conference on artificial intelligence and
statistics.
Args:
n_inputs: The number of input nodes into each output.
n_outputs: The number of output nodes for each input.
uniform: If true use a uniform distribution, otherwise use a normal.
Returns:
An initializer.
"""
if uniform:
# 6 was used in the paper.
init_range = math.sqrt(6.0 / (n_inputs + n_outputs))
return tf.random_uniform_initializer(-init_range, init_range)
else:
# 3 gives us approximately the same limits as above since this repicks
# values greater than 2 standard deviations from the mean.
stddev = math.sqrt(3.0 / (n_inputs + n_outputs))
return tf.truncated_normal_initializer(stddev=stddev)
TF-contribにはxavier_initializer
。使用方法の例を次に示します。
import tensorflow as tf
a = tf.get_variable("a", shape=[4, 4], initializer=tf.contrib.layers.xavier_initializer())
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print sess.run(a)
これに加えて、tensorflowには他の初期化子があります。
調べたところ、何も組み込まれていませんでした。しかし、これによると:
http://andyljones.tumblr.com/post/110998971763/an-explanation-of-xavier-initialization
Xavierの初期化は、分散がニューロンの数の関数である(通常はガウス)分布をサンプリングするだけです。 tf.random_normal
あなたのためにそれを行うことができます、あなたはただstddevを計算する必要があります(すなわちあなたが初期化しようとしている重み行列によって表されているニューロンの数)。
kernel_initializer
パラメータを介してtf.layers.conv2d, tf.layers.conv2d_transpose, tf.layers.Dense
など
例えば
layer = tf.layers.conv2d(
input, 128, 5, strides=2,padding='SAME',
kernel_initializer=tf.contrib.layers.xavier_initializer())
https://www.tensorflow.org/api_docs/python/tf/layers/conv2d
https://www.tensorflow.org/api_docs/python/tf/layers/conv2d_transpose