본문 바로가기
인공지능(AI)/머신러닝

[핸즈온 머신러닝] 10장 케라스를 사용한 인공 신경망 소개

by hyezzisss 2022. 2. 14.

1. 생물학적 뉴런에서 인공 뉴런까지


3) 퍼셉트론

  • TLU 또는 LTU라고 불리는 조금 다른 형태의 인공 뉴런을 기반으로 함
  • TLU는 입력의 가중치 합을 계산 한 뒤 계산된 합에 계단 함수를 적용하여 결과를 출력
    • 퍼셉트론에서 가장 널리 사용되는 계단 함수는 헤비사이드 계단 함수
  • 퍼셉트론은 하나의 TLU로 구성되며 한 층에 있는 모든 뉴런이 이전 층의 모든 뉴런과 연결되어 있을 때 완전 연결 층 또는 밀집 층이라고 함
  • 입력층은 모두 입력 뉴런으로 구성되며 편향 특성이 더해짐
  • 잘못된 예측을 하는 모든 출력 뉴렁네 대해 올바른 예측을 만들 수 있도록 입력에 연결된 가중치를 강화시키면서 훈련됨
# 분꽃 데이터 사용
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import Perceptron

iris = load_iris()
X = iris.data[:, (2, 3)] # 꽃잎의 길이와 너비
y = (iris.target == 0).astype(np.int) # 부채분꽃인가?

per_clf = Perceptron()
per_clf.fit(X, y)
y_pred = per_clf.predict([2, 0.5])
  • 사이킷런의 Perceptron 클래스의 매개변수 -> 아래와 같은 SGDClassifier와 같음
    • loss = "perceptron"
    • learning_rate = "constrant"
    • eta0 = 1 (학습률)
    • penalty=None (규제 없음)
  • 퍼셉트론을 여러 개 쌓아 올리면 일부 제약을 줄일 수 있다는 사실이 밝혀짐 이를 다층 퍼셉트론이라고 함

4) 다층 퍼셉트론과 역전파

  • 다층 퍼셉트론은 입력층 하나와 은닉층이라 불리는 하나 이상의 TLU층과 마지막 출력층으로 구성됨
  • 입력층과 가까운 층을 보통 하위 층, 출력에 가까운 층을 상위 층이라고 함
  • 은닉층을 여러 개 쌓아 올린 인공 신경망을 심층 신경망이라고 함
    • 은닉층의 연결 가중치를 랜덤하게 초기화하는 것이 중요
  • 알고리즘 
    • 각 훈련 샘플에 대해 역전파 알고리즘이 먼저 예측을 만듦 (정방향 계산)
    • 역방향으로 각 층을 거치면서 각 연결이 오차에 기여한 정도를 측정 (역방향 계산)
    • 이 오차가 감소하도록 가중치 조정 (경사 하강법)
  • 널리 쓰이는 활성화 함수
    • 하이퍼볼릭 탄젠트 함수 : 출력 범위는 -1 ~ 1
    • ReLU 함수 : 연속적이지만 z=0에서 미분 불가능, 출력에 최댓값이 없음

  • 활성화 함수가 필요한 이유
    • 선형 변환을 여러 개 연결해도 얻을 수 있는 것은 선형 변환뿐임
    • 따라서 층 사이에 비선형성을 추가하지 않으면 아무리 층을 많이 쌓아도 하나의 층과 동일해짐

5) 회귀를 위한 다층 퍼셉트론

  • 일반적으로 회귀용 다층 퍼셉트론을 만들 때 출력 뉴런에 활성화 함수를 사용하지 않고 어떤 범위의 값도 출력되도록 함
  • 이용하는 활성화 함수
    • 출력이 항상 양수여야 한다면 ReLU 또는 softplus
    • 어떤 범위 안의 값을 예측하고 싶다면 로지스틱 함수나 하이퍼볼릭 탄젠트 함수
  • 훈련에 사용하는 손실 함수는 전형적으로 평균 제곱 오차 but 이상치가 많다면 평균 절댓값 오차 또는 이 둘을 조합한 후버 손실 사용
  • 아래 표는 회귀 MLP의 전형적인 구조
하이퍼파라미터 일반적인 값
입력 뉴런 수 특성마다 하나
은닉층 수 일반적으로 1 ~ 5
은닉층의 뉴런 수 일반적으로 10 ~ 100
출력 뉴런 수 예측 차원마다 하나
은닉층의 활성화 함수 ReLU 또는 SELU
출력층의 활성화 함수 없음 (출력이 양수일 때)
ReLU/softplus나 (출력을 특정 범위로 제한할 때) Logstic/tanh를 사용
손실 함수 MSE나 (이상치가 있다면) MAE/Huber

6) 분류를 위한 다층 퍼셉트론

  • 이진 분류의 경우 로지스틱 활성화 함수를 가진 하나의 출력 뉴런만 필요 -> 출력은 0 ~ 1 사이의 실수
  • 다중 분류의 경우 클래스마다 하나의 출력 뉴런이 필요 -> 출력층에는 소프트맥스 활성화 함수를 사용
    • 소프트 맥스 함수는 모든 예측 확률을 0과 1 사이로 만들고 더했을 때 1이 되도록 만듦
  • 분류 MLP의 전형적인 구조
하이퍼파라미터 이진 분류 다중 레이블 분류 다중 분류
입력층과 은닉층 회귀와 동일 회귀와 동일 회귀와 동일
출력 뉴런 수 1개 레이블마다 1개 클래스마다 1개
출력층의 활성화 함수 로지스틱 함수 로지스틱 함수 소프트맥스 함수
손실 함수 크로스 엔트로피 크로스 엔트로피 크로스 엔트로피

2. 케라스로 다층 퍼셉트론 구현하기


# 2개의 은닉층으로 이루어진 분류용 다층 퍼셉트론
model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=[28, 28])
model.add(keras.layers.Dense(300, activation="relu"))
model.add(keras.layers.Dense(100, activation="relu"))
model.add(kears.layers.Dense(10, activation="softmax"))
# 층을 하나씩 추가하지 않고 Sequential 모델을 만들 때 층의 리스트 전달 가능
model = keras.models.Flatten(input_shape=[28, 28]),
	keras.layers.Dense(300, activation="relu"),
    keras.layers.Dense(100, activation="relu"),
    keras.layers.Dense(10, activation="softmax")
])

model.summary()
  • Dense 층은 연결 가중치를 무작위로 초기화하며 편향은 0으로 초기화

모델 컴파일

  • compile() 메서드를 호출하여 사용할 손실 함수와 옵티마이저를 지정해야 함
model.compile(loss="sparse_categorical_crossentropy",
        	optimizer="sgd",
            	metrics=["accuracy"])
  • label이 0~9까지 클래스 인덱스 하나가 있는 경우에는 "sparse_categorical_crossentropy"
  • 샘플마다 클래스별 타깃 확률 즉 원-핫 벡터라면 "categorical_crossenetropy"
  • 이진 분류나 다중 레이블 이진 분류를 수행한다면 출력층에 softmax 대신 sigmoid를 사용하고 binary_crossentropy 손실 사용

모델 훈련과 평가

history = model.fit(X_train, y_train, epochs=30,
			validation_data=(X_valid, y_valid))
  • 케라스는 에포크가 끝날 때마다 검증 세트를 사용해 손실과 추가적인 측정 지표 계산
model.evaluate(X_test, y_test)

3) 시퀀셜 API를 사용하여 회귀용 다층 퍼셉트론 만들기

 Scaler = StandardScaler()
 X_train = scaler.fit_transform(X_train)
 X_valid = scaler.transform(X_valid)
 X_test = scaler.transform(X_test)
 
 model = keras.models.Sequential([
 	keras.layers.Dense(30, activation="relu", input_shape=X_train.shape[1:]),
    keras.layers.Dense(1)
])

model.compile(loss="mean_squared_error", optimizer="sgd")
history = model.fit(X_train, y_train, epochs=20,
					validation_data=(X_valid, y_valid)

mse_test = model.evaluate(X_test, y_test)
y_pred = model.predict(X_new)
  • 분류와 비슷하며 주된 차이점은 출력층이 활성화 함수가 없는 하나의 뉴런을 가진다는 점과 손실 함수로 평균 제곱 오차를 사용

6) 모델 저장과 복원

model.save("my_keras_model.h5")
model = keras.model.load_model("my_keras_model.h5")

7) 콜백 사용하기

  • 훈련이 오래 걸리는 경우 훈련 도중 일정 간격으로 체크포인트를 저장해야 하며 콜백을 사용하여 fit() 메서드에서 저장
  • save_best_only=True로 지정할 경우 최상의 검증 세트 점수에만 모델을 저장
checkpoint_cb = keras.callbacks.ModelCheckpoint("my_keras_model.h5",
						save_best_only=True)
# 일정 에포크 동안 점수가 향상되지 않으면 훈련 멈추기
# early_stopping_cb = keras.callbacks.ModelCheckpoint(patience=10, restore_best_weight=True)
history = model.fit(X_train, y_train, epochs=10,
			validation_data=(X_valid, y_valid),
                    callbacks=[checkpoint_cb])
model = keras.models.load_model("my_keras_model.h5") # 최상의 모델로 복원

8) 텐서보드를 사용해 시각화하기

import os
root_logdir = os.path.join(os.curdir, "my_logs")

def get_run_logdir():
	import time
    run_id = time.strftime("run_%Y_%m_%d-%H_%M_%S")
    return os.path.join(root_logdir, run_id)
    
run_logdir = get_run_logdir()

tensorboard_cb = keras.callbacks.TensorBoard(run_logdir)
history = model.fit(X_train, y_train, epochs=30,
			validation_data=(X_valid, y_valid),
                    callbacks=[tensorboard_cb])
  • tensorboard --logdir=./my_logs --port=6006

3. 신경망 하이퍼파라미터 튜닝하기


  • 많은 조합 시도해보고 어떤 것이 검증 세트에서 가장 좋은 점수를 내는지 확인하기
    • GridSearchCV나 RandomizedSearchCV 사용
  • 하이퍼파라미터 되적화에 사용할 수 있는 파이썬 라이브러리 들
    • Hyperopt : 모든 종류의 복잡한 탐색 공간에 대해 최적화 수행
    • Hyperas, kopt, Talos : 케라스 모델을 위한 하이퍼파라미터 최적화 라이브러리
    • 케라스 튜너 
    • Scikit-Optimize : 범용 최적화 라이브러리
    • Spearmint : 베이즈 최적화 라이브러리
    • Hyperband : 빠른 하이퍼파라미터 튜닝 라이브러리
    • Sklearn-Deap

1) 은닉층 개수

  • 복잡한 문제의 경우 심층 신경망이 얕은 신경망보다 파라미터 효율성이 좋음
  • 전이 학습 : 네트워크의 하위 층을 재사용하여 고수준 구조만 학습

2) 은닉층의 뉴런 개수

  • 일반적으로 각 층의 뉴런을 점점 줄여서 깔때기처럼 구성
    • 저수준의 많은 특성이 고수준의 적은 특성으로 합쳐질 수 있기 때문'
    • 요즘 대부분의 경우 모든 은닉층에 같은 크기를 사용해도 동일하거나 더 나은 성능을 냄
    • 데이터셋에 따라 다르지만 다른 은닉층 보다 첫 번째 은닉층을 크게 하는 것이 도움이 됨
  • 네트워크가 과대적합이 되기 전까지 점진적으로 뉴런 수를 늘릴 수 있음
    • 실전에서는 필요보다 더 많은 층과 뉴런을 가진 모델을 선택하고 과대 적합되지 않도록 조기 종료나 규제 기법 사용하는 것이 간단하고 효과적 -> 스트레치 팬츠 방식
  • 일반적으로 층이 뉴런 수보다 층 수를 늘리는 쪽이 이득이 많음

3) 학습률, 배치 크기 그리고 다른 하이퍼파라미터

학습률

  • 일반적으로 최적의 학습률은 최대 학습률의 ㅈ러반 정도
  • 매우 낮은 학습률(10^-5)에서 점진적으로 매우 큰 학습률(10)까지 수백 번 반복하여 모델 훈련

옵티마이저

  • 미니배치 경사 하강법보다 더 좋은 옵티마이저를 선택하는 것도 매우 중요

배치 크기

  • 모델 성능과 훈련 시간에 큰 영향을 미침
  • 큰 배치 크기의 장점
    • GPU와 같은 하드웨어 가속기 효율적 활용 가능 -> 훈련 알고리즘이 초당 더 많은 샘플 처리 가능
    • GPU 램에 맞는 가장 큰 배치 크기 사용하라고 권장
  • 큰 배치 크기 단점
    • 훈련 초기 종종 불안정하게 훈련됨
    • 작은 배치 크기로 훈련된 모델만큼 일반화 성능 못 낼 수도 있음
  • 따라서 학습률 예열(작은 학습률로 시작해 점점 커지기)을 사용해 큰 배치 크기를 시도해보고 불안정하거나 최종 성능이 만족스럽지 않으면 작은 배치 크기 사용

활성화 함수

  • 일반적으로 ReLU가 모든 은닉층에 좋은 기본값
  • 출력층은 수행하는 작업에 따라 달라짐

반복 횟수

  • 대부분의 경우 반복 횟수는 튜닝할 필요 없으며 조기 종료 사용

 

 

댓글