Stage 4 · Ray Tune 튜닝 — 하이퍼파라미터 자동화
한눈에 보기
머신러닝을 하다 보면 “learning_rate를 몇으로, 깊이는 얼마로” 하는 하이퍼파라미터를 만지게 됩니다. 이걸 하나하나 손으로 돌리면 시간 낭비가 큽니다. Ray Tune은 이 탐색을 코어 수만큼 병렬로 자동화하고, 좋은 조합을 일찍 남기고 나쁜 조합은 일찍 끊는 도구입니다. 단독 함수도, Stage 5의 Trainer도 모두 Objective로 감쌀 수 있습니다.
이번 포스트에서 다루는 핵심 질문은 세 가지입니다.
- Tuner로 탐색 공간을 정의하고 학습 함수를 최적화하는 기본 흐름은?
- ASHA/HyperBand 같은 조기 종료와 탐색 알고리즘은 어떻게 쓰나?
- 한 대의 노트북에서 코어를 오버서브스크라이브해 트라이얼을 병렬화하는 전략은?
Tuner 기본
목표는 단순한 함수(Objective) 입니다. config(딕셔너리)를 받아 메트릭을 tune.report로 보고합니다.
import ray
from ray import tune
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
ray.init(num_cpus=4)
def train_rf(config):
X, y = load_iris(return_X_y=True)
model = RandomForestClassifier(
n_estimators=config["n_estimators"],
max_depth=config["max_depth"],
)
score = cross_val_score(model, X, y, cv=3).mean()
tune.report({"mean_accuracy": score}) # 메트릭 보고
search_space = {
"n_estimators": tune.grid_search([50, 100, 200]),
"max_depth": tune.choice([2, 4, 8]),
}
tuner = tune.Tuner(
train_rf,
param_space=search_space,
tune_config=tune.TuneConfig(metric="mean_accuracy", mode="max"),
)
results = tuner.fit()
best = results.get_best_result(metric="mean_accuracy", mode="max")
print("최고 점수:", best.metrics["mean_accuracy"])
print("최고 config:", best.config)
param_space: 탐색 공간.tune.grid_search([...])(모두 시도),tune.choice/uniform/loguniform등.tune.report: 각 트라이얼이 학습 중 메트릭을 보고.TuneConfig(metric, mode): 최적화 대상과 방향(max/min).get_best_result: 최고 트라이얼.
탐색 공간은 loguniform처럼 로그 스케일도 지정할 수 있습니다 — 넓은 값 범위를 효율적으로 탐색합니다.
search_space = {
"lr": tune.loguniform(1e-4, 1e-2), # 로그 스케일
"dropout": tune.uniform(0.0, 0.5),
}
조기 종료와 탐색 알고리즘
조기 종료 — ASHA / HyperBand
성능이 나쁜 트라이얼을 일찍 멈추면, 자원을 유망한 트라이얼에 집중할 수 있습니다. ASHA(Async Successive Halving)와 HyperBand가 대표적입니다.
from ray.tune.schedulers import ASHAScheduler, HyperBandScheduler
tuner = tune.Tuner(
train_rf,
param_space=search_space,
tune_config=tune.TuneConfig(
metric="mean_accuracy",
mode="max",
scheduler=ASHAScheduler(time_attr="training_iteration", max_t=100),
),
)
results = tuner.fit()
탐색 알고리즘 — Optuna 등
무작위·그리드 대신 지능형 탐색을 쓰려면 ray.tune.search의 알고리즘을 연결합니다.
from ray.tune.search.optuna import OptunaSearch
tuner = tune.Tuner(
train_rf,
param_space=search_space,
tune_config=tune.TuneConfig(
metric="mean_accuracy",
mode="max",
search_alg=OptunaSearch(),
),
)
지원 목록: Optuna, Hyperopt, BayesOpt, BOHB, Nevergrad, Ax 등.
로컬 리소스 제어 — 코어 오버서브스크라이빙
한 대 노트북의 코어 수는 한정적입니다. 트라이얼당 1 CPU가 기본이므로 4코어면 4개만 동시에 돕니다. 더 빨리 많이 돌리고 싶다면:
max_concurrent_trials: 동시 트라이얼 수 상한을 정합니다.tune.with_resources(trainable, {"cpu": 0.5}): 트라이얼당 소수 CPU를 줘서 한 코어에 여러 트라이얼을 올립니다(오버서브스크라이빙).
from ray import tune
# 각 트라이얼이 0.5 CPU → 4코어에 최대 8개 트라이얼을 병렬
tuner = tune.Tuner(
tune.with_resources(train_rf, {"cpu": 0.5}),
param_space=search_space,
tune_config=tune.TuneConfig(
metric="mean_accuracy",
mode="max",
max_concurrent_trials=8,
),
)
results = tuner.fit()
실무 요령: 각 트라이얼이 순수 Python/사이킷런이라면 GIL 때문에 소수 CPU 오버서브스크라이빙이 이득입니다. 반면 NumPy/Torch처럼 GIL을 풀어 코어를 다 쓰는 트라이얼이라면 1 CPU당 1 트라이얼이 맞습니다. 트라이얼의 성격에 따라
with_resources를 조절하세요.
GPU 참고:
gpu자원을 지정하면 트라이얼에CUDA_VISIBLE_DEVICES가 설정됩니다. 지정하지 않으면 CUDA가 비활성화됩니다.
로컬 활용 전략 — 실전 요약
- 코어 수만큼 병렬 탐색: 기본값만으로도 코어 수 트라이얼이 동시에 돕니다.
- 조기 종료로 낭비 줄이기: ASHA를 붙이면 나쁜 하이퍼파라미터 조합을 일찍 끊습니다.
- 소수 CPU 오버서브스크라이빙: GIL-bound(사이킷런 등) 트라이얼이면
{"cpu": 0.5}로 8개까지 병렬. - Train과 연결: Stage 5의
Trainer를 Objective로 감싸 하이퍼파라미터 탐색 + 분산 학습을 동시에.
Summary
- Ray Tune은 탐색 공간(
param_space)에서 여러 트라이얼을 병렬 생성해 Objective 함수를 최적화합니다. grid_search/loguniform/choice등으로 공간을 정의하고,tune.report로 메트릭을 보고합니다.- ASHA/HyperBand 조기 종료와 Optuna 등 탐색 알고리즘으로 효율을 올립니다.
- 로컬에선
with_resources(소수 CPU) +max_concurrent_trials로 한 코어에 여러 트라이얼을 얹는 오버서브스크라이빙이 핵심 전략입니다.
다음 학습 (Next Learning)
- Stage 5 · Ray Train 분산 학습 —
Tuner로 감쌀 수 있는Trainer로 모델을 워커에 분산 학습합니다. - Stage 3 · Ray Data 파이프라인 — 튜닝에 넘길 데이터셋 전처리.
- PostgreSQL Essential Curriculum — 튜닝과 결합할 수 있는 데이터 소스/DB 학습.