第4回 Java WebアプリでTensorFlow(検討編) (1/3)

技術特集

1_tensorflow_keras1_tit

tit_tensorflow_keras

第4回はTensorFlowで作成した学習済みモデルの実際のシステムでの動かし方、もっと具体的にはJavaで書いたWebアプリからの利用方法について検討します。

TensorFlow, the TensorFlow logo and any related marks are trademarks of Google Inc.
この記事のTensorFlowロゴ画像を含む図は、CC-BY 3.0ライセンスのもと利用許諾されたTensorFlowロゴ画像の派生物です。

1) それ、Javaで動く?

第3回までの内容で、ディープラーニングをTensorFlowで実装することができました。
それを報告すると、あなたのボスは何と言うでしょうか?
あなたのボスがノリノリな人物であれば「よし、では早速それを例のシステムに取り込もう!」と言うかもしれません。
喜んで次の打ち合わせ日時を決めたあと、ボスは自席に戻るあなたを呼び止めてこう言います。

「よく知らないけど、それJavaで動くようにしといてね。」

そうでした。「例のシステム」はJavaによるWebシステム。手元にあるのはPythonスクリプトです。
さて、どうしたものか・・・。

ディープラーニングを始めとする機械学習を行うときに最もよく使われる言語としては、2017年現在で言えばPythonということになるかと思います。
ひるがえって、学習済みモデルを利用する側はどうでしょう?これは一概には言えませんが、筆者が自席から周りを見渡すと、GUIならWebシステム、WebシステムならとりあえずJavaという雰囲気を感じます。

そこで今回は、Javaで書かれている既存アプリケーションに「AI機能」を組み込む、というなんだか他人事でなさそうな状況を想定し、ディープラーニングとアプリケーションの環境の違いを乗り越える方法について検討していきたいと思います。

選択肢1:JavaからPythonプロセスを起動する

もし既にディープラーニングをPythonで実装してしまっている場合、この選択肢を勧める悪魔のささやきが聞こえてくるでしょう。

実際考え方としては単純で、JavaからPythonプロセスを起動し、標準入出力やパイプを用いてデータをやりとりすれば良いわけです。
手元のPythonプログラムも最小限の改修で利用できますし、どのライブラリを利用していても使える方法ですから、試験的に動かしてみるぶんには悪くないかもしれません。

しかし本番環境への適用を視野に入れると、Pythonプロセスの管理のわずらわしさ(起動完了確認、異常終了時の対応等)、処理のスケーラビリティなど、一筋縄ではいかないことが多くなってきます。
先々苦労しそうな雰囲気を感じて突貫するか撤退するかはそれぞれの判断ですが、私であればこの方法を押し通したいとはあまり思いません。

選択肢2:あきらめてJavaで再実装する

アプリケーションにあわせてディープラーニング用ライブラリを再選定し、処理を再実装するというパターンです。
はじめから本番への適用を見据えたプロジェクトであれば、そもそもディープラーニングをはじめる前に、アプリケーションにあわせてライブラリを選定することもあるでしょう。

既にPythonで作ってしまっている場合、新たなライブラリの習得と今あるモデル再実装というコストはかかってしまいますが、アプリケーションと同じ環境で動くという利点は見過ごせないものがあります。
アプリケーションとの連携がとりやすくなりますし、ソースコードの管理と保守において、1つの言語だけを見ればよいので人員確保や育成が容易になることが期待できます。
(もちろん、その言語ができることとディープラーニングの保守ができることは別の問題ですが……まあ容易になることは間違いないということでこの場はご容赦願います)。

また新たなライブラリの習得コストについても、別のディープラーニングライブラリでの実装経験からある程度勘が働く可能性もあり、やってみたら案外簡単にできてしまうかも、という希望的観測もできます。
というのも、言語やライブラリが違うといえどディープラーニングで実装する内容は同じわけで、特にKerasやTensorFlowのLayes APIのような高レベルAPIでは、その実装方法もおのずと類似したものになる傾向があるからです。

ただし、やはり勇気がいる選択肢であることには間違いありません。
特に、現状でディープラーニング実装に有利なPython環境をあえて捨てることに大きな未練が残る方法です。

選択肢3:TensorFlow Java APIを併用する

復数の言語から利用できるライブラリの場合は、モデルの構築と学習はやりやすい言語で行い、利用はアプリケーションに合わせた言語で行うということが可能な場合があります。

TensorFlowはPythonのほかにJavaとC++からも利用できますので、Pythonで学習してJavaで利用するということが可能です。
TensorFlow以外には、AWSが肩入れしているMXNetはPythonやScalaをはじめとする6つの言語から、またMicrosoftによるCNTKはPythonとC#およびC++から利用できます。

ただし、TensorFlowのJava版はまた試験段階であり、今後もAPIに後方互換性のない変更が入る場合がある旨警告がなされています。
また最新の機能が常にJava APIに取り込まれるわけではなく、第3回のコードで使用しているEstimatorをはじめとする多くの機能がJavaからは利用できません。

これらの障壁をくぐり抜けてJavaから利用できるようにした場合、最後にメモリ消費の問題が残ります。
大規模な学習済みモデルは利用時にけっこうな量のメモリを消費するため、アプリケーションのメモリを圧迫してしまうことになりがちです。
そうなると、学習済みモデルとアプリケーションを分離して管理したい気持ちが高まってきて、次の選択肢が浮かびます。

選択肢4:学習済みモデルをサービス化して分離する

学習済みモデルを動かす部分をRESTやSOAP等を経由して呼び出せるサービスとして実装することで、アプリケーションから分離して管理できるようにするというアプローチです。

この方法の長所は以下の3点です:

  • ディープラーニングとアプリケーションをそれぞれ最適な言語環境で実装できる
  • 追加コストもそれほど多くない
    • 学習済みモデルの利用をサービス化する分のコスト
  • サービスの管理をアプリケーション部と分離できる
    • ソースコード管理、死活管理、メモリ管理など
    • アプリケーションと学習済みモデルを別のマシンで動かすことも可能

つまり、選択肢1~3それぞれの欠点を緩和した、バランスのとれた方式ということができます。