NVIDIA NeMo RL 완전 가이드: LLM 강화학습 post-training 마스터하기
⏱️ 예상 읽기 시간: 25분
서론
Large Language Model(LLM)의 성능을 극대화하려면 초기 사전 훈련(pre-training) 이후의 post-training 과정이 핵심입니다. NVIDIA NeMo RL은 이러한 post-training을 위한 확장 가능한 툴킷으로, Supervised Fine-Tuning(SFT), Direct Preference Optimization(DPO), Reward Model(RM) 훈련을 효율적으로 지원합니다.
본 튜토리얼에서는 NVIDIA NeMo RL을 활용하여 실제 LLM 강화학습 파이프라인을 구축하고 실행하는 방법을 완전히 마스터해보겠습니다.
📋 주요 학습 내용
- NeMo RL 핵심 개념: SFT, DPO, RM, GRPO 이해
- 환경 설정: 로컬 macOS 개발환경 구축
- 단일 노드 훈련: 기본 모델 훈련 실습
- 멀티 노드 확장: 대규모 분산 훈련 설정
- 모델 평가: 훈련된 모델 성능 검증
- 실전 활용: 프로덕션 환경 배포 준비
🔧 시스템 요구사항
하드웨어 요구사항
- GPU: NVIDIA GPU (CUDA 지원) - RTX 3080 이상 권장
- 메모리: 최소 16GB RAM, 32GB 권장
- 저장공간: 최소 50GB 여유 공간
소프트웨어 요구사항
- 운영체제: macOS 12.0+ 또는 Linux
- Python: 3.8-3.11
- CUDA: 11.8 이상 (GPU 사용 시)
- Docker: 최신 버전 (선택사항)
NeMo RL 핵심 개념 이해
1. Supervised Fine-Tuning (SFT)
SFT는 사전 훈련된 모델을 특정 작업에 맞게 조정하는 지도학습 방식입니다.
# SFT 기본 설정 예시
sft_config = {
"model_name": "meta-llama/Llama-3.2-1B-Instruct",
"dataset": "helpsteer_data",
"batch_size": 32,
"learning_rate": 5e-5,
"epochs": 3
}
2. Direct Preference Optimization (DPO)
DPO는 인간의 선호도를 직접 모델에 반영하는 혁신적인 방법입니다.
# DPO 설정 예시
dpo_config = {
"preference_dataset": "helpsteer3",
"beta": 0.1, # KL divergence 가중치
"sft_loss_weight": 0.1,
"preference_average_log_probs": True
}
3. Reward Model (RM)
RM은 모델 출력의 품질을 평가하는 보조 모델입니다.
# RM 훈련 설정
rm_config = {
"base_model": "meta-llama/Llama-3.2-1B-Instruct",
"preference_data": "helpsteer3",
"ranking_loss": "cross_entropy"
}
환경 설정 및 설치
1. 레포지토리 클론 및 서브모듈 초기화
# NeMo RL 레포지토리 클론
git clone https://github.com/NVIDIA-NeMo/RL.git
cd RL
# 서브모듈 초기화 (중요!)
git submodule update --init --recursive
2. 파이썬 환경 설정
# Python 버전 확인
python --version # 3.8-3.11 확인
# UV 패키지 매니저 설치 (권장)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 가상환경 생성 및 활성화
uv venv nemo-rl-env
source nemo-rl-env/bin/activate
3. 의존성 설치
# 기본 의존성 설치
uv pip install -e .
# GPU 지원을 위한 추가 패키지
uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 평가 도구 설치
uv pip install --extra eval
4. 환경 변수 설정
# ~/.zshrc 또는 ~/.bashrc에 추가
export NEMO_RL_HOME="$HOME/RL"
export CUDA_VISIBLE_DEVICES=0 # 사용할 GPU 지정
export PYTHONPATH="$NEMO_RL_HOME:$PYTHONPATH"
# 환경 변수 적용
source ~/.zshrc
SFT (Supervised Fine-Tuning) 실습
1. 기본 SFT 실행
단일 GPU에서 Llama 3.2 1B 모델을 훈련해보겠습니다.
# 기본 SFT 실행
uv run python examples/run_sft.py
2. 설정 커스터마이징
더 많은 GPU를 활용하여 더 큰 모델을 훈련해보겠습니다.
# 8B 모델로 8GPU 훈련
uv run python examples/run_sft.py \
policy.model_name="meta-llama/Llama-3.1-8B-Instruct" \
policy.train_global_batch_size=128 \
sft.val_global_batch_size=128 \
cluster.gpus_per_node=8 \
checkpointing.checkpoint_dir="results/sft_llama8b" \
logger.wandb_enabled=True \
logger.wandb.name="sft-llama8b-tutorial"
3. 데이터셋 커스터마이징
자체 데이터셋을 사용하려면 다음과 같이 설정합니다.
# custom_sft_config.yaml
data:
dataset_name: "custom_dataset"
dataset_path: "/path/to/your/dataset"
prompt_template: "Human: {input}\n\nAssistant: {output}"
sft:
max_epochs: 5
save_interval: 500
val_check_interval: 100
# 커스텀 설정으로 실행
uv run python examples/run_sft.py --config custom_sft_config.yaml
DPO (Direct Preference Optimization) 실습
1. 기본 DPO 실행
HelpSteer3 데이터셋을 사용한 선호도 기반 훈련을 시작해보겠습니다.
# 단일 GPU DPO 실행
uv run python examples/run_dpo.py
2. 고급 DPO 설정
# 고급 DPO 설정으로 실행
uv run python examples/run_dpo.py \
policy.model_name="meta-llama/Llama-3.1-8B-Instruct" \
policy.train_global_batch_size=256 \
dpo.sft_loss_weight=0.1 \
dpo.preference_average_log_probs=True \
dpo.beta=0.1 \
cluster.gpus_per_node=8 \
checkpointing.checkpoint_dir="results/dpo_llama8b" \
logger.wandb_enabled=True \
logger.wandb.name="dpo-llama8b-tutorial"
3. DPO 모니터링
# TensorBoard로 훈련 과정 모니터링
tensorboard --logdir results/dpo_llama8b/tensorboard
# Weights & Biases 대시보드 확인
# https://wandb.ai 에서 프로젝트 확인
Reward Model (RM) 훈련
1. 기본 RM 훈련
# 단일 GPU RM 훈련
uv run python examples/run_rm.py
2. 멀티 GPU RM 훈련
# 8GPU RM 훈련
uv run python examples/run_rm.py \
cluster.gpus_per_node=8 \
checkpointing.checkpoint_dir="results/rm_llama1b" \
logger.wandb_enabled=True \
logger.wandb.name="rm-llama1b-tutorial"
3. RM 성능 평가
# 훈련된 RM 평가
uv run python examples/eval_rm.py \
--model_path results/rm_llama1b/final \
--test_dataset helpsteer3_test
모델 평가 및 변환
1. 체크포인트 변환
PyTorch DCP 형식에서 Hugging Face 형식으로 변환합니다.
# DCP → Hugging Face 변환
uv run python examples/converters/convert_dcp_to_hf.py \
--config results/dpo_llama8b/step_170/config.yaml \
--dcp-ckpt-path results/dpo_llama8b/step_170/policy/weights/ \
--hf-ckpt-path results/dpo_llama8b/hf
2. 모델 평가 실행
# 변환된 모델 평가
uv run python examples/run_eval.py \
generation.model_name=$PWD/results/dpo_llama8b/hf \
generation.temperature=0.7 \
generation.top_p=0.9 \
data.dataset_name=math500 \
eval.num_tests_per_prompt=16 \
cluster.gpus_per_node=8
3. 벤치마크 테스트
# MATH-500 벤치마크 테스트
uv run python examples/run_eval.py \
--config examples/configs/evals/math_eval.yaml \
generation.model_name=agentica-org/DeepScaleR-1.5B-Preview \
generation.temperature=0.6 \
generation.top_p=0.95 \
generation.vllm_cfg.max_model_len=32768 \
data.dataset_name=math500 \
eval.num_tests_per_prompt=16 \
cluster.gpus_per_node=8
멀티노드 분산 훈련
1. Slurm 클러스터 설정
# multi_node_sft.sh
#!/bin/bash
NUM_ACTOR_NODES=2
COMMAND="uv run ./examples/run_sft.py \
--config examples/configs/sft.yaml \
cluster.num_nodes=2 \
cluster.gpus_per_node=8 \
checkpointing.checkpoint_dir='results/sft_llama8b_2nodes' \
logger.wandb_enabled=True \
logger.wandb.name='sft-llama8b-multinode'" \
CONTAINER=YOUR_CONTAINER \
MOUNTS="$PWD:$PWD" \
sbatch \
--nodes=${NUM_ACTOR_NODES} \
--account=YOUR_ACCOUNT \
--job-name=nemo-rl-sft \
--partition=YOUR_PARTITION \
--time=4:0:0 \
--gres=gpu:8 \
ray.sub
2. Kubernetes 클러스터 설정
# k8s-nemo-rl-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: nemo-rl-training
spec:
template:
spec:
containers:
- name: nemo-rl
image: nvcr.io/nvidia/nemo:24.01.01
command: ["uv", "run", "python", "examples/run_sft.py"]
args:
- "--config"
- "examples/configs/sft.yaml"
- "cluster.num_nodes=2"
- "cluster.gpus_per_node=8"
resources:
limits:
nvidia.com/gpu: 8
volumeMounts:
- name: data-volume
mountPath: /workspace/data
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: nemo-rl-data
restartPolicy: Never
실전 활용 및 최적화
1. 성능 최적화 팁
# config/optimization.yaml
trainer:
gradient_clip_val: 1.0
accumulate_grad_batches: 4
precision: 16-mixed # Mixed precision 사용
model:
micro_batch_size: 8
global_batch_size: 256
activation_checkpointing: true
optimizer:
name: adamw
lr: 3e-4
weight_decay: 0.01
betas: [0.9, 0.95]
2. 메모리 최적화
# 메모리 효율적인 훈련
uv run python examples/run_sft.py \
model.activation_checkpointing=true \
model.sequence_parallel=true \
model.tensor_model_parallel_size=2 \
trainer.precision=16-mixed
3. 데이터 파이프라인 최적화
# data_config.py
data_config = {
"num_workers": 8,
"pin_memory": True,
"persistent_workers": True,
"prefetch_factor": 2,
"drop_last": True
}
문제 해결 및 디버깅
1. 일반적인 오류 해결
# 서브모듈 초기화 오류
ModuleNotFoundError: No module named 'megatron'
# 해결방법
git submodule update --init --recursive
NRL_FORCE_REBUILD_VENVS=true uv run examples/run_sft.py
2. GPU 메모리 부족
# 배치 크기 조정
uv run python examples/run_sft.py \
model.micro_batch_size=4 \
trainer.accumulate_grad_batches=8
3. 디버그 모드 실행
# 상세 로그와 함께 실행
NEMO_LOG_LEVEL=DEBUG uv run python examples/run_sft.py \
trainer.limit_train_batches=10 \
trainer.limit_val_batches=5 \
trainer.max_epochs=1
고급 활용 사례
1. 커스텀 데이터셋 구성
# custom_dataset.py
from torch.utils.data import Dataset
import json
class CustomPreferenceDataset(Dataset):
def __init__(self, data_path):
with open(data_path, 'r') as f:
self.data = json.load(f)
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
item = self.data[idx]
return {
'prompt': item['prompt'],
'chosen': item['chosen'],
'rejected': item['rejected']
}
2. 커스텀 평가 메트릭
# custom_metrics.py
def calculate_preference_accuracy(predictions, labels):
"""선호도 예측 정확도 계산"""
correct = sum(pred == label for pred, label in zip(predictions, labels))
return correct / len(predictions)
def calculate_reward_correlation(predicted_rewards, human_ratings):
"""예측 보상과 인간 평가 간 상관관계"""
import numpy as np
return np.corrcoef(predicted_rewards, human_ratings)[0, 1]
3. 하이퍼파라미터 튜닝
# hyperparameter_search.py
import optuna
def objective(trial):
lr = trial.suggest_float('learning_rate', 1e-5, 1e-3, log=True)
beta = trial.suggest_float('dpo_beta', 0.01, 1.0)
batch_size = trial.suggest_categorical('batch_size', [16, 32, 64, 128])
# 모델 훈련 및 평가
score = train_and_evaluate(lr=lr, beta=beta, batch_size=batch_size)
return score
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=50)
성능 벤치마크 및 비교
1. 베이스라인 모델과 비교
# benchmark.py
models = {
'baseline': 'meta-llama/Llama-3.2-1B-Instruct',
'sft_trained': 'results/sft_llama1b/hf',
'dpo_trained': 'results/dpo_llama1b/hf',
'rm_trained': 'results/rm_llama1b/hf'
}
for name, model_path in models.items():
score = evaluate_model(model_path)
print(f"{name}: {score}")
2. 메트릭 수집 및 분석
# metrics_analysis.py
import matplotlib.pyplot as plt
import pandas as pd
def plot_training_curves(log_dir):
"""훈련 곡선 시각화"""
df = pd.read_csv(f"{log_dir}/metrics.csv")
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
# Loss curves
axes[0,0].plot(df['step'], df['train_loss'], label='Train')
axes[0,0].plot(df['step'], df['val_loss'], label='Validation')
axes[0,0].set_title('Loss Curves')
axes[0,0].legend()
# Reward curves (for DPO/RM)
axes[0,1].plot(df['step'], df['reward_accuracy'])
axes[0,1].set_title('Reward Accuracy')
# Learning rate
axes[1,0].plot(df['step'], df['learning_rate'])
axes[1,0].set_title('Learning Rate Schedule')
# GPU utilization
axes[1,1].plot(df['step'], df['gpu_utilization'])
axes[1,1].set_title('GPU Utilization')
plt.tight_layout()
plt.savefig(f"{log_dir}/training_analysis.png")
프로덕션 배포 준비
1. 모델 최적화
# 추론 최적화된 모델 생성
uv run python examples/optimize_for_inference.py \
--model_path results/dpo_llama8b/hf \
--output_path results/dpo_llama8b/optimized \
--optimization_level 3
2. Docker 컨테이너화
# Dockerfile
FROM nvcr.io/nvidia/nemo:24.01.01
WORKDIR /workspace
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
RUN pip install -e .
EXPOSE 8000
CMD ["python", "serve_model.py"]
3. 서비스 API 구성
# serve_model.py
from fastapi import FastAPI
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
app = FastAPI()
# 모델 로드
model_path = "results/dpo_llama8b/hf"
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.float16,
device_map="auto"
)
@app.post("/generate")
async def generate_text(prompt: str, max_length: int = 512):
inputs = tokenizer(prompt, return_tensors="pt")
with torch.no_grad():
outputs = model.generate(
**inputs,
max_length=max_length,
do_sample=True,
temperature=0.7,
top_p=0.9
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
return {"response": response}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
결론
NVIDIA NeMo RL은 LLM의 post-training을 위한 강력하고 확장 가능한 플랫폼입니다. 본 튜토리얼을 통해 다음과 같은 내용을 마스터했습니다:
🎯 주요 성과
- SFT, DPO, RM 훈련 방법론 이해 및 실습
- 단일/멀티 노드 환경에서의 확장 가능한 훈련
- 모델 평가 및 성능 최적화 기법
- 프로덕션 배포를 위한 모델 최적화
🚀 다음 단계
- GRPO (Generalized Preference Optimization) 고급 기법 탐구
- 커스텀 데이터셋 구성 및 도메인 특화 모델 개발
- 대규모 클러스터 환경에서의 분산 훈련 최적화
- A/B 테스팅을 통한 모델 성능 검증
💡 추가 리소스
NVIDIA NeMo RL을 활용하여 여러분만의 고성능 LLM을 구축해보세요! 🚀
🧪 실습 테스트 스크립트
본 튜토리얼과 함께 제공되는 테스트 스크립트를 활용하여 NeMo RL 환경을 쉽게 설정할 수 있습니다.
1. 기본 설치 테스트
# 테스트 스크립트 다운로드 및 실행
curl -O https://raw.githubusercontent.com/thakicloud/tutorials/main/nemo-rl-test/test-nemo-rl-setup.sh
chmod +x test-nemo-rl-setup.sh
./test-nemo-rl-setup.sh
2. Alias 설정
# 편리한 단축 명령어 설정
curl -O https://raw.githubusercontent.com/thakicloud/tutorials/main/nemo-rl-test/setup-nemo-rl-aliases.sh
chmod +x setup-nemo-rl-aliases.sh
./setup-nemo-rl-aliases.sh
# 설정 적용
source ~/.zshrc
# 사용법 확인
nemo-help
3. 실제 테스트 결과
macOS Sonoma 14.7 환경에서 테스트 완료
# 시스템 환경
macOS Sonoma 14.7
Python 3.11.8
UV 0.4.15
# 테스트 결과
✓ Python 버전이 호환됩니다 (3.8-3.11)
✓ Git이 설치되어 있습니다
✓ UV 패키지 매니저가 설치되어 있습니다
✓ 레포지토리 클론 및 서브모듈 초기화 완료
✓ 가상환경 생성 및 활성화 완료
✓ 기본 의존성 설치 완료
✓ PyTorch CPU 버전 설치 완료
✓ NeMo RL 모듈 임포트 성공
✓ 설정 모듈 로드 성공
✓ 모든 예제 스크립트 문법 검사 통과
4. 개발환경 버전 정보
개발환경:
OS: macOS Sonoma 14.7
Python: 3.11.8
UV: 0.4.15
PyTorch: 2.1.0+cpu
CUDA: N/A (CPU 테스트)
테스트 통과 항목:
- 환경 요구사항 검증
- 레포지토리 클론 및 서브모듈
- 가상환경 생성
- 의존성 설치
- 모듈 임포트
- 설정 파일 확인
- 예제 스크립트 문법 검사
5. GPU 환경 추가 설정
GPU가 있는 환경에서는 다음 추가 설정을 진행하세요:
# CUDA 버전 확인
nvidia-smi
# GPU 지원 PyTorch 설치
uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 실제 모델 훈련 테스트
nemo-sft-1b trainer.max_epochs=1 trainer.limit_train_batches=10
다음 포스트 예고: NeMo RL과 Kubernetes를 활용한 대규모 분산 훈련 아키텍처 구축 가이드를 준비 중입니다. 구독하고 최신 튜토리얼을 받아보세요!