web-dev-qa-db-ja.com

TensorFlowでNaN値をデバッグするにはどうすればよいですか?

TensorFlowを実行していて、NaNを生成するものがありました。私はそれが何であるか知りたいのですが、これを行う方法がわかりません。主な問題は、「通常の」手続き型プログラムでは、操作が実行される直前にprintステートメントを書くだけだということです。 TensorFlowの問題は、最初にグラフを宣言(または定義)するため、これを行うことができないため、グラフ定義にprintステートメントを追加しても役に立たないことです。 NaNを引き起こしている可能性があるものを追跡するためのルール、アドバイス、ヒューリスティック、何かがありますか?


この場合、私は以下を持っているので、どの行を見るべきかをより正確に知っています:

_Delta_tilde = 2.0*tf.matmul(x,W) - tf.add(WW, XX) #note this quantity should always be positive because its pair-wise euclidian distance
Z = tf.sqrt(Delta_tilde)
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)
A = tf.exp(Z) 
_

この行が存在する場合、サマリーライターが宣言したとおりにNaNを返します。どうしてこれなの? Zが平方根化された後、Zがどのような値を持つかを少なくとも探索する方法はありますか?


私が投稿した特定の例では、tf.Print(0,Z)を試しましたが、成功しませんでしたが、何も印刷されませんでした。次のように:

_Delta_tilde = 2.0*tf.matmul(x,W) - tf.add(WW, XX) #note this quantity should always be positive because its pair-wise euclidian distance
Z = tf.sqrt(Delta_tilde)
tf.Print(0,[Z]) # <-------- TF PRINT STATMENT
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)
A = tf.exp(Z) 
_

私は実際に_tf.Print_が何をすべきかを理解していません。なぜ2つの引数が必要なのですか? 1つのテンソルを印刷したい場合、なぜ2を渡す必要がありますか?私には奇妙に思えます。


私は関数を見ていました tf.add_check_numerics_ops() しかし、それはそれを使用する方法を言っていません(加えて、ドキュメントはあまり役に立たないようです)。誰もこれの使い方を知っていますか?


私はデータが悪いかもしれないと述べたコメントを持っているので、標準のMNISTを使用しています。ただし、正の量(ペアワイズエイクレイディアン距離)を計算し、それを平方根化しています。したがって、データが具体的にどのように問題になるかはわかりません。

43
Pinocchio

NaNの結果を取得できる理由はいくつかあります。多くの場合、学習率が高すぎるためですが、入力キューのデータの破損や0の計算ログなど、他の多くの理由が考えられます。

とにかく、あなたが説明するような印刷でのデバッグは、単純な印刷では行えません(これにより、グラフ内のテンソル情報が印刷されるだけで、実際の値は印刷されません)。

ただし、tf.printをグラフのバルディングのopとして使用すると( tf.print )、グラフが実行されると、実際の値が印刷されます(そして、ISこれらの値を見て、ネットの動作をデバッグして理解するための良い練習です。

ただし、print-statementを完全に正しい方法で使用しているわけではありません。これはopであるため、テンソルを渡し、実行中のグラフで後で作業する必要がある結果テンソルを要求する必要があります。そうでない場合、opは実行されず、印刷は行われません。これを試して:

Z = tf.sqrt(Delta_tilde)
Z = tf.Print(Z,[Z], message="my Z-values:") # <-------- TF PRINT STATMENT
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)
22
Phillip Bock

以前は、バグを修正するよりもnanとinfsが発生する可能性のある場所を特定する方がはるかに難しいと感じていました。 @scaiの答えを補完するものとして、ここにいくつかのポイントを追加したいと思います。

デバッグモジュールは、次の方法でインポートできます。

from tensorflow.python import debug as tf_debug

印刷や表明よりもはるかに優れています。

次の方法でセッションのラッパーを変更するだけで、デバッグ機能を追加できます。

sess = tf_debug.LocalCLIDebugWrapperSession(sess)
sess.add_tensor_filter("has_inf_or_nan", tf_debug.has_inf_or_nan)

そして、コマンドラインインターフェイスを要求し、次のように入力します:run -f has_inf_or_nanおよびlt -f has_inf_or_nan nansまたはinfsの場所を見つけます。最初のものは、大惨事が発生する最初の場所です。変数名によって、コード内のOriginをトレースできます。

リファレンス: https://developers.googleblog.com/2017/02/debug-tensorflow-models-with-tfdbg.html

9
Lerner Zhang

グラフの作成が完了した後に呼び出すことができるようです。

check = tf.add_check_numerics_ops()

これにより、すべての浮動小数点演算のチェックが追加されると思います。次に、セッション実行機能で、チェック操作を追加できます。

sess.run([check, ...])

8
chasep255

バージョン0.12の時点で、TensorFlowにはtfdbgという組み込みデバッガーが付属しています。このタイプの不正な数値の問題(infnanなど)のデバッグのワークフローを最適化します。ドキュメントは次の場所にあります。 https://www.tensorflow.org/programmers_guide/debugger

7
scai

まず、入力データを適切に確認する必要があります。ほとんどの場合、これが理由です。もちろん、常にではありません。

私は通常、Tensorboardを使用して、トレーニング中に何が起こっているかを確認します。だから、各ステップの値を見ることができます

Z = tf.pow(Z, 2.0)    
summary_z = tf.scalar_summary('z', Z) 
#etc..
summary_merge = tf.merge_all_summaries()
#on each desired step save: 
    summary_str = sess.run(summary_merge)
    summary_writer.add_summary(summary_str, i)

また、現在の値を単純に評価して出力できます。

 print(sess.run(Z))
3
Alex Joz

ネットワークモデル内のすべてのドロップアウトレイヤーを削除することで、NaNの問題を修正できました。何らかの理由でネットワーク内のユニット(ニューロン?)が多くの入力接続を失ったため(ドロップアウト後にゼロになったため)、情報がフィードスルーされたときの値はNaNだったと思われます。それぞれ100ユニットを超えるレイヤーでdropout = 0.8を使用すると、それが何度も発生する可能性はありません。そのため、問題はおそらく別の理由で修正されました。いずれにしても、ドロップアウトレイヤーをコメントアウトすると、問題が解決しました。

編集:おっと! 3つのユニットで構成される最終出力レイヤーの後にドロップアウトレイヤーを追加したことに気付きました。今ではもっと理にかなっています。だから、それをしないでください!

1
sOvr9000

tfdbg.has_inf_or_nanの現在の実装は、NaNを含むテンソルにヒットしてもすぐには壊れないようです。停止すると、表示されるテンソルの巨大なリストはnot実行順にソートされます。 Nansの最初の出現を見つけるためのハックの可能性は、すべてのテンソルを一時ディレクトリにダンプし、後で検査することです。これを行うためのクイックとダーティ を次に示します。 (NaNsが最初の数回の実行で表示されると仮定)

0
Yuq Wang