ハードウェア技術者のスキルアップ日誌

某家電メーカーの技術者がスキルアップのために勉強したことを記録するブログです

Tensorflowの基本の使い方①

前回はKerasの使い方を整理しました。

masaeng.hatenablog.com

イチからネットワークを作るときはKerasで問題ありません。
しかし、Tensorflowで作られたオープンソースのモデルを修正したい場合、Kerasだけの知識だけでは思い通りのことができないことが多くありました。
そこでTensorflowの低位APIの使い方も勉強していこうと思います。

 

Tensorflowを扱う上での基本の考え方

Tensorflowは処理順にコードを書いていくのではなく、まず初めに計算内容を記述した「計算グラフ」を定義してそのあとに計算処理を実行するという使い方をします。
この考え方が分かっていない状態では公開されているコードを読んでも理解が十分できませんでした。しっかり抑えておきましょう。

計算グラフとは数値と演算の組み合わせでどのような計算をするかを示したものです。一例を以下に示します。これは非常に単純な例ですが、Deep Learningで使用するLayerも計算グラフで表すことができます。

    f:id:masashi_k:20200718230529p:plain

計算グラフは計算処理の内容を表すだけでこれだけでは計算ができません。
計算を実行するときにはセッションというものを用意します。
この時、実際に計算を行うハードウェア(CPU、GPUなど)を指定することも可能。
セッション内で計算するグラフを指定し、計算処理を実行します。

      f:id:masashi_k:20200718231449p:plain

 

グラフの構成要素

グラフがどのような要素で出来ているかを詳しく見ていきます。

数値の型

数値を入れることができる型が3種類あります。数値は1次元に限らず、多次元配列(テンソル)を入れることが可能です。

  1. 定数 tf.constant(value, dtype, shape, name)
     計算の中で変更されない値に使用します。
  2. 変数 tf.Variable(inital_value, name, dtype, expected_shape, constraint)
     グラフの計算の過程で変化する値に使用します。
     (例えば、学習時に更新される重みパラメータなど)
     変数はセッションの最初で初期化する必要があります。
      tf.variables_initializer()
      tf.global_variables_initializer()
  3. プレースホルダー tf.placeholder(dtype, shape, name)}
     データが格納される入れ物でグラフ構築時には値が入っていない。
     セッション実行時に引数feed_dictに値を指定することでその値をグラフに渡す。
演算 tf.Operation()

多次元配列(テンソル)の演算を行います。
具体的には足し算、行列積などの数値計算です。

tensorflowで使用できる演算は公式ドキュメントに記載されています。
https://www.tensorflow.org/api_docs/python/tf/math
https://www.tensorflow.org/api_docs/python/tf/linalg

 

グラフの作り方

上で述べた数値と演算を使ってグラフを作っていきます。

tf.Graph()を準備し、その中で計算したい処理内容を記述します。
ここではグラフの定義を明示的に行っていますが、上の2行はなくても問題ありません。
Tensorflowはデフォルトでグラフが一つ用意されており、何も指定しなければそこにグラフを作っていきます。
下のサンプル中のas_defaultメソッドはこのグラフをデフォルトグラフにするという意味になります。

g = tf.Graph()
    with g.as_default():
        x = tf.constant(1, name="x")
        y = tf.constant(2, name="y")

        z = tf.add(x, y)

 

一方、複数のグラフをそれぞれ定義して使い分けるときは以下のようにします。
それぞれのグラフについてas_default()をつける必要があるので注意

g_1 = tf.Graph()
with g_1.as_default():
  # Operations created in this scope will be added to `g_1`.
  c = tf.constant("Node in g_1")
 
g_2 = tf.Graph()
with g_2.as_default():
  # Operations created in this scope will be added to `g_2`.
  d = tf.constant("Node in g_2")

 

計算の実行

最後に定義した計算グラフを実行します。
tf.Sessonでセッションを構築し、その中でSession.run()を実行することで計算結果を得ることができます。

sess.run()の引数(以下のサンプルではz)は計算結果を得たいテンソルを指定します。
計算グラフの再集団の結果だけではなく、計算の途中のノードでも取り出せます。

グラフの中にplaceholderがある場合は、sess.run()の引数feed_dictでplaceholderに入れる値を渡します。

# グラフを定義 
x = tf.constant(1, name="x")
y = tf.placeholder(tf.int32, name="y")
z = tf.add(x, y)

# セッション構築、実行
with tf.Session() as sess:
    output = sess.run(z, feed_dict={y:3})

 

上記のサンプルでは明示的にグラフの定義をしておらず、デフォルトグラフをセッションで実行しています。複数のグラフを使う場合にはtf.Session()の引数でグラフを指定します。

g_1 = tf.Graph()
with g_1.as_default():
  # Operations created in this scope will be added to `g_1`.
  c = tf.constant("Node in g_1")
 
  # Sessions created in this scope will run operations from `g_1`.
  sess_1 = tf.Session()
 
g_2 = tf.Graph()
with g_2.as_default():
  # Operations created in this scope will be added to `g_2`.
  d = tf.constant("Node in g_2")
 
# Alternatively, you can pass a graph when constructing a `tf.Session`:
# `sess_2` will run operations from `g_2`.
sess_2 = tf.Session(graph=g_2)

 

まとめ

Tensorflowを使う上での基本の考えをまとめてきました。次回はTensorflowでDeep Learningを実行するサンプルを作って、流れを把握できるようにしていきたいと思います。