すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:クラウドネイティブ AI スイート開発者ガイド

最終更新日:Mar 04, 2025

このトピックでは、Fashion-MNIST というオープンソースのデータセットを例として使用し、クラウドネイティブ AI コンポーネントセットを使用して次のタスクを実行する方法について説明します。Container Service for Kubernetes (ACK) クラスタでのディープ ラーニング ジョブの実行、分散トレーニングのパフォーマンスの最適化、モデルの調整、および ACK クラスタへのモデルのデプロイ。

背景情報

クラウドネイティブ AI コンポーネントセットには、Helm チャートを使用して個別にデプロイできるコンポーネントが含まれています。これらのコンポーネントを使用して、AI プロジェクトを高速化できます。

クラウドネイティブ AI コンポーネントセットは、管理者と開発者の 2 種類のロールに適しています。

  • 管理者は、ユーザーと権限の管理、クラスタリソースの割り当て、外部ストレージの構成、データセットの管理、ダッシュボードを使用したリソース使用率の監視を行います。

  • 開発者は、クラスタリソースを使用し、ジョブを送信します。開発者は管理者によって作成され、Arena や Jupyter Notebook などのツールを使用して開発を実行するには、権限を付与される必要があります。

前提条件

次の操作は管理者によって実行されます。

  • ACK クラスタが作成されます。詳細については、「ACK マネージドクラスターを作成する」をご参照ください。

    • クラスタ内の各ノードのディスクサイズは 300 GB 以上です。

    • 最適なデータアクセラレーションが必要な場合は、それぞれ 8 つの V100 GPU を提供する 4 つの Elastic Compute Service (ECS) インスタンスを使用します。

    • 最適なトポロジー認識が必要な場合は、それぞれ 2 つの V100 GPU を提供する 2 つの ECS インスタンスを使用します。

  • クラウドネイティブ AI コンポーネントセットに含まれるすべてのコンポーネントがクラスタにインストールされています。詳細については、「クラウドネイティブ AI スイートをデプロイする」をご参照ください。

  • AI ダッシュボードを使用する準備ができています。詳細については、「AI ダッシュボードにアクセスする」をご参照ください。

  • AI 開発者コンソールを使用する準備ができています。詳細については、「AI 開発者コンソールにログインする」をご参照ください。

    説明

    Alibaba Cloud が提供する AI コンソール (AI ダッシュボードと AI 開発者コンソールを含む) は、2025 年 1 月 22 日からホワイトリストメカニズムを通じて段階的にロールアウトされました。

    • 既存のデプロイ: この日付より前に AI Dashboard または AI Developer Console をデプロイ済みの場合、現在の使用状況に影響はありません。

    • 新規インストール: ホワイトリストに登録されていないユーザーは、オープンソースコミュニティを通じて AI コンソールをインストールおよび構成できます。オープンソースの構成手順の詳細については、「オープンソース AI コンソール」をご参照ください。

  • Fashion-MNIST データセットがダウンロードされ、Object Storage Service (OSS) バケットにアップロードされます。モデルを OSS バケットにアップロードする方法の詳細については、「オブジェクトをアップロードする」をご参照ください。

  • テストコードを格納する Git リポジトリのアドレス、ユーザー名、およびパスワードが取得されます。

  • kubectl クライアントがクラスタに接続されています。詳細については、「クラスタの kubeconfig ファイルを取得し、kubectl を使用してクラスタに接続する」をご参照ください。

  • Arena がインストールされています。詳細については、「Arena クライアントを構成する」をご参照ください。

テスト環境

この例では、クラウドネイティブ AI コンポーネントセットとオープンソースの Fashion-MNIST データセットを使用して、AI モデルの開発、トレーニング、高速化、管理、評価、およびデプロイが行われます。

次の表は、クラスタ内のノードを示しています。

ホスト名

IP

ロール

GPU 数

vCPU の数

メモリ

cn-beijing.192.168.0.13

192.168.0.13

ジャンプサーバー

1

8

30580004 KiB

cn-beijing.192.168.0.16

192.168.0.16

ワーカー

1

8

30580004 KiB

cn-beijing.192.168.0.17

192.168.0.17

ワーカー

1

8

30580004 KiB

cn-beijing.192.168.0.240

192.168.0.240

ワーカー

1

8

30580004 KiB

cn-beijing.192.168.0.239

192.168.0.239

ワーカー

1

8

30580004 KiB

実験の目的

このトピックでは、次の目的を達成することを目指しています。

  • データセットを管理する。

  • Jupyter Notebook を使用して開発環境を構築する。

  • スタンドアロンのトレーニングジョブを送信する。

  • 分散トレーニングジョブを送信する。

  • Fluid を使用してトレーニングジョブを高速化する。

  • ACK の AI ジョブスケジューラを使用してトレーニングジョブを高速化する。

  • モデルを管理する。

  • モデルを評価する。

  • 推論サービスをデプロイする。

手順 1: ユーザーを作成し、リソースを割り当てる

開発者は、管理者から次の情報とリソースを取得する必要があります。

  • ユーザーのユーザー名とパスワード。ユーザーの作成方法の詳細については、「ユーザーを管理する」をご参照ください。

  • リソースクォータ。リソースクォータの割り当て方法の詳細については、「弾性クォータグループを管理する」をご参照ください。

  • 開発者が AI 開発者コンソールを使用してジョブを送信する場合の AI 開発者コンソールのエンドポイント。AI 開発者コンソールへのアクセス方法の詳細については、「AI 開発者コンソールにログインする」をご参照ください。

    説明

    Alibaba Cloud が提供する AI コンソール (AI ダッシュボードと AI 開発者コンソールを含む) は、2025 年 1 月 22 日からホワイトリストメカニズムを通じて段階的にロールアウトされました。

    • 既存のデプロイ: この日付より前に AI Dashboard または AI Developer Console をデプロイ済みの場合、現在の使用状況は影響を受けません。

    • 新規インストール: ホワイトリストに登録されていないユーザーは、オープンソースコミュニティを通じて AI コンソールをインストールおよび構成できます。オープンソースの構成手順の詳細については、「オープンソース AI コンソール」をご参照ください。

  • 開発者が Arena を使用してジョブを送信する場合、クラスタにログインするために使用される kubeconfig ファイル。クラスタにログインするために使用される kubeconfig ファイルの取得方法の詳細については、「手順 2: クラスタ認証情報の種類を選択する」をご参照ください。

手順 2: データセットを作成する

管理者はデータセットを準備する必要があります。この例では、Fashion-MNIST データセットを使用します。

A: Fashion-mnist データセットを追加する

  1. 次の YAML テンプレートを使用して、fashion-mnist.yaml という名前のファイルを作成します。

    この例では、Fashion-MNIST データセットを格納する OSS バケットをマウントするために、永続ボリューム (PV) と永続ボリューム要求 (PVC) が作成されます。

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: fashion-demo-pv
    spec:
      accessModes:
      - ReadWriteMany
      capacity:
        storage: 10Gi
      csi:
        driver: ossplugin.csi.alibabacloud.com
        volumeAttributes:
          bucket: fashion-mnist
          otherOpts: ""
          url: oss-cn-beijing.aliyuncs.com
          akId: "AKID"
          akSecret: "AKSECRET"
        volumeHandle: fashion-demo-pv
      persistentVolumeReclaimPolicy: Retain
      storageClassName: oss
      volumeMode: Filesystem
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: fashion-demo-pvc
      namespace: demo-ns
    spec:
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 10Gi
      selector:
        matchLabels:
          alicloud-pvname: fashion-demo-pv
      storageClassName: oss
      volumeMode: Filesystem
      volumeName: fashion-demo-pv
  2. 次のコマンドを実行して、fashion-mnist.yaml ファイルを作成します。

    kubectl create -f fashion-mnist.yaml
  3. 作成された PV と PVC のステータスを確認します。

    • 次のコマンドを実行して、作成された PV のステータスを確認します。

      kubectl get pv fashion-mnist-jackwg

      予期される出力:

      NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                          STORAGECLASS   REASON   AGE
      fashion-mnist-jackwg   10Gi       RWX            Retain           Bound    ns1/fashion-mnist-jackwg-pvc   oss                     8h
    • 次のコマンドを実行して、作成された PVC のステータスを確認します。

      kubectl get pvc fashion-mnist-jackwg-pvc -n ns1

      予期される出力:

      NAME                       STATUS   VOLUME                 CAPACITY   ACCESS MODES   STORAGECLASS   AGE
      fashion-mnist-jackwg-pvc   Bound    fashion-mnist-jackwg   10Gi       RWX            oss            8h

    出力は、PV と PVC の両方が Bound 状態であることを示しています。

B: データセットを高速化する

管理者は、AI ダッシュボードを使用してデータセットを高速化する必要があります。

  1. AI ダッシュボードにアクセスする (管理者として)。
  2. AI ダッシュボードの左側のナビゲーションウィンドウで、[データセット] > [データセットリスト] を選択します。
  3. [データセットリスト] ページで、データセットを見つけ、[オペレーター] 列の [高速化] をクリックします。

    次の図は、高速化されたデータセットを示しています。Accelerate the dataset

手順 3: モデルを開発する

このセクションでは、Jupyter Notebook を使用して開発環境を構築する方法について説明します。手順:

  1. オプション。カスタムイメージを使用して Jupyter Notebook を作成します。

  2. Jupyter Notebook を使用してモデルを開発およびテストします。

  3. Jupyter Notebook を使用してコードを Git リポジトリに送信します。

  4. Arena SDK を使用してトレーニングジョブを送信します。

A (オプション): カスタムイメージを使用して Jupyter Notebook を作成する

AI 開発者コンソールは、Jupyter Notebook を作成するために TensorFlow と PyTorch をサポートするさまざまなバージョンのイメージを提供します。カスタムイメージを使用して Jupyter Notebook を作成することもできます。

  1. 次の Dockerfile テンプレートを使用して、Dockerfile という名前のファイルを作成します。

    カスタムイメージの制限の詳細については、「Notebook を作成して使用する」をご参照ください。

    cat<<EOF >dockerfile
    FROM tensorflow/tensorflow:1.15.5-gpu
    USER root
    RUN pip install jupyter && \
        pip install ipywidgets && \
        jupyter nbextension enable --py widgetsnbextension && \
        pip install jupyterlab && jupyter serverextension enable --py jupyterlab
    EXPOSE 8888
    #USER jovyan
    CMD ["sh", "-c", "jupyter-lab --notebook-dir=/home/jovyan --ip=0.0.0.0 --no-browser --allow-root --port=8888 --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.allow_origin='*' --NotebookApp.base_url=${NB_PREFIX} --ServerApp.authenticate_prometheus=False"]
    EOF
  2. 次のコマンドを実行して、Dockerfile からイメージをビルドします。

    docker build -f dockerfile .

    予期される出力:

    Sending build context to Docker daemon  9.216kB
    Step 1/5 : FROM tensorflow/tensorflow:1.15.5-gpu
     ---> 73be11373498
    Step 2/5 : USER root
     ---> Using cache
     ---> 7ee21dc7e42e
    Step 3/5 : RUN pip install jupyter &&     pip install ipywidgets &&     jupyter nbextension enable --py widgetsnbextension &&     pip install jupyterlab && jupyter serverextension enable --py jupyterlab
     ---> Using cache
     ---> 23bc51c5e16d
    Step 4/5 : EXPOSE 8888
     ---> Using cache
     ---> 76a55822ddae
    Step 5/5 : CMD ["sh", "-c", "jupyter-lab --notebook-dir=/home/jovyan --ip=0.0.0.0 --no-browser --allow-root --port=8888 --NotebookApp.token='' --NotebookApp.password='' --NotebookApp.allow_origin='*' --NotebookApp.base_url=${NB_PREFIX} --ServerApp.authenticate_prometheus=False"]
     ---> Using cache
     ---> 3692f04626d5
    Successfully built 3692f04626d5
  3. 次のコマンドを実行して、イメージを Docker イメージリポジトリにプッシュします。

    docker tag ${IMAGE_ID} registry-vpc.cn-beijing.aliyuncs.com/${DOCKER_REPO}/jupyter:fashion-mnist-20210802a
    docker push registry-vpc.cn-beijing.aliyuncs.com/${DOCKER_REPO}/jupyter:fashion-mnist-20210802a
  4. Docker イメージリポジトリからイメージをプルするために使用されるシークレットを作成します。

    詳細については、「既存の Docker 認証情報に基づいてシークレットを作成する」をご参照ください。

    kubectl create secret docker-registry regcred \
      --docker-server=<Your registry server> \
      --docker-username=<Username> \
      --docker-password=<Password> \
      --docker-email=<Your email address>
  5. AI 開発者コンソールで Jupyter Notebook を作成します。

    詳細については、「Notebook を作成して使用する」をご参照ください。

    次の図は、Jupyter Notebook を作成するためのパラメータを示しています。Create a Jupyter notebook

B: Jupyter Notebook を使用してモデルを開発およびテストする

  1. AI 開発者コンソールにログインする
  2. AI 開発者コンソールの左側のナビゲーションウィンドウで、[notebook] をクリックします。
  3. [notebook] ページで、[実行中] [状態] の Jupyter Notebook をクリックします。

  4. CLI ランチャーを作成し、データセットがマウントされていることを確認します。

    pwd
    /root/data
    ls -alh

    予期される出力:

    total 30M
    drwx------ 1 root root    0 Jan  1  1970 .
    drwx------ 1 root root 4.0K Aug  2 04:15 ..
    drwxr-xr-x 1 root root    0 Aug  1 14:16 saved_model
    -rw-r----- 1 root root 4.3M Aug  1 01:53 t10k-images-idx3-ubyte.gz
    -rw-r----- 1 root root 5.1K Aug  1 01:53 t10k-labels-idx1-ubyte.gz
    -rw-r----- 1 root root  26M Aug  1 01:54 train-images-idx3-ubyte.gz
    -rw-r----- 1 root root  29K Aug  1 01:53 train-labels-idx1-ubyte.gz
  5. Fashion-MNIST データセットに基づいてモデルをトレーニングするために使用される Jupyter Notebook を作成します。次のコードブロックは、Notebook を初期化するために使用されます。

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    
    import os
    import gzip
    import numpy as np
    import tensorflow as tf
    from tensorflow import keras
    print('TensorFlow version: {}'.format(tf.__version__))
    dataset_path = "/root/data/"
    model_path = "./model/"
    model_version =  "v1"
    
    def load_data():
        files = [
            'train-labels-idx1-ubyte.gz',
            'train-images-idx3-ubyte.gz',
            't10k-labels-idx1-ubyte.gz',
            't10k-images-idx3-ubyte.gz'
        ]
        paths = []
        for fname in files:
            paths.append(os.path.join(dataset_path, fname))
        with gzip.open(paths[0], 'rb') as labelpath:
            y_train = np.frombuffer(labelpath.read(), np.uint8, offset=8)
        with gzip.open(paths[1], 'rb') as imgpath:
            x_train = np.frombuffer(imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)
        with gzip.open(paths[2], 'rb') as labelpath:
            y_test = np.frombuffer(labelpath.read(), np.uint8, offset=8)
        with gzip.open(paths[3], 'rb') as imgpath:
            x_test = np.frombuffer(imgpath.read(), np.uint8, offset=16).reshape(len(y_test), 28, 28)
        return (x_train, y_train),(x_test, y_test)
    
    def train():
        (train_images, train_labels), (test_images, test_labels) = load_data()
    
        # scale the values to 0.0 to 1.0
        train_images = train_images / 255.0
        test_images = test_images / 255.0
    
        # reshape for feeding into the model
        train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
        test_images = test_images.reshape(test_images.shape[0], 28, 28, 1)
    
        class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
                    'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
    
        print('\ntrain_images.shape: {}, of {}'.format(train_images.shape, train_images.dtype))
        print('test_images.shape: {}, of {}'.format(test_images.shape, test_images.dtype))
    
        model = keras.Sequential([
        keras.layers.Conv2D(input_shape=(28,28,1), filters=8, kernel_size=3,
                            strides=2, activation='relu', name='Conv1'),
        keras.layers.Flatten(),
        keras.layers.Dense(10, activation=tf.nn.softmax, name='Softmax')
        ])
        model.summary()
        testing = False
        epochs = 5
        model.compile(optimizer='adam',
                    loss='sparse_categorical_crossentropy',
                    metrics=['accuracy'])
        logdir = "/training_logs"
        tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)
        model.fit(train_images,
            train_labels,
            epochs=epochs,
            callbacks=[tensorboard_callback],
        )
        test_loss, test_acc = model.evaluate(test_images, test_labels)
        print('\nTest accuracy: {}'.format(test_acc))
        export_path = os.path.join(model_path, model_version)
        print('export_path = {}\n'.format(export_path))
        tf.keras.models.save_model(
            model,
            export_path,
            overwrite=True,
            include_optimizer=True,
            save_format=None,
            signatures=None,
            options=None
        )
        print('\nSaved model success')
    if __name__ == '__main__':
        train()
    重要

    dataset_path と model_path をデータセットとモデルのパスに置き換えます。これにより、Notebook はクラスタにマウントされているデータセットにアクセスできます。

  6. Notebook の Execute icon アイコンをクリックします。

    予期される出力:

    TensorFlow version: 1.15.5
    
    train_images.shape: (60000, 28, 28, 1), of float64
    test_images.shape: (10000, 28, 28, 1), of float64
    Model: "sequential_2"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #
    =================================================================
    Conv1 (Conv2D)               (None, 13, 13, 8)         80
    _________________________________________________________________
    flatten_2 (Flatten)          (None, 1352)              0
    _________________________________________________________________
    Softmax (Dense)              (None, 10)                13530
    =================================================================
    Total params: 13,610
    Trainable params: 13,610
    Non-trainable params: 0
    _________________________________________________________________
    Train on 60000 samples
    Epoch 1/5
    60000/60000 [==============================] - 3s 57us/sample - loss: 0.5452 - acc: 0.8102
    Epoch 2/5
    60000/60000 [==============================] - 3s 52us/sample - loss: 0.4103 - acc: 0.8555
    Epoch 3/5
    60000/60000 [==============================] - 3s 55us/sample - loss: 0.3750 - acc: 0.8681
    Epoch 4/5
    60000/60000 [==============================] - 3s 55us/sample - loss: 0.3524 - acc: 0.8757
    Epoch 5/5
    60000/60000 [==============================] - 3s 53us/sample - loss: 0.3368 - acc: 0.8798
    10000/10000 [==============================] - 0s 37us/sample - loss: 0.3770 - acc: 0.8673
    
    Test accuracy: 0.8672999739646912
    export_path = ./model/v1
    Saved model success

C: Jupyter Notebook を使用してコードを Git リポジトリに送信する

Notebook を作成した後、Notebook を使用してコードを Git リポジトリに送信できます。

  1. 次のコマンドを実行して Git をインストールします。

    apt-get update
    apt-get install git
  2. 次のコマンドを実行して Git を初期化し、ユーザー名とパスワードを Notebook に保存します。

    git config --global credential.helper store
    git pull ${YOUR_GIT_REPO}
  3. 次のコマンドを実行して、コードを Git リポジトリにプッシュします。

    git push origin fashion-test

    予期される出力:

    Total 0 (delta 0), reused 0 (delta 0)
    To codeup.aliyun.com:60b4cf5c66bba1c04b442e49/tensorflow-fashion-mnist-sample.git
     * [new branch]      fashion-test -> fashion-test

D: Arena SDK を使用してトレーニングジョブを送信する

  1. Arena SDK の依存関係をインストールします。

    !pip install coloredlogs
  2. 次のコードを使用して、初期化用の Python ファイルを作成します。

    import os
    import sys
    import time
    from arenasdk.client.client import ArenaClient
    from arenasdk.enums.types import *
    from arenasdk.exceptions.arena_exception import *
    from arenasdk.training.tensorflow_job_builder import *
    from arenasdk.logger.logger import LoggerBuilder
    
    def main():
        print("start to test arena-python-sdk")
        client = ArenaClient("","demo-ns","info","arena-system") # トレーニングジョブは demo-ns 名前空間に送信されます。
        print("create ArenaClient succeed.")
        print("start to create tfjob")
        job_name = "arena-sdk-distributed-test"
        job_type = TrainingJobType.TFTrainingJob
        try:
            # build the training job
            job =  TensorflowJobBuilder().with_name(job_name)\
                .witch_workers(1)\
                .with_gpus(1)\
                .witch_worker_image("tensorflow/tensorflow:1.5.0-devel-gpu")\
                .witch_ps_image("tensorflow/tensorflow:1.5.0-devel")\
                .witch_ps_count(1)\
                .with_datas({"fashion-demo-pvc":"/data"})\
                .enable_tensorboard()\
                .with_sync_mode("git")\
                .with_sync_source("https://codeup.aliyun.com/60b4cf5c66bba1c04b442e49/tensorflow-fashion-mnist-sample.git")\  # Git リポジトリのアドレス。
                .with_envs({\
                    "GIT_SYNC_USERNAME":"USERNAME", \   # Git リポジトリのユーザー名。
                    "GIT_SYNC_PASSWORD":"PASSWORD",\    # Git リポジトリのパスワード。
                    "TEST_TMPDIR":"/",\
                })\
                .with_command("python code/tensorflow-fashion-mnist-sample/tf-distributed-mnist.py").build()
            # if training job is not existed,create it
            if client.training().get(job_name, job_type):
                print("the job {} has been created, to delete it".format(job_name))
                client.training().delete(job_name, job_type)
                time.sleep(3)
    
            output = client.training().submit(job)
            print(output)
    
            count = 0
            # waiting training job to be running
            while True:
                if count > 160:
                    raise Exception("timeout for waiting job to be running")
                jobInfo = client.training().get(job_name,job_type)
                if jobInfo.get_status() == TrainingJobStatus.TrainingJobPending:
                    print("job status is PENDING,waiting...")
                    count = count + 1
                    time.sleep(5)
                    continue
                print("current status is {} of job {}".format(jobInfo.get_status().value,job_name))
                break
            # get the training job logs
            logger = LoggerBuilder().with_accepter(sys.stdout).with_follow().with_since("5m")
            #jobInfo.get_instances()[0].get_logs(logger)
            # display the training job information
            print(str(jobInfo))
            # delete the training job
            #client.training().delete(job_name, job_type)
        except ArenaException as e:
            print(e)
    
    main()
    • namespace: この例では、トレーニングジョブは demo-ns 名前空間に送信されます。

    • with_sync_source: Git リポジトリのアドレス。

    • with_envs: Git リポジトリのユーザー名とパスワード。

  3. Notebook の Execute icon アイコンをクリックします。

    予期される出力:

    2021-11-02/08:57:28 DEBUG util.py[line:19] - execute command: [arena get --namespace=demo-ns --arena-namespace=arena-system --loglevel=info arena-sdk-distributed-test --type=tfjob -o json]
    2021-11-02/08:57:28 DEBUG util.py[line:19] - execute command: [arena submit --namespace=demo-ns --arena-namespace=arena-system --loglevel=info tfjob --name=arena-sdk-distributed-test --workers=1 --gpus=1 --worker-image=tensorflow/tensorflow:1.5.0-devel-gpu --ps-image=tensorflow/tensorflow:1.5.0-devel --ps=1 --data=fashion-demo-pvc:/data --tensorboard --sync-mode=git --sync-source=https://codeup.aliyun.com/60b4cf5c66bba1c04b442e49/tensorflow-fashion-mnist-sample.git --env=GIT_SYNC_USERNAME=kubeai --env=GIT_SYNC_PASSWORD=kubeai@ACK123 --env=TEST_TMPDIR=/ python code/tensorflow-fashion-mnist-sample/tf-distributed-mnist.py]
    start to test arena-python-sdk
    create ArenaClient succeed.
    start to create tfjob
    2021-11-02/08:57:29 DEBUG util.py[line:19] - execute command: [arena get --namespace=demo-ns --arena-namespace=arena-system --loglevel=info arena-sdk-distributed-test --type=tfjob -o json]
    service/arena-sdk-distributed-test-tensorboard created
    deployment.apps/arena-sdk-distributed-test-tensorboard created
    tfjob.kubeflow.org/arena-sdk-distributed-test created
    
    job status is PENDING,waiting...
    2021-11-02/09:00:34 DEBUG util.py[line:19] - execute command: [arena get --namespace=demo-ns --arena-namespace=arena-system --loglevel=info arena-sdk-distributed-test --type=tfjob -o json]
    current status is RUNNING of job arena-sdk-distributed-test
    {
        "allocated_gpus": 1,
        "chief_name": "arena-sdk-distributed-test-worker-0",
        "duration": "185s",
        "instances": [
            {
                "age": "13s",
                "gpu_metrics": [],
                "is_chief": false,
                "name": "arena-sdk-distributed-test-ps-0",
                "node_ip": "192.168.5.8",
                "node_name": "cn-beijing.192.168.5.8",
                "owner": "arena-sdk-distributed-test",
                "owner_type": "tfjob",
                "request_gpus": 0,
                "status": "Running"
            },
            {
                "age": "13s",
                "gpu_metrics": [],
                "is_chief": true,
                "name": "arena-sdk-distributed-test-worker-0",
                "node_ip": "192.168.5.8",
                "node_name": "cn-beijing.192.168.5.8",
                "owner": "arena-sdk-distributed-test",
                "owner_type": "tfjob",
                "request_gpus": 1,
                "status": "Running"
            }
        ],
        "name": "arena-sdk-distributed-test",
        "namespace": "demo-ns",
        "priority": "N/A",
        "request_gpus": 1,
        "tensorboard": "http://192.168.5.6:31068",
        "type": "tfjob"
    }

手順 4: モデルをトレーニングする

スタンドアロン TensorFlow トレーニングジョブ、分散 TensorFlow トレーニングジョブ、Fluid 高速トレーニングジョブ、および ACK の AI ジョブスケジューラによって高速化された分散トレーニングジョブを送信するには、次の例を参照してください。

例 1: スタンドアロン Tensorflow トレーニングジョブを送信する

Notebook を使用してモデルを開発し、モデルを保存した後、Arena または AI 開発者コンソールを使用してトレーニングジョブを送信できます。

方法 1: Arena を使用してスタンドアロン TensorFlow トレーニングジョブを送信する

arena \
  submit \
  tfjob \
  -n ns1 \
  --name=fashion-mnist-arena \
  --data=fashion-mnist-jackwg-pvc:/root/data/ \
  --env=DATASET_PATH=/root/data/ \
  --env=MODEL_PATH=/root/saved_model \
  --env=MODEL_VERSION=1 \
  --env=GIT_SYNC_USERNAME=<GIT_USERNAME> \
  --env=GIT_SYNC_PASSWORD=<GIT_PASSWORD> \
  --sync-mode=git \
  --sync-source=https://codeup.aliyun.com/60b4cf5c66bba1c04b442e49/tensorflow-fashion-mnist-sample.git \
  --image="tensorflow/tensorflow:2.2.2-gpu" \
  "python /root/code/tensorflow-fashion-mnist-sample/train.py --log_dir=/training_logs"

方法 2: AI 開発者コンソールを使用してスタンドアロン TensorFlow トレーニングジョブを送信する

  1. データソースを構成します。詳細については、「データセットを構成する」をご参照ください。

    Configure a dataset

    次の表に、いくつかのパラメータを示します。

    パラメーター

    必須

    [名前]

    fashion-demo

    はい

    [名前空間]

    demo-ns

    はい

    [persistentvolumeclaim]

    fashion-demo-pvc

    はい

    [ローカルディレクトリ]

    /root/data

    いいえ

  2. ソースコードを構成します。詳細については、「ソースコードリポジトリを構成する」をご参照ください。

    Configure the source code

    パラメーター

    必須

    [名前]

    fashion-git

    はい

    [git リポジトリ]

    https://codeup.aliyun.com/60b4cf5c66bba1c04b442e49/tensorflow-fashion-mnist-sample.git

    はい

    [デフォルトブランチ]

    master

    いいえ

    [ローカルディレクトリ]

    /root/

    いいえ

    [git ユーザー]

    非公開 Git リポジトリのユーザー名。

    いいえ

    [git シークレット]

    非公開 Git リポジトリのパスワード。

    いいえ

  3. スタンドアロン TensorFlow トレーニングジョブを送信します。詳細については、「TensorFlow トレーニングジョブを送信する」をご参照ください。

    ジョブパラメータを構成した後、[送信] をクリックします。トレーニングジョブがジョブリストに表示されます。次の図は、ジョブパラメータを示しています。Submit a standalone training job

    パラメーター

    説明

    [ジョブ名]

    この例では、fashion-tf-ui が使用されています。

    [ジョブタイプ]

    この例では、[TF スタンドアロン] が選択されています。

    [名前空間]

    この例では、demo-ns が選択されています。データセットが属する名前空間を選択する必要があります。

    [データ構成]

    この例では、fashion-demo が選択されています。ステップ 1 で構成したデータソースを選択する必要があります。

    [コード構成]

    この例では、fashion-git が選択されています。ステップ 2 で構成したソースコードを選択する必要があります。

    [コードブランチ]

    この例では、マスターが指定されています。

    [実行コマンド]

    この例では、次のコマンドが指定されています。"export DATASET_PATH=/root/data/ &&export MODEL_PATH=/root/saved_model &&export MODEL_VERSION=1 &&python /root/code/tensorflow-fashion-mnist-sample/train.py"

    [非公開 Git]

    非公開 Git リポジトリを使用するには、最初に非公開 Git リポジトリのユーザー名とパスワードを指定する必要があります。

    [インスタンス数]

    デフォルト値: 1。

    [イメージ]

    この例では、tensorflow/tensorflow:2.2.2-gpu が指定されています。

    [イメージプルシークレット]

    プライベートイメージリポジトリからイメージをプルするには、最初にシークレットを作成する必要があります。

    [CPU (コア)]

    デフォルト値: 4。

    [メモリ (GB)]

    デフォルト値: 8。

    Arena コマンドの詳細については、「Arena を使用して TensorFlow トレーニングジョブを送信する」をご参照ください。

  4. ジョブを送信した後、ジョブログを確認します。

    1. AI 開発者コンソールの左側のナビゲーションウィンドウで、[ジョブリスト] をクリックします。

    2. [ジョブリスト] ページで、送信したジョブの名前をクリックします。

    3. 詳細ページで、[インスタンス] タブをクリックします。表示するインスタンスを見つけて、ログ[オペレーター] 列の をクリックします。

      例:

      train_images.shape: (60000, 28, 28, 1), of float64
      test_images.shape: (10000, 28, 28, 1), of float64
      Model: "sequential"
      _________________________________________________________________
      Layer (type)                 Output Shape              Param #
      =================================================================
      Conv1 (Conv2D)               (None, 13, 13, 8)         80
      _________________________________________________________________
      flatten (Flatten)            (None, 1352)              0
      _________________________________________________________________
      Softmax (Dense)              (None, 10)                13530
      =================================================================
      Total params: 13,610
      Trainable params: 13,610
      Non-trainable params: 0
      _________________________________________________________________
      Epoch 1/5
      2021-08-01 14:21:17.532237: E tensorflow/core/profiler/internal/gpu/cupti_tracer.cc:1430] function cupti_interface_->EnableCallback( 0 , subscriber_, CUPTI_CB_DOMAIN_DRIVER_API, cbid)failed with error CUPTI_ERROR_INVALID_PARAMETER
      2021-08-01 14:21:17.532390: I tensorflow/core/profiler/internal/gpu/device_tracer.cc:216]  GpuTracer has collected 0 callback api events and 0 activity events.
      2021-08-01 14:21:17.533535: I tensorflow/core/profiler/rpc/client/save_profile.cc:168] Creating directory: /training_logs/train/plugins/profile/2021_08_01_14_21_17
      2021-08-01 14:21:17.533928: I tensorflow/core/profiler/rpc/client/save_profile.cc:174] Dumped gzipped tool data for trace.json.gz to /training_logs/train/plugins/profile/2021_08_01_14_21_17/fashion-mnist-arena-chief-0.trace.json.gz
      2021-08-01 14:21:17.534251: I tensorflow/core/profiler/utils/event_span.cc:288] Generation of step-events took 0 ms
      
      2021-08-01 14:21:17.534961: I tensorflow/python/profiler/internal/profiler_wrapper.cc:87] Creating directory: /training_logs/train/plugins/profile/2021_08_01_14_21_17Dumped tool data for overview_page.pb to /training_logs/train/plugins/profile/2021_08_01_14_21_17/fashion-mnist-arena-chief-0.overview_page.pb
      Dumped tool data for input_pipeline.pb to /training_logs/train/plugins/profile/2021_08_01_14_21_17/fashion-mnist-arena-chief-0.input_pipeline.pb
      Dumped tool data for tensorflow_stats.pb to /training_logs/train/plugins/profile/2021_08_01_14_21_17/fashion-mnist-arena-chief-0.tensorflow_stats.pb
      Dumped tool data for kernel_stats.pb to /training_logs/train/plugins/profile/2021_08_01_14_21_17/fashion-mnist-arena-chief-0.kernel_stats.pb
      
      1875/1875 [==============================] - 3s 2ms/step - loss: 0.5399 - accuracy: 0.8116
      Epoch 2/5
      1875/1875 [==============================] - 3s 2ms/step - loss: 0.4076 - accuracy: 0.8573
      Epoch 3/5
      1875/1875 [==============================] - 3s 2ms/step - loss: 0.3727 - accuracy: 0.8694
      Epoch 4/5
      1875/1875 [==============================] - 3s 2ms/step - loss: 0.3512 - accuracy: 0.8769
      Epoch 5/5
      1875/1875 [==============================] - 3s 2ms/step - loss: 0.3351 - accuracy: 0.8816
      313/313 [==============================] - 0s 1ms/step - loss: 0.3595 - accuracy: 0.8733
      2021-08-01 14:21:34.820089: W tensorflow/python/util/util.cc:329] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
      WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
      Instructions for updating:
      If using Keras pass *_constraint arguments to layers.
      
      Test accuracy: 0.8733000159263611
      export_path = /root/saved_model/1
      
      
      Saved model success
  5. TensorBoard でデータを表示します。

    kubectl port-forward コマンドを使用して、ローカルポートを TensorBoard サービスにマップできます。次の操作を実行して、MaxCompute と VPC 間の接続を確立できます。

    1. 次のコマンドを実行して、TensorBoard サービスの IP アドレスをクエリします。

      kubectl get svc -n demo-ns

      予期される出力:

      NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)               AGE
      tf-dist-arena-tensorboard   NodePort    172.16.XX.XX     <none>        6006:32226/TCP        80m
    2. 次のコマンドを実行して、ローカルポートを TensorBoard サービスにマップします。

      kubectl port-forward svc/tf-dist-arena-tensorboard -n demo-ns 6006:6006

      予期される出力:

      Forwarding from 127.0.0.1:6006 -> 6006
      Forwarding from [::1]:6006 -> 6006
      Handling connection for 6006
      Handling connection for 6006
    3. ブラウザのアドレスバーに http://localhost:6006/ と入力して、TensorBoard でデータを表示します。

      Tensorboard

例 2: 分散 Tensorflow トレーニングジョブを送信する

方法 1: Arena を使用して分散 TensorFlow トレーニングジョブを送信する

  1. 次のコマンドを実行して、Arena を使用して分散 TensorFlow トレーニングジョブを送信します。

    arena submit tf \
        -n demo-ns \
        --name=tf-dist-arena \
        --working-dir=/root/ \
        --data fashion-mnist-pvc:/data \
        --env=TEST_TMPDIR=/ \
        --env=GIT_SYNC_USERNAME=kubeai \
        --env=GIT_SYNC_PASSWORD=kubeai@ACK123 \
        --env=GIT_SYNC_BRANCH=master \
        --gpus=1 \
        --workers=2 \
        --worker-image=tensorflow/tensorflow:1.5.0-devel-gpu \
        --sync-mode=git \
        --sync-source=https://codeup.aliyun.com/60b4cf5c66bba1c04b442e49/tensorflow-fashion-mnist-sample.git \
        --ps=1 \
        --ps-image=tensorflow/tensorflow:1.5.0-devel \
        --tensorboard \
        "python code/tensorflow-fashion-mnist-sample/tf-distributed-mnist.py --log_dir=/training_logs"
  2. 次のコマンドを実行して、TensorBoard サービスの IP アドレスをクエリします。

    kubectl get svc -n demo-ns

    予期される出力:

    NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                 AGE
    tf-dist-arena-tensorboard   NodePort    172.16.204.248   <none>        6006:32226/TCP          80m
  3. 次のコマンドを実行して、ローカルポートを TensorBoard サービスにマップします。

    TensorBoard を表示するには、kubectl port-forward コマンドを使用して、ローカルポートを TensorBoard サービスにマップします。

    kubectl port-forward svc/tf-dist-arena-tensorboard -n demo-ns 6006:6006

    予期される出力:

    Forwarding from 127.0.0.1:6006 -> 6006
    Forwarding from [::1]:6006 -> 6006
    Handling connection for 6006
    Handling connection for 6006
  4. ブラウザのアドレスバーに http://localhost:6006/ と入力して、TensorBoard でデータを表示します。

    View data on TensorBoard

方法 2: AI 開発者コンソールを使用して分散 TensorFlow トレーニングジョブを送信する

  1. データソースを構成します。詳細については、「データセットを構成する」をご参照ください。

    この例では、データソースの構成は 1 で使用したものと同じです。

  2. ソースコードを構成します。詳細については、「ソースコードリポジトリを構成する」をご参照ください。

    この例では、ソースコードの構成は 2 で使用したものと同じです。

  3. 分散 TensorFlow トレーニングジョブを送信します。詳細については、「TensorFlow トレーニングジョブを送信する」をご参照ください。

    ジョブパラメータを構成した後、[送信] をクリックします。トレーニングジョブがジョブリストに表示されます。次の図は、ジョブパラメータを示しています。Submit a distributed TensorFlow training job

    パラメーター

    説明

    [ジョブ名]

    この例では、fashion-ps-ui が使用されます。

    [ジョブタイプ]

    この例では、[TF 分散] が選択されています。

    [名前空間]

    この例では、demo-ns が選択されています。データセットが属する名前空間を選択する必要があります。

    [データ構成]

    この例では、fashion-demo が選択されています。ステップ 1 で構成したデータソースを選択する必要があります。

    [コード構成]

    この例では、fashion-git が選択されています。ステップ 2 で構成したソースコードを選択する必要があります。

    [実行コマンド]

    この例では、次のコマンドが指定されています。"export TEST_TMPDIR=/root/ && python code/tensorflow-fashion-mnist-sample/tf-distributed-mnist.py --log_dir=/training_logs"

    [イメージ]

    • [リソース] セクションの [ワーカー] タブで、[イメージ]tensorflow/tensorflow:1.5.0-devel-gpu に設定します。

    • [リソース] セクションの [PS] タブで、[イメージ]tensorflow/tensorflow:1.5.0-devel に設定します。

    Arena コマンドの詳細については、「Arena を使用して TensorFlow トレーニングジョブを送信する」をご参照ください。

  4. TensorBoard でデータを表示します。詳細については、「2 から 4[方法 1: Arena を使用して分散 Tensorflow トレーニングジョブを送信する]」をご参照ください。

例 3: Fluid 高速トレーニングジョブを送信する

この例では、データセットは AI ダッシュボードで高速化され、高速化されたデータセットを使用するトレーニングジョブが送信されます。結果は、トレーニングジョブの完了に必要な時間が短縮されたことを示しています。手順:

  1. 管理者は、AI ダッシュボードでデータセットを高速化します。

  2. 開発者は Arena を使用して、高速化されたデータセットを使用するトレーニングジョブを送信します。

  3. Arena を使用して、トレーニングジョブの完了に必要な時間をクエリします。

  1. データセットを高速化します。

    手順 2: データセットを作成する で fashion-demo-pvc を高速化した場合は、この手順をスキップします。データセットを高速化する方法の詳細については、「OSS に基づいて高速化されたデータセットを作成する」をご参照ください。

  2. 高速化されたデータセットを使用するトレーニングジョブを送信します。

    開発者は、高速化されたデータセットを使用するトレーニングジョブを demo-ns 名前空間に送信します。高速化されたデータセットを使用するジョブの構成と通常のデータセットを使用するジョブの構成は、次のパラメータ設定が異なります。

    • --data: 高速化された VPC。この例では fashion-demo-pvc-acc です。

    • --env=DATASET_PATH: データセット PVC のマウントパス。この例では、/root/data/--data の と、PVC の名前である fashion-demo-pvc-acc です。

    arena \
      submit \
      tfjob \
      -n demo-ns \
      --name=fashion-mnist-fluid \
      --data=fashion-demo-pvc-acc:/root/data/ \
      --env=DATASET_PATH=/root/data/fashion-demo-pvc-acc \
      --env=MODEL_PATH=/root/saved_model \
      --env=MODEL_VERSION=1 \
      --env=GIT_SYNC_USERNAME=${GIT_USERNAME} \
      --env=GIT_SYNC_PASSWORD=${GIT_PASSWORD} \
      --sync-mode=git \
      --sync-source=https://codeup.aliyun.com/60b4cf5c66bba1c04b442e49/tensorflow-fashion-mnist-sample.git \
      --image="tensorflow/tensorflow:2.2.2-gpu" \
      "python /root/code/tensorflow-fashion-mnist-sample/train.py --log_dir=/training_logs"
  3. 次のコマンドを実行して、2 つのトレーニングジョブの完了に必要な時間を比較します。

    arena list -n demo-ns

    予期される出力:

    NAME                 STATUS     TRAINER  DURATION  GPU(Requested)  GPU(Allocated)  NODE
    fashion-mnist-fluid  SUCCEEDED  TFJOB    33s       0               N/A             192.168.5.7
    fashion-mnist-arena  SUCCEEDED  TFJOB    3m        0               N/A             192.168.5.8

    arena list コマンドの出力は、Fluid 高速トレーニングジョブの完了には 33 秒かかったのに対し、通常のデータセットを使用するトレーニングジョブの完了には 3 分かかったことを示しています。どちらのジョブも同じコードで同じノードで実行されています。

例 4: ACK の AI ジョブスケジューラを使用して分散トレーニングジョブを高速化する

ACK は、AI およびビッグデータコンピューティング用に最適化された AI ジョブスケジューラを提供します。AI ジョブスケジューラは、ギャングスケジューリング、容量スケジューリング、およびトポロジー対応スケジューリングをサポートしています。この例では、トポロジー対応 GPU スケジューリングが有効になっているトレーニングジョブを使用します。

AI ワークロードの高パフォーマンスを確保するために、AI ジョブスケジューラは、ノード上の異種リソースに関するトポロジー情報に基づいて最適なスケジューリングソリューションを選択します。情報には、GPU が NVLink と PCIe スイッチを使用して相互に通信する方法、および CPU の非均一メモリアクセス (NUMA) トポロジーが含まれます。トポロジー対応 GPU スケジューリングの詳細については、「GPU トポロジー対応スケジューリング」をご参照ください。トポロジー対応 CPU スケジューリングの詳細については、「トポロジー対応 CPU スケジューリングを有効にする」をご参照ください。

次の手順を実行して、トポロジー対応 GPU スケジューリングが有効になっているトレーニングジョブとトポロジー対応 GPU スケジューリングが無効になっているトレーニングジョブを送信します。次に、ジョブの完了に必要な時間を比較します。

  1. 次のコマンドを実行して、トポロジー対応 GPU スケジューリングが無効になっているトレーニングジョブを送信します。

    arena submit mpi \
      --name=tensorflow-4-vgg16 \
      --gpus=1 \
      --workers=4 \
      --image=registry.cn-hangzhou.aliyuncs.com/kubernetes-image-hub/tensorflow-benchmark:tf2.3.0-py3.7-cuda10.1 \
      "mpirun --allow-run-as-root -np "4" -bind-to none -map-by slot -x NCCL_DEBUG=INFO -x NCCL_SOCKET_IFNAME=eth0 -x LD_LIBRARY_PATH -x PATH --mca pml ob1 --mca btl_tcp_if_include eth0 --mca oob_tcp_if_include eth0 --mca orte_keep_fqdn_hostnames t --mca btl ^openib python /tensorflow/benchmarks/scripts/tf_cnn_benchmarks/tf_cnn_benchmarks.py --model=vgg16 --batch_size=64 --variable_update=horovod"
  2. トポロジー対応 GPU スケジューリングが有効になっているトレーニングジョブを送信します。

    ジョブを実行するノードにラベルを追加する必要があります。この例では、cn-beijing.192.168.XX.XX ノードが使用されます。ノードを実際に使用するノードに置き換えます。

    kubectl label node cn-beijing.192.168.XX.XX ack.node.gpu.schedule=topology --overwrite

    次のコマンドを実行して、トポロジー対応 GPU スケジューリングを有効にするために使用される --gputopology=true で構成されたトレーニングジョブを送信します。

    arena submit mpi \
      --name=tensorflow-topo-4-vgg16 \
      --gpus=1 \
      --workers=4 \
      --gputopology=true \
      --image=registry.cn-hangzhou.aliyuncs.com/kubernetes-image-hub/tensorflow-benchmark:tf2.3.0-py3.7-cuda10.1 \
      "mpirun --allow-run-as-root -np "4" -bind-to none -map-by slot -x NCCL_DEBUG=INFO -x NCCL_SOCKET_IFNAME=eth0 -x LD_LIBRARY_PATH -x PATH --mca pml ob1 --mca btl_tcp_if_include eth0 --mca oob_tcp_if_include eth0 --mca orte_keep_fqdn_hostnames t --mca btl ^openib python /tensorflow/benchmarks/scripts/tf_cnn_benchmarks/tf_cnn_benchmarks.py --model=vgg16 --batch_size=64 --variable_update=horovod"
  3. トレーニングジョブの完了に必要な時間を比較します。

    1. 次のコマンドを実行して、2 つのトレーニングジョブの完了に必要な時間を比較します。

      arena list -n demo-ns

      予期される出力:

      NAME                             STATUS     TRAINER  DURATION  GPU(Requested)  GPU(Allocated)  NODE
      tensorflow-topo-4-vgg16          SUCCEEDED  MPIJOB   44s       4               N/A             192.168.4.XX1
      tensorflow-4-vgg16-image-warned  SUCCEEDED  MPIJOB   2m        4               N/A             192.168.4.XX0
    2. 次のコマンドを実行して、トポロジー対応 GPU スケジューリングが無効になっているトレーニングジョブの GPU 処理時間の合計をクエリします。

      arena logs tensorflow-topo-4-vgg16 -n demo-ns

      予期される出力:

      100 images/sec: 251.7 +/- 0.1 (jitter = 1.2)  7.262
      ----------------------------------------------------------------
      total images/sec: 1006.44
    3. 次のコマンドを実行して、トポロジー対応 GPU スケジューリングが有効になっているトレーニングジョブの GPU 処理時間の合計をクエリします。

      arena logs tensorflow-4-vgg16-image-warned -n demo-ns

      予期される出力:

      100 images/sec: +/- 0.2 (jitter = 1.5)  7.261
      ----------------------------------------------------------------
      total images/sec: 225.50

次の表は、2 つのジョブの結果を示しています。

トレーニング ジョブ

GPU あたりの処理時間 (ns)

GPU 処理時間合計 (ns)

期間 (秒)

トポロジー対応 GPU スケジューリング有効

56.4

225.50

44

トポロジー対応 GPU スケジューリング無効

251.7

1006.44

120

ノードでトポロジー対応 GPU スケジューリングが有効になっている場合、通常の GPU スケジューリングを有効にすることはできません。通常の GPU スケジューリングを再開するには、次のコマンドを実行してノードラベルを変更します。

kubectl label node cn-beijing.192.168.XX.XX0 ack.node.gpu.schedule=default --overwrite

手順 5: モデルを管理する

  1. AI 開発者コンソールにログインする
  2. AI 開発者コンソールの左側のナビゲーションウィンドウで、[モデル管理] をクリックします。
  3. [モデル管理] ページで、[モデルの作成] をクリックします。

  4. [作成] ダイアログボックスで、[モデル名][モデルバージョン]、および [ジョブ名] を設定します。

    この例では、[モデル名] は fsahion-mnist-demo、[モデルバージョン] は v1、[ジョブ名] は tf-single に設定されています。

  5. [OK] をクリックします。モデルがページに表示されます。

    Create a model

    モデルを評価する場合は、[操作] 列の [新しいモデル評価] をクリックします。

手順 6: モデルを評価する

クラウドネイティブコンポーネントセットをインストールした後、Arena または AI 開発者コンソールを使用して評価ジョブを送信できます。この例では、Fashion-MNIST データセットに基づいてトレーニングされたモデルのチェックポイントを評価するために、評価ジョブが送信されます。手順:

  1. Arena を使用して、チェックポイントをエクスポートするトレーニングジョブを送信します。

  2. Arena を使用して評価ジョブを送信します。

  3. AI 開発者コンソールを使用して、異なるモデルの評価結果を比較します。

  1. チェックポイントをエクスポートするトレーニングジョブを送信します。

    次のコマンドを実行して、Arena を使用して、チェックポイントを fashion-demo-pvc にエクスポートするトレーニングジョブを送信します。

    arena \
      submit \
      tfjob \
      -n demo-ns \ # ビジネス要件に基づいて名前空間を変更できます。
      --name=fashion-mnist-arena-ckpt \
      --data=fashion-demo-pvc:/root/data/ \
      --env=DATASET_PATH=/root/data/ \
      --env=MODEL_PATH=/root/data/saved_model \
      --env=MODEL_VERSION=1 \
      --env=GIT_SYNC_USERNAME=${GIT_USERNAME} \ # Git リポジトリのユーザー名。
      --env=GIT_SYNC_PASSWORD=${GIT_PASSWORD} \ # Git リポジトリのパスワード。
      --env=OUTPUT_CHECKPOINT=1 \
      --sync-mode=git \
      --sync-source=https://codeup.aliyun.com/60b4cf5c66bba1c04b442e49/tensorflow-fashion-mnist-sample.git \
      --image="tensorflow/tensorflow:2.2.2-gpu" \
      "python /root/code/tensorflow-fashion-mnist-sample/train.py --log_dir=/training_logs"
  2. 評価ジョブを送信します。

    1. ジョブのデプロイに使用するイメージをビルドします。

      モデル評価のコードを取得します。kubeai-sdk ディレクトリで次のコマンドを実行して、イメージを作成およびプッシュします。

      docker build . -t ${DOCKER_REGISTRY}:fashion-mnist
      docker push ${DOCKER_REGISTRY}:fashion-mnist
    2. 次のコマンドを実行して、MySQL へのアクセスを提供するサービスをクエリします。

      kubectl get svc -n kube-ai ack-mysql

      予期される出力:

      NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
      ack-mysql   ClusterIP   172.16.XX.XX    <none>        3306/TCP   28h
    3. 次のコマンドを実行して、Arena を使用して評価ジョブを送信します。

      arena evaluate model \
       --namespace=demo-ns \
       --loglevel=debug \
       --name=evaluate-job \
       --image=registry.cn-beijing.aliyuncs.com/kube-ai/kubeai-sdk-demo:fashion-minist \
       --env=ENABLE_MYSQL=True \
       --env=MYSQL_HOST=172.16.77.227 \
       --env=MYSQL_PORT=3306 \
       --env=MYSQL_USERNAME=kubeai \
       --env=MYSQL_PASSWORD=kubeai@ACK \
       --data=fashion-demo-pvc:/data \
       --model-name=1 \
       --model-path=/data/saved_model/ \
       --dataset-path=/data/ \
       --metrics-path=/data/output \
       "python /kubeai/evaluate.py"
      説明

      前の手順の出力から IP アドレスとポートを取得して、MySQL にアクセスできます。

  3. 評価結果を比較します。

    1. AI 開発者コンソールの左側のナビゲーションウィンドウで、[モデル管理] をクリックします。

      Model evaluation list

    2. [ジョブリスト] セクションで、評価ジョブの名前をクリックしてメトリックを表示できます。

      Evaluation job metrics

      異なる評価ジョブのメトリックを比較することもできます。Compare the metrics of different evaluation jobs

手順 7: モデルをサービスとしてデプロイする

モデルを開発および評価した後、モデルをサービスとしてデプロイできます。次の手順では、前のモデルを tf-serving という名前の推論サービスとしてデプロイする方法について説明します。Arena は、Triton や Seldon など、さまざまなサービスアーキテクチャをサポートしています。詳細については、「Arena serve guide」をご参照ください。

この例では、手順 4: モデルをトレーニングする でトレーニングされたモデルを使用します。モデルは、手順 2: データセットを作成する で使用された fashion-minist-demo PVC に格納されます。モデルを他のタイプのストレージに格納する場合は、最初に使用するストレージタイプの PVC を作成する必要があります。

  1. 次のコマンドを実行して、Arena を使用して TensorFlow モデルを TensorFlow Serving にデプロイします。

    arena serve tensorflow \
      --loglevel=debug \
      --namespace=demo-ns \
      --name=fashion-mnist \
      --model-name=1  \
      --gpus=1  \
      --image=tensorflow/serving:1.15.0-gpu \
      --data=fashion-demo-pvc:/data \
      --model-path=/data/saved_model/ \
      --version-policy=latest
  2. 次のコマンドを実行して、デプロイした推論サービスの名前をクエリします。

    arena serve list -n demo-ns

    予期される出力:

    NAME           TYPE        VERSION       DESIRED  AVAILABLE  ADDRESS         PORTS                   GPU
    fashion-mnist  Tensorflow  202111031203  1        1          172.16.XX.XX    GRPC:8500,RESTFUL:8501  1

    ADDRESS 列と PORTS 列の IP アドレスとポートを使用して、クラスタ内から推論サービスにリクエストを送信できます。

  3. Jupyter で Jupyter Notebook を作成し、Notebook をクライアントとして使用して、tf-serving サービスに HTTP リクエストを送信します。

    この例では、手順 3: モデルを開発する で作成した Jupyter Notebook を使用します。

    • Notebook を初期化するために使用されるコードの server_ip フィールドの値として 172.16.XX.XX を指定します。172.16.XX.XX は、前の手順の ADDRESS 列で返されます。

    • Notebook を初期化するために使用されるコードの server_http_port フィールドの値として 8501 を指定します。ポート 8501 は前の手順の PORTS 列で返され、RESTful API の呼び出しに使用されます。

    例:

    import os
    import gzip
    import numpy as np
    # import matplotlib.pyplot as plt
    import random
    import requests
    import json
    
    server_ip = "172.16.XX.XX"
    server_http_port = 8501
    
    dataset_dir = "/root/data/"
    
    def load_data():
            files = [
                'train-labels-idx1-ubyte.gz',
                'train-images-idx3-ubyte.gz',
                't10k-labels-idx1-ubyte.gz',
                't10k-images-idx3-ubyte.gz'
            ]
    
            paths = []
            for fname in files:
                paths.append(os.path.join(dataset_dir, fname))
    
            with gzip.open(paths[0], 'rb') as labelpath:
                y_train = np.frombuffer(labelpath.read(), np.uint8, offset=8)
            with gzip.open(paths[1], 'rb') as imgpath:
                x_train = np.frombuffer(imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)
            with gzip.open(paths[2], 'rb') as labelpath:
                y_test = np.frombuffer(labelpath.read(), np.uint8, offset=8)
            with gzip.open(paths[3], 'rb') as imgpath:
                x_test = np.frombuffer(imgpath.read(), np.uint8, offset=16).reshape(len(y_test), 28, 28)
    
    
            return (x_train, y_train),(x_test, y_test)
    
    def show(idx, title):
      plt.figure()
      plt.imshow(test_images[idx].reshape(28,28))
      plt.axis('off')
      plt.title('\n\n{}'.format(title), fontdict={'size': 16})
    
    class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
                   'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
    
    (train_images, train_labels), (test_images, test_labels) = load_data()
    train_images = train_images / 255.0
    test_images = test_images / 255.0
    
    # reshape for feeding into the model
    train_images = train_images.reshape(train_images.shape[0], 28, 28, 1)
    test_images = test_images.reshape(test_images.shape[0], 28, 28, 1)
    
    print('\ntrain_images.shape: {}, of {}'.format(train_images.shape, train_images.dtype))
    print('test_images.shape: {}, of {}'.format(test_images.shape, test_images.dtype))
    
    rando = random.randint(0,len(test_images)-1)
    #show(rando, 'An Example Image: {}'.format(class_names[test_labels[rando]]))
    
    # !pip install -q requests
    
    # import requests
    # headers = {"content-type": "application/json"}
    # json_response = requests.post('http://localhost:8501/v1/models/fashion_model:predict', data=data, headers=headers)
    # predictions = json.loads(json_response.text)['predictions']
    
    # show(0, 'The model thought this was a {} (class {}), and it was actually a {} (class {})'.format(
    #   class_names[np.argmax(predictions[0])], np.argmax(predictions[0]), class_names[test_labels[0]], test_labels[0]))
    
    
    def request_model(data):
        headers = {"content-type": "application/json"}
        json_response = requests.post('http://{}:{}/v1/models/1:predict'.format(server_ip, server_http_port), data=data, headers=headers)
        print('=======response:', json_response, json_response.text)
        predictions = json.loads(json_response.text)['predictions']
    
        print('The model thought this was a {} (class {}), and it was actually a {} (class {})'.format(class_names[np.argmax(predictions[0])], np.argmax(predictions[0]), class_names[test_labels[0]], test_labels[0]))
        #show(0, 'The model thought this was a {} (class {}), and it was actually a {} (class {})'.format(
        #  class_names[np.argmax(predictions[0])], np.argmax(predictions[0]), class_names[test_labels[0]], test_labels[0]))
    
    # def request_model_version(data):
    #     headers = {"content-type": "application/json"}
    #     json_response = requests.post('http://{}:{}/v1/models/1/version/1:predict'.format(server_ip, server_http_port), data=data, headers=headers)
    #     print('=======response:', json_response, json_response.text)
    
    #     predictions = json.loads(json_response.text)
    #     for i in range(0,3):
    #       show(i, 'The model thought this was a {} (class {}), and it was actually a {} (class {})'.format(
    #         class_names[np.argmax(predictions[i])], np.argmax(predictions[i]), class_names[test_labels[i]], test_labels[i]))
    
    data = json.dumps({"signature_name": "serving_default", "instances": test_images[0:3].tolist()})
    print('Data: {} ... {}'.format(data[:50], data[len(data)-52:]))
    #request_model_version(data)
    request_model(data)

    Notebook の Execute icon アイコンをクリックします。次の出力が返されます。

    train_images.shape: (60000, 28, 28, 1), of float64
    test_images.shape: (10000, 28, 28, 1), of float64
    Data: {"signature_name": "serving_default", "instances": ...  [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0]]]]}
    =======response: <Response [200]> {
        "predictions": [[7.42696e-07, 6.91237556e-09, 2.66364452e-07, 2.27735413e-07, 4.0373439e-07, 0.00490919966, 7.27086217e-06, 0.0316713452, 0.0010733594, 0.962337255], [0.00685342, 1.8516447e-08, 0.9266119, 2.42278338e-06, 0.0603800081, 4.01338771e-12, 0.00613868702, 4.26091073e-15, 1.35764185e-05, 3.38685469e-10], [1.09047969e-05, 0.999816835, 7.98738e-09, 0.000122893631, 4.85748023e-05, 1.50353979e-10, 3.57102294e-07, 1.89657579e-09, 4.4604468e-07, 9.23274524e-09]
        ]
    }
    The model thought this was a Ankle boot (class 9), and it was actually a Ankle boot (class 9)

FAQ

  • Jupyter Notebook コンソールに一般的に使用されるソフトウェアをインストールするにはどうすればよいですか?

    Jupyter Notebook コンソールに一般的に使用されるソフトウェアをインストールするには、次のコマンドを実行します。

    apt-get install ${Software name}
  • Jupyter Notebook コンソールの文字化けの問題を修正するにはどうすればよいですか?

    次の内容に基づいて /etc/locale ファイルを変更し、ターミナルを再度開きます。

    LC_CTYPE="da_DK.UTF-8"
    LC_NUMERIC="da_DK.UTF-8"
    LC_TIME="da_DK.UTF-8"
    LC_COLLATE="da_DK.UTF-8"
    LC_MONETARY="da_DK.UTF-8"
    LC_MESSAGES="da_DK.UTF-8"
    LC_PAPER="da_DK.UTF-8"
    LC_NAME="da_DK.UTF-8"
    LC_ADDRESS="da_DK.UTF-8"
    LC_TELEPHONE="da_DK.UTF-8"
    LC_MEASUREMENT="da_DK.UTF-8"
    LC_IDENTIFICATION="da_DK.UTF-8"
    LC_ALL=