背景
ClojureとはJavaの処理系で動作するLisp言語の一つです。TensorFlowとは、Googleが開発している機械学習プログラムです。
TensorFlowがJava APIを提供しているので、Javaで書かれた物体認識プログラムをClojureに書き換えて動かしてみました。
書き換えに戸惑う部分があったので、動かし方と共に共有します。
使ったもの
cljコマンドが実行できる環境cljプロジェクトを作成
この記事では~/gitprojectsというディレクトリの中にclj-tensorflow-practiceというプロジェクトを作り、そのプロジェクトで物体認識プログラムを動かします。mkdir -p ~/gitprojects/clj-tensorflow-practice cd ~/gitprojects/clj-tensorflow-practice
TensorFlowを利用できるように、下記のようなednファイルを作成します。
~/gitprojects/clj-tensorflow-practice/deps.edn
{:deps {org.tensorflow/tensorflow {:mvn/version "1.8.0"}}}
動作確認用プログラムを作成・実行
TensorFlow for Javaのインストール手順で紹介されているプログラムをClojureで書き換えて、TensorFlowが動いていることを確認しました。
~/gitprojects/clj-tensorflow-practice/src/hello_tf.clj
(ns hello-tf (:import [org.tensorflow Graph Session Tensor TensorFlow])) (defn -main [] (let [g (new Graph) value (str "Hello from " (TensorFlow/version)) t (Tensor/create (byte-array (map byte value))) _ (-> (.opBuilder g "Const" "MyConst") (.setAttr "dtype" (.dataType t)) (.setAttr "value" t) .build) output (-> (new Session g) .runner (.fetch "MyConst") .run (.get 0))] (prn (String. (.bytesValue output)))))
下記のようなコマンドで実行できました。
cd ~/gitprojects/clj-tensorflow-practice clj -m hello-tf
学習済みデータをダウンロード
物体認識プログラムを動かす前に、Googleが提供している学銃済みデータをダウンロードします。cd ~/gitprojects/clj-tensorflow-practice mkdir data cd data wget https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip unzip inception5h.zip
認識したい画像を配置
物体認識プログラムで認識させたい画像を配置します。今回はOpenCVのサンプルプログラムで使われることが多いLenaさんの画像を利用しました。
cd ~/gitprojects/clj-tensorflow-practice mkdir img cd img wget https://raw.githubusercontent.com/opencv/opencv/master/samples/data/lena.jpg
物体認識プログラムを作成・実行
TensorFlowのリポジトリで公開されている、Javaで書かれた物体認識プログラムをClojureで書き換えました。プログラムは150行位あり、ところどころ修正するかもしれないので、リポジトリに公開しているファイル(下記のリンク)をご覧ください。
asukiaaa/clj-tensorflow-practice/src/main.clj
とりあえず動かしたい場合は、このようなコマンドでダウンロードできます。
cd ~/gitprojects/clj-tensorflow-practice/src wget https://raw.githubusercontent.com/asukiaaa/clj-tensorflow-practice/master/src/main.clj
cljコマンドでmainを指定して実行できます。
cd ~/gitprojects/clj-tensorflow-practice clj -m main
Lenaさんの画像にカウボーイハットがある可能性が高いと判定されました。
実装に時間がかかった部分を共有
main.cljを書く際に、時間を取られた部分を共有します。型の変換
Clojureは、整数はlong、自然数はdoubleで値を保持しますが、TensorFlowではそれぞれIntとFloatで値を保持します。TensorFlowのConstで値を作成する際に、それぞれ型を変換する必要があり、それに気づくのに時間を取られました。
(defn get-constant ([g name value type] (prn name value type) (let [t (Tensor/create value)] (-> (.opBuilder g "Const" name) (.setAttr "dtype" (DataType/fromClass type)) (.setAttr "value" t) .build (.output 0)))) ([g name value] (cond (integer? value) (get-constant g name (Integer. value) Integer) (float? value) (get-constant g name (Float. value) Float) (and (vector? value) (integer? (first value))) (get-constant g name (int-array value) Integer) :else (get-constant g name value String))))
多重配列の作成
Javaでも扱える多重配列をClojureで定義するには、make-arrayを使うと下記のように記述できます。下記の記述では、2x100のFloat型の配列を定義しています。
(make-array Float/TYPE 1 100)
これは自分のClojureに対する経験不足のために時間を取られた件です。
良い学びになりました。
まとめ
ClojureでTensorFlowの画像認識プログラムを動かせました。やりたかったことが出来て満足です。
共有したい情報は以上です。
参考
Installing TensorFlow for JavaMaven Repository: org.tensorflow
0 件のコメント :
コメントを投稿