デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理と英語を基礎からやり直す。https://qiita.com/yaju

TensorFlowコトハジメ 概要

はじめに

静岡Developers勉強会では、今年の勉強会のテーマとして「人工知能ハンズオン」を2016/4/23に開催します。
これまでインストール記事ばかりで中身が書けていなかったので、概要から書いていきます。

TensorFlowとは

読み方は「テンソルフローテンサーフロー」となります。【2017/02/18 訂正】googleの中の人がテンサーフローと呼んで欲しい
Googleが2015年11月10日に公開したオープンソース多層NN(ディープラーニング)に特化したライブラリで現状C++/PythonでのAPIが存在しています。
Tensor(テンソル)のFlow(流れ)で状態記述します。

ディープラーニングやマシーンラーニングの使いやすいライブラリが整ってはいるものの、それらに特化したフレームワークではなく、多次元配列に入る数字を非常に高速に計算するための汎用のHPCフレームワークとしても使うことができます。

Tensor(テンソル)とは

テンソル(英: tensor, 独: Tensor)とは、 線形的な量または線形的な幾何概念を 一般化したもので、基底を選べば、多次元の配列として表現できるようなものである。 Wikipedia

乱暴に言えば多次元配列に相当する

  • 添え字のついた変数(配列)
    { X_{ij} } { Z_{ijk} }
  • スカラー、ベクトル、行列の一般名

f:id:Yaju3D:20160417104606p:plain

テンソルデータ例

  • 濃淡画像  ・・・ 2階のテンソル
  • カラー画像 ・・・ 3階のテンソル(RGB x 濃淡画像)
  • カラー動画 ・・・ 4階のテンソル(フレーム x カラー画像)

可視化する限度は3階までが限界
f:id:Yaju3D:20160417031730p:plain
図1: ユーザ × 商品 × 時間の3階テンソルとして表現された購買データ
テンソルというのはテーブル形式のデータを多次元に拡張したもので、例えば、複数のユーザがいくつかの種類の商品をある時刻に購入したという購買データを考えるとユーザ × 商品 × 時間の3階テンソルとして表現することができます。

また、テンソルとはごく簡単にいえば「任意座標系で表した量」ということになります。図1だと、購入商品(item)の3個(Qty)が量となります。

f:id:Yaju3D:20160417025250p:plain
他にも2次元画像をRGBに分解して、任意座標のピクセル値(R * 2562 + G * 256 + B)が量となります。

Tensor(テンソル)の計算

高校の数学で行列同士の計算(加算、減算、積、商(逆行列))を習いますが、テンソル同士も行列と同じように計算することが出来ます。計算方法はここでは説明しません。 参照:TensorFlow APIドキュメントを眺める -Math編-

計算例 [1.1.1.1.]+[2.2.2.2.]=[3.3.3.3.]

import tensorflow as tf

with tf.Session():
  input1 = tf.constant([1.0, 1.0, 1.0, 1.0])
  input2 = tf.constant([2.0, 2.0, 2.0, 2.0])
  output = tf.add(input1, input2)
  result = output.eval()
  print(result)

#[ 3.  3.  3.  3.]
畳み込み演算とは?

「畳む」…複数ヶ所(連続的)から値を持ってくる
「込む」…積算する
掛け算の結果を足し集める演算からなり、大量な計算が必要になることからコンピュータ処理の得意とするところです。
数学用語ではコンボリューション(Convolution)といいます。

畳み込み演算の簡単な例として、画像処理ソフトウェアで画像を「ぼかす」フィルターをかける場合を考えます。これは、画像の各ピクセルにおいて、その部分の色をその周りのピクセルの色とまぜて平均化した色に置き換えれば実現できます。その際の掛け算の係数は、3×3などのサイズのマトリックスで指定します。参照:空間フィルタリング処理 f:id:Yaju3D:20160417025351p:plain 3×3サイズのマトリックスを1ピクセルずらしながら演算する。
f:id:Yaju3D:20160417025404g:plain
畳み込み結果の画像が入力サイズより一回り小さくなります。もし同サイズにしたい場合には外側に「ふち」をつけて大きくします。
「ふち」の部分の画素は未定なので何らかの方法(最周囲の画素等)で決める必要があります。

TensorFlowの計算処理

テンソルを計算するには、かなりの計算量が必要となります。CPUが複数あれば並列で計算させることで結果が速く出せますし、GPUを使えば多くの計算結果が速く導くことが可能となります。またクラウドを使って、1台ではなく複数台のコンピューターに分散させればそれだけ速く計算結果を求めることが出来るのです。
そのために、TensorFlowは計算処理を「データフローグラフ」(以降 略:グラフ(Graph))構造で表します。

グラフとは

グラフはノード(Node)といわれる計算ブロックのようなものをエッジ(edge)といわれる線で繋げたもので、データはノードからノードへ、エッジのつながり方に従って受け渡され、計算が行われます。 f:id:Yaju3D:20160417025430p:plain

Opノード

TensorFlowではノードは「op」(operation:計算操作の略)と言われます。 f:id:Yaju3D:20160417025458p:plain

セッション

グラフはセッションに割り当てて計算を行います。セッションは、計算可能になったノード(エッジから送られてくる計算結果がすべてそろったノード)を非同期/並列に計算していきます。
計算に際しては、どのデバイス(cpu/gpu)で行うのかの割振りも行います。 f:id:Yaju3D:20160417025520p:plain

計算方法

TensorFlowでは計算処理は2フェイズ(Define & Run)で行います。

  • Define(定義)
    計算のグラフモデルを構築するフェイズで、この時点では計算結果は確定しない
  • Run(実行)
    グラフモデルから計算結果を確定するフェイズでセッション(Session)にモデルを投入し、計算結果を得る
TensorFlowによる計算プログラム

Pythonの通常の計算プログラム

x = 35
y = x + 5
print(y)

TensorFlowで同じように計算プログラム

import tensorflow as tf

x = tf.constant(35, name='x')
y = tf.Variable(x + 5, name='y')

print(y)

これを実行するとエラー<tensorflow.python.ops.variables.Variable object at 0x7f074bfd9ef0>になります。
これはモデルを定義しただけでは計算が出来ないためです。
計算処理は2フェイズ(Define & Run)する必要があり修正したのが下記となります。

import tensorflow as tf

x = tf.constant(35, name='x')
y = tf.Variable(x + 5, name='y')

# 変数を初期化するための OP を追加します。
model = tf.initialize_all_variables()

with tf.Session() as session:
    session.run(model)
    print(session.run(y)

実際にデータを処理するにはtf.Sessionを使います。セッションの最初に変数を初期化する必要があり、これには「tf.initialize_all_variables」を使います。
これにより計算結果「40」が表示されます。
参照:http://learningtensorflow.com/lesson2/

参照

テンソル分解の基礎と 画像・信号処理への応用 - SlideShare
TensorFlowで遊んでみよう! - SlideShare
Generalization of Tensor Factorization and Applications SlideShare
Bci deep learning_juas - SlideShare
第13回助教の会
コンボリューションを用いた画像の平滑化、鮮鋭化とエッジ検出
Image Scaling using Deep Convolutional Neural Networks
How common is it for neural networks to be represented by tensors of rank 3 or greater?
TensorFlow Tutorialの数学的背景 − Deep MNIST for Experts(その1)- めもめも
4.たたみ込み演算による画像処理
TensorFlowを算数で理解する
TensorFlowのキーコンセプト: Opノード、セッション、変数

TensorFlowコトハジメ フィボナッチ数列

はじめに

前回、TensorFlowの概要記事を書いた。概要としてはまだ足りないのだが、次に進まないとならない。
TensorFlowのプログラムを組むのに簡単な例として、フィボナッチ数列が良さそうなので、これを題材として理解してみる。

ネットで検索したフィボナッチ数列のPython用プログラムを参考とする。
参照:Python(11)再帰のお勉強:フィボナッチの数列

フィボナッチ数列(Fibonacci number)とは

1+1=2、1+2=3、2+3=5、3+5=8… と、前項2つを加えて、次々とできる数の列のことをフィボナッチ数列といいます。
f:id:Yaju3D:20160417173452p:plain
このフィボナッチ数列の隣接する2つの数の比は限りなく黄金比に近づいています。花びらの数、葉のつき方など自然界にもこの周期が現れるものも多くあります。 また、名刺の縦横比、建物や絵画、彫刻などのバランスの美しさにも、この黄金比が現れていることが多いのです。
blog.livedoor.jp

{F_{0}=0}
{F_{1}=1}
{F_{n}=F_{n-1}+F_{n-2}} {(n>1)}

この漸化式で表せる数列です。
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, …

プログラム 1

d136o/tensor_overflow.py

import argparse
import tensorflow as tf
import sys

def flowfib(n):
    # f_n = f_n-1 + f_n-2
    f = [tf.constant(0),tf.constant(1)]
    
    if n>2:
        for i in range(2,n):
            f_i = f[i-1] + f[i-2]
            f.append(f_i)
    
    with tf.Session() as sess:
        result = sess.run(f)
        print(result)

flowfib(20)

#[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]

説明

[TensorFlow] APIドキュメントを眺める -Tensor編-

整数リテラルを使って生成した Tensor については tf.int32 が要素の数値型として適用される模様です。

import tensorflow as tf
a = tf.constant(0)
a.dtype

# tf.int32

appendは、Pythonの要素追加メソッドです。

f.append(f_i)

プログラム 2

qiita.com

import tensorflow as tf

u = tf.Variable(tf.cast(1,"int64"))
v = tf.Variable(tf.cast(0,"int64"))

update_u = tf.assign(u, tf.add(u,v)) # u = u + v
update_v = tf.assign(v, tf.sub(u,v)) # v = u - v

init = tf.initialize_all_variables()

with tf.Session() as sess:
    sess.run(init)
    for i in range(100):
        print(i, sess.run(v))
        sess.run(update_u)
        sess.run(update_v)

説明

定義の値の更新の代入にはtf.assignを使う。足し算(tf.add)、引き算(tf.sub)を使う。 https://www.tensorflow.org/versions/0.6.0/api_docs/python/state_ops.html#assign

update_u = tf.assign(u, tf.add(u,v)) # u = u + v
update_v = tf.assign(v, tf.sub(u,v)) # v = u - v

セッションの最初に変数を初期化する必要がある。これには、init = tf.initialize_all_variablesを使う。sess.run(init)にて初期化を実行する。

init = tf.initialize_all_variables()

sess.run(init)

sess.runにより値を取ったり、手続きを実行したりします。

print(i, sess.run(v)) #値の取得
sess.run(update_u)   #定義の実行
sess.run(update_v)   #定義の実行

最後に

モデルを定義してから実行するというのが、今までの習っていたプログラムと違うので、慣れる必要がありますね。 mirai-tec.hatenablog.com

スポンサーリンク