2016-06-21 16 views
0

私はTensorflowに2層の非畳み込みネットワークを持っています。tanhをアクティベーション機能として使用しています。私は重みがで割った切断正規分布で初期化する必要があることを理解しsqrt(nInputs)例:SupressingウェイトがTensorflowニューラルネットのパフォーマンスを向上させるのはなぜですか?

weightsLayer1 = tf.Variable(tf.div(tf.truncated_normal([nInputUnits, nUnitsHiddenLayer1),math.sqrt(nInputUnits)))) 

はNNとTensorflowで頼りなさそう初心者のビットが、私は誤ってそれだけを読みやすくするために2行としてこれを実装しています:

weightsLayer1 = tf.Variable(tf.truncated_normal([nInputUnits, nUnitsHiddenLayer1]) 
weightsLayer1 = tf.div(weightsLayer1, math.sqrt(nInputUnits)) 

これは間違っており、2行目では各学習ステップで重みが再計算されることがわかりました。しかし、驚いたことに、「間違った」実装は、列車とテスト/評価の両方のデータセットで、一貫してより良いパフォーマンスをもたらします。私は、オプティマイザによって選択された値以外の値にウェイトを再計算しているので、不正確な2行の実装は列車の難破線でなければならないと思っていましたが、最適化プロセスで大混乱を招くかもしれませんが、 。誰にもこれについての説明がありますか?私はTensorflow adamオプティマイザを使用しています。

更新2016.6.22 - 上記の2番目のコードブロックを更新しました。

+0

まず、2行の実装では、 '' sqrt(nInputUnits) 'で2回除算を行い、効果的に' 'nInputUnits''で除算します。それは意図的なのでしょうか? Second:私はあなたの質問を正確に理解していないのですか?変数 '' weightsLayer1''がトレーニングステップを実行するたびに再初期化されるのではないかと心配していますか?もしそうなら、そうではありません。私はこれについて詳しく説明することができますが、あなたが実際に求めているのかどうかは完全にはわかりません。 – lballes

+0

私の間違いは、上記の2行の場合が間違って入力された、私はそれを修正しました。 'sqrt(nInputUnits)'で1回だけ除算します。 2行の場合、 'weightsLayer1'は' tf.Variable'行で1回だけ初期化されています。私の質問:a)2番目の行( 'weightsLayer1 = tf.div(weightsLayer1、math.sqrt(nInputUnits)))は実行時に実行されますか? b)そうであれば、オプティマイザによって計算された 'weightsLayer1'の値を変更し、最適化プロセスに干渉しますか?c)そうであれば、これはオプティマイザによって計算された 'weightsLayer1'の値よりどうすればよいでしょうか? –

+0

さて、私は今それを得たと思います。下の私の答えを見てください。 – lballes

答えて

4

。しかし、それはウェイト変数の値が各ステップでsqrt(nInputUnits)でスケールダウンされることを意味しません。この行は、変数に格納されている値に影響するインプレース操作ではありません。新しいテンソルを計算し、変数の値をsqrt(nInputUnits)で割った値を保持し、そのテンソルを仮定して残りの計算グラフに入ります。これはオプティマイザを妨げません。重みの任意のスケーリングだけで有効な計算グラフを定義しています。オプティマイザは、この変数に関するグラディエントを計算することができます(これは除算操作を通じて逆伝播します)。対応する更新操作を作成します。

定義しているモデルに関して、2つのバージョンは完全に同等です。元のモデルのweightsLayer1の値のセット(除算を行わない場合)は、sqrt(nInputUnits)で単純にスケールアップすると、2番目のモデルで同じ結果が得られます。あなたが望むなら、2つはまったく同じモデルクラスを表します。

なぜ、他のものよりもうまくいくのですか?あなたの推測は私のものと同じくらい良いです。あなたのすべての変数について同じ部門を行っている場合、あなたは効果的にあなたの学習率をsqrt(nInputUnits)で分けました。この小さな学習率は、手元の問題に有益であったかもしれません。

編集:変数に同じ名前を付けて、新しく作成したテンソルが混乱の原因になると思います。あなたは

A = tf.Variable(1.0) 
A = tf.mul(A, 2.0) 
# Do something with A 

を行うと、その後2行目は、新たなテンソルを作成します(上述のように)、あなたは名前を再バインドする(そして、それは唯一の名前です)という新しいテンソルへA。定義されているグラフでは、命名は絶対に無関係です。

A = tf.Variable(1.0) 
print A 
B = A 
A = tf.mul(A, 2.0) 
print A 
print B 

出力はあなたprint Aはそれが告げる最初の時間が

<tensorflow.python.ops.variables.Variable object at 0x7ff025c02bd0> 
Tensor("Mul:0", shape=(), dtype=float32) 
<tensorflow.python.ops.variables.Variable object at 0x7ff025c02bd0> 

です:あなたは、次のコードを実行した場合

A = tf.Variable(1.0) 
B = tf.mul(A, 2.0) 
# Do something with B 

は多分これが透明になる:次のコードは、同じグラフを定義しますAは変数オブジェクトですA = tf.mul(A, 2.0)を実行してAを再度印刷すると、Aという名前がtf.Tensorオブジェクトにバインドされていることがわかります。しかし、変数は依然として存在し、Bという名前の背後にあるオブジェクトを見ると分かります。

+0

ありがとうございます。したがって、 'A = tf.Variable(1.0)'と 'A = tf.mul(A、2.0)'を実行すると、2行目はAを変更せず、Aという名前の別のテンソルを作成し、TensorflowはAが計算グラフの他の場所で使用されているときの最初のAではなく、2番目のA?私はこれが機能的には変数Aの値を変更することと同等であると思います、はい? –

+0

更新された回答をご覧ください。 – lballes

1

これは、コードの一行が何である:

t = tf.truncated_normal([ nInputUnits, nUnitsHiddenLayer1 ]) 

は切断正規分布の標準偏差として1.0で初期化、形状のTensor [nInputUnits、nUnitsHiddenLayer1]を作成します。

t1 = tf.div(t, math.sqrt(nInputUnits)) 

divideすべてmath.sqrtとTの値(nInputUnits)コードの

あなたの二行とまったく同じことを行う(1.0は標準STDDEV値です)。 1行目と2行目では、すべての値がmath.sqrt(nInputUnits)で除算されます。あなたの文のよう

私は今、これは間違っていることを知っていて、2行目は、重みが各学習段階で再計算されますことを。

確かにあなたが正しいですEDIT私のミス

、それらはすべてのexecuctionでmath.sqrt(nInputUnits)で割った値が、再初期化されていません!ここ

weightsLayer1 = tf.truncated_normal([ nInputUnits, nUnitsHiddenLayer1 ]) 
weightsLayer1 = tf.Variable(tf.div(weightsLayer1, math.sqrt(nInputUnits))) 

2行目は、すべての段階で、予め形成されています:

weightsLayer1 = tf.Variable(tf.truncated_normal([ nInputUnits, nUnitsHiddenLayer1 ]) 
weightsLayer1 = tf.div(weightsLayer1, math.sqrt(nInputUnits)) 

はなぜ二を行うのに重要なポイントは、あなたがtf.variable()

ここで入れ両方の線が一度だけ初期化されているところでありますより良い結果が得られますか?私にはある種の正規化のように見えますが、知識のある人はそのことを確認する必要があります。

ps。 あなたはこのようなことがより読みやすく書くことができます:あなたはweightsLayer1 = tf.div(weightsLayer1, math.sqrt(nInputUnits))は、各ステップで実行されていることを正しい

weightsLayer1 = tf.Variable(tf.truncated_normal([ nInputUnits, nUnitsHiddenLayer1 ] , stddev = 1./math.sqrt(nInputUnits)) 
+0

私は理解しています。 'Y = tf.Variable(2.0)'は、グラフの各実行ステップで 'Y = tf.div(Y、X)'が実行されている間に一度だけ実行される初期化です。あれは正しいですか?もしそうなら、私は物事を一度初期化していますが、2番目の行が各ステップで実行され、重み値がオプティマイザによって計算されたもの以外に変更されるように見えます。 –

関連する問題