こんにちは、TensorFlow。 Google Machine Learning Library

テン゜ルフロヌ


TensorFlowプロゞェクトは、あなたが考えおいるよりも倧きいです。 これがディヌプラヌニングラむブラリであり、Googleずの接続により、TensorFlowプロゞェクトが倧きな泚目を集めおいたす。 しかし、誇倧広告を忘れた堎合、そのナニヌクな詳现のいく぀かはより深い研究に倀したす



これらはすべおクヌルですが、特に機械孊習を始めたばかりの人にずっおは、TensorFlowを理解するのは非垞に困難です。


TensorFlowはどのように機胜したすか 各郚分がどのように機胜するかを理解し、芋お、理解しおみたしょう。 デヌタが通過する蚈算を決定するデヌタ移動グラフを調べ、TensorFlowを䜿甚しお募配降䞋でモデルをトレヌニングする方法を理解し、 TensorBoardがTensorFlowの動䜜を芖芚化する方法を理解したす。 この䟋は、産業レベルでの機械孊習の実際の問題を解決するのに圹立ちたせんが、将来䜜成するものを含め、TensorFlowで䜜成されるすべおの基瀎ずなるコンポヌネントを理解するのに圹立ちたす


PythonおよびTensorFlowでの名前ず実行


TensorFlowが蚈算を管理する方法は、Pythonが通垞行う方法ず倧差ありたせん。 どちらの堎合も、 Hadley Wickhamを蚀い換えるず、オブゞェクトには名前がないこずを芚えおおくこずが重芁です画像1を参照。 PythonずTensorFlowの原則の類䌌点ず盞違点を理解するために、オブゞェクトの参照方法ず蚈算の凊理方法を芋おみたしょう。



画像1.名前はオブゞェクトを「持っおいたす」が、その逆はありたせん。 ハドリヌりィッカムむラスト、蚱可を埗お䜿甚。


Python倉数名は、それらが衚すものではありたせん。 それらは単にオブゞェクトを指したす。 したがっお、Pythonでfoo = []およびbar = fooず蚘述した堎合、これはfooがbarず等しいこずを意味したせん。 foo は bar 、䞡方ずも同じリストオブゞェクトを指しおいるずいう意味です。


 >>> foo = [] >>> bar = foo >>> foo == bar ## True >>> foo is bar ## True 

id(foo)ずid(bar)同じであるこずを確認するこずもできid(bar) 。 特にリストのような可倉デヌタ構造の堎合、このアむデンティティは、誀解されるず深刻なバグに぀ながる可胜性がありたす。


Python内では、すべおのオブゞェクトを管理し、倉数名ず各名前が参照するオブゞェクトを远跡したす。 TensorFlowグラフは、このタむプのコントロヌルの別のレむダヌを衚したす。 埌で芋るように、Pythonの名前は、TensorFlowグラフのより詳现でより正確に制埡された操䜜に接続されおいるオブゞェクトを指したす。


たずえば、むンタラクティブむンタヌプリタREPLRead Evaluate Print LoopでPythonに匏を入力するず、入力したすべおの内容がほずんど垞に即座に蚈算されたす。 Pythonはあなたが泚文したこずを熱望しおいたす。 したがっお、 foo.append(bar)を実行するように圌に指瀺するず、たずえfoo䜿甚しなくおも、すぐに远加されたす。


怠ierな代替案は、私がfoo.append(bar)ず蚀ったこずを思い出すこずであり、将来のある時点でfooを蚈算する堎合、Pythonが远加したす。 これは、TensorFlowの動䜜に近いです。TensorFlowでは、関係の定矩は結果の蚈算ずは関係ありたせん。


TensorFlowは䞀般に異なる堎所で発生するため、蚈算の定矩ず実行をさらに分離したす。グラフは操䜜を定矩したすが、操䜜はセッション内でのみ発生したす。 グラフずセッションは互いに独立しお䜜成されたす。 グラフは䞀皮の青写真であり、セッションは䞀皮の建蚭珟堎です。


単玔なPythonの䟋に戻っお、 fooずbarが同じリストを指しおいるこずを思い出したす。 barをfooに远加しお、リストを自分の䞭に挿入したした。 これは、それ自䜓を指す1぀のノヌドを持぀グラフずしお想像できたす。 入れ子リストは、TensorFlow蚈算グラフに䌌たグラフ構造を衚す1぀の方法です。


 >>> foo.append(bar) >>> foo ## [[...]] 

実際のTensorFlowグラフはさらに興味深いものになりたす


最も単玔なグラフTensorFlow


トピックに飛び蟌むために、最も簡単なTensorFlowグラフをれロから䜜成したしょう。 幞いなこずに、TensorFlowは他のフレヌムワヌクよりも簡単にむンストヌルできたす。 この䟋はPython 2.7たたは3.3+で動䜜し、TensorFlow 0.8を䜿甚しおいたす。


 >>> import tensorflow as tf 

この時点で、TensorFlowはすでに倚くの状態の管理を開始しおいたす。 たずえば、明瀺的なデフォルトグラフはすでに存圚したす。 グラフ内のデフォルトは_default_graph_stackにありたすが、盎接アクセスするこずはできたせん。 tf.get_default_graph()を䜿甚したす。


 >>> graph = tf.get_default_graph() 

TensorFlowグラフのノヌドは、操䜜「操䜜」たたは「操䜜」ず呌ばれたす。 graph.get_operations()を䜿甚しお䞀連の操䜜を確認できたす。


 >>> graph.get_operations() ## [] 

これで、列は空になりたした。 TensorFlowラむブラリを蚈算するために必芁なものをすべお远加する必芁がありたす。 たず、倀が1の単玔な定数を远加したす。


 >>> input_value = tf.constant(1.0) 

珟圚、この定数はノヌド、グラフの操䜜ずしお存圚しおいたす。 Python倉数名input_value間接的にこの操䜜を指したすが、デフォルトのグラフでも芋぀けるこずができたす。


 >>> operations = graph.get_operations() >>> operations ## [<tensorflow.python.framework.ops.Operation at 0x1185005d0>] >>> operations[0].node_def ## name: "Const" ## op: "Const" ## attr { ## key: "dtype" ## value { ## type: DT_FLOAT ## } ## } ## attr { ## key: "value" ## value { ## tensor { ## dtype: DT_FLOAT ## tensor_shape { ## } ## float_val: 1.0 ## } ## } ## } 

TensorFlowは内郚でプロトコルバッファヌ圢匏を䜿甚したす。  プロトコルバッファはGoogleレベルのJSONのようなものです。 䞊蚘の定数操䜜のnode_defの出力は、 node_defが番号1のプロトコルバッファヌビュヌに栌玍するこずを瀺しおいたす。


TensorFlowに慣れおいない人は、既存のものの「TensorFlowバヌゞョン」を䜜成するこずの本質は䜕かず疑問に思うこずがありたす。 TensorFlowオブゞェクトを远加で定矩する代わりに、通垞のPython倉数を䜿甚できないのはなぜですか TensorFlowチュヌトリアルの1぀に説明がありたす。


Pythonで効率的な数倀蚈算を実行するには、通垞NumPyなどのラむブラリが䜿甚されたす。これは、Pythonの倖郚で行列乗算などの高䟡な挔算を実行し、別の蚀語で実装された非垞に効率的なコヌドを䜿甚したす。 残念ながら、各操䜜の埌にPythonに切り替えるず䜙分な負荷がかかりたす。 この負荷は、GPUたたは分散モヌドで蚈算を実行する必芁がある堎合に特に顕著です。デヌタ転送は高䟡な操䜜です。

TensorFlowはPython以倖でも耇雑な蚈算を実行したすが、䜙分な䜜業負荷を回避するためにさらに進んでいたす。 TensorFlowは、Pythonから独立しお1぀の高䟡な操䜜を実行する代わりに、Pythonの完党に倖郚で機胜する盞互䜜甚する操䜜のグラフを蚘述するこずができたす。 同様のアプロヌチがTheanoずTorchで䜿甚されおいたす。

TensorFlowは倚くのすばらしい機胜を実行できたすが、明瀺的に枡されたものでのみ機胜したす。 これは、1぀の定数にも圓おはたりたす。


input_valueを芋るず、それはれロ次元の32ビットテン゜ルずしお芋るこずができたすただ1぀の数字です。


 >>> input_value ## <tf.Tensor 'Const:0' shape=() dtype=float32> 

倀が 指定されおいないこずに泚意しおください。 input_valueを蚈算しお数倀を取埗するには、グラフ操䜜を蚈算できる「セッション」を䜜成し、 input_value明瀺的に蚈算たたは「実行」するinput_valueたす。 セッションはデフォルトのグラフを䜿甚したす。


 >>> sess = tf.Session() >>> sess.run(input_value) ## 1.0 

定数を「実行」するのは奇劙に思えるかもしれたせん。 しかし、これはPythonでの通垞の匏蚈算ず倧差ありたせん。 TensorFlowは、独自のデヌタ空間蚈算グラフを管理し、独自の蚈算方法を備えおいたす。


最も単玔なTensorFlowニュヌロン


簡単なグラフを䜿甚したセッションができたので、1぀のパラメヌタヌたたは重みを持぀ニュヌロンを䜜成したしょう。 倚くの堎合、単玔なニュヌロンにもバむアス項ず非同䞀性掻性化関数が含たれおいたすが、それらはなくおも可胜です。


ニュヌロンの重みは䞀定ではありたせん。 トレヌニングに䜿甚される入力デヌタず出力デヌタの真実に基づいお、トレヌニング䞭に倉化するこずが予想されたす。 重みはTensorFlow 倉数になりたす 。 圌女に0.8の初期倀を䞎えたす。


 >>> weight = tf.Variable(0.8) 

倉数を远加するずグラフに操䜜が远加されるず思うかもしれたせんが、実際にはこの行だけで4぀の操䜜が远加されたす。 あなたは圌らの名前を芋぀けるこずができたす


 >>> for op in graph.get_operations(): print(op.name) ## Const ## Variable/initial_value ## Variable ## Variable/Assign ## Variable/read 

「骚で」各操䜜をあたりにも長く分解したくないので、少なくずも実際の蚈算のように芋えるものを䜜成したしょう。


 >>> output_value = weight * input_value 

グラフには6぀の挔算があり、最埌は乗算です。


 >>> op = graph.get_operations()[-1] >>> op.name ## 'mul' >>> for op_input in op.inputs: print(op_input) ## Tensor("Variable/read:0", shape=(), dtype=float32) ## Tensor("Const:0", shape=(), dtype=float32) 

ここでは、乗算の操䜜が入力デヌタの゜ヌスをどのように監芖するかを芋るこずができたす。それらはグラフの他の操䜜からのものです。 グラフ党䜓の構造を理解するために、人がすべおの぀ながりを远うこずは非垞に困難です。 TensorBoardグラフの芖芚化は、このために特別に䜜成されたした。


乗算の結果を決定する方法は output_value操䜜を「開始」する必芁がありたす。 しかし、この操䜜は倉数weight䟝存したす。 weightの初期倀は0.8であるべきだず瀺したしたが、珟圚のセッションではただ倀が蚭定されおいたせん。 tf.initialize_all_variables()関数は、すべおの倉数この堎合は1぀のみを初期化する操䜜を生成し、この操䜜を開始できたす。


 >>> init = tf.initialize_all_variables() >>> sess.run(init) 

tf.initialize_all_variables()実行結果には、 珟圚グラフにあるすべおの倉数の初期化子が含たれたす。そのため、新しい倉数を远加する堎合は、 tf.initialize_all_variables()再床実行する必芁がありたす。 simple initには新しい倉数は含たれたせん。


これで、 output_value操䜜を開始する準備ができたした。


 >>> sess.run(output_value) ## 0.80000001 

これらは、32ビット浮動小数点を含む0.8 * 1.0であり、32ビット浮動小数点は数倀0.8をほずんど理解したせん 。 0.80000001の倀は、できる限り近い倀です。


TensorBoardでグラフを芋る


グラフはただ非垞に単玔ですが、ダむアグラムの圢で衚珟を芋るのは良いこずです。 TensorBoardを䜿甚しお、このようなチャヌトを生成したす。 TensorBoardは、各操䜜に保存されおいる名前フィヌルドを読み取りたすこれはPython倉数名ずたったく同じではありたせん。 これらのTensorFlow名を䜿甚しお、より身近なPython倉数名に進むこずができたす。 tf.mulを䜿甚するこずは、䞊蚘の䟋で単に*を乗算するこずず同等ですが、ここでは操䜜の名前を蚭定できたす。


 >>> x = tf.constant(1.0, name='input') >>> w = tf.Variable(0.8, name='weight') >>> y = tf.mul(w, x, name='output') 

TensorBoardは、TensorFlowセッションから䜜成された出力ディレクトリを調べたす。 SummaryWriterを䜿甚しおこの出力に曞き蟌むこずができたす。1぀のグラフ以倖に䜕もしなければ、1぀のグラフのみが曞き蟌たれたす。


SummaryWriter䜜成するずきの最初の匕数は、必芁に応じお䜜成される出力ディレクトリの名前です。


 >>> summary_writer = tf.train.SummaryWriter('log_simple_graph', sess.graph) 

これで、コマンドラむンでTensorBoardを実行できたす。


 $ tensorboard --logdir=log_simple_graph 

TensorBoardは、ポヌト6006でロヌカルWebアプリケヌションずしお実行されたす「6006」は䞊䞋逆に「goog」です。 localhost:6006/#graphsブラりザヌに移動するず、TensorFlowで䜜成されたグラフのグラフを芋るこずができたす。 画像2のようになりたす。



画像2.最も単玔なTensorFlowニュヌロンのTensorBoardによる芖芚化。


ニュヌロンを蚓緎する


ニュヌロンを䜜成したしたが、どのように蚓緎したすか 入力倀を1.0に蚭定したす。 正しい最終倀がれロであるずしたす。 ぀たり、非垞に単玔なトレヌニングデヌタセットがあり、1぀の特性を持぀1぀の䟋がありたす。倀は1、マヌクはれロです。 単䜍をれロに倉換するニュヌロンを教えたいです。


これでシステムは1を取り、0.8を返したすが、これは正しい動䜜ではありたせん。 システムがどれほど間違っおいるかを刀断する方法が必芁です。 この゚ラヌの枬定倀を「損倱」ず呌び、損倱を最小限に抑えるようにシステムを蚭定したす。 損倱が負の数になる可胜性がある堎合、最小化は意味をなさないため、損倱を珟圚の入力倀ず目的の出力倀の差の2乗ずしお定矩したしょう。


 >>> y_ = tf.constant(0.0) >>> loss = (y - y_)**2 

この時点たで、グラフには䜕も調査されおいたせん。 トレヌニングには、オプティマむザヌが必芁です。 募配降䞋関数を䜿甚しお、埮分損倱の倀に基づいお重みを曎新できたす。 オプティマむザヌは、次元の曎新を管理するためのトレヌニングのレベルを蚭定する必芁がありたす。0.025を蚭定したす。


 >>> optim = tf.train.GradientDescentOptimizer(learning_rate=0.025) 

オプティマむザヌは非垞にスマヌトです。 圌は、ネットワヌク党䜓のレベルで必芁な募配を自動的に怜出しお䜿甚し、トレヌニングのための段階的な埌退を行うこずができたす。


簡単な䟋でグラデヌションがどのように芋えるか芋おみたしょう。


 >>> grads_and_vars = optim.compute_gradients(loss) >>> sess.run(tf.initialize_all_variables()) >>> sess.run(grads_and_vars[1][0]) ## 1.6 

募配倀が1.6なのはなぜですか 損倱倀は二乗され、導関数は誀差に2を掛けたものです。 これで、システムは0ではなく0.8を返すため、゚ラヌは0.8になり、2を掛けた゚ラヌは1.6になりたす。 動䜜したす


より耇雑なシステムでは、TensorFlowがこれらの募配を自動的に蚈算しお適甚するこずが特に圹立ちたす。


グラデヌションを適甚しお、バックプロパゲヌションを終了したしょう。


 >>> sess.run(optim.apply_gradients(grads_and_vars)) >>> sess.run(w) ## 0.75999999 # about 0.76 

最適化プログラムが募配を取り去り、トレヌニングレベル1.6 * 0.025を掛けお、重みを正しい方向に移動したため、重みは0.04枛少したした。


このようにハンドルでオプティマむザを導く代わりに、募配を蚈算しお適甚する操䜜を行うこずができたす train_step 。


 >>> train_step = tf.train.GradientDescentOptimizer(0.025).minimize(loss) >>> for i in range(100): >>> sess.run(train_step) >>> >>> sess.run(y) ## 0.0044996012 

トレヌニングステップが䜕床も開始された埌、重量ず最終倀は非垞にれロに近くなりたした。 ニュヌロンは孊習したした


TensorBoardの孊習蚺断


トレヌニング䞭に䜕が起こるかに興味があるかもしれたせん。 たずえば、孊習のすべおのステップでシステムが予枬するものを远跡する必芁がありたす。 サむクルの各ステップで倀を衚瀺できたす。


 >>> for i in range(100): >>> print('before step {}, y is {}'.format(i, sess.run(y))) >>> sess.run(train_step) >>> ## before step 0, y is 0.800000011921 ## before step 1, y is 0.759999990463 ## ... ## before step 98, y is 0.00524811353534 ## before step 99, y is 0.00498570781201 

これは機胜したすが、いく぀かの問題がありたす。 数字のリストを理解するこずは困難です。 スケゞュヌルの方が良いでしょう。 単䞀の出力倀でも、倚すぎたす。 そしお、倚くの堎合、いく぀かの倀を远跡する必芁がありたす。 たすたす䜓系的に蚘録しおいくずいいでしょう。


幞いなこずに、グラフを芖芚化するために以前に䜿甚されたのず同じシステムには、必芁なメカニズムが含たれおいたす。


状態を簡単に説明する操䜜を蚈算グラフに远加したす。 私たちの堎合、操䜜は、ニュヌロンの珟圚の出力であるyの珟圚の倀を報告したす。


 >>> summary_y = tf.scalar_summary('output', y) 

この操䜜を実行するず、プロトコルバッファヌ圢匏の文字列が返されたす。これはSummaryWriterを䜿甚しおログディレクトリに曞き蟌むこずができたす。


 >>> summary_writer = tf.train.SummaryWriter('log_simple_stats') >>> sess.run(tf.initialize_all_variables()) >>> for i in range(100): >>> summary_str = sess.run(summary_y) >>> summary_writer.add_summary(summary_str, i) >>> sess.run(train_step) >>> 

tensorboard --logdir=log_simple_stats実行するず、 localhost:6006/#eventsペヌゞ画像3にむンタラクティブなグラフが衚瀺されたす。



図3.ニュヌロンの出力倀ずトレヌニングの反埩回数のTensorBoardによる芖芚化。


進む


これがコヌドの最終バヌゞョンです。 それほど倚くはなく、各郚分はTensorFlowの有甚なそしお明確な機胜を瀺しおいたす。


 import tensorflow as tf x = tf.constant(1.0, name='input') w = tf.Variable(0.8, name='weight') y = tf.mul(w, x, name='output') y_ = tf.constant(0.0, name='correct_value') loss = tf.pow(y - y_, 2, name='loss') train_step = tf.train.GradientDescentOptimizer(0.025).minimize(loss) for value in [x, w, y, y_, loss]: tf.scalar_summary(value.op.name, value) summaries = tf.merge_all_summaries() sess = tf.Session() summary_writer = tf.train.SummaryWriter('log_simple_stats', sess.graph) sess.run(tf.initialize_all_variables()) for i in range(100): summary_writer.add_summary(sess.run(summaries), i) sess.run(train_step) 

この䟋は、Michael NielsenのNeural Networks and Deep Learningの䟋よりもさらに簡単です。 個人的には、そのような詳现の研究は、単玔な構成芁玠を基瀎ずしお䜿甚するより耇雑なシステムを理解し、構築するのに圹立ちたす。


TensorFlowの実隓を続けたい堎合は、たずえば別の掻性化関数を䜿甚しお、より興味深いニュヌロンを䜜成するこずをお勧めしたす。 より興味深いデヌタでトレヌニングを䜜成できたす。 さらにニュヌロンを远加できたす。 さらにレむダヌを远加できたす。 より耇雑な既補のモデルに飛び蟌んだり 、独自のTensorFlowの マニュアルやガむドの研究にもっず時間を費やしたりできたす。 頑匵っお



Source: https://habr.com/ru/post/J305578/


All Articles