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

Platform For AI:分散トレーニング DLC のクイックスタート

最終更新日:Nov 28, 2025

Deep Learning Containers (DLC) を使用すると、分散型または単一ノードのトレーニングジョブを迅速に作成できます。Kubernetes 上に構築された DLC は、手動でマシンを購入してランタイム環境を設定する必要がなく、既存のワークフローを変更することなく使用できます。このトピックでは、MNIST の手書き認識タスクを例に、DLC を使用して単一ノード、単一 GPU のトレーニングと、複数ノード、複数 GPU の分散トレーニングを行う方法を説明します。

説明

MNIST の手書き認識は、ディープラーニングにおける古典的な入門タスクです。その目的は、10 種類の手書き数字 (0 から 9) を認識する機械学習モデルを構築することです。

image

前提条件

Alibaba Cloud アカウントを使用して Platform for AI (PAI) をアクティブ化し、ワークスペースを作成します。PAI コンソールにログインします。左上のコーナーでリージョンを選択します。その後、必要な権限を付与し、プロダクトをアクティブ化します。

課金

このトピックの例では、パブリックリソースを使用して DLC ジョブを作成します。課金方法は従量課金です。課金ルールの詳細については、「Deep Learning Containers (DLC) の課金」をご参照ください。

単一ノード、単一 GPU トレーニング

データセットの作成

データセットには、モデルトレーニングのためのコード、データ、および結果が保存されます。このトピックでは、Object Storage Service (OSS) データセットを例として使用します。

  1. PAI コンソールの左側のナビゲーションウィンドウで、[データセット] > [カスタムデータセット] > [データセットの作成] をクリックします。

  2. データセットのパラメーターを設定します。主要なパラメーターは以下の通りです。その他のパラメーターはデフォルト値を使用できます。

    • [名前]: 例: dataset_mnist

    • [ストレージタイプ][Alibaba Cloud Object Storage Service (OSS)]

    • [OSS パス]image アイコンをクリックし、[バケット] を選択し、dlc_mnist などの新しいフォルダーを作成します。

      OSS をアクティブ化していない場合、または現在のリージョンで利用可能なバケットがない場合は、以下の手順に従って OSS をアクティブ化し、バケットを作成します:

      (オプション) OSS のアクティブ化とバケットの作成

      1. OSS をアクティブ化します

      2. OSS コンソールにログインします [バケットの作成] をクリックします。 [バケット名] を入力します。 [リージョン] で、PAI と同じリージョンを選択します。 他のパラメーターはデフォルト値を使用します。 次に、[作成] をクリックします。

        image

    [確認] をクリックしてデータセットを作成します。

  3. トレーニングコードとデータをアップロードします。

    1. mnist_train.py をクリックして、提供されているトレーニングコードをダウンロードします。プロセスを簡略化するため、コードは実行時にデータセットの dataSet フォルダーにトレーニングデータを自動的にダウンロードするように設定されています。

      本番環境で使用する場合は、事前にコードとトレーニングデータを PAI データセットにアップロードできます。

      単一ノード、単一 GPU トレーニングコードの例: mnist_train.py

      import torch
      import torch.nn as nn
      import torch.nn.functional as F
      import torch.optim as optim
      from torch.utils.data import DataLoader
      from torchvision import datasets, transforms
      from torch.utils.tensorboard import SummaryWriter
      
      # ハイパーパラメーター
      batch_size = 64  # 各トレーニングバッチのデータ量
      learning_rate = 0.01  # 学習率
      num_epochs = 20  # トレーニングエポック数
      
      # GPU が利用可能かどうかを確認
      device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
      
      # データの前処理
      transform = transforms.Compose([
          transforms.ToTensor(),
          transforms.Normalize((0.5,), (0.5,))
      ])
      
      train_dataset = datasets.MNIST(root='/mnt/data/dataSet', train=True, download=True, transform=transform)
      val_dataset = datasets.MNIST(root='/mnt/data/dataSet', train=False, download=False, transform=transform)
      
      train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
      val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)
      
      
      # シンプルなニューラルネットワークを定義
      class SimpleCNN(nn.Module):
          def __init__(self):
              super(SimpleCNN, self).__init__()
              # 最初の畳み込み層:入力チャンネル 1 (グレースケール画像)、出力チャンネル 10、カーネルサイズ 5x5
              self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
              # 2番目の畳み込み層:入力チャンネル 10、出力チャンネル 20、カーネルサイズ 3x3
              self.conv2 = nn.Conv2d(10, 20, kernel_size=3)
              # 全結合層:入力は 20 × 5 × 5 (畳み込みとプーリング後の特徴マップサイズ)、出力は 128
              self.fc1 = nn.Linear(20 * 5 * 5, 128)
              # 出力層:128 -> 10 (10個の数字クラスに対応)
              self.fc2 = nn.Linear(128, 10)
      
          def forward(self, x):
              # 入力 x の形状: [batch, 1, 28, 28]
              x = F.max_pool2d(F.relu(self.conv1(x)), 2)  # [batch, 10, 12, 12]
              x = F.max_pool2d(F.relu(self.conv2(x)), 2)  # [batch, 20, 5, 5]
              x = x.view(-1, 20 * 5 * 5)  # [batch, 500] にフラット化
              x = F.relu(self.fc1(x))      # [batch, 128]
              x = self.fc2(x)              # [batch, 10]
              return x
      
      
      # モデルをインスタンス化し、利用可能であれば GPU に移動
      model = SimpleCNN().to(device)
      criterion = nn.CrossEntropyLoss()
      optimizer = optim.SGD(model.parameters(), lr=learning_rate)
      
      # モデルのトレーニングプロセスを可視化するために TensorBoard の SummaryWriter を作成
      writer = SummaryWriter('/mnt/data/output/runs/mnist_experiment')
      
      # 最高の精度を持つモデルを保存するための変数
      best_val_accuracy = 0.0
      
      # モデルをトレーニングし、損失と精度を記録
      for epoch in range(num_epochs):
          model.train()
          for batch_idx, (data, target) in enumerate(train_loader):
              data, target = data.to(device), target.to(device)  # データとターゲットを GPU に移動
      
              # 勾配をゼロにする
              optimizer.zero_grad()
              # 順伝播
              output = model(data)
              # 損失を計算
              loss = criterion(output, target)
              # 逆伝播
              loss.backward()
              # パラメーターを更新
              optimizer.step()
      
              # トレーニング損失を TensorBoard に記録
              if batch_idx % 100 == 0:  # 100 バッチごとに記録
                  writer.add_scalar('Loss/train', loss.item(), epoch * len(train_loader) + batch_idx)
                  print(f'Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)} ({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}')
      
          # モデルを検証し、検証損失と精度を記録
          model.eval()
          val_loss = 0
          correct = 0
          with torch.no_grad():  # 勾配を計算しない
              for data, target in val_loader:
                  data, target = data.to(device), target.to(device)  # データとターゲットを GPU に移動
                  output = model(data)
                  val_loss += criterion(output, target).item()  # 検証損失を累積
                  pred = output.argmax(dim=1, keepdim=True)  # 予測ラベルを取得
                  correct += pred.eq(target.view_as(pred)).sum().item()  # 正解予測数を累積
      
          val_loss /= len(val_loader)  # 平均検証損失を計算
          val_accuracy = 100. * correct / len(val_loader.dataset)  # 検証精度を計算
          print(f'Validation Loss: {val_loss:.4f}, Accuracy: {correct}/{len(val_loader.dataset)} ({val_accuracy:.0f}%)')
      
          # 検証損失と精度を TensorBoard に記録
          writer.add_scalar('Loss/validation', val_loss, epoch)
          writer.add_scalar('Accuracy/validation', val_accuracy, epoch)
      
          # 最高の検証精度を持つモデルを保存
          if val_accuracy > best_val_accuracy:
              best_val_accuracy = val_accuracy
              torch.save(model.state_dict(), '/mnt/data/output/best_model.pth')
              print(f'Model saved with accuracy: {best_val_accuracy:.2f}%')
      
      # SummaryWriter を閉じる
      writer.close()
      print('Training complete. writer.close()')
    2. コードをアップロードします。データセットの詳細ページで、[データの表示] をクリックして OSS コンソールを開きます。次に、[オブジェクトのアップロード] > [ファイルの選択] > [オブジェクトのアップロード] をクリックして、トレーニングコードを OSS にアップロードします。

      image

DLC ジョブの作成

  1. PAI コンソールの左側のナビゲーションウィンドウで、[Deep Learning Containers (DLC)] > [ジョブの作成] をクリックします。

    image

  2. DLC ジョブのパラメーターを設定します。主要なパラメーターは以下の通りです。その他のパラメーターはデフォルト値を使用できます。すべてのパラメーターの詳細については、「トレーニングジョブの作成」をご参照ください。

    • [イメージ設定][イメージアドレス] を選択し、ご利用の [リージョン] のイメージ URL を入力します。

      image

      リージョン

      イメージ URL

      中国 (北京)

      dsw-registry-vpc.cn-beijing.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      中国 (上海)

      dsw-registry-vpc.cn-shanghai.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      中国 (杭州)

      dsw-registry-vpc.cn-hangzhou.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      その他のリージョン

      リージョン ID を検索し、イメージ URL の <Region ID> を置き換えて完全なリンクを取得します:

      dsw-registry-vpc.<Region ID>.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      このイメージは、「インタラクティブモデリング (DSW) のクイックスタート」の環境と互換性があることが確認されています。PAI を使用したモデリングの典型的なワークフローは、まず DSW で環境を検証してコードを開発し、次に DLC を使用してトレーニングを行うことです。
    • [データセットのマウント][カスタムデータセット] を選択し、前のステップで作成したデータセットを選択します。デフォルトの [マウントパス]/mnt/data です。

    • 起動コマンド: python /mnt/data/mnist_train.py

      この起動コマンドは、DSW またはローカルで実行する場合と同じです。ただし、mnist_train.py/mnt/data/ にマウントされるため、コードパスを /mnt/data/mnist_train.py に更新する必要があります。
    • [ソース][パブリックリソース] を選択します。[リソースタイプ] には、ecs.gn7i-c8g1.2xlarge を選択します。

      このインスタンス仕様が在庫切れの場合は、別の GPU インスタンスを選択できます。

    [確認] をクリックしてジョブを作成します。ジョブの完了には約 15 分かかります。ログをクリックすると、トレーニングプロセスをモニターできます。

    image

    ジョブが完了すると、最適なモデルのチェックポイントと TensorBoard のログが、マウントされたデータセットの output パスに保存されます。

    image

(オプション) TensorBoard の表示

TensorBoard 可視化ツールを使用して、損失曲線を表示し、トレーニングの詳細を理解できます。

重要

DLC ジョブで TensorBoard を使用するには、データセットを設定する必要があります。

  1. DLC ジョブの詳細ページで、[TensorBoard] タブをクリックし、次に [TensorBoard の作成] をクリックします。

    image

  2. [設定タイプ][タスクごと] に設定します。[サマリーパス] には、トレーニングコードでサマリーが保存されるパス /mnt/data/output/runs/ を入力します。[確認] をクリックして開始します。

    これはコードスニペット writer = SummaryWriter('/mnt/data/output/runs/mnist_experiment')
  3. [TensorBoard の表示] をクリックして、トレーニングデータセット (train_loss) と検証セット (validation_loss) の損失曲線を表示します。

    image

    (オプション) 損失グラフに基づいてハイパーパラメーターを調整し、モデルのパフォーマンスを向上させる

    損失値の傾向を観察することで、モデルのトレーニングパフォーマンスを評価できます:

    • トレーニング終了時に train_loss と validation_loss の両方がまだ減少している場合、これはアンダーフィッティングを示します。

      これに対処するには、`num_epochs` (トレーニングエポック数、トレーニングの深さと正の相関) を増やすか、`learning_rate` をわずかに上げてからモデルを再トレーニングします。

    • train_loss が減少し続ける一方で validation_loss が増加し始める場合、これはオーバーフィッティングを示します。

      これに対処するには、`num_epochs` を減らすか、`learning_rate` をわずかに下げてからモデルを再トレーニングします。

    • トレーニングが終了する前に train_loss と validation_loss の両方が安定した場合、これは良好な適合を示します。

      モデルが良好に適合している場合は、次のステップに進むことができます。

トレーニング済みモデルのデプロイ

詳細については、「EAS を使用してモデルをオンラインサービスとしてデプロイする」をご参照ください。

単一ノード複数 GPU または複数ノード複数 GPU の分散トレーニング

単一 GPU のビデオメモリがトレーニングのニーズに不十分な場合、またはトレーニングプロセスを高速化したい場合は、単一ノード複数 GPU または複数ノード複数 GPU の分散トレーニングジョブを作成できます。

このトピックでは、それぞれ 1 つの GPU を持つ 2 つのインスタンスの例を使用します。この例は、単一ノード複数 GPU または複数ノード複数 GPU トレーニングの他の構成にも適用されます。

データセットの作成

単一ノード、単一 GPU トレーニング中にすでにデータセットを作成している場合は、mnist_train_distributed.py コードをダウンロードしてアップロードするだけで済みます。そうでない場合は、まずデータセットを作成し、次にコードをアップロードする必要があります。

単一ノード複数 GPU または複数ノード複数 GPU トレーニングコードの例: mnist_train_distributed.py

import os
import torch
import torch.distributed as dist
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader
from torch.utils.data.distributed import DistributedSampler
from torchvision import datasets, transforms
from torch.utils.tensorboard import SummaryWriter

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=3)
        self.fc1 = nn.Linear(20 * 5 * 5, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = F.max_pool2d(F.relu(self.conv1(x)), 2)
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = x.view(-1, 20 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

def main():
    rank = int(os.environ["RANK"])
    world_size = int(os.environ["WORLD_SIZE"])
    local_rank = int(os.environ["LOCAL_RANK"])
    dist.init_process_group(backend='nccl')
    torch.cuda.set_device(local_rank)
    device = torch.device('cuda', local_rank)

    batch_size = 64
    learning_rate = 0.01
    num_epochs = 20

    transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,))
    ])

    # メインプロセス (rank=0) のみがダウンロードを行う必要があります。他のプロセスはそれが完了するのを待つ必要があります。
    # rank!=0 のプロセスを先にバリアで待機させます。
    if rank != 0:
        dist.barrier()

    # すべてのプロセスがデータセットの作成を実行します。
    # ただし、実際にダウンロードを行うのは rank=0 のプロセスのみです。
    train_dataset = datasets.MNIST(root='/mnt/data/dataSet', train=True, download=(rank == 0), transform=transform)

    # rank=0 のプロセスがダウンロードを完了した後、それもバリアに到達し、すべてのプロセスを解放します。
    if rank == 0:
        dist.barrier()

    # この時点で、すべてのプロセスが同期され、後続のコードを実行し続けることができます。
    val_dataset = datasets.MNIST(root='/mnt/data/dataSet', train=False, download=False, transform=transform)

    train_sampler = DistributedSampler(train_dataset, num_replicas=world_size, rank=rank, shuffle=True)
    train_loader = DataLoader(train_dataset, batch_size=batch_size, sampler=train_sampler, num_workers=4, pin_memory=True)
    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=4, pin_memory=True)

    model = SimpleCNN().to(device)
    model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[local_rank])
    criterion = nn.CrossEntropyLoss().to(device)
    optimizer = optim.SGD(model.parameters(), lr=learning_rate)

    if rank == 0:
        writer = SummaryWriter('/mnt/data/output_distributed/runs/mnist_experiment')
    best_val_accuracy = 0.0

    for epoch in range(num_epochs):
        train_sampler.set_epoch(epoch)
        model.train()
        for batch_idx, (data, target) in enumerate(train_loader):
            data, target = data.to(device, non_blocking=True), target.to(device, non_blocking=True)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
            if batch_idx % 100 == 0:
                # 各 rank と local_rank が自身の損失を出力します。
                print(f"Rank: {rank}, Local_Rank: {local_rank} -- Train Epoch: {epoch} "
                      f"[{batch_idx * len(data) * world_size}/{len(train_loader.dataset)} "
                      f"({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}")

                if rank == 0:
                    writer.add_scalar('Loss/train', loss.item(), epoch * len(train_loader) + batch_idx)

        # 検証
        model.eval()
        val_loss = 0
        correct = 0
        total = 0
        with torch.no_grad():
            for data, target in val_loader:
                data, target = data.to(device, non_blocking=True), target.to(device, non_blocking=True)
                output = model(data)
                val_loss += criterion(output, target).item() * data.size(0)
                pred = output.argmax(dim=1, keepdim=True)
                correct += pred.eq(target.view_as(pred)).sum().item()
                total += target.size(0)
        val_loss_tensor = torch.tensor([val_loss], dtype=torch.float32, device=device)
        correct_tensor = torch.tensor([correct], dtype=torch.float32, device=device)
        total_tensor = torch.tensor([total], dtype=torch.float32, device=device)
        dist.all_reduce(val_loss_tensor, op=dist.ReduceOp.SUM)
        dist.all_reduce(correct_tensor, op=dist.ReduceOp.SUM)
        dist.all_reduce(total_tensor, op=dist.ReduceOp.SUM)

        val_loss = val_loss_tensor.item() / total_tensor.item()
        val_accuracy = 100. * correct_tensor.item() / total_tensor.item()

        if rank == 0:
            print(f'Validation Loss: {val_loss:.4f}, Accuracy: {int(correct_tensor.item())}/{int(total_tensor.item())} ({val_accuracy:.0f}%)')
            writer.add_scalar('Loss/validation', val_loss, epoch)
            writer.add_scalar('Accuracy/validation', val_accuracy, epoch)
            if val_accuracy > best_val_accuracy:
                best_val_accuracy = val_accuracy
                torch.save(model.module.state_dict(), '/mnt/data/output_distributed/best_model.pth')
                print(f'Model saved with accuracy: {best_val_accuracy:.2f}%')
    if rank == 0:
        writer.close()
    dist.destroy_process_group()
    if rank == 0:
        print('Training complete. writer.close()')


if __name__ == "__main__":
    main()

DLC ジョブの作成

  1. PAI コンソールの左側のナビゲーションウィンドウで、[Deep Learning Containers (DLC)] > [ジョブの作成] をクリックします。

    image

  2. DLC ジョブのパラメーターを設定します。主要なパラメーターは以下の通りです。その他のパラメーターはデフォルト値を使用できます。すべてのパラメーターの詳細については、「トレーニングジョブの作成」をご参照ください。

    • [イメージ設定][イメージアドレス] を選択し、ご利用の [リージョン] のイメージ URL を入力します。

      image

      リージョン

      イメージ URL

      中国 (北京)

      dsw-registry-vpc.cn-beijing.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      中国 (上海)

      dsw-registry-vpc.cn-shanghai.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      中国 (杭州)

      dsw-registry-vpc.cn-hangzhou.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      その他のリージョン

      リージョン ID を検索し、イメージ URL の <Region ID> を置き換えて完全なリンクを取得します:

      dsw-registry-vpc.<Region ID>.cr.aliyuncs.com/pai/modelscope:1.28.0-pytorch2.3.1tensorflow2.16.1-gpu-py311-cu121-ubuntu22.04

      このイメージは、「インタラクティブモデリング (DSW) のクイックスタート」の環境と互換性があることが確認されています。PAI を使用したモデリングの典型的なワークフローは、まず DSW で環境とコードを検証し、次に DLC を使用してトレーニングを行うことです。
    • [データセットのマウント][カスタムデータセット] を選択し、前のステップで作成したデータセットを選択します。デフォルトの [マウントパス]/mnt/data です。

    • [起動コマンド]torchrun --nproc_per_node=1 --nnodes=${WORLD_SIZE} --node_rank=${RANK} --master_addr=${MASTER_ADDR} --master_port=${MASTER_PORT} /mnt/data/mnist_train_distributed.py

      DLC は、MASTER_ADDRWORLD_SIZE環境変数$VARIABLE_NAME
    • [ソース][パブリックリソース] を選択します。[数量] を 2 に設定します。[リソースタイプ] には、ecs.gn7i-c8g1.2xlarge を選択します。

      このインスタンス仕様が在庫切れの場合は、別の GPU インスタンスを選択できます。

    [確認] をクリックしてジョブを作成します。ジョブの実行には約 10 分かかります。ジョブの実行中、[概要] ページで両方のインスタンスのトレーニング [ログ] を表示できます。

    image

    ジョブが完了すると、最適なモデルのチェックポイントと TensorBoard のログが、マウントされたデータセットの output_distributed パスに保存されます。

    image

(オプション) TensorBoard の表示

TensorBoard 可視化ツールを使用して、損失曲線を表示し、トレーニングの詳細を理解できます。

重要

DLC ジョブで TensorBoard を使用するには、データセットを設定する必要があります。

  1. DLC ジョブの詳細ページで、[TensorBoard] タブをクリックし、次に [TensorBoard の作成] をクリックします。

    image

  2. [設定タイプ][タスクごと] に設定します。[サマリーパス] には、トレーニングコードでサマリーが保存されるパス /mnt/data/output_distributed/runs を入力します。[確認] をクリックして開始します。

    これはコードスニペット writer = SummaryWriter('/mnt/data/output_distributed/runs/mnist_experiment')
  3. [TensorBoard の表示] をクリックして、トレーニングデータセット (train_loss) と検証セット (validation_loss) の損失曲線を表示します。

    image

    (オプション) 損失グラフに基づいてハイパーパラメーターを調整し、モデルのパフォーマンスを向上させる

    損失値の傾向を観察することで、モデルのトレーニングパフォーマンスを評価できます:

    • トレーニング終了時に train_loss と validation_loss の両方がまだ減少している場合、これはアンダーフィッティングを示します。

      これに対処するには、`num_epochs` (トレーニングエポック数、トレーニングの深さと正の相関) を増やすか、`learning_rate` をわずかに上げてからモデルを再トレーニングします。

    • train_loss が減少し続ける一方で validation_loss が増加し始める場合、これはオーバーフィッティングを示します。

      これに対処するには、`num_epochs` を減らすか、`learning_rate` をわずかに下げてからモデルを再トレーニングします。

    • トレーニングが終了する前に train_loss と validation_loss の両方が安定した場合、これは良好な適合を示します。

      モデルが良好に適合している場合は、次のステップに進むことができます。

トレーニング済みモデルのデプロイ

詳細については、「EAS を使用してモデルをオンラインサービスとしてデプロイする」をご参照ください。

関連ドキュメント