TECHSTEP

ITインフラ関連の記事を公開してます。

TensorFlow再入門 ~基本の使い方をおさらいする~

はじめに

機械学習で有名なライブラリの一つとしてTensorFlowが挙げられます。昨年は社内勉強会で発表するなどしていたので少しだけ触っていたのですが、なかなか使い方を習得できず苦労していました。 そしてしばらく触っていなかった結果、すっかり使い方を忘れてしまったので、改めて基本的な使い方から復習しています。

注意点

  • 利用するバージョン

今回触っているのはTensorFlow ver1.12.0です。つい最近TensorFlow 2.0のPreview版が発表されましたが、大幅に仕様が変更されており、本記事での書き方の多くの部分は適用できなくなっています。なので使うバージョンには注意しておきましょう。

  • 実行環境

今回はPythonでTensorFlowを動かします。 現在はJavascriptやGoなど様々な環境で利用できるようになっていますが、そちらの紹介はしませんのでご注意ください。

TensorFlowとは

TensorFlowは2015年にGoogleが発表したオープンソース機械学習フレームです。Googleの提供するサービスはもちろんのこと、世界中の企業や研究機関で広く利用されています。TensorFlowの論文によると、もともとはDistBeliefと呼ばれるライブラリから改良されて誕生したようです。特徴として、 大規模な計算処理を行うこと、幅広い環境で実行することを念頭に設計されています。

f:id:FY0323:20190211221330p:plain

TensorFlowを動かす上で必要な要素

それではTensorFlowの使い方を見てみます。 TensorFlowを利用して機械学習を実行する場合の流れは、大まかに言えば以下のようになります。

  1. ライブラリのインポート
  2. データセットの読み込み
  3. データフローグラフの構築
  4. 各変数の初期化
  5. 計算処理の実行
  6. 計算結果の評価

1. ライブラリのインポート

まずは必要なライブラリをインポートします。TensorFlowをインポートして利用する際は「tf」という名前で扱うことが多いです。

2. データセットの読み込み

TensorFlowに限らず機械学習を行うにはデータが必須です。そのため、TensorFlowを実行するにはまずデータを読み込むことが必要です。

データを読み込む際は、Pandasなどを利用することができます。CSVファイルのデータなどをPandasを利用して読み込み、それをそのままTensorFlowで利用できます。

3. データフローグラフの構築

TensorFlowではデータフローグラフと呼ばれる「計算の過程をグラフにして表したもの」を利用します。データフローグラフは定数や変数、そして関数で構成されます。まずデータフローグラフを定義し、それをTensorFlowに取り込み、実際の計算処理は最適化されたC++コードで実行します。

データフローグラフを用いる利点として、「計算処理の高速化」があります。データフローグラフを使うことで局所的な計算を可能にし、無駄なリソース消費を抑えることができます。

またデータフローグラフを使うことでグラフを複数のグループに分割し、そのグループを複数のCPU/GPUで並列に処理することができます。TensorFlowは分散処理もサポートしているため、複数台のサーバを利用して大規模な計算処理も短時間で完了することができます。

また、この段階ではTensorオブジェクトを作成しているだけであり、実際の計算はまだ実行されていません。計算を実行するにはSessionオブジェクトを作成してrunを実行する必要があります。

4. 各変数の初期化

データフローグラフを作成したらそれを実行しますが、その前に各変数を初期化する必要があります。

なぜ初期化が必要かについてははっきりとした理由がわかりませんでしたが、こちらの記事でその理由が推察されていました。

TensorFlowでは、初期化を明示的に実行しないと変数が確保されません。 これは、GPUへのメモリ転送などのオーバーヘッドを避けるためだと思われます。

5. 各関数の実行(実行フェーズ)

変数の初期化を完了したら、作成したデータフローグラフを用いて計算処理を実行します。実際の計算ではまずSessionオブジェクトを作成して、TensorFlow Runtimeと接続する必要があります。

ここを実行することで初めて実際の計算が実行され、スカラー値が返されます。

6. 計算結果の確認・評価

計算処理が完了後、結果を確認します。結果がよくなければ条件を変えて再実行し、望ましい結果が得られるまで繰り返します。

実装

それでは実際の計算処理を実行します。ここでは単純な足し算を実行してみます。

実行環境

  • Google Colaboratory
  • 言語:Python 3.6.7(Colaboratoryの環境に依存)

※Colaboratoryでの実行結果は「>」で表しています。

実際のコード

前述した1から5までの流れに沿って、実際のコードを紹介します。

# ライブラリのインポート
import tensorflow as tf

# データフローグラフの設計
x = tf.constant(3)
y = tf.constant(4)
add = tf.add(x, y)

# 計算処理の実行
sess = tf.Session()
result = sess.run(add)

# 結果確認
print(result)
> 7
1. ライブラリのインポート ~ 3. データフローグラフの構築

ここでは単純な足し算を実行するので、あらかじめデータセットを読み込ませるような処理は行いません。なので、まずはデータフローグラフを定義するところから始めます。

まず定数や変数などを定義するには、tfモジュールに含まれる幾つかの関数を利用できます。主に使用するのは以下の3つです。

tf.constant
  • tf.constant: 定数を定義します。ここでの定数とは「計算の過程で値が更新されないもの」と言う意味です。
    • 使い方:
# デフォルト値
tf.constant(
    value,
    dtype=None,
    shape=None,
    name='Const',
    verify_shape=False
)

# 使用例
# 1次元テンソル
tensor = tf.constant([1, 2, 3, 4, 5, 6, 7]) => [1 2 3 4 5 6 7]

# 2次元テンソル
tensor = tf.constant(-1.0, shape=[2, 3]) => [[-1. -1. -1.]
                                             [-1. -1. -1.]]
tf.Variable
  • tf.Variable: 変数を定義します。定数とは異なり、変数は「計算の過程で値が更新されるもの」です。
    • 使い方:
# デフォルト値
tf.Variable(
    initial_value=None,
    trainable=True,
    collections=None,
    validate_shape=True,
    caching_device=None,
    name=None,
    variable_def=None,
    dtype=None,
    expected_shape=None,
    import_scope=None,
    constraint=None,
    use_resource=None,
    synchronization=tf.VariableSynchronization.AUTO,
    aggregation=tf.VariableAggregation.NONE
)

またtf.Variableとは別にtf.get_variableも変数の定義に利用できます。公式のドキュメントではtf.get_variableの利用を推奨しております

# デフォルト値
tf.get_variable(
    name,
    shape=None,
    dtype=None,
    initializer=None,
    regularizer=None,
    trainable=None,
    collections=None,
    caching_device=None,
    partitioner=None,
    validate_shape=True,
    use_resource=None,
    custom_getter=None,
    constraint=None,
    synchronization=tf.VariableSynchronization.AUTO,
    aggregation=tf.VariableAggregation.NONE
)

tf.Variableとtf.get_variableとでは、既存の変数に対する応答が違います。

  • tf.Variable: 既存の変数を指定した場合は、別名で新たな変数を作成する
  • tf.get_variable: 既存の変数を指定した場合は、その変数を取得する

上記の使い分けについてはこちらの記事が参考になりました。

tf.placeholder
  • tf.placeholder: データを格納します。実際の計算処理を行う際はfeed_dictオプションを利用し、辞書型で指定した値を格納します。
    • 使い方:
# デフォルト値
tf.placeholder(
    dtype,
    shape=None,
    name=None
)

# 使用例
x = tf.placeholder(tf.float32, shape=(1024, 1024))
y = tf.matmul(x, x)

with tf.Session() as sess:
  print(sess.run(y))  # xには何の値も入っていないのでエラーになる

  rand_array = np.random.rand(1024, 1024)
  print(sess.run(y, feed_dict={x: rand_array}))  # xにrand_arrayを挿入して計算を実行

またtf.placeholder_with_defaultを使うと、tf.placeholderに初期値を与えることができます。

# デフォルト値
tf.placeholder_with_default(
    input,
    shape,
    name=None
)
関数の定義

次にデータフローグラフ上の関数を定義するには、上述したtfモジュールにある幾つかの関数に加え、mathモジュールを利用できます。 mathモジュールには現時点で108種類の関数が用意されていますが、ここではごくごく一部のものだけ紹介します。

関数名 内容
tf.add 加算処理を定義する
tf.math.add 加算処理を定義する
tf.subtract 減算処理を定義する
tf.math.subtract 減算処理を定義する
tf.multiply 積算処理を定義する
tf.math.multiply 積算処理を定義する
tf.divide 除算処理を定義する
tf.math.divide 除算処理を定義する
tf.scalar_mul スカラー値の積算処理を定義する
tf.math.scalar_mul スカラー値の積算処理を定義する
tf.matmul 行列式の積算処理を定義する

※tf.addとtf.math.addのように対応する関数はエイリアスであり、使い方は一緒です。

ここでは「3+4=7」の加算処理を定義します。足し算の定義は複数の書き方があるので、例を書きます。

# 足し算の定義その1
add = x + y

# 足し算の定義その2
add = tf.math.add(x, y)

# 足し算の定義その3
add = tf.add(x, y)

ここまでの流れは以下の部分に該当します。

# ライブラリのインポート
import tensorflow as tf

# データフローグラフの設計
x = tf.constant(3)
y = tf.constant(4)
add = tf.add(x, y)
4. 各変数の初期化 ~ 6. 計算結果の確認・評価
tf.initializers

変数の初期化を実行するには、tfモジュールに加えて、initializersモジュールも利用できます。変数ごとに個別に初期化することも可能ですが、すべての変数をまとめて初期化することもできます。

関数名 内容
tf.variables_initializer 引数で与えられた変数を初期化する
tf.initializers.variables 引数で与えられた変数を初期化する
tf.global_variables_initializer グラフに定義されたグローバル変数を初期化する
tf.initializers.global_variables グラフに定義されたグローバル変数を初期化する

※こちらも対応する関数はエイリアスであり、使い方は一緒です。

# 特定の変数の初期化
tf.initializers.variables(
    var_list,
    name='init'
)

# グローバル変数の初期化
tf.initializers.global_variables()

今回は変数は定義していませんので、初期化を実行する必要はありません。

tf.Session

設定したデータフローグラフを使い、実際に計算処理を実行するには、Sessionモジュールを利用します。 runメソッドを実行することで計算処理を実行します。

# デフォルト値
tf.Session(
    target='',
    graph=None,
    config=None
)

tf.Session.run(
    fetches,
    feed_dict=None,
    options=None,
    run_metadata=None
)
tf.metrics

最後に処理結果を確認します。評価にはtf.metricsと言うモジュールも利用できます。

ここまでの流れは以下の部分に該当します。

# 計算処理の実行
sess = tf.Session()
result = sess.run(add)

# 結果確認
print(result)
> 7

まとめ

TensorFlowのごくごく簡単な使い方を書きました。特にデータフローグラフを定義する際に使うモジュール・関数は、調べてみるとたくさんの種類が存在することが分かりました。これを機にこれらの道具について、改めて種類と使いかたを整理しておくと良いかもしれません。

参考リンク

TensorFlowとは? データフローグラフを構築・実行してみよう

TensorFlowの基礎

TensorFlowを遊び倒す! 2-2. Variables: Creation, Initializing, Saving, and Restoring