Transformers documentation
옵티마이저와 스케줄러
옵티마이저와 스케줄러
옵티마이저는 학습 중에 모델 가중치를 업데이트합니다. 스케줄러는 옵티마이저를 감싸서 각 학습 단계마다 학습률을 조정합니다. Trainer는 create_optimizer_and_scheduler()를 호출할 때 이 둘을 모두 생성합니다.
┌────────────┐ ┌──────────────┐
│ Optimizer │ │ Scheduler │
│ (adamw_torch_fused)◄─│ (linear) │
│ │ │ │
│ param_groups | |
│ └ lr ◄────────┤ |
│ └ weight_decay │ │
└──────┬─────┘ └──────────────┘
│
┌──── EACH TRAINING STEP ───────────────────────────────────────────┐
│ │ │
│ model(batch) │ │
│ │ │ │
│ ▼ │ │
│ loss ──► loss.backward() ──► param.grad │
│ │ │
│ ┌─────────────┘ │
│ ▼ │
│ optimizer.step() │
│ │ │
│ ▼ │
│ param.data updated │
│ │ │
│ ▼ │
│ lr_scheduler.step() ──► recalculates lr │
│ │ writes to optimizer │
│ ▼ .param_groups['lr'] │
│ model.zero_grad() │
│ │
└───────────────────────────────────────────────────────────────────┘lr_scheduler_type()와 optim()와 같은 옵티마이저 및 스케줄러 동작을 TrainingArguments에서 설정합니다. 기본값(adamw_torch 옵티마이저와 linear 웜업 스케줄러)은 대부분의 파인튜닝 실행에 좋은 출발점이 됩니다.
from transformers import TrainingArguments
args = TrainingArguments(
...,
# Optimizer
optim="adamw_torch", # or "adamw_torch_fused", "adafactor", "sgd", etc.
learning_rate=2e-5,
weight_decay=0.01,
adam_beta1=0.9,
adam_beta2=0.999,
adam_epsilon=1e-8,
# Scheduler
lr_scheduler_type="cosine", # "linear", "cosine", "constant_with_warmup", etc.
warmup_steps=500,
lr_scheduler_kwargs={"num_cycles": 3}, # scheduler-specific extras
)메트릭 기반 스케줄러
일부 스케줄러는 고정된 스케줄을 따르는 대신 학습 동적 특성에 적응합니다.
GreedyLR는 평가 결과를 기반으로 학습률을 업데이트합니다. 지표가 계속 개선되면 factor로 나누어 학습률을 높이고, 지표가 개선되지 않으면 factor를 곱하여 학습률을 낮춥니다. 학습률이 min_lr에 도달한 후 reset_start 스텝 동안 개선되지 않으면, GreedyLR는 초기 상태로 리셋되어 새로운 사이클을 시작합니다.
GreedyLR는 학습 중 평가가 필요합니다. eval_strategy를 "steps" 또는 "epoch"으로 설정하세요.
args = TrainingArguments(
+ lr_scheduler_type="greedy",
+ lr_scheduler_kwargs={"patience": 10, "factor": 0.95, "min_lr": 1e-5},
+ eval_strategy="steps",
+ eval_steps=200,
... # remaining args from the TrainingArguments intro config
)기본
mode="min"은 loss에 적용됩니다. accuracy처럼 값이 클수록 좋은 메트릭을 추적하는 경우,lr_scheduler_kwargs에"mode": "max"를 전달하세요.
전체 설정 가능한 매개변수 목록은 GreedyLR 클래스를 참조하세요.
옵티마이저 통합
Transformers는 특수한 학습 시나리오를 위해 서드파티 옵티마이저를 통합합니다.
| 옵티마이저 | 설치 | optim="value" | 설명 |
|---|---|---|---|
| APOLLO | apollo-torch | apollo_adamw | Memory-efficient full-param via random projections; rank-1 sufficient |
| GrokAdamW | grokadamw | grokadamw | 지연 일반화(그로킹)를 대상으로 합니다 |
| LOMO / AdaLomo | lomo-optim | lomo / adalomo | … |
| 스케줄 없음 | schedulefree | schedule_free_adamw, schedule_free_radam, schedule_free_sgd | LR annealing을 제거합니다. lr_scheduler_type="constant"와 함께 사용하세요 |
| GaLore | galore-torch | galore_adamw, galore_adafactor, galore_adamw_8bit | 그라디언트 저랭크 투영을 통한 전체 파라미터 학습 |
| StableAdamW | torch-optimi | stable_adamw | AdamW + AdaFactor 업데이트 클리핑; 그라디언트 클리핑 불필요 |
pip install apollo-torch
Approximated Gradient Scaling for Memory Efficient LLM Optimization (APOLLO)는 사전 학습 및 파인튜닝 시 전체 파라미터 학습을 위한 메모리 효율적인 옵티마이저입니다. SVD 대신 저렴한 랜덤 프로젝션을 사용하여 SGD 수준의 메모리 비용으로 AdamW와 동등한 성능을 달성합니다. 극단적인 메모리 절감이 필요할 때는 랭크-1 변형인 APOLLO-Mini를 사용하세요.
optim_target_modules 매개변수를 사용하여 학습할 레이어를 지정합니다.
args = TrainingArguments(
+ optim="apollo_adamw",
+ optim_target_modules=[r".*.attn.*", r".*.mlp.*"],
... # remaining args from the TrainingArguments intro config
)optim_args를 통해 추가 하이퍼파라미터를 전달합니다.
scale을n/r로 설정하세요. 여기서n은 원래 공간의 차원,r은 저랭크 공간의 차원입니다.scale을 기본값으로 유지하면서 학습률을 조정하면 유사한 효과를 얻을 수 있습니다.
| parameter | 설명 | APOLLO | APOLLO-Mini |
|---|---|---|---|
| rank | rank | 256 | 1 |
| scale_type | 스케일 팩터가 적용되는 방식 | channel (채널별 스케일링) | tensor (텐서별 스케일링) |
| scale | 트레이닝을 안정화하기 위해 그라디언트 업데이트를 조정 | 1.0 | 128 |
| update_proj_gap | 투영 행렬을 업데이트하기 전 단계 | 200 | 200 |
| proj | projection type | random | random |
rank-1 구성으로 APOLLO-Mini를 활성화합니다.
args = TrainingArguments(
optim="apollo_adamw",
optim_target_modules=[r".*.attn.*", r".*.mlp.*"],
optim_args="proj=random,rank=1,scale=128.0,scale_type=tensor,update_proj_gap=200",
... # remaining args from the TrainingArguments intro config
)pip install grokadamw
GrokAdamW는 느리게 변화하는 기울기로 인해 모델이 지연된 일반화를 보이는 grokking 현상을 대상으로 합니다.
args = TrainingArguments(
+ optim="grokadamw",
... # remaining args from the TrainingArguments intro config
)pip install lomo-optim
Low-Memory Optimization (LOMO)는 저메모리 전체 파라미터 파인튜닝을 위한 두 가지 옵티마이저인 LOMO와 AdaLomo를 포함합니다. 두 옵티마이저 모두 그래디언트 계산과 파라미터 업데이트를 하나의 단계로 통합합니다. AdaLomo는 Adam과 유사하게 파라미터별 적응형 학습률을 추가합니다.
AdaLomo는
grad_norm없이 사용할 때 성능과 처리량이 향상되어 가장 효과적입니다.
args = TrainingArguments(
+ optim="adalomo",
learning_rate=2e-6,
... # remaining args from the TrainingArguments intro config
)pip install schedulefree
Schedule Free optimizer(SFO)는 모멘텀을 평균화와 보간의 조합으로 대체하여 학습률 어닐링이 전혀 필요 없도록 합니다.
SFO는 RAdam(schedule_free_radam), AdamW(schedule_free_adamw), SGD(schedule_free_sgd) 옵티마이저를 지원합니다. RAdam 스케줄러는 warmup_steps가 필요하지 않습니다.
SFO는 lr_scheduler_type="constant"와 함께 사용하세요. 다른 스케줄러 유형도 동작하지만 SFO의 의도된 동작에 영향을 미칩니다.
args = TrainingArguments(
+ optim="schedule_free_radam",
+ lr_scheduler_type="constant",
learning_rate=2e-6,
... # remaining args from the TrainingArguments intro config
)pip install torch-optimi
StableAdamW는 AdaFactor의 업데이트 클리핑을 AdamW에 이식하여 그라디언트 클리핑이 필요 없도록 합니다. 그 외에는 AdamW의 대체재로 그대로 사용할 수 있습니다.
큰 배치 크기로 학습 중이거나 손실 스파이크가 여전히 관찰되는 경우,
beta_2를 0.95에서 0.99 사이로 설정해 보세요.
args = TrainingArguments(
+ optim="stable_adamw",
learning_rate=2e-6,
... # remaining args from the TrainingArguments intro config
)pip install galore-torch trl
Gradient Low-Rank Projection (GaLore)는 LLM 학습 시 메모리를 절감합니다. LoRA와 같은 저랭크 적응 방법과 달리, GaLore은 전체 파라미터 학습을 유지합니다.
trl.SFTConfig의 optim을 GaLore 옵티마이저("galore_adamw", "galore_adafactor", 또는 "galore_adamw_8bit")로 설정합니다. optim_target_modules로 대상 모듈을 지정하고, optim_args를 통해 GaLore 전용 매개변수(rank, update_proj_gap, scale)를 설정합니다.
from trl import SFTConfig
args = SFTConfig(
output_dir="./galore",
max_steps=100,
optim="galore_adamw",
optim_target_modules=[r".*.attn.*", r".*.mlp.*"],
optim_args="rank=64, update_proj_gap=100, scale=0.10",
)레이어별 최적화를 위해 옵티마이저 이름에 _layerwise를 추가합니다("galore_adamw_layerwise"). GaLore의 대상인 선형 레이어만 저랭크 분해를 사용하며, 나머지 레이어는 일반 방식으로 최적화됩니다.
from trl import SFTConfig, SFTTrainer
args = SFTConfig(
output_dir="./galore",
max_steps=100,
optim="galore_adamw_layerwise",
optim_target_modules=[r".*.attn.*", r".*.mlp.*"],
optim_args="rank=64, update_proj_gap=100, scale=0.10",
)Layerwise mode는 실험적 기능입니다. 단일 GPU에서만 실행되며, DistributedDataParallel(DDP)을 지원하지 않고, gradient clipping과 DeepSpeed가 작동하지 않을 수 있습니다.
옵티마이저와 스케줄러 사용자 정의
아직 통합되지 않은 옵티마이저를 사용하거나, 레이어별 학습률을 조정하거나, 사용자 정의 로직을 적용하려면 사용자 정의 옵티마이저와 스케줄러를 생성하세요.
클래스와 kwargs를 전달
~Trainer.optimizer_cls_and_kwargs는 사용자 정의 optimizer 클래스를 허용하되, 파라미터 그룹화와 디바이스 배치는 Trainer에 위임합니다.
Trainer는 create_optimizer()가 실행될 때까지 옵티마이저 생성을 지연시키므로, 모델은 이미 올바른 장치에 배치되어 있습니다.
import torch
trainer = Trainer(
...
optimizer_cls_and_kwargs=(
torch.optim.SGD,
{"momentum": 0.9, "nesterov": True}
),
)prebuilt 인스턴스 전달
~Trainer.optimizers에 미리 정의된 optimizer와 scheduler를 전달합니다. Trainer는 미리 생성된 인스턴스가 제공되면 create_optimizer()와 create_scheduler()를 건너뜁니다. scheduler를 전달하지 않으면 Trainer가 자동으로 생성합니다.
모델을 올바른 장치에 배치한 후 옵티마이저를 구성하세요. 매개변수는
Trainer가 모델을 이동하기 전에 구성 시점에 결정됩니다. 분산 학습에서는 장치 불일치가 조용히 잘못된 동작을 유발할 수 있습니다.
import torch
from transformers import Trainer, get_cosine_schedule_with_warmup
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)
scheduler = get_cosine_schedule_with_warmup(
optimizer, num_warmup_steps=500, num_training_steps=10_000
)
trainer = Trainer(
...
optimizers=(optimizer, scheduler),
)Prebuilt instances는 create_optimizer()와 create_scheduler()를 우회하므로, 직접 parameter groups를 지정해야 합니다.
옵티마이저 및 스케줄러 메서드 오버라이드
전체 제어를 위해 create_optimizer()와 create_scheduler()를 서브클래스로 구현하세요. 두 메서드는 모두 train() 실행 중에 호출됩니다.
SchedulerType에 없는 OneCycleLR와 같은 스케줄러를 사용하려면 create_scheduler()를 오버라이드하세요.
각 메서드에서 self에 할당하고 이를 반환하도록 확인하세요.
import torch
from transformers import Trainer
class MyTrainer(Trainer):
def create_scheduler(self, num_training_steps, optimizer=None):
optimizer = optimizer or self.optimizer
self.lr_scheduler = torch.optim.lr_scheduler.OneCycleLR(
optimizer,
max_lr=0.1,
total_steps=num_training_steps,
)
return self.lr_scheduler기본 옵티마이저가 작동하는 경우 create_optimizer()를 오버라이드할 필요가 없습니다. 메서드를 완전히 교체하는 것보다 super()를 사용하여 메서드를 확장하는 것이 더 쉽습니다. 예를 들어, 모든 다른 설정은 그대로 유지하면서 추가적인 파라미터 그룹을 추가할 수 있습니다.
class MyTrainer(Trainer):
def create_optimizer(self, model=None):
super().create_optimizer(model) # builds the default two param groups
# add extra param group
self.optimizer.add_param_group({
"params": self.model.classifier.parameters(),
"lr": self.args.learning_rate * 10,
})
return self.optimizer