인공 신경망
퍼셉트론(perceptron), 다층 퍼셉트론 (MLP)
이전 내용
신경망 하이퍼파라미터 튜닝하기
신경망의 유연성은 조정할 하이퍼파라미터가 많기 때문에 단점이 될 수도 있다.
복잡한 네트워크 구조에서뿐만 아니라 기본적인 다층 퍼셉트론에서도 층의 개수, 층마다 있는 뉴런의 개수, 각 층에서 사용하는 활성화 함수, 가중치 초기화 전략, 사용할 옵티마이저, 학습률, 배치 크기 등 많은 것을 바꿀 수 있다.
[최적의 하이퍼파라미터 조합 찾는 법]
1. 케라스 모델을 사이킷런 추정기로 변환한 다음, GridSearchCV 또는 RandomizedSearchCV를 사용하여 하이퍼파라미터 미세 튜닝
▶ SciKeras 라이브러리의 KerasRegressor와 KerasClassifier 래퍼 클래스를 사용할 수 있다.
하단의 링크는 SciKeras 0.13.0 사용에 관한 자세한 설명이 담겨 있는 페이지이다.
2. 케라스 튜너 라이브러리 사용
▶ 케라스 튜너: 케라스 모델을 위한 하이퍼파라미터 튜닝 라이브러리. 이 라이브러리는 여러 가지 튜닝 전략을 제공하며, 사용자 정의가 가능하고, 텐서보드와의 통합이 뛰어나다.
케라스 튜너 라이브러리를 사용한 하이퍼파라미터 미세 튜닝
케라스 튜너 소개 링크
◆ 케라스 튜너 설치 및 실행 하기 (주피터 노트북) - feat. 패션MNIST 데이터셋
import tensorflow as tf
from tensorflow import keras
!pip install -q -U keras-tuner
import kerastuner as kt
여기서는 패션 MNIST 데이터셋을 사용하여 케라스 튜너를 실습해본다.
먼저, 패션MNIST 데이터셋을 로드하고, 훈련 데이터와 검증 데이터를 분류한다.
fashion_mnist = tf.keras.datasets.fashion_mnist.load_data()
(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist
X_train, y_train = X_train_full[:-5000], y_train_full[:-5000]
X_valid, y_valid = X_train_full[-5000:], y_train_full[-5000:]
◆ 케라스 모델을 구축, 컴파일하여 반환하는 함수 작성
이 함수는 kt.HyperParameters 객체를 매개변수로 받는다. 이를 사용해 하이퍼파라미터와 함께 가능한 값의 범위를 정의할 수 있고, 이러한 하이퍼파라미터를 사용해 모델을 만들고 컴파일할 수 있다.
아래는 은닉 층의 수(n_hidden), 각 층의 뉴런 수(n_neurons), 학습률(learning_rate), 사용할 옵티마이저(optimizer) 등의 하이퍼파라미터를 사용하여 패션 MNIST 이미지를 분류하기 위한 MLP를 만들고 컴파일한다.
import keras_tuner as kt
def build_model(hp):
n_hidden = hp.Int('n_hidden', min_value=0, max_value=8, default=2)
n_neurons = hp.Int('n_neurons', min_value=16, max_value=256)
learning_rate = hp.Float('learning_rate', min_value=1e-4, max_value=1e-2, sampling='log')
optimizer = hp.Choice('optimizer', values=['sgd', 'adam'])
if optimizer == 'sgd':
optimizer = tf.keras.optimizers.SGD(learning_rate=learning_rate)
else:
optmizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten())
for _ in range(n_hidden):
model.add(tf.keras.layers.Dense(n_neurons, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
return model
[코드 설명]
- 하이퍼파라미터 정의(은닉 층, 뉴런 수): 예를 들어 hp.Int('n_hidden', min_value=0, max_value=8, default=2 는 n_hidden 이라는 하이퍼파라미터가 Hyper Parameters 객체 hp에 있는지 확인하고, 있다면 그 값을 반환한다. 그렇지 않은 경우 가능한 값의 범위가 0에서 8포함인 'n_hidden' 이라는 새로운 정수 하이퍼 파라미터를 등록하고 기본값 2를 반환한다. (기본값 미설정 시, min_value 반환) *n_neurons 역시 비슷한 방식으로 등록
- 하이퍼파라미터 정의 (학습률): learning_rate 하이퍼 파라미터는 10^-4 ~ 10^-2 범위의 실수로 등록되며, sampling=log 이므로, 모든 범위에서 학습률이 동일하게 샘플링
- 하이퍼파라미터 정의(optimizer): 'sgd' 또는 'adam'으로 등록되며, 기본값은 첫 번째 값인 'sgd'. optimizer 값에 따라 주어진 학습률을 가진 SGD 옵티마이저 또는 Adam 옵티마이저 생성
- 하이퍼파라미터를 사용한 모델 구축: Flatten 층으로 시작하여 Sequential 모델을 생성한 다음, 요청된 수 (n_hidden)만큼 ReLU 활성화 함수를 사용하는 은닉 층을 만들고, 소프트맥스 활성화 함수와 10개의 뉴런 (클래스 당 1개)이 있는 출력 층 생성
- 모델을 컴파일하고 반환
◆ 기본적인 랜덤 서치 수행
기본적인 랜덤 서치를 수행하려면 kt.RandomSearch 튜너를 만들고 build_model 함수를 생성자에 전달한 후 튜너의 search() 메서드를 호출하면 된다.
random_search_tuner = kt.RandomSearch(
build_model, objective='val_accuracy', max_trials=5, overwrite=True,
directory='my_fasion_mnist', project_name='my_rnd_search', seed=42)
random_search_tuner.search(X_train, y_train, epochs=10,
validation_data=(X_valid, y_valid))
▶ RandomSearch 튜너는 먼저 모든 하이퍼파라미터 사양을 수집하기 위해 빈 Hyperparameters 객체로 build_model()을 한 번 호출하고, 5번을 시도(max_trials=5)한다. 각 시도마다 해당 범위 내에서 랜덤하게 샘플링된 하이퍼파라미터를 사용하여 모델을 만든 다음, 해당 모델을 10 에포크 동안 훈련하고 my_fashion_mnist/my_rnd_search 디렉터리의 서브 디렉터리에 저장한다.
overwrite=True 이므로 훈련이 시작되기 전에 my_rnd_search 디렉터리가 삭제된다.
(overwrite=False, max_trails=10 으로 두 번째 실행하면 튜너가 중단한 지점부터 계속 튜닝하여 5번 더 실행된다.)
objective='val_accuracy' 로 설정되어 있으므로 튜너는 검증 정확도가 높은 모델을 선호하고 따라서 튜너가 검색을 완료하면 이에 해당하는 최상의 모델을 얻을 수 있다.
top3_models = random_search_tuner.get_best_models(num_models=3)
best_model = top3_models[0]
print(top3_models)
print(best_model)
또한, get_best_hyperparameters() 를 호출하여 최상의 모델의 kt.HyperParameters를 얻을 수 있다.
top3_params = random_search_tuner.get_best_hyperparameters(num_trials=3)
best_params = top3_params[0] # 첫 번째 하이퍼파라미터 객체 가져오기
best_params.values # 하이퍼파라미터 값을 딕셔너리 형태로 출력
각 튜너는 오라클의 안내를 받는데, 오라클의 정의는 아래와 같다.
※ 오라클(Oracle)의 정의
오라클은 주로 머신러닝 튜너(tuner)나 하이퍼파라미터 최적화에서 사용되는 개념으로, 다음과 같은 역할을 한다
1. 하이퍼파라미터 검색 전략: 오라클은 하이퍼파라미터의 검색 및 선택 과정을 규정하는 역할을 한다. 이는 어떤 하이퍼파라미터 조합이 시도될지, 그리고 각 조합이 평가되는 방식을 관리한다.
2. 의사결정 과정: 오라클은 이전의 시도 결과를 바탕으로, 다음에 어떤 하이퍼파라미터 조합을 시험할지 결정한다. 이를 통해 모델 성능을 최적화하기 위해 하이퍼파라미터를 효율적으로 탐색한다.
3. 평가 및 피드백: 오라클은 각 하이퍼파라미터 조합에 대한 평가 결과를 모니터링하고, 이 정보를 바탕으로 다음 탐색 단계를 조절한다.
구체적으로 Keras Tuner 라이브러리 관점에서 오라클은 하이퍼파라미터 검색 방법을 정의하는 객체로, 랜덤 서치, 베이지안 옵티마이제이션, 하이퍼밴드 등 다양한 검색 전략을 사용하여 최적의 하이퍼파라미터를 찾도록 한다.
예를 들어, RandomSearch 오라클은 랜덤하게 하이퍼파라미터 조합을 시도하며, BayesianOptimization 오라클은 이전의 평가 결과들을 바탕으로 더 유망한 하이퍼파라미터 조합을 선택한다.
튜너는 각 시도 전에 오라클에 다음 시도가 무엇인지 알려달라고 요청한다. 오라클은 모든 시도를 기록하기 때문에 최상의 시도를 요청하여 해당 시도의 요약을 출력할 수 있다.
best_trial = random_search_tuner.oracle.get_best_trials(num_trials=1)[0]
best_trial.summary()
물론, 모든 측정 지표에 직접 액세스할 수도 있다.
best_trial.metrics.get_last_value('val_accuracy')
최상의 모델 성능이 만족스럽다면 전체 훈련 세트 (X_train_full 와 y_train_full)에서 몇 번의 에포크 동안 이어서 훈련한 다음 테스트 세트에서 평가하고 제품에 배포할 수 있다.
best_model.fit(X_train_full, y_train_full, epochs=10)
test_loss, test_accuracy = best_model.evaluate(X_test, y_test)
◆ model.fit() 매개변수를 미세 튜닝 (하이퍼밴드 튜너)
경우에 따라 데이터 전처리 하이퍼파라미터 또는 배치 크기와 같은 model.fit() 매개변수를 미세 튜닝해야 할 수도 있는데, 이를 위해서는 약간 다른 기법을 사용해야 한다.
build_model() 함수를 작성하는 대신 kt.HyperModel 클래스의 서브클래스를 만들고 build()와 fit() 메서드 두 개를 정의해야 한다.
- build() 메서드: build_model() 함수와 동일한 작업 수행
- fit() 메서드: HyperParameters 객체와 컴파일된 모델, model.fit() 의 모든 매개변수를 인수로 받아 모델을 훈련하고 History 객체 반환. 하이퍼파라미터를 사용하여 데이터 전처리 방법과 배치 크기 등을 결정할 수 있음.
아래의 예는 동일한 하이퍼파라미터를 사용하여 이전과 동일한 모델을 만들지만 불리언 타입의 normalize 하이퍼파라미터를 사용해 모델을 훈련하기 전에 훈련 데이터를 표준화할지 여부를 제어하는 클래스이다.
class MyClassificationHyperModel(kt.HyperModel):
def build(self, hp):
return build_model(hp)
def fit(self, hp, model, X, y, **kwargs):
if hp.Boolean('normalize'):
norm_layer = tf.keras.layers.Normalization()
X = norm_layer(X)
return model.fit(X, y, **kwargs)
그런 다음 build_model() 함수 대신 이 클래스의 객체를 원하는 튜너에 전달할 수 있다.
예를 들어 MyClassificationHyperModel 객체를 기반으로 kt.Hyperband 튜너를 만들어 본다.
hyperband_tuner = kt.Hyperband(
MyClassificationHyperModel(), objective='val_accuracy', seed=42,
max_epochs=10, factor=3, hyperband_iterations=2,
overwrite=True, directory='my_fashion_mnist', project_name='hyperband')
▶ 이 튜너는 먼저 몇 번의 에포크 동안 여러 모델을 훈련한 다음,
- 최악의 모델을 제거하고 상위 1/Factor 모델만 남긴다(여기서는 factor=3 이므로, 1/3). 이 선택 과정을 단일 모델이 남을 때까지 반복한다.
- max_epochs 매개변수는 최상의 모델을 훈련할 최대 에포크 수를 지정한다. (hyperband_iterations=2 이므로, 과정이 두 번 반복 됨)
- 각 하이퍼밴드 반복에서 전체 모델의 총 훈련 에포크 수는 max_epochs * (log(max_epochs) / log(factor)) ** 2 이다.
이제 하이퍼밴드 튜너를 실행해 본다.
이번에는 루트 로그 디렉터리(튜너가 각 시도마다 다른 서브디렉터리 사용)를 지정한 텐서보드 콜백과 조기 종료 콜백 사용.
from pathlib import Path
from time import strftime
root_logdir = Path(hyperband_tuner.project_dir) / "tensorboard"
tensorboard_cb = tf.keras.callbacks.TensorBoard(root_logdir)
early_stopping_cb = tf.keras.callbacks.EarlyStopping(patience=2)
hyperband_tuner.search(X_train, y_train, epochs=10,
validation_data=(X_valid, y_valid),
callbacks=[early_stopping_cb, tensorboard_cb])
▶ 이제 텐서보드를 실행할 때 --logdir로 my_fashion_mnist/hyperband/tensorboard 디렉터리를 지정하면 모든 시도의 결과를 확인할 수 있다.
◆ BayesianOptimization 튜너
하이퍼밴드는 리소스를 할당하는 방식에서 순수 랜덤 검색보다 더 똑똑하지만 여전히 하이퍼파라미터 공간을 랜덤으로 탐색하는 방식을 사용한다. 따라서 빠르지만 듬성듬성하다는 단점이 있다.
케라스 튜너에는 kt.BayesianOptimization 튜너도 포함되어 있는데, 이 알고리즘은 가우스 과정이라는 확률 모델을 적용하여 하이퍼파라미터 공간의 어느 영역이 가장 유망한지 점진적으로 학습한다. 이를 통해 최적의 하이퍼파라미터를 점진적으로 찾아갈 수 있다.
단점은 알고리즘에 자체 하이퍼파라미터가 있다는 것인데,
- alpha: 여러 번의 시도에 걸친 성능 측정에서 예상되는 잡음 수준
- beta: 하이퍼파라미터 공간에서 알려진 좋은 영역을 단순히 활용하는 대신 알고리즘이 얼마나 공간을 탐색할지 지정
그 외에는 이전 튜너와 동일하게 사용할 수 있다.
bayesian_opt_tuner = kt.BayesianOptimization(
MyClassificationHyperModel(), objective="val_accuracy", seed=42,
max_trials=10, alpha=1e-4, beta=2.6,
overwrite=True, directory="my_fashion_mnist", project_name="bayesian_opt")
bayesian_opt_tuner.search(X_train, y_train, epochs=10,
validation_data=(X_valid, y_valid),
callbacks=[early_stopping_cb])
%tensorboard --logdir=my_fashion_mnist/hyperband/tensorboard
★ 텐서보드 사용 후 종료하기!
# Windows 환경에 적합한 명령어로 TensorBoard 프로세스 찾기
!tasklist | findstr tensorboard
이 명령어는 현재 실행 중인 모든 프로세스 중 'tensorboard'를 포함하는 프로세스를 찾는다. 명령어 출력에서 PID(프로세스 ID)를 확인할 수 있다. (Console 앞에 있는 숫자)
TensorBoard 프로세스 종료: 아래와 같이 특정 PID를 활용하여 프로세스를 종료한다.
PID 뒤에 위에서 확인했던 Console 앞 숫자를 넣어준다.
!taskkill /PID 19608 /F
!taskkill /PID 28152 /F
최적의 하이퍼파라미터 선택 가이드라인
다음은 신속한 프로토타입을 만들고 탐색 공간을 제한하기 위해 각 하이퍼파라미터에 어떤 값이 적절한지 선택하는 가이드라인이다.
◆ 은닉 층의 개수 및 뉴런 개수
은닉 층의 개수와 각 층의 뉴런 수는 주어진 문제에 따라 다르며, 다음과 같은 일반적인 원칙을 따를 수 있다.
- 단층 퍼셉트론 (Single-layer perceptron): 단순한 문제(선형적으로 구분 가능한 문제)에 적합합니다.
- 다층 퍼셉트론 (Multi-layer perceptron, MLP): 비선형 문제를 해결하는 데 사용됩니다. 한 층 이상의 은닉 층을 포함합니다.
[방법론]
1. 작게 시작하고 점진적으로 늘리기:
- 처음에는 한 개의 은닉 층과 적당한 수의 뉴런으로 모델을 시작한다 (예: 32, 64, 128).
- 모델의 성능을 평가하면서 필요한 경우 은닉 층과 뉴런 수를 점진적으로 늘린다.
2. Heuristic approaches:
- 입력 데이터의 복잡성에 따라 은닉 층과 뉴런 수를 결정한다. 데이터가 복잡할수록 더 많은 은닉 층과 뉴런이 필요할 수 있다.
3.과적합 방지:
- 너무 많은 뉴런과 층을 사용하면 모델이 과적합될 수 있으므로, 교차 검증 또는 정규화를 통해 모델의 성능을 지속적으로 평가하며 조정한다.
◆ 주요 하이퍼파라미터 선택
다음은 주요 하이퍼파라미터와 이들의 좋은 값을 찾는 방법이다.
1. 학습률 (Learning Rate)
- 기본값: 보통 0.01 또는 0.001로 시작.
- 조정 방법:
- 작은 값을 사용하여 점진적으로 최적값에 도달하도록 함.
- 필요한 경우 학습률 스케줄러(ex: ReduceLROnPlateau)를 사용하여 학습률을 동적으로 조절.
2. 배치 크기 (Batch Size)
- 기본값: 보통 32, 64 또는 128의 값을 사용.
-조정 방법:
- 작은 배치 크기(예: 32)는 더 많은 업데이트로 더 세밀한 학습을 제공하지만 느릴 수 있다.
- 큰 배치 크기(예: 128)는 더 빠르지만 메모리 소요가 클 수 있다.
- 주어진 하드웨어 환경과 데이터셋 크기를 고려하여 적절한 배치 크기를 선택.
3. 옵티마이저 (Optimizer)
- 기본 선택:
- Adam: 대부분의 경우 기본 선택.
- SGD (Stochastic Gradient Descent): 학습률과 모멘텀을 사용하여 더 나은 최적화를 제공.
- RMSprop: 강력한 대안이며 특히 RNN에서 좋은 성능을 보임.
- 조정 방법:
- 기본적으로 Adam을 사용하고, 필요한 경우 다른 옵티마이저를 시도.
4. 활성화 함수 (Activation Function)
- 기본 선택:
- ReLU (Rectified Linear Unit): 대부분의 경우 기본 선택.
- Sigmoid: 출력 층에 사용하거나 이진 분류 문제에서 사용.
- Tanh: ReLU 대신 사용할 수 있으며, 출력이 -1에서 1 사이로 제한.
- 조정 방법:
ReLU를 기본으로 사용하고, 필요한 경우 다른 활성화 함수를 시도하며 성능을 평가.
5. 반복 횟수 (Number of Epochs)
- 기본값: 10에서 100 사이로 시작.
- 조정 방법:
- 과적합되지 않도록 조기에 종료 (Early stopping) 메커니즘을 사용.
- 훈련이 정체되는 시점을 확인하고 필요한 반복 횟수를 조절.
◆ 하이퍼파라미터 최적화 전략
1. 그리드 검색 (Grid Search):
여러 하이퍼파라미터의 다양한 조합을 시도하여 최적 조합을 찾는다. 단, 시간이 많이 소요되므로 신중하게 설정하는 것이 좋다.
2. 랜덤 검색 (Random Search):
무작위로 조합을 시도하여 특정 범위 내에 최적값을 찾는다. 그리드 검색보다 계산 비용이 낮다.
3. 베이지안 최적화 (Bayesian Optimization):
이전 결과를 바탕으로 다음 후보를 선택하여 효율적으로 최적 하이퍼파라미터를 찾는다.
다음 내용
[출처]
핸즈 온 머신러닝
'[파이썬 Projects] > <파이썬 딥러닝, 신경망>' 카테고리의 다른 글
[딥러닝] 심층 신경망 훈련 - 2 (2) | 2024.11.24 |
---|---|
[딥러닝] 심층 신경망 훈련 - 1 (0) | 2024.11.23 |
[딥러닝] 케라스로 다층 퍼셉트론 구현하기 - 3 (1) | 2024.11.20 |
[딥러닝] 케라스로 다층 퍼셉트론 구현하기 - 2 (0) | 2024.11.20 |
[딥러닝] 케라스로 다층 퍼셉트론 구현하기 - 1 (0) | 2024.11.19 |