※下記のコードはチームメンバーのある方(後日公開予定)と協力し作成したものになります。
概要
DeepSeek-R1推論用の環境をコピーしてGSPO用環境を構築し、ByteDanceのverlを用いてGSPOを実行する手順です。本コードではフルパラメータチューニングで行っています。
※LoRAを用いる場合はこちら「GSPO (Group Sequence Policy Optimization) をVERLを使って実装する~LoRA編~」
※既存環境をコピーしているのは、DeepSeek-R1でのGSPO実行を想定していたためです。
GSPOはMixture-of-Experts (MoE) モデルでGRPOよりも安定した学習ができると主張されている強化学習手法です。実際に、提案プレプリントで紹介されていたように、GRPOをよりも素早くLossが落ちることを確認済みです。
参考文献)
前提条件
-
DeepSeek-R1推論用環境構築 oNo.1チームで構築した
conda_env_deepseek環境 - H100の1ノード (8台)
- HuggingFaceとWandBのアカウント
Part 1: 環境構築
Step 1: 8GPUノードを取得
srun --partition=××× \\
--nodes=1 --gpus-per-node=8 \\
--cpus-per-task=240 --time=04:00:00 \\
--job-name="gspo_setup" --pty bash -i
Step 2: DeepSeek環境をコピー
# モジュールのロード
module reset
module load nccl/2.22.3
module load hpcx/2.18.1-gcc-cuda12/hpcx-mt
module load miniconda/24.7.1-py311
source /home/appli/miniconda3/24.7.1-py311/etc/profile.d/conda.sh
# 環境のコピー
export DEEPSEEK_ENV="$HOME/conda_env_deepseek"
export GSPO_ENV="$HOME/conda_env_gspo"
# 既存のGSPO環境があれば削除
[ -d "$GSPO_ENV" ] && conda env remove --prefix "$GSPO_ENV" -y && rm -rf "$GSPO_ENV"
# DeepSeek環境をクローン
conda create --prefix "$GSPO_ENV" --clone "$DEEPSEEK_ENV" -y
conda activate "$GSPO_ENV"
Step 3: VERLインストールと依存関係の導入
cd ~/
mkdir -p deps
cd ~/deps
# 既存のVERLがあれば削除
[ -d "verl" ] && rm -rf verl
# VERLをクローン(GSPOサポート済み)
git clone <https://github.com/volcengine/verl.git>
cd verl
# 依存関係のインストール(cffiを追加)
pip install --no-cache-dir six regex deepspeed wandb \\
huggingface_hub tensorboard mpi4py sentencepiece nltk ninja \\
packaging wheel transformers accelerate safetensors einops peft \\
datasets trl matplotlib sortedcontainers cffi
# VERLをインストール
pip install --no-deps -e .
# hydra-coreの追加(必須)
pip install hydra-core omegaconf
# Protobufバージョン固定
pip install --force-reinstall "protobuf==4.25.5"
cd ~/
Step 4: 【重要】依存関係のバージョンを固定
vllm, transformers, trlなどのライブラリ間の複雑な互換性問題を回避するため、以下のコマンドで**動作確認済みのバージョンの組み合わせ(ゴールデンセット)**を強制的にインストールします。←バージョン固定しないとエラーが延々と起きる
pip install --force-reinstall \\
numpy==1.26.4 \\
vllm==0.9.2 \\
transformers==4.53.2 \\
tokenizers==0.21.1 \\
fsspec==2025.3.0 \\
trl==0.20.0
Step 5: 環境変数の設定
# .bashrcに追加
cat >> ~/.bashrc << 'EOF'
# GSPO環境用
alias gspo-env='conda activate $HOME/conda_env_gspo'
export PYTHONPATH="$HOME/deps/verl:$PYTHONPATH"
EOF
source ~/.bashrc
Step 6: 環境の確認
以下のスクリプトを実行し、バージョンが一致することを確認します(一部警告が出ることがありますが、主要ライブラリのバージョンが合っていれば問題ありません)。
python - <<'PY'
import sys, torch, vllm, transformers, flash_attn
try:
import verl
verl_version = verl.__version__
except:
verl_version = "Not installed"
print("=== GSPO環境検証 ===")
print("Python :", sys.version.split()[0])
print("Torch :", torch.__version__)
print("CUDA :", torch.version.cuda)
print("FlashAttn :", flash_attn.__version__)
print("vLLM :", vllm.__version__)
print("VERL :", verl_version)
print("Transformers :", transformers.__version__)
print("GPU count :", torch.cuda.device_count())
print("✅ 環境構築完了!")
PY
【期待される出力バージョン】
-
vLLM:
0.9.2 -
Transformers:
4.53.2
Part 2: GSPO実行
Step 1: ログイン設定
huggingface-cliがユーザーのローカル領域を参照してエラーになる場合があるため、python -mを付けてConda環境内のコマンドを明示的に実行します。
# HuggingFaceログイン(トークンが必要)
python -m huggingface_hub.commands.huggingface_cli login
# WandBログイン(APIキーが必要)
python -m wandb login
Step 2: 実験ディレクトリ作成
mkdir -p ~/experiments/gspo/{checkpoints,logs}
cd ~/experiments/gspo
Step 3: GSPOトレーニングスクリプト作成
実行前にモデルをダウンロードしてください。また、下記のモデルは検証用にLlama-32.B-1B-Instructを用いているものの、Qwen-3-32Bでも動きました(記憶が正しければ...)。ただし、1ノードではOut-of-Memoryになるため、マルチノードで実行する必要があります。一方で、フルパラメータチューニングではなく、LoRAにすれば1ノードでGSPOを実行できました。
※LoRAを用いたコードはこちら「GSPO (Group Sequence Policy Optimization) をVERLを使って実装する~LoRA編~」
cat > run_gspo.sh << 'EOF'
#!/bin/bash
# GSPO Training Script - Final Fix: Correct config location
# プロジェクトパスの設定
export PROJECT_BASE="/home/llm_project"
export MODEL_BASE="$PROJECT_BASE/models/base"
export DATA_BASE="$PROJECT_BASE/data/raw"
export MY_EXP_BASE="$HOME/experiments"
# ネットワーク設定
export NCCL_SOCKET_IFNAME=enp25s0np0
export NVTE_FUSED_ATTN=0
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export VLLM_ATTENTION_BACKEND=FLASH_ATTN
unset ROCR_VISIBLE_DEVICES
ulimit -v unlimited
# 警告を抑制
export PYTHONWARNINGS="ignore::UserWarning"
# WandB設定
export WANDB_ENTITY="YOUR_USERNAME"
export WANDB_PROJECT_NAME="llm_competition"
export WANDB_RUN_NAME="gspo_$(date +%Y%m%d_%H%M%S)"
echo "=== GSPO Training Configuration ==="
echo "Base Model: $MODEL_BASE/Llama-3.2-1B-Instruct"
echo "Data: $DATA_BASE/gsm8k"
echo "Output: $MY_EXP_BASE/gspo/checkpoints"
echo "=================================="
# データファイルの存在確認
if [ ! -f "$DATA_BASE/gsm8k/train.parquet" ]; then
echo "Error: Training data not found at $DATA_BASE/gsm8k/train.parquet"
exit 1
fi
PYTHONUNBUFFERED=1 python -m verl.trainer.main_ppo \
algorithm.adv_estimator=grpo \
actor_rollout_ref.actor.policy_loss.loss_mode=gspo \
actor_rollout_ref.actor.loss_agg_mode=seq-mean-token-mean \
data.train_files="$DATA_BASE/gsm8k/train.parquet" \
data.val_files="$DATA_BASE/gsm8k/test.parquet" \
data.train_batch_size=512 \
data.max_prompt_length=512 \
data.max_response_length=256 \
data.dataloader_num_workers=0 \
data.shuffle=true \
actor_rollout_ref.rollout.name=vllm \
actor_rollout_ref.rollout.mode=sync \
actor_rollout_ref.rollout.dtype=bfloat16 \
actor_rollout_ref.model.path="$MODEL_BASE/Llama-3.2-1B-Instruct" \
actor_rollout_ref.model.use_remove_padding=true \
actor_rollout_ref.actor.optim.lr=1e-6 \
actor_rollout_ref.actor.ppo_mini_batch_size=128 \
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=8 \
actor_rollout_ref.actor.use_kl_loss=false \
actor_rollout_ref.actor.kl_loss_coef=0.0 \
actor_rollout_ref.actor.entropy_coeff=0 \
actor_rollout_ref.actor.clip_ratio_low=0.0003 \
actor_rollout_ref.actor.clip_ratio_high=0.0004 \
actor_rollout_ref.actor.use_dynamic_bsz=true \
actor_rollout_ref.actor.entropy_checkpointing=true \
actor_rollout_ref.rollout.n=16 \
actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=16 \
actor_rollout_ref.rollout.tensor_model_parallel_size=1 \
actor_rollout_ref.rollout.gpu_memory_utilization=0.8 \
actor_rollout_ref.rollout.temperature=1.0 \
actor_rollout_ref.rollout.top_p=1.0 \
actor_rollout_ref.rollout.top_k=-1 \
actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=8 \
algorithm.use_kl_in_reward=false \
reward_model.reward_manager=dapo \
+reward_model.reward_kwargs.overlong_buffer_cfg.enable=false \
+reward_model.reward_kwargs.overlong_buffer_cfg.len=128 \
+reward_model.reward_kwargs.overlong_buffer_cfg.penalty_factor=1.0 \
+reward_model.reward_kwargs.overlong_buffer_cfg.log=false \
+reward_model.reward_kwargs.max_resp_len=256 \
trainer.critic_warmup=0 \
trainer.logger="['console','wandb']" \
trainer.val_before_train=false \
trainer.n_gpus_per_node=8 \
trainer.nnodes=1 \
trainer.save_freq=10 \
trainer.test_freq=10 \
trainer.default_local_dir="$MY_EXP_BASE/gspo/checkpoints" \
trainer.project_name="$WANDB_PROJECT_NAME" \
trainer.experiment_name="$WANDB_RUN_NAME" \
trainer.total_epochs=10 \
trainer.total_training_steps=500 \
2>&1 | tee "gspo_training_$(date +%Y%m%d_%H%M%S).log"
EOF
chmod +x run_gspo.sh
Step 4: WandBユーザー名の設定
# WandBユーザー名を実際の値に変更(重要!)
sed -i 's/YOUR_USERNAME/あなたのWandBユーザー名/' run_gspo.sh
Step 5: トレーニング実行
# Rayのクリーンアップ(念のため)
ray stop
# GSPOトレーニング開始
./run_gspo.sh
本プロジェクトは、国立研究開発法人新エネルギー・産業技術総合開発機構(「NEDO」)の「日本語版医療特化型LLMの社会実装に向けた安全性検証・実証」における基盤モデルの開発プロジェクトの一環として行われました。
