【TensorFlow】学習済みモデルをサーバーで動かすServingとは

今日は、TensorFlowの学習済みモデルを、サーバーで動かすためのTensorFlow Servingを紹介します。

TensorFlow Servingは、

  • TensorFlowで学習したモデルを活用して、面白そうなサービスができそうなんだけど、どうやって一般公開すればいいの?
  • 他のプログラミング言語から、学習済みモデルを活用したいな…。
  • モデルの学習がさらに進んで精度が上がったから、新バージョンとして公開したい!

といった、疑問や要求に応えられるシステムです。

この記事では、TensorFlow Servingの概要動作させるまでのステップを理解できます。

TensorFlow Servingの基本的なところをこの記事でおさえておけば、いざ必要に迫られたときにスムーズにTensorFlow Servingを導入できるでしょう!

では、始めましょう。

目次

TensorFlow Servingとは

tensor-serving01

参考:https://www.tensorflow.org/serving/

TensorFlow Servingは、TensorFlowの学習済みモデルを本番環境で運用するためのシステムです。

ここでは、MNISTの学習済みモデルを本番環境で利用する場合を例に、TensorFlow Servingの利用方法を説明しましょう。

大まかに、以下の3つの作業を行います。

①GPUが搭載されているPCなど、機械学習を得意とするコンピュータを利用してMNISTの学習済みモデル(SavedModel形式のデータ)を作成します。

②作成したMNISTの学習済みモデル(SavedModel形式のデータ)を、Linuxサーバーなどに構築したTensorFlow Servingに登録して、TensorFlow Servingを起動します。

③TensorFlow Servingに対して、クライアントプログラムから予測したい手書き数字の画像データを送信すると、TensorFlow Servingから予測結果が返ってきます。

TensorFlow Servingをインストールするサーバーで行う作業は、本来は②だけです。

この記事では、環境構築の手間を省くため、Windows 10 ProにTensorFlow Serving用のDockerコンテナを作成し、①も②も③も、そのDockerコンテナで行います。

Dockerのインストールについては、以下の記事でも説明していますので、参考にしてください。

Dockerコンテナを起動しよう

上で説明した①~③をすべて行う環境を構築するため、Dockerコンテナを起動します。

Dockerイメージを作成する

TensorFlow Serving用のDockerイメージは用意されていませんが、TensorFlow Serving公式のDockerファイルがあります。

このDockerファイルを利用すると、Ubuntu 16.04をベースにしてgRPCBazelなどが利用できるDockerイメージを作成できます。

(1)Windows 10で、以下のDockerファイルをダウンロードし、任意の場所に保存します。

参考:https://raw.githubusercontent.com/tensorflow/serving/master/tensorflow_serving/tools/docker/Dockerfile.devel

ここでは、「D:\Docker\Dockerfile.devel」に保存しました。

(2)Dockerファイルを以下のように修正します。

修正前:

ENV BAZEL_VERSION 0.5.4

修正後:

ENV BAZEL_VERSION 0.12.0

(3)スタートボタンをクリックし、「Windows PowerShell」「Windows PowerShell」の順にクリックします。

tensor-docker08

Windows PowerShell(以降、PowerShell)が起動します。

(4)PowerShellで「cd D:\Docker」と入力し、Enterキーを押します。

「D:\Docker」は、「Dockerfile.devel」を保存したフォルダです。

(5)PowerShellで以下のコマンドを入力します。

docker build --pull -t yazaki/tensorflow-serving-devel -f Dockerfile.devel .

「yazaki/tensorflow-serving-devel」は、任意の文字列で構いませんが、同じような形式にしておくと良いでしょう。

また、最後に半角スペースと「.」(ピリオド)があることを見落とさないでください。

時間がかかりますが、Dockerイメージが作成されます。

※以下のようなエラーメッセージが表示されたときは、DockerのNetworkの設定を変更してください。

Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

参考:https://naughtldy.hatenablog.jp/entry/2017/05/22/080000

(5)「docker images」と入力し、Enterキーを押します。

以下のように、「yazaki/tensorflow-serving-devel」と「ubuntu」の2つのDockerイメージが作成されたことが表示されます。

REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
yazaki/tensorflow-serving-devel   latest              716c800e41c4        27 seconds ago      1.05GB
ubuntu                            16.04               0b1edfbffd27        5 weeks ago         113MB

Dockerコンテナを起動する

続けて、作成したDockerイメージからDockerコンテナを作成して起動しましょう。

(1)PowerShellで以下のコマンドを入力します。

docker run -it yazaki/tensorflow-serving-devel

以下のようにDockerコンテナ(Ubuntu 16.04.4 LTSのbash)のプロンプトが表示されます。

root@78eab4985d97:/# 

MNISTの学習済みモデルを作成しよう

次に、MNISTの学習済みモデル(SavedModel形式のデータ)を作成します。

上で説明した①の操作に相当する作業です。

本来は、GPUが搭載されているPCなど、機械学習を得意とするコンピュータを利用して時間を短縮するべきですが、今回想定しているMNISTの学習済みモデル(SavedModel形式のデータ)を作成する程度であれば、Dockerコンテナ上で作業をしても、それほど時間はかかりません。

(1)Dockerコンテナのプロンプトで以下のコマンドを入力します。

pip install tensorflow

最後に以下のメッセージが表示されますが、今回の記事の範囲ではアップデートする必要がないので無視しました。

You are using pip version 8.1.1, however version 10.0.1 is available.

(2)以下のコマンドを入力します。

git clone --recurse-submodules https://github.com/tensorflow/serving

TensorFlow ServingのGitHubリポジトリがクローンされます。

(3)以下のコマンドを1行ずつ順番に入力します。

cd /serving/tensorflow_serving/example/

python mnist_saved_model.py .

これも、最後に半角スペースと「.」(ピリオド)があることを見落とさないでください。

ここまでの作業で、「/serving/tensorflow_serving/example」ディレクトリに、「1」ディレクトリが作成され、その中に「saved_model.pb」と「variables」ディレクトリが作成されます。

これらのデータをまとめてSavedModel形式と呼びます。

「ls 1 -al」と入力してEnterキーを押し、「1」ディレクトリの中を確認してみましょう。

root@78eab4985d97:/serving/tensorflow_serving/example# ls 1 -al
total 32
drwxr-xr-x 3 root root  4096 Jun  4 22:16 .
drwxr-xr-x 3 root root  4096 Jun  4 22:16 ..
-rw-r--r-- 1 root root 19183 Jun  4 22:16 saved_model.pb
drwxr-xr-x 2 root root  4096 Jun  4 22:16 variables

ちなみに「variables」ディレクトリの中は以下のようになっています。

root@78eab4985d97:/serving/tensorflow_serving/example# ls 1/variables/ -al
total 44
drwxr-xr-x 2 root root  4096 Jun  4 22:16 .
drwxr-xr-x 3 root root  4096 Jun  4 22:16 ..
-rw-r--r-- 1 root root 31400 Jun  4 22:16 variables.data-00000-of-00001
-rw-r--r-- 1 root root   159 Jun  4 22:16 variables.index

TensorFlow Servingを起動しよう

次は、上で説明した②に相当する作業です。

作成したMNISTの学習済みモデル(SavedModel形式のデータ)を、Linuxサーバーなどに構築したTensorFlow Servingに登録して起動します。

TensorFlow ServingをDockerコンテナにインストールする

起動する前にインストールが必要です。

この記事では、TensorFlow Servingをapt-getでインストールします。

以下のページではソースコードからビルドする方法も紹介されていますので、挑戦してみても良いでしょう。

参考:https://www.tensorflow.org/serving/setup#installing_from_source

ちなみに、私も何度か試しましたがうまく行きませんでした。

では、apt-getでインストールしましょう。

(1)Dockerコンテナのプロンプトで「cd /」と入力し、Enterキーを押します。

(2)「su」と入力し、Enterキーを押します。

表示は変わりませんが、スーパーユーザー(rootユーザー)に切り替わっています。

(3)以下のコマンドを入力します。

echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" | tee /etc/apt/sources.list.d/tensorflow-serving.list

「/etc/apt/sources.list.d/tensorflow-serving.list」が作成されます。

(4)以下のコマンドを1行ずつ順番に入力します。

curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | apt-key add -

apt-get update && apt-get install tensorflow-model-server

add-apt-repository ppa:ubuntu-toolchain-r/test

(5)「Press [ENTER] to continue or ctrl-c to cancel adding it」と表示されたら、Enterキーを押します。

(6)以下のコマンドを入力します。

apt-get update && apt-get install gcc-4.9

(7)「Do you want to continue? [Y/n]」と表示されたら、Enterキーを押します。

(8)以下のコマンドを入力します。

apt-get upgrade libstdc++6

(9)「Do you want to continue? [Y/n]」と表示されたら、Enterキーを押します。

以上で、TensorFlow Servingのインストールが完了しました。

TensorFlow Servingを起動する

いよいよです。

TensorFlow ServingにSavedModel形式でエクスポートした学習済みモデルを登録して、TensorFlow Servingを起動します。

(1)以下のコマンドを入力します。

tensorflow_model_server --port=9000 --model_name=mnist --model_base_path=/serving/tensorflow_serving/example/

「/serving/tensorflow_serving/example/」は、SavedModel形式のデータ(「1」ディレクトリ)が存在するディレクトリです。

これで、TensorFlow Servingが起動しました。

クライアントからTensorFlow Servingにデータを送ろう

次に、クライアントプログラムからTensorFlow Servingに、予測したい手書き数字の画像データを送信して、予測結果を取得します。

上で説明した③に相当する作業です。

繰り返しになりますが、今回は環境構築の手間を省くために、TensorFlow Servingが起動しているDockerコンテナを利用しています。

(1)新しくPowerShellを起動し、「docker ps -a」と入力します。

以下のように表示されます。

CONTAINER ID        IMAGE                             COMMAND             CREATED             STATUS              PORTS               NAMES
78eab4985d97        yazaki/tensorflow-serving-devel   "/bin/bash"         8 hours ago         Up 25 minutes                           quizzical_nightingale

コンテナID(上の例では「78eab4985d97」)が表示されていますね。

(2)以下のコマンドを入力します。

docker exec -it 78eab4985d97 bash

TensorFlow Servingが起動しているDockerコンテナで、新しくbashが起動します。

(3)Dockerコンテナのプロンプトで、以下のコマンドを入力します。

pip install tensorflow-serving-api

最後に以下のメッセージが表示されますが、今回の記事の範囲ではアップデートする必要がないので無視しました。

You are using pip version 8.1.1, however version 10.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

(4)以下のコマンドを入力します。

python /serving/tensorflow_serving/example/mnist_client.py --server=localhost:9000

TensorFlow Servingに100個のテストデータが送信され、エラー率が表示されます。

Inference error rate: 7.0%

今回は7.0%が失敗(つまり93.0%が成功)したようです。

精度はさておき、TensorFlow Servingにデータを送信して、結果が返ってくることが確認できました。

まだちょっと不安な方は、/serving/tensorflow_serving/example/mnist_client.pyの以下の部分を変更すると、TensorFlow Servingに登録したモデルが予測した数字も確認できます。

変更前:

      sys.stdout.write('.')
      sys.stdout.flush()
      response = numpy.array(
          result_future.result().outputs['scores'].float_val)
      prediction = numpy.argmax(response)

変更後:

      # sys.stdout.write('.')
      # sys.stdout.flush()
      response = numpy.array(
          result_future.result().outputs['scores'].float_val)
      prediction = numpy.argmax(response)
      sys.stdout.write(str(prediction) + ",")
      sys.stdout.flush()

なお、このプログラムはPythonで書かれていますが、TensorFlow Servingとの通信はgRPCを使っていますので、Pythonに限定されません。

たとえば、Javaで書いたプログラムからTensorFlow ServingにgRPCを使ってデータを送信すれば、推測した結果が得られます。

まとめ

今回は、Dockerコンテナを利用して、TensorFlow Servingが動作する環境を作成する手順を説明しました。

また、Pythonで書かれたクライアントプログラムから、TensorFlow Servingに登録した学習済みモデルにMNISTデータを推測させる方法も確認できました。

今回説明した内容は、基本的な作業になりますので、次は自分でモデルを用意したり、クライアントプログラムを他の言語で作成したりしてみると良いでしょう。

それでは!

この記事を書いた人

侍エンジニア塾は「人生を変えるプログラミング学習」をコンセンプトに、過去多くのフリーランスエンジニアを輩出したプログラミングスクールです。侍テック編集部では技術系コンテンツを中心に有用な情報を発信していきます。

目次