mcpField
R
ray-train

ray-train

github.com/orchestra-researchクラウド・DevOps14.1k1.0k 回インストール19 週間前に更新
リポジトリ

ray-train について

ray-trainは、Ray Trainで分散機械学習を行う開発者向けのリファレンススキルです。単一GPUのコードをマルチノードクラスターへ拡張する方法や、チューニング、障害復旧、チェックポイントの扱いを紹介します。

主な機能

  1. 01PyTorchの学習を拡張
  2. 02HuggingFace Transformersとの統合
  3. 03Ray Tuneによる調整
  4. 04障害復旧とチェックポイント
  5. 05マルチノード学習の調整

活用シーン

  1. 01単一GPUの学習を複数マシンへ拡張
  2. 02クラスターでハイパーパラメーターを探索
  3. 03チェックポイントから学習を再開

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/orchestra-research/ai-research-skills --skill ray-train

インストール後、Claude Code で/ray-trainを入力して読み込まれたか確認します。

同梱ファイルreferences/multi-node.md

詳細

Ray Train - 分散トレーニングのオーケストレーション

クイックスタート

Ray Train は、最小限のコード変更で、単一 GPU からマルチノードクラスターまで機械学習のトレーニングをスケールできます。

インストール:

pip install -U "ray[train]"

基本的な PyTorch のトレーニング(単一ノード):

import ray
from ray import train
from ray.train import ScalingConfig
from ray.train.torch import TorchTrainer
import torch
import torch.nn as nn

# Define training function
def train_func(config):
    # Your normal PyTorch code
    model = nn.Linear(10, 1)
    optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

    # Prepare for distributed (Ray handles device placement)
    model = train.torch.prepare_model(model)

    for epoch in range(10):
        # Your training loop
        output = model(torch.randn(32, 10))
        loss = output.sum()
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

        # Report metrics (logged automatically)
        train.report({"loss": loss.item(), "epoch": epoch})

# Run distributed training
trainer = TorchTrainer(
    train_func,
    scaling_config=ScalingConfig(
        num_workers=4,  # 4 GPUs/workers
        use_gpu=True
    )
)

result = trainer.fit()
print(f"Final loss: {result.metrics['loss']}")

これだけです! Ray が次の処理を担います:

  • 分散処理の調整
  • GPU の割り当て
  • フォールトトレランス
  • チェックポイントの保存
  • メトリクスの集約

一般的なワークフロー

ワークフロー 1:既存の PyTorch コードをスケールする

元の単一 GPU コード:

model = MyModel().cuda()
optimizer = torch.optim.Adam(model.parameters())

for epoch in range(epochs):
    for batch in dataloader:
        loss = model(batch)
        loss.backward()
        optimizer.step()

Ray Train バージョン(マルチ GPU/マルチノードにスケール):

from ray.train.torch import TorchTrainer
from ray import train

def train_func(config):
    model = MyModel()
    optimizer = torch.optim.Adam(model.parameters())

    # Prepare for distributed (automatic device placement)
    model = train.torch.prepare_model(model)
    dataloader = train.torch.prepare_data_loader(dataloader)

    for epoch in range(epochs):
        for batch in dataloader:
            loss = model(batch)
            loss.backward()
            optimizer.step()

            # Report metrics
            train.report({"loss": loss.item()})

# Scale to 8 GPUs
trainer = TorchTrainer(
    train_func,
    scaling_config=ScalingConfig(num_workers=8, use_gpu=True)
)
trainer.fit()

メリット:同じコードを 1 GPU でも 1000 GPU でも実行できます

ワークフロー 2:HuggingFace Transformers との統合
from ray.train.huggingface import TransformersTrainer
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments

def train_func(config):
    # Load model and tokenizer
    model = AutoModelForCausalLM.from_pretrained("gpt2")
    tokenizer = AutoTokenizer.from_pretrained("gpt2")

    # Training arguments (HuggingFace API)
    training_args = TrainingArguments(
        output_dir="./output",
        num_train_epochs=3,
        per_device_train_batch_size=8,
        learning_rate=2e-5,
    )

    # Ray automatically handles distributed training
    from transformers import Trainer
    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=train_dataset,
    )

    trainer.train()

# Scale to multi-node (2 nodes × 8 GPUs = 16 workers)
trainer = TransformersTrainer(
    train_func,
    scaling_config=ScalingConfig(
        num_workers=16,
        use_gpu=True,
        resources_per_worker={"GPU": 1}
    )
)

result = trainer.fit()
ワークフロー 3:Ray Tune によるハイパーパラメーターの調整
from ray import tune
from ray.train.torch import TorchTrainer
from ray.tune.schedulers import ASHAScheduler

def train_func(config):
    # Use hyperparameters from config
    lr = config["lr"]
    batch_size = config["batch_size"]

    model = MyModel()
    optimizer = torch.optim.Adam(model.parameters(), lr=lr)

    model = train.torch.prepare_model(model)

    for epoch in range(10):
        # Training loop
        loss = train_epoch(model, optimizer, batch_size)
        train.report({"loss": loss, "epoch": epoch})

# Define search space
param_space = {
    "lr": tune.loguniform(1e-5, 1e-2),
    "batch_size": tune.choice([16, 32, 64, 128])
}

# Run 20 trials with early stopping
tuner = tune.Tuner(
    TorchTrainer(
        train_func,
        scaling_config=ScalingConfig(num_workers=4, use_gpu=True)
    ),
    param_space=param_space,
    tune_config=tune.TuneConfig(
        num_samples=20,
        scheduler=ASHAScheduler(metric="loss", mode="min")
    )
)

results = tuner.fit()
best = results.get_best_result(metric="loss", mode="min")
print(f"Best hyperparameters: {best.config}")

結果:クラスター全体で分散ハイパーパラメーター探索を実行できます

ワークフロー 4:チェックポイントとフォールトトレランス
from ray import train
from ray.train import Checkpoint

def train_func(config):
    model = MyModel()
    optimizer = torch.optim.Adam(model.parameters())

    # Try to resume from checkpoint
    checkpoint = train.get_checkpoint()
    if checkpoint:
        with checkpoint.as_directory() as checkpoint_dir:
            state = torch.load(f"{checkpoint_dir}/model.pt")
            model.load_state_dict(state["model"])
            optimizer.load_state_dict(state["optimizer"])
            start_epoch = state["epoch"]
    else:
        start_epoch = 0

    model = train.torch.prepare_model(model)

    for epoch in range(start_epoch, 100):
        loss = train_epoch(model, optimizer)

        # Save checkpoint every 10 epochs
        if epoch % 10 == 0:
            checkpoint = Checkpoint.from_directory(
                train.get_context().get_trial_dir()
            )
            torch.save({
                "model": model.state_dict(),
                "optimizer": optimizer.state_dict(),
                "epoch": epoch
            }, checkpoint.path / "model.pt")

            train.report({"loss": loss}, checkpoint=checkpoint)

trainer = TorchTrainer(
    train_func,
    scaling_config=ScalingConfig(num_workers=8, use_gpu=True)
)

# Automatically resumes from checkpoint if training fails
result = trainer.fit()
ワークフロー 5:マルチノードトレーニング
from ray.train import ScalingConfig

# Connect to Ray cluster
ray.init(address="auto")  # Or ray.init("ray://head-node:10001")

# Train across 4 nodes × 8 GPUs = 32 workers
trainer = TorchTrainer(
    train_func,
    scaling_config=ScalingConfig(
        num_workers=32,
        use_gpu=True,
        resources_per_worker={"GPU": 1, "CPU": 4},
        placement_strategy="SPREAD"  # Spread across nodes
    )
)

result = trainer.fit()

Ray クラスターを起動:

# On head node
ray start --head --port=6379

# On worker nodes
ray start --address=<head-node-ip>:6379

代替手段と比べた使いどころ

次の場合は Ray Train を使用します:

  • 複数のマシンにまたがってトレーニングする場合(マルチノード)
  • 大規模なハイパーパラメーター調整が必要な場合
  • フォールトトレランスが必要な場合(失敗したワーカーを自動で再起動)
  • トレーニング中にノードを追加/削除する弾力的なスケーリングが必要な場合
  • 統一されたフレームワークを使いたい場合(PyTorch/TF/HF で同じコードを使用)

主な利点:

  • マルチノードのオーケストレーション:マルチノードを最も簡単にセットアップできます
  • Ray Tune との統合:クラス最高水準のハイパーパラメーター調整
  • フォールトトレランス:障害から自動的に復旧
  • 弾力性:再起動せずにノードを追加/削除できます
  • フレームワーク非依存:PyTorch、TensorFlow、HuggingFace、XGBoost に対応

代わりに次のツールを使用します:

  • Accelerate:単一ノードのマルチ GPU 向けで、よりシンプルです
  • PyTorch Lightning:高レベルの抽象化とコールバック
  • DeepSpeed:最高のパフォーマンスを実現できますが、セットアップは複雑です
  • Raw DDP:最大限の制御と最小限のオーバーヘッド

よくある問題

問題:Ray クラスターに接続できない

ray のステータスを確認します:

ray status

# Should show:
# - Nodes: 4
# - GPUs: 32
# - Workers: Ready

接続されていない場合:

# Restart head node
ray stop
ray start --head --port=6379 --dashboard-host=0.0.0.0

# Restart worker nodes
ray stop
ray start --address=<head-ip>:6379

問題:メモリ不足

ワーカー数を減らすか、勾配蓄積を使用します:

scaling_config=ScalingConfig(
    num_workers=4,  # Reduce from 8
    use_gpu=True
)

# In train_func, accumulate gradients
for i, batch in enumerate(dataloader):
    loss = model(batch) / accumulation_steps
    loss.backward()

    if (i + 1) % accumulation_steps == 0:
        optimizer.step()
        optimizer.zero_grad()

問題:トレーニングが遅い

データの読み込みがボトルネックになっていないか確認します:

import time

def train_func(config):
    for epoch in range(epochs):
        start = time.time()
        for batch in dataloader:
            data_time = time.time() - start
            # Train...
            start = time.time()
            print(f"Data loading: {data_time:.3f}s")

データの読み込みが遅い場合は、ワーカー数を増やします:

dataloader = DataLoader(dataset, num_workers=8)

高度なトピック

マルチノードのセットアップ:references/multi-node.md を参照してください。AWS、GCP、Kubernetes、SLURM での Ray クラスターのデプロイについて説明しています。

ハイパーパラメーターの調整:references/hyperparameter-tuning.md を参照してください。Ray Tune との統合、探索アルゴリズム(Optuna、HyperOpt)、集団ベースのトレーニングについて説明しています。

カスタムトレーニングループ:references/custom-loops.md を参照してください。Ray Train の高度な使い方、カスタムバックエンド、他のフレームワークとの統合について説明しています。

ハードウェア要件

  • 単一ノード:1 台以上の GPU(または CPU)
  • マルチノード:ネットワーク接続された 2 台以上のマシン
  • クラウド:AWS、GCP、Azure(Ray のオートスケーリング)
  • オンプレミス:Kubernetes、SLURM クラスター

対応アクセラレーター:

  • NVIDIA GPU(CUDA)
  • AMD GPU(ROCm)
  • TPU(Google Cloud)
  • CPU

リソース

コメント