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

Platform For AI:Deep Learning Containers (DLC) クイックスタート

最終更新日:Jan 28, 2026

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

説明

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

image

前提条件

ルートアカウントを使用して PAI をアクティブ化し、ワークスペースを作成します。PAI コンソールにログインします。左上のコーナーでリージョンを選択してサービスをアクティブ化します。次に、ワンクリック権限付与を使用してプロダクトをアクティブ化します。

課金の説明

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

シングルノード・シングル GPU トレーニング

データセットの作成

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

  1. PAI コンソールの左側のナビゲーションウィンドウで、Datasets > Custom Dataset > Create datasets を選択します。

    image

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

    • Name:たとえば、dataset_mnist

    • Storage TypeOSS

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

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

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

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

      2. OSS コンソールログオンしますバケットの作成 をクリックします。[バケット名] を入力します。RegionPAI と同じリージョンに設定します。他のパラメーターはデフォルト値のままにし、[作成] をクリックします。

        image

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

  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. コードをアップロードするには、データセット詳細ページで View Data をクリックして OSS コンソールに移動します。次に、オブジェクト > ファイルの選択 > アップロード の順にクリックして、トレーニングコードをアップロードします。

      image

DLC ジョブの作成

  1. PAI コンソールの左側のナビゲーションウィンドウで、Deep Learning Containers (DLC) > Create Job を選択します。

    image

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

    • Image ConfigurationImage Address を選択します。次に、Region に対応するレジストリアドレスを入力します。

      image

      リージョン

      対応するレジストリアドレス

      北京

      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 の照会」を行い、レジストリアドレスの <Region ID> を置き換えて完全な URL を取得します。

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

      このランタイムイメージは、「Interactive Modelling (DSW) クイックスタート」の環境と互換性があることが確認されています。通常、PAI を使用してモデリングを行う場合、まず DSW で環境を検証してコードを開発し、その後 DLC を使用してトレーニングを行います。
    • Dataset Mount: Custom Dataset を選択して、前のステップで作成したデータセットを選択します。 デフォルトの Mount Path/mnt/data です。

    • Startup Commandpython /mnt/data/mnist_train.py

      この起動コマンドは、DSW またはローカルで実行する場合と同じです。ただし、mnist_train.py/mnt/data/ にマウントされているため、コードパスを /mnt/data/mnist_train.py に変更する必要があります。
    • Source: Public Resources を選択します。Resource Type には、ecs.gn7i-c8g1.2xlarge を選択します。

      このインスタンスタイプが在庫切れの場合は、別の GPU アクセラレーションインスタンスタイプを選択できます。

    OK をクリックしてジョブを作成します。 ジョブの実行には約 15 分かかります。 ジョブの実行中に、「ログ」をクリックしてトレーニングプロセスを表示できます。

    image

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

    image

TensorBoard の表示 (オプション)

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

重要

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

  1. DLC ジョブの詳細ページで、ページ上部の Tensorboard > Create TensorBoard をクリックします。

    image

  2. Configuration TypeBy Task に設定します。Summary Path フィールドに、トレーニングコードでサマリーが保存されているパス /mnt/data/output/runs/ を入力します。OK をクリックして開始します。

    対応するコードスニペット:writer = SummaryWriter('/mnt/data/output/runs/mnist_experiment')
  3. View 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 の VRAM がトレーニングのニーズに対して不十分な場合、またはトレーニングプロセスを高速化したい場合は、シングルノード・マルチ 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) > Create Job を選択します。

    image

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

    • Image Configuration: Image Address を選択します。次に、お使いの Region に対応するレジストリアドレスを入力します。

      image

      リージョン

      レジストリアドレス

      北京

      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 の照会」を行い、レジストリアドレスの <Region ID> を置き換えて完全な URL を取得します。

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

      このランタイムイメージは、「Interactive Modelling (DSW) クイックスタート」の環境と互換性があることが確認されています。通常、PAI を使用してモデリングを行う場合、まず DSW で環境を検証してコードを開発し、その後 DLC を使用してトレーニングを行います。
    • Dataset MountCustom Dataset を選択し、前のステップで作成したデータセットを選択します。 デフォルトの Mount Path/mnt/data です。

    • Startup Commandtorchrun --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
    • Source: Public Resources を選択します。Number of Nodes を 2 に設定します。Resource Type には、ecs.gn7i-c8g1.2xlarge を選択します。

      このインスタンスタイプが在庫切れの場合は、別の GPU アクセラレーションインスタンスタイプを選択できます。

    Confirm をクリックしてジョブを作成します。ジョブの実行には約 10 分かかります。実行中は、Overview ページで 2 つのインスタンスのトレーニングLogを表示できます。

    image

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

    image

TensorBoard の表示 (オプション)

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

重要

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

  1. DLC ジョブの詳細ページで、ページ上部の TensorBoard > Create TensorBoard をクリックします。

    image

  2. Configuration TypeBy Task に設定します。Summary Path フィールドに、トレーニングコードでサマリーが保存されているパス /mnt/data/output_distributed/runs を入力します。OK をクリックして開始します。

    対応するコードスニペット:writer = SummaryWriter('/mnt/data/output_distributed/runs/mnist_experiment')
  3. View 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 を使用してモデルをオンラインサービスとしてデプロイする」をご参照ください。

関連ドキュメント