W&B Sweeps는 하이퍼파라미터 값을 탐색하는 전략과 이를 평가하는 코드를 결합합니다. 탐색 전략은 모든 옵션을 시도하는 간단한 방식부터 베이지안 최적화 및 Hyperband(BOHB)와 같은 복잡한 방식까지 다양합니다.
Sweep 구성을 Python dictionary 또는 YAML 파일로 정의하세요. Sweep 구성을 정의하는 방법은 Sweeps를 어떻게 관리하느냐에 따라 달라집니다.
커맨드라인에서 Sweep을 초기화하고 sweep 에이전트를 시작하려면 YAML 파일에 Sweep 구성을 정의하세요. Python 스크립트나 노트북 내에서 전체 Sweep 과정을 초기화하고 시작하려면 Python dictionary로 정의하세요.
다음 가이드는 Sweep 구성을 작성하는 방법을 설명합니다. 최상위 Sweep 구성 키에 대한 전체 목록은 Sweep 구성 옵션을 참조하세요.
기본 구조
두 가지 Sweep 구성 형식(YAML 및 Python dictionary) 모두 키-값 쌍과 중첩 구조를 활용합니다.
Sweep 구성 내의 최상위 키를 사용하여 Sweep의 이름(name 키), 탐색할 파라미터(parameters 키), 파라미터 공간을 탐색하는 방법론(method 키) 등 Sweep 검색의 특성을 정의합니다.
예를 들어, 다음 코드조각은 동일한 Sweep 구성을 YAML 파일과 Python dictionary로 각각 정의한 모습을 보여줍니다. Sweep 구성 내에는 program, name, method, metric, parameters라는 5개의 최상위 키가 지정되어 있습니다.
커맨드라인(CLI)에서 대화식으로 Sweeps를 관리하려면 YAML 파일에 Sweep 구성을 정의하세요.program: train.py
name: sweepdemo
method: bayes
metric:
goal: minimize
name: validation_loss
parameters:
learning_rate:
min: 0.0001
max: 0.1
batch_size:
values: [16, 32, 64]
epochs:
values: [5, 10, 15]
optimizer:
values: ["adam", "sgd"]
Python 스크립트나 노트북에서 트레이닝 알고리즘을 정의하는 경우, Python dictionary 데이터 구조로 Sweep을 정의하세요.다음 코드조각은 sweep_configuration이라는 변수에 Sweep 구성을 저장하는 예시입니다.sweep_configuration = {
"name": "sweepdemo",
"method": "bayes",
"metric": {"goal": "minimize", "name": "validation_loss"},
"parameters": {
"learning_rate": {"min": 0.0001, "max": 0.1},
"batch_size": {"values": [16, 32, 64]},
"epochs": {"values": [5, 10, 15]},
"optimizer": {"values": ["adam", "sgd"]},
},
}
최상위 parameters 키 내부에는 learning_rate, batch_size, epoch, optimizer 키가 중첩되어 있습니다. 지정된 각 중첩 키에 대해 하나 이상의 값, 분포, 확률 등을 제공할 수 있습니다. 자세한 내용은 Sweep 구성 옵션의 parameters 섹션을 참조하세요.
이중 중첩 파라미터
Sweep 구성은 중첩된 파라미터를 지원합니다. 중첩 파라미터를 정의하려면 최상위 파라미터 이름 아래에 추가 parameters 키를 포함하세요.
다음 예시는 세 개의 중첩 파라미터 nested_category_1, nested_category_2, nested_category_3을 포함하는 Sweep 구성을 보여줍니다. 각 중첩 파라미터에는 momentum과 weight_decay라는 두 개의 추가 파라미터가 포함됩니다.
nested_category_1, nested_category_2, nested_category_3은 예시를 위한 이름입니다. 여러분의 유스 케이스에 맞는 이름으로 바꾸어 사용하세요.
다음 코드조각은 YAML 파일과 Python dictionary 모두에서 중첩 파라미터를 정의하는 방법을 보여줍니다.
program: sweep_nest.py
name: nested_sweep
method: random
metric:
name: loss
goal: minimize
parameters:
optimizer:
values: ['adam', 'sgd']
fc_layer_size:
values: [128, 256, 512]
dropout:
values: [0.3, 0.4, 0.5]
epochs:
value: 1
learning_rate:
distribution: uniform
min: 0
max: 0.1
batch_size:
distribution: q_log_uniform_values
q: 8
min: 32
max: 256
nested_category_1:
parameters:
momentum:
distribution: uniform
min: 0.0
max: 0.9
weight_decay:
values: [0.0001, 0.0005, 0.001]
nested_category_2:
parameters:
momentum:
distribution: uniform
min: 0.0
max: 0.9
weight_decay:
values: [0.1, 0.2, 0.3]
nested_category_3:
parameters:
momentum:
distribution: uniform
min: 0.5
max: 0.7
weight_decay:
values: [0.2, 0.3, 0.4]
{
"program": "sweep_nest.py",
"name": "nested_sweep",
"method": "random",
"metric": {
"name": "loss",
"goal": "minimize"
},
"parameters": {
"optimizer": {
"values": ["adam", "sgd"]
},
"fc_layer_size": {
"values": [128, 256, 512]
},
"dropout": {
"values": [0.3, 0.4, 0.5]
},
"epochs": {
"value": 1
},
"learning_rate": {
"distribution": "uniform",
"min": 0,
"max": 0.1
},
"batch_size": {
"distribution": "q_log_uniform_values",
"q": 8,
"min": 32,
"max": 256
},
"nested_category_1": {
"parameters": {
"momentum": {
"distribution": "uniform",
"min": 0.0,
"max": 0.9
},
"weight_decay": {
"values": [0.0001, 0.0005, 0.001]
}
}
},
"nested_category_2": {
"parameters": {
"momentum": {
"distribution": "uniform",
"min": 0.0,
"max": 0.9
},
"weight_decay": {
"values": [0.1, 0.2, 0.3]
}
}
},
"nested_category_3": {
"parameters": {
"momentum": {
"distribution": "uniform",
"min": 0.5,
"max": 0.7
},
"weight_decay": {
"values": [0.2, 0.3, 0.4]
}
}
}
}
}
Sweep 구성에 정의된 중첩 파라미터는 W&B Run 설정에 지정된 키를 덮어씁니다.예를 들어, 중첩된 기본값으로 Run을 초기화하는 train.py 스크립트가 있다고 가정해 봅시다:def main():
with wandb.init(config={"nested_param": {"manual_key": 1}}) as run:
# 트레이닝 코드가 여기에 들어갑니다.
Sweep 구성의 최상위 "parameters" 키 아래에 중첩 파라미터를 정의합니다:sweep_configuration = {
"method": "grid",
"metric": {"name": "score", "goal": "minimize"},
"parameters": {
"top_level_param": {"value": 0},
"nested_param": {
"parameters": {
"learning_rate": {"value": 0.01},
"double_nested_param": {
"parameters": {"x": {"value": 0.9}, "y": {"value": 0.8}}
},
}
},
},
}
sweep_id = wandb.sweep(sweep=sweep_configuration, project="<project>")
wandb.agent(sweep_id, function=main, count=4)
Sweep이 실행되는 동안 run.config["nested_param"]은 Sweep 구성에 의해 정의된 하위 트리(learning_rate, double_nested_param)를 반영하며, wandb.init(config=...)에서 정의된 manual_key는 포함하지 않습니다.
Sweep 구성 템플릿
다음 템플릿은 파라미터를 구성하고 검색 제약 조건을 지정하는 방법을 보여줍니다. hyperparameter_name을 실제 하이퍼파라미터 이름으로 바꾸고, <>로 묶인 값들을 적절히 입력하세요.
program: <insert>
method: <insert>
parameter:
hyperparameter_name0:
value: 0
hyperparameter_name1:
values: [0, 0, 0]
hyperparameter_name:
distribution: <insert>
value: <insert>
hyperparameter_name2:
distribution: <insert>
min: <insert>
max: <insert>
q: <insert>
hyperparameter_name3:
distribution: <insert>
values:
- <list_of_values>
- <list_of_values>
- <list_of_values>
early_terminate:
type: hyperband
s: 0
eta: 0
max_iter: 0
command:
- ${Command macro}
- ${Command macro}
- ${Command macro}
- ${Command macro}
과학적 표기법을 사용하여 숫자 값을 표현하려면 YAML의 !!float 연산자를 추가하여 값을 부동 소수점 숫자로 형변환하세요. 예: min: !!float 1e-5. Command 예시를 참조하세요.
Sweep 구성 예시
program: train.py
method: random
metric:
goal: minimize
name: loss
parameters:
batch_size:
distribution: q_log_uniform_values
max: 256
min: 32
q: 8
dropout:
values: [0.3, 0.4, 0.5]
epochs:
value: 1
fc_layer_size:
values: [128, 256, 512]
learning_rate:
distribution: uniform
max: 0.1
min: 0
optimizer:
values: ["adam", "sgd"]
sweep_config = {
"method": "random",
"metric": {"goal": "minimize", "name": "loss"},
"parameters": {
"batch_size": {
"distribution": "q_log_uniform_values",
"max": 256,
"min": 32,
"q": 8,
},
"dropout": {"values": [0.3, 0.4, 0.5]},
"epochs": {"value": 1},
"fc_layer_size": {"values": [128, 256, 512]},
"learning_rate": {"distribution": "uniform", "max": 0.1, "min": 0},
"optimizer": {"values": ["adam", "sgd"]},
},
}
Bayes hyperband 예시
program: train.py
method: bayes
metric:
goal: minimize
name: val_loss
parameters:
dropout:
values: [0.15, 0.2, 0.25, 0.3, 0.4]
hidden_layer_size:
values: [96, 128, 148]
layer_1_size:
values: [10, 12, 14, 16, 18, 20]
layer_2_size:
values: [24, 28, 32, 36, 40, 44]
learn_rate:
values: [0.001, 0.01, 0.003]
decay:
values: [1e-5, 1e-6, 1e-7]
momentum:
values: [0.8, 0.9, 0.95]
epochs:
value: 27
early_terminate:
type: hyperband
s: 2
eta: 3
max_iter: 27
다음 탭에서는 early_terminate에 대해 최소 또는 최대 반복 횟수를 지정하는 방법을 보여줍니다:
이 예시의 브래킷은 [3, 3*eta, 3*eta*eta, 3*eta*eta*eta]이며, 이는 [3, 9, 27, 81]과 같습니다.early_terminate:
type: hyperband
min_iter: 3
이 예시의 브래킷은 [27/eta, 27/eta/eta]이며, 이는 [9, 3]과 같습니다.early_terminate:
type: hyperband
max_iter: 27
s: 2
매크로 및 커스텀 커맨드 인수 예시
더 복잡한 커맨드라인 인수의 경우, 매크로를 사용하여 환경 변수, Python 인터프리터 및 추가 인수를 전달할 수 있습니다. W&B는 사전 정의된 매크로와 Sweep 구성에서 지정할 수 있는 커스텀 커맨드라인 인수를 지원합니다.
예를 들어, 다음 Sweep 구성(sweep.yaml)은 Sweep이 실행될 때 ${env}, ${interpreter}, ${program} 매크로가 적절한 값으로 대체되어 Python 스크립트(run.py)를 실행하는 커맨드를 정의합니다.
--batch_size=${batch_size}, --test=True, --optimizer=${optimizer} 인수는 커스텀 매크로를 사용하여 Sweep 구성에 정의된 batch_size, test, optimizer 파라미터 값을 전달합니다.
program: run.py
method: random
metric:
name: validation_loss
parameters:
learning_rate:
min: 0.0001
max: 0.1
command:
- ${env}
- ${interpreter}
- ${program}
- "--batch_size=${batch_size}"
- "--optimizer=${optimizer}"
- "--test=True"
연결된 Python 스크립트(run.py)는 argparse 모듈을 사용하여 이러한 커맨드라인 인수를 파싱할 수 있습니다.
# run.py
import wandb
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--batch_size', type=int)
parser.add_argument('--optimizer', type=str, choices=['adam', 'sgd'], required=True)
parser.add_argument('--test', type=str2bool, default=False)
args = parser.parse_args()
# W&B Run 초기화
with wandb.init('test-project') as run:
run.log({'validation_loss':1})
Sweep 구성에서 사용할 수 있는 사전 정의된 매크로 목록은 Sweep 구성 옵션의 Command 매크로 섹션을 참조하세요.
불리언(Boolean) 인수
argparse 모듈은 기본적으로 불리언 인수를 지원하지 않습니다. 불리언 인수를 정의하려면 action 파라미터를 사용하거나 불리언 값의 문자열 표현을 불리언 타입으로 변환하는 커스텀 함수를 사용할 수 있습니다.
예를 들어, 다음 코드조각을 사용하여 불리언 인수를 정의할 수 있습니다. ArgumentParser에 store_true 또는 store_false를 인수로 전달하세요.
import wandb
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--test', action='store_true')
args = parser.parse_args()
args.test # --test가 전달되면 True, 그렇지 않으면 False가 됩니다.
문자열 표현을 불리언 타입으로 변환하는 커스텀 함수를 정의할 수도 있습니다. 예를 들어, 다음 코드조각은 문자열을 불리언 값으로 변환하는 str2bool 함수를 정의합니다.
def str2bool(v: str) -> bool:
"""문자열을 불리언으로 변환합니다. argparse가
기본적으로 불리언 인수를 지원하지 않기 때문에 필요합니다.
"""
if isinstance(v, bool):
return v
return v.lower() in ('yes', 'true', 't', '1')