W&B를 사용하는 Keras-Tuner
W&B와 Keras-Tuner 통합
Kaggle Notebook 확인하기
인공 신경망(artificial neural network)은 사전 제약, 가중치(weight) 및 편향(biases)으로 구성됩니다. 이러한 제약, 즉, 뉴런(neurons)의 수, 활성화 선택 (비선형(non-linearity)), 레이어의 수는 일반적으로 초매개변수라고 불립니다. 광범위한 분야의 연구는 초매개변수 활성화에 기반을 두고 있습니다. 이는 사람들이 가중치 및 편향뿐만 아니라 초매개변수에도 많은 관심이 있음을 의미합니다. 여기에는 그리드(Grid), 랜덤(Random), 베이지안(Bayesian)과 같은 훌륭한 접근법이 있으며, 이들은 이 분야에 이미 큰 족적을 남겼습니다.
딥러닝 실험의 경우 우수한 초매개변수 선택에 많은 시간이 소요됩니다. 우수한 초매개변수의 선택은 실험의 판도를 바꾸는 요인이 될 수 있습니다. 이 주제는 현재 널리 연구되고 있으며, 다양한 검색 알고리즘의 등장과 함께 초매개변수를 자동으로 조정할 수 없습니다. 초매개변수 공간을 자동으로 검색하여 초매개변수를 조정하는 개념은 수동으로 이 작업을 수행해온 딥러닝 연구원들이 시간을 아끼는 데 큰 도움이 되었습니다.
이 기사에서, 초매개변수 조정의 자동화에 도움이 되는 툴인 Keras-tuner에 대해 살펴보겠습니다. 이 툴의 기본사항의 이해뿐만 아니라 저희가 선호하는 실험 추적기인 wandb와의 통합도 해보겠습니다.
이 가사에서 다룰 주제는 다음과 같습니다:
Keras-tuner
의 API- Wandb 통합 코드
- 스윕(sweeps) 살펴보기
- 결론
keras-tuner
의 API
Keras 팀은 툴의 API 설계에 심혈을 기울이고 있습니다. 이 툴은 유사 사고 프로세스에서 벗어나지 않습니다.
이 API가 제공하는 4가지 기본 인터페이스가 있습니다. 이러한 인터페이스는 API의 핵심입니다.
- 초매개변수: 이 클래스는 초매개변수 컨테이너 역할을 합니다. 이 클래스의 인스턴스는 현재 초매개변수의 및 전체 검색 공간에 대한 정보를 합니다. 2.하이퍼모델(Hypermodel): 이 클래스의 인스턴스는 전체 초매개변수 공간을 모델링하는 개체로 여겨질 수 있습니다. 이 인스턴스는 초매개변수 공간뿐만 아니라 초매개변수로부터의 딥러닝 모델 샘플링도 구축합니다.
- 오라클(Oracles): 이 클래스의 각 인스턴스는 특정 초매개변수 조정 알고리즘을 구현합니다.
- 튜너(Tuners):
Tuner
인스턴스는 초매개변수 조정을 수행합니다.Oracle
이 전달인자(argument)로Tuner
에 전달됩니다. 오라클은 다음에 시도해야 할 매개변수를Tuner
에 알려줍니다.
API 설계에 대한 하향식 접근법은 읽기 쉽고 이해하기 쉽습니다. 이 모두를 반복하려면 다음을 수행합니다.
HyperParameters
객체(object) 구축;HyperParameters
를Hypermodel
에 전달하여 검색 공간 구축;- 조정 알고리즘을 제공하는
Oracles
구축 Oracles
에 따라 초매개변수를 조정하는Tuners
구축
# keras-tuner
를 사용하는 코드
이 섹션에서 예시와 함께 keras-tuner의 기본적 사용법을 설명하겠습니다. 해당 예시는 자체 문서에서 가져왔습니다.
튜너(tuner)를 실행하는 데 필요한 가져오기(imports)는 젖혀두고, 먼저 전체 검색 공간을 에뮬레이팅(emulate)할 하이퍼모델을 우선 구축할 필요가 있습니다.
Hypermodel은 다음의 두 가지 방법으로 구축할 수 있습니다:
- 함수를 통해 모델 구축하기
Hypermodel
클래스에서 하위분류하기
함수
여기서 HyperParameters
를 전달인자로 사용하는 함수를 만듭니다. 이 함수는 HyperParameters
에서 샘플링하며 모델을 만들고 반환합니다. 이를 통해 검색 공간에서 다양한 모델이 만들어집니다.
# build with function
def build_model(hp):
model = keras.Sequential()
model.add(layers.Dense(units=hp.Int('units',
min_value=32,
max_value=512,
step=32),
activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
model.compile(
optimizer=keras.optimizers.Adam(
hp.Choice('learning_rate',
values=[1e-2, 1e-3, 1e-4])),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
Hypermodel
클래스 하위분류하기
이 방법을 사용하면, build()
방법을 오버라이딩(override) 해야 합니다. build()
방법에서 사용자는 HyperParameters
에서 샘플링하여 적절한 모델을 구축할 수 있습니다.
# build with inheritance
class MyHyperModel(HyperModel):
def __init__(self, num_classes):
self.num_classes = num_classes
def build(self, hp):
model = keras.Sequential()
model.add(layers.Dense(units=hp.Int('units',
min_value=32,
max_value=512,
step=32),
activation='relu'))
model.add(layers.Dense(self.num_classes, activation='softmax'))
model.compile(
optimizer=keras.optimizers.Adam(
hp.Choice('learning_rate',
values=[1e-2, 1e-3, 1e-4])),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
두 경우 모두, Hypermodel
은 HyperParameters
을 제공함으로써 생성됩니다. 관심 있으신 분들께서는 초매개변수가 샘플링되는 방식을 살펴보시기 바랍니다. 패키지는 정적 선택(static choices)뿐만 아니라 조건부 초매개변수(conditional hyperparameters)도 제공합니다.
Hypermodel
이 준비되면, Tuner
를 구축해야 합니다. Tuner
는 초매개변수 공간을 검색하여 가장 최적화된 초매개변수 세트를 제공합니다. 두 가지 Hypermodel
설정 모두에 대한 튜너(tuners)를 아래에 작성했습니다.
# tuner for function
tuner = RandomSearch(
build_model,
objective='val_accuracy',
max_trials=5,
executions_per_trial=3,
directory='my_dir',
project_name='helloworld')
# tuner for subclass
hypermodel = MyHyperModel(num_classes=10)
tuner = RandomSearch(
hypermodel,
objective='val_accuracy',
max_trials=10,
directory='my_dir',
project_name='helloworld')
참고: 사용자 지정
Tuner
를 사용하여, 튜너(tuner)
가 검색 알고리즘을 사용할 수 있도록 도와주는 Oracle을 튜너에 전달해야 합니다.
모든 설정이 완료되면, 검색을 실행할 수 있습니다. search
방법은 fit
방법과 동일한 설계를 따릅니다. search
후, 최상의 모델 및 최상의 초매개변수에 대하여 튜너를 쿼리 할 수 있습니다.
tuner.search(x, y,
epochs=5,
validation_data=(val_x, val_y))
keras-tuner
와 wandb
를 통합하는 코드
Kaggle Notebook 확인하기
keras-tuner
와 함께 모든 모델을 한 곳에서 추적할 수 있다면 얼마나 좋을까요? 여기서 생성되고 검색되는 모든 모델 추적에 도움이 되도록 wandb
와 keras-tuner
를 통합하겠습니다. 이는 최상의 모델을 회수(retrieve)하는 데 도움이 될 뿐만 아니라 가치 높은 통찰력을 얻으실 수 있습니다.
이 섹션에서는 keras-tuner의 하위분류를 위하여 수정된 코드를 실행해보겠습니다.
Hypermodel
여기서 Hypermodel
구축을 위한 기능적인 방법을 사용해보겠습니다. 이는 모델을 구축하는 아주 쉬운 방법입니다.
이번 예시에서 conditional hyperparameters
의 사용법이 구현되었음을 확인할 수 있습니다. 여기서 조정 가능한 수의 conv_layers를 생성하는 for 루프(loop)를 갖고 있으며, 이는 그 자체에 조정 가능한 filters와kernel_size
매개변수를 포함하고 있습니다.
def build_model(hp):
"""
Builds a convolutional model.
Args:
hp: Hyperparamet object, This is the object that helps
us sample hyperparameter for a particular trial.
Returns:
model: Keras model, Returns a keras model.
"""
inputs = tf.keras.Input(shape=(28, 28, 1))
x = inputs
# In this example we also get to look at
# conditional heyperparameter settings.
# Here the `kernel_size` is conditioned
# with the for loop counter.
for i in range(hp.Int('conv_layers', 1, 3)):
x = tf.keras.layers.Conv2D(
filters=hp.Int('filters_' + str(i), 4, 32, step=4, default=8),
kernel_size=hp.Int('kernel_size_' + str(i), 3, 5),
activation='relu',
padding='same')(x)
# choosing between max pool and avg pool
if hp.Choice('pooling' + str(i), ['max', 'avg']) == 'max':
x = tf.keras.layers.MaxPooling2D()(x)
else:
x = tf.keras.layers.AveragePooling2D()(x)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.ReLU()(x)
if hp.Choice('global_pooling', ['max', 'avg']) == 'max':
x = tf.keras.layers.GlobalMaxPooling2D()(x)
else:
x = tf.keras.layers.GlobalAveragePooling2D()(x)
outputs = tf.keras.layers.Dense(10, activation='softmax')(x)
model = tf.keras.Model(inputs, outputs)
return model
Tuner
config
및 loss
를 로그하하기 위해 튜너(tuner)를 wandb와 통합하는 것은 아주 쉬운 일이었습니다. API는 사용자에게 kt.Tuner
클래스의run_trial
방법을 오버라이드(override) 할 수 있게 합니다. run_trial
방법에서 HyperParameters
객체를 활용할 수 있습니다. 이는 wandb run의 config로써 현재 초매개변수를 쿼리 하는 데 사용됩니다. 이는 이제 모델의 메트릭을 로그할 수 있음을 의미할 뿐만 아니라, wandb가 대시보드에 제공하는 뛰어난 위젯의 도움을 통해 초매개변수를 비교할 수 있음을 뜻합니다.
class MyTuner(kt.Tuner):
"""
Custom Tuner subclassed from `kt.Tuner`
"""
def run_trial(self, trial, train_ds):
"""
The overridden `run_trial` function
Args:
trial: The trial object that holds information for the
current trial.
train_ds: The training data.
"""
hp = trial.hyperparameters
# Batching the data
train_ds = train_ds.batch(
hp.Int('batch_size', 32, 128, step=32, default=64))
# The models that are created
model = self.hypermodel.build(trial.hyperparameters)
# Learning rate for the optimizer
lr = hp.Float('learning_rate', 1e-4, 1e-2, sampling='log', default=1e-3)
if hp.Choice('optimizer', ['adam', 'sgd']) == 'adam':
optimizer = tf.keras.optimizers.Adam(lr)
else:
optimizer = tf.keras.optimizers.SGD(lr)
epoch_loss_metric = tf.keras.metrics.Mean()
# build the train_step
@tf.function
def run_train_step(data):
"""
The run step
Args:
data: the data that needs to be fit
Returns:
loss: Returns the loss for the present batch
"""
images = tf.dtypes.cast(data['image'], 'float32') / 255.
labels = data['label']
with tf.GradientTape() as tape:
logits = model(images)
loss = tf.keras.losses.sparse_categorical_crossentropy(
labels, logits)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
epoch_loss_metric.update_state(loss)
return loss
# WANDB INITIALIZATION
# Here we pass the configuration so that
# the runs are tagged with the hyperparams
# This also directly means that we can
# use the different comparison UI widgets in the
# wandb dashboard off the shelf.
run = wandb.init(entity='ariG23498', project='keras-tuner', config=hp.values)
for epoch in range(10):
self.on_epoch_begin(trial, model, epoch, logs={})
for batch, data in enumerate(train_ds):
self.on_batch_begin(trial, model, batch, logs={})
batch_loss = run_train_step(data)
self.on_batch_end(trial, model, batch, logs={'loss': batch_loss})
if batch % 100 == 0:
loss = epoch_loss_metric.result().numpy()
# Log the batch loss for WANDB
run.log({f'e{epoch}_batch_loss':loss})
# Epoch loss logic
epoch_loss = epoch_loss_metric.result().numpy()
# Log the epoch loss for WANDB
run.log({'epoch_loss':epoch_loss, 'epoch':epoch})
# `on_epoch_end` has to be called so that
# we can send the logs to the `oracle` which handles the
# tuning.
self.on_epoch_end(trial, model, epoch, logs={'loss': epoch_loss})
epoch_loss_metric.reset_states()
# Finish the wandb run
run.finish()
결론
빠르게 notebook을 살펴보고 스스로 우수한 툴을 사용해 보시는 것을 독자분들께 권하고 싶습니다. 다음에 참조하기 위해 keras-tuner
에 대한 훌륭한 문서를 읽어보실 수 있습니다.
초매개변수 조정이라는 주제는 너무 광범위하게 연구되고 있어 많은 사람들은 또한 유전 알고리즘(genetic algorithm) 통합을 시도했었으며 우리 생물과 유사한 모델 진화 개념을 사용했습니다. 주제에서는 벗어난 이야기지만 관심 있는 독자분들은 hyperparameter tuning with Genetic Algorithm(유전 알고리즘을 통한 초매개변수 조정개념 해체를 다루고 있는 제기사를 살펴보시기 바랍니다.
Twitter @ariG23498로 연락해주시기 바랍니다.