ヘルプKaggleにTensorFlowグレートバリアリーフを保護チャレンジに参加

KubernetesでTensorFlowサービングを使用する

このチュートリアルでは、Dockerコンテナで実行されているTensorFlow Servingコンポーネントを使用して、TensorFlow ResNetモデルを提供する方法と、Kubernetesで提供クラスターをデプロイする方法を示します。

TensorFlow Servingの詳細については、TensorFlowServingの基本チュートリアルTensorFlowServingの上級チュートリアルをお勧めします。

TensorFlow ResNetモデルの詳細については、TensorFlowのResNetを読むことをお勧めします

  • パート1で環境をセットアップします
  • パート2は、ローカルのDockerサービングイメージを実行する方法を示しています
  • パート3は、Kubernetesにデプロイする方法を示しています。

パート1:セットアップ

始める前に、まずDockerをインストールします。

ResNetSavedModelをダウンロードする

すでにローカルモデルディレクトリがある場合は、ローカルモデルディレクトリをクリアしましょう。

rm -rf /tmp/resnet

深い残差ネットワーク(略してResNets)は、非常に深い畳み込みニューラルネットワークのトレーニングを可能にするために、アイデンティティマッピングの画期的なアイデアを提供しました。この例では、ImageNetデータセット用にResNetのTensorFlowSavedModelをダウンロードします。

mkdir /tmp/resnet
curl -s http://download.tensorflow.org/models/official/20181001_resnet/savedmodels/resnet_v2_fp32_savedmodel_NHWC_jpg.tar.gz | \
tar --strip-components=2 -C /tmp/resnet -xvz

SavedModelがあることを確認できます。

$ ls /tmp/resnet/*
saved_model.pb  variables

パート2:Dockerでの実行

デプロイのためにイメージをコミットする

ここで、サービングイメージを$USER/resnet_serving 、Kubernetesデプロイメント用の新しいイメージ$USER/resnet_servingへのすべての変更をコミットします。

まず、サービングイメージをデーモンとして実行します。

docker run -d --name serving_base tensorflow/serving

次に、ResNetモデルデータをコンテナーのモデルフォルダーにコピーします。

docker cp /tmp/resnet serving_base:/models/resnet

最後に、コンテナをResNetモデルの提供にコミットします。

docker commit --change "ENV MODEL_NAME resnet" serving_base \
  $USER/resnet_serving

それでは、サービングベースコンテナを停止しましょう

docker kill serving_base
docker rm serving_base

サーバーを起動します

それでは、ResNetモデルでコンテナーを起動して、提供の準備を整え、gRPCポート8500を公開しましょう。

docker run -p 8500:8500 -t $USER/resnet_serving &

サーバーにクエリを実行します

クライアントの場合、TensorFlow ServingGitHubリポジトリのクローンを作成する必要があります。

git clone https://github.com/tensorflow/serving
cd serving

resnet_client_grpc.pyを使用してサーバーにクエリを実行します。クライアントは画像をダウンロードし、 ImageNetカテゴリに分類するためにgRPCを介して送信します。

tools/run_in_docker.sh python tensorflow_serving/example/resnet_client_grpc.py

これにより、次のような出力が得られます。

outputs {
  key: "classes"
  value {
    dtype: DT_INT64
    tensor_shape {
      dim {
        size: 1
      }
    }
    int64_val: 286
  }
}
outputs {
  key: "probabilities"
  value {
    dtype: DT_FLOAT
    tensor_shape {
      dim {
        size: 1
      }
      dim {
        size: 1001
      }
    }
    float_val: 2.41628322328e-06
    float_val: 1.90121829746e-06
    float_val: 2.72477100225e-05
    float_val: 4.42638565801e-07
    float_val: 8.98362372936e-07
    float_val: 6.84421956976e-06
    float_val: 1.66555237229e-05
...
    float_val: 1.59407863976e-06
    float_val: 1.2315689446e-06
    float_val: 1.17812135159e-06
    float_val: 1.46365800902e-05
    float_val: 5.81210713335e-07
    float_val: 6.59980651108e-05
    float_val: 0.00129527016543
  }
}
model_spec {
  name: "resnet"
  version {
    value: 1538687457
  }
  signature_name: "serving_default"
}

できます!サーバーは猫の画像を正常に分類します!

パート3:Kubernetesにデプロイする

このセクションでは、パート0で構築したコンテナイメージを使用して、 Google CloudPlatformKubernetesを使用してサービングクラスタをデプロイします。

GCloudプロジェクトのログイン

ここでは、あなたが作成し、ログインしていると仮定のgcloudというプロジェクトtensorflow-serving

gcloud auth login --project tensorflow-serving

コンテナクラスターを作成する

まず、サービスをデプロイするためのGoogle KubernetesEngineクラスターを作成します

$ gcloud container clusters create resnet-serving-cluster --num-nodes 5

これは次のようなものを出力するはずです:

Creating cluster resnet-serving-cluster...done.
Created [https://container.googleapis.com/v1/projects/tensorflow-serving/zones/us-central1-f/clusters/resnet-serving-cluster].
kubeconfig entry generated for resnet-serving-cluster.
NAME                       ZONE           MASTER_VERSION  MASTER_IP        MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
resnet-serving-cluster  us-central1-f  1.1.8           104.197.163.119  n1-standard-1  1.1.8         5          RUNNING

gcloud containerコマンドのデフォルトクラスターを設定し、クラスターのクレデンシャルをkubectlに渡します。

gcloud config set container/cluster resnet-serving-cluster
gcloud container clusters get-credentials resnet-serving-cluster

結果は次のようになります。

Fetching cluster endpoint and auth data.
kubeconfig entry generated for resnet-serving-cluster.

Dockerイメージをアップロードする

次に、画像をGoogle Container Registryにプッシュして、 Google CloudPlatformで実行できるようにします。

まず、ContainerRegistry形式とプロジェクト名を使用して$USER/resnet_servingイメージにタグを付けます。

docker tag $USER/resnet_serving gcr.io/tensorflow-serving/resnet

次に、gcloudをクレデンシャルヘルパーとして使用するようにDockerを構成します。

gcloud auth configure-docker

次に、イメージをレジストリにプッシュします。

docker push gcr.io/tensorflow-serving/resnet

Kubernetesのデプロイとサービスを作成する

デプロイは、 Kubernetesデプロイメントによって制御されるresnet_inferenceサーバーの3つのレプリカで構成されます。レプリカは、外部ロードバランサーとともにKubernetesサービスによって外部に公開されます。

私たちは、Kubernetes設定例を使用して作成resnet_k8s.yaml

kubectl create -f tensorflow_serving/example/resnet_k8s.yaml

出力あり:

deployment "resnet-deployment" created
service "resnet-service" created

デプロイメントとポッドのステータスを表示するには:

$ kubectl get deployments
NAME                    DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
resnet-deployment    3         3         3            3           5s
$ kubectl get pods
NAME                         READY     STATUS    RESTARTS   AGE
resnet-deployment-bbcbc   1/1       Running   0          10s
resnet-deployment-cj6l2   1/1       Running   0          10s
resnet-deployment-t1uep   1/1       Running   0          10s

サービスのステータスを表示するには:

$ kubectl get services
NAME                    CLUSTER-IP       EXTERNAL-IP       PORT(S)     AGE
resnet-service       10.239.240.227   104.155.184.157   8500/TCP    1m

すべてが稼働するまでに時間がかかる場合があります。

$ kubectl describe service resnet-service
Name:           resnet-service
Namespace:      default
Labels:         run=resnet-service
Selector:       run=resnet-service
Type:           LoadBalancer
IP:         10.239.240.227
LoadBalancer Ingress:   104.155.184.157
Port:           <unset> 8500/TCP
NodePort:       <unset> 30334/TCP
Endpoints:      <none>
Session Affinity:   None
Events:
  FirstSeen LastSeen    Count   From            SubobjectPath   Type        Reason      Message
  --------- --------    -----   ----            -------------   --------    ------      -------
  1m        1m      1   {service-controller }           Normal      CreatingLoadBalancer    Creating load balancer
  1m        1m      1   {service-controller }           Normal      CreatedLoadBalancer Created load balancer

サービスの外部IPアドレスは、LoadBalancerIngressの横に表示されます。

モデルをクエリする

これで、ローカルホストから外部アドレスでサービスにクエリを実行できます。

$ tools/run_in_docker.sh python \
  tensorflow_serving/example/resnet_client_grpc.py \
  --server=104.155.184.157:8500
outputs {
  key: "classes"
  value {
    dtype: DT_INT64
    tensor_shape {
      dim {
        size: 1
      }
    }
    int64_val: 286
  }
}
outputs {
  key: "probabilities"
  value {
    dtype: DT_FLOAT
    tensor_shape {
      dim {
        size: 1
      }
      dim {
        size: 1001
      }
    }
    float_val: 2.41628322328e-06
    float_val: 1.90121829746e-06
    float_val: 2.72477100225e-05
    float_val: 4.42638565801e-07
    float_val: 8.98362372936e-07
    float_val: 6.84421956976e-06
    float_val: 1.66555237229e-05
...
    float_val: 1.59407863976e-06
    float_val: 1.2315689446e-06
    float_val: 1.17812135159e-06
    float_val: 1.46365800902e-05
    float_val: 5.81210713335e-07
    float_val: 6.59980651108e-05
    float_val: 0.00129527016543
  }
}
model_spec {
  name: "resnet"
  version {
    value: 1538687457
  }
  signature_name: "serving_default"
}

これで、Kubernetesでサービスとして機能するResNetモデルが正常にデプロイされました。