年収100兆円を目指して機械学習を学ぶシリーズです。
そういえばTensorflowは正しくはTensorFlowだということに気付いたけど、もうタイトル変更するのが面倒なのでTensorflowで押し切ることにします。
グラフ定義 -- 計算の定義と実行の分離というパラダイム
さて、Tensorflowでは Tensor
を扱うわけだけど、最近のプログラミング言語のパラダイムとして受け入れられつつある、計算の定義と実行の分離が採用されている。どういうことかというと、まず Tensor
計算グッズを グラフ として組み合わせたものを定義しておいて、最終的にそれに入力となる Tensor
を突っ込んで実行すると Tensor
が得られる、という仕組みになっている。つまり、都度計算するのではなく、手順だけ先に教えて最後にガッと計算してもらおう、という考え方。
グラフを組み立てるのに用いる「Tensor
を計算した結果が入るはずのもの(まだ未計算)」を表現するモデルとして、 Output
というクラスが用意されていて、ユーザはこの Output
を組み立てることでより大きな Output
を形作り、最終的に Tensor
を入力して計算を行う、という手筈になっている。Scala標準の Future
にちょっと似てますな。
そして Output
もまた Tensor
同様に Shape
といった属性を持っているので、実質 Tensor
として扱うことができる。唯一の違いはまだ計算されていないことだけ。(計算の種類によっては、実行時に初めてShapeが判明するケースもあるとのこと。)
余談だが、計算の定義と実行の分離を採用しているライブラリやフレームワークとしては、Cats Effect (IOモナドを導入している) やAkka Streams (Graphを構築してからデータを投入する) などが挙げられる。このモデルを採用する利点は、組み立ててから実行するので計算順序がこんがらがったりしないし、ランタイムがある程度実行順序に介入できるため最適化の余地が生まれること。
チュートリアル
余談はさておき、チュートリアルをやっていきましょう。
って思ったけど、チュートリアルがスカスカで何も分からないぜ!
オレオレチュートリアル
しょうがないのでテストとか本家Tensorflowのドキュメントを見て勘で使い方を勉強するコーナーが始まるぜ。
ネットに良さげなチュートリアルが転がってたからこれを見るぜ。
Session
グラフを定義する前に、まず Session
という概念について知っておく必要があるみたいだ。
Session
とはグラフの実行環境のハンドラである。 Cats Effect とか Akka とかをやっていると、あ〜 ExecutionContext
みたいなもんですねと納得いくと思うのだが、一応説明しておく。
先程説明した通り Tensorflow では計算の定義と実行が分離されているので、計算の定義とは別に、実行側のメカニズムを明示的に用意してやる必要がある。それが Session
である。言い換えると Output
実際に実行する君みたいな感じだ。Tensorflow でグラフを実行するときは、この Session
を作成して実行してもらうことになるというわけ。
Session
は org.platanios.tensorflow.tensorflow.api.core.client.Session
に定義されている。
import org.platanios.tensorflow /* ... */ println("session") import tensorflow.api.core.client.Session val sess = Session() val o1 = Tensor[Int](Seq(Seq(1, 2), Seq(3, 4))).toOutput val o2 = Tensor[Int](Seq(Seq(1, 2), Seq(3, 4))).toOutput val o1o2 = o1 * o2 val t1t2 = sess.run(fetches = Seq(o1o2)) println(t1t2.summarize()) sess.close()
session 2022-12-31 19:39:54.156088: I tensorflow/compiler/jit/xla_gpu_device.cc:99] Not creating XLA devices, tf_xla_enable_xla_devices not set 2022-12-31 19:39:54.274911: I tensorflow/core/platform/profile_utils/cpu_utils.cc:112] CPU Frequency: 2699905000 Hz Tensor[Int, [1, 1, 2, 2]] [[[[1, 4], [9, 16]]]]
なんか勘で書いたら動いた。天才かな?
これも勘だけど、定義とcloseがあるってことはスコープを切った賢い振舞いができるのでは?と思ったけど難しかったので諦めた。
基本的に、即値である Tensor
の類は Output
に変換することができるので、入力するテンソルを変換してからSession.run
に渡してやると良さそう。
さて、機械学習をやるからには単にテンソルを計算するだけではなくて、学習、すなわちモデル中の変数を最適化したり、プレースホルダ機能を使ってエンドユーザからの入力を受け付けていくことになるのだけれど、これはまた次回。