[Hands-On ML] 10장 케라스를 사용한 인공 신경망 소개(2)
“핸즈온 머신러닝”의 “10장 케라스를 사용한 인공신경망 소개” 파트를 읽고 공부한 내용을 정리해보았다. 케라스로 다층 퍼셉트론을 구현하는 방법을 다뤄볼 것이다.
10.2 케라스로 다층 퍼셉트론 구현하기
-
케라스란
- 모든 종류의 신경망을 손쉽게 만들도록, 훈련, 평가, 실행할 수 있는 고수준 딥러닝 API이다.
10.2.1 텐서플로 2 설치
# 버전 확인
import tensorflow as tf
from tensorflow import keras
tf.__version__, keras.__version__
두 번째 버전이 tf.keras에서 구현된 케라스의 API 버전이다.
10.2.2 시퀀셜 API를 사용하여 이미지 분류기 만들기
케라스를 사용하여 데이터셋 적재하기
# 패션 MNIST 적재하기
fashion_mnist = keras.datasets.fashion_mnist
(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()
# 훈련 세트이 크기와 데이터 타입 확인하기
X_train_full.shape, X_train_full.dtype
# 검증 데이터 셋 만들기
# 입력 데이터의 스케일 조정: 픽셀 강도를 255.0으로 나누어 0~1 사이 범위로 조정한다.
X_valid, X_train = X_train_full[:5000] / 255.0, X_train_full[5000:] / 255.0
y_valid, y_train = y_train_full[:5000], y_train_full[5000:]
X_test = X_test / 255.0
# 레이블에 해당하는 아이템 나타내기 위해 클래스 이름의 리스트 만들기
class_names = ["T-shirt", "Trouser", "Pullover", "Dress", "Coat", "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"]
class_names[y_train[0]]
시퀀셜 API를 사용하여 모델 만들기
# 두 개의 은닉층으로 이루어진 분류용 다층 퍼셉트론
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(keras.layers.Dense(10, activation='softmax'))
코드 설명
-
첫 번째 라인은 Sequential 모델을 만든다. 순서대로 연결된 층을 일렬로 쌓아서 구성한다. (Sequential API)
-
첫 번째 층을 만들고 모델에 추가한다. Flatten 층은 입력 이미지를 1차원 배열로 변환한다. 모델의 첫번 째 층이므로 input_shape을 지정해야한다.
-
뉴런 300개를 가진 Dense 은닉층을 추가한다. ReLU 활성화 함수를 사용한다.
-
뉴런 100개를 가진 두 번째 Dense 은닉층을 추가한다. ReLU 활성화 함수 사용한다.
-
마지막 층인 뉴런 10개를 가진 Dense 출력층을 추가한다. 소프트맥스 활성화 함수를 사용한다.
# 위의 코드와 다른 버전
model = keras.models.Sequential([
keras.layers.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()
-
첫번째 은닉층은 784x300개의 연결 가중치와 300개의 편향을 가진다. 즉 235500의 파라미터가 생성된다.
-
이때 훈련 데이터가 많지 않은 경우, 과대 적합의 위험을 가진다.
# 모델에 있는 층을 리스트로 출력하거나 인덱스로 층을 선택할 수 있다.
model.layers
hidden1 = model.layers[1]
hidden1
hidden1.name
model.get_layer('dense_3') is hidden1
# 층의 모든 파라미터에 접근해보자
weights, biases = hidden1.get_weights()
weights, biases
weights.shape, biases.shape
-
Dense 층은 연결 가중치를 무작위로 초기화하고, 편향은 0으로 초기화한다.
-
다른 초기화 방법은 11장에서 다루도록 한다.
모델 컴파일
-
모델을 만든 후 사용할 손실 함수와 옵티마이저를 지정해야한다.
-
또한 훈련과 평가 시에 계산할 지표를 추가로 지정할 수 있다.
model.compile(loss='sparse_categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
코드 설명
-
레이블이 정수 하나로 이루어져 있고, 클래스가 배타적일 때 “sparse_categorical_crossentropy” 손실을 사용한다.
-
샘플마다 클래스별 타깃 확률을 가지고 있다면 “categorical_crossentropy” 손실을 사용해야한다.
-
옵티마이저에 “sgd”를 지정하면 경사하강법을 이용하여 모델을 훈련한다는 의미이다. 즉, 역전파 알고리즘을 수행한다. 11장에서 더 효율적인 옵티마이저를 다뤄보자
모델 훈련과 평가
history = model.fit(X_train, y_train, epochs=30,
validation_data = (X_valid, y_valid))
-
케라스는 에포크가 끝날 때마다 검증 세트를 사용해 손실과 추가적인 측정 지표를 계산한다.
-
훈련 세트 성능이 검증 세트보다 월등히 높다면 모델이 과대적합되었을 것이다.
TIP
-
validation_data 매개변수에 검증 세트를 전달하는 대신 케라스가 검증에 사용할 훈련 세트의 비율을 지정할 수 있다.
-
validation_split=0.1로 쓰면 케라스는 섞기 전 훈련 데이터의 마지막 10%를 사용한다.
가중치 부여
-
훈련 세트의 클래스가 편중되어 있다면 fit() 메서드를 호출할 때 class_weigth 매개변수를 지정하는 것이 좋다.
- 적게 등장하는 클래스는 높은 가중치를 부여하고, 많이 등장하는 클래스는 낮은 가중치를 부여한다.
-
샘플별로 가중치를 부여하고 싶다면 sample_weight 매개변수를 지정한다.
History 객체
-
훈련 파라미터(history.params), 수행된 에포크(history.epoch)가 포함된다.
-
딕셔너리 속성(history.history)
-
훈련 세트와 검증 세트에 대한 손실과 측정한 지표를 담은 속성
-
이 딕셔너리를 이용해 판다스 데이터 프레임을 만들고 plot() 메서드를 호출해서 학습 곡선을 볼 수 있다.
-
import pandas as pd
import matplotlib.pyplot as plt
pd.DataFrame(history.history).plot(figsize=(8, 5))
plt.grid(True)
plt.gca().set_ylim(0, 1) # 수직축의 범위를 0~1 사이로 설정
plt.show()
해석
-
훈련하는 동안 훈련 정확도와 검증 정확도가 꾸준히 상승하는 것을 볼 수 있다.
-
검증 곡선이 훈련 곡선과 가깝다. => 크게 과대적합되지 않았다.
-
훈련 곡선을 볼 때 왼쪽으로 에포크의 절반만큼 이동해서 생각하기
- 검증 손실은 에포크가 끝난 후에 계산되므로 훈련 손실 곡선은 에포크의 절반만큼 왼쪽으로 이동해야한다.
-
검증 손실이 여전히 감소한다면 모델이 완전히 수렴되지 않아 훈련을 계속해야하는 의미이다.
-
모델 성능이 만족스럽지 않으면 처음으로 되돌아가서 하이퍼 파라미터를 튜닝해야한다.
-
학습률 튜닝
-
다른 옵티마이저 테스트해보기
-
다시 1번으로
-
층 개수, 층의 뉴런 개수, 은닉층의 활성화 함수, 배치 크기 등 튜닝
-
-
모델의 성능이 만족스럽다면 테스트 세트로 모델 평가하기
# 모델 평가
model.evaluate(X_test, y_test)
-
테스트 세트에서는 하이퍼파라미터를 튜닝하려는 유혹을 참아야한다!!
-
그렇지 않으면 일반화 오차를 제대로 추정할 수 없다.
모델을 사용해 예측을 만들기
# 새로운 샘플에 대해 예측 만들기
X_new = X_test[:3]
y_proba = model.predict(X_new)
y_proba.round(2)
코드 설명
- 0에서 9까지 클래스마다 각각의 확률을 모델이 추정했다.
# 가장 높은 확률을 가진 클래스만 출력하기
y_pred = model.predict(X_new).argmax(axis=-1)
y_pred
10.2.3 시퀀셜 API를 사용하여 회귀용 다층 퍼셉트론 만들기
캘리포니아 주택 가격 데이터셋 적재하기
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
housing = fetch_california_housing()
X_train_full, X_test, y_train_full, y_test = train_test_split(housing.data, housing.target)
X_train, X_valid, y_train, y_valid = train_test_split(X_train_full, y_train_full)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_valid = scaler.transform(X_valid)
X_test = scaler.transform(X_test)
분류와 차이점
-
출력층이 활성화 함수가 없는 하나의 뉴런을 가진다.
-
손실 함수로 평균 제곱 오차를 사용한다.
# 시퀀셜 API를 이용해 모델 만들기
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)
# 모델 예측하기
X_new = X_test[:3]
y_pred = model.predict(X_new)
결론
-
시퀀셜 API는 사용하기 매우 쉽지만,
-
입력과 출력이 여러 개이거나 더 복잡한 네트워크 토폴로지를 갖는 신경망을 만들어야할 때 함수형(functional) API를 사용한다.
10.2.4 함수형 API를 사용해 복잡한 모델 만들기
순차적이지 않은 신경망 (ex Wide & Deep 신경망)
-
입력의 일부 또는 전체가 출력층에 바로 연결된다.
-
신경망이 복잡한 패턴과 간단한 규칙을 모두 학습할 수 있다.
-
순차적인 신경망 (일반적인 MLP)
- 층 전체에 모든 데이터를 통과시키기 때문에 데이터에 있는 간단한 패턴이 연속된 변환으로 왜곡될 수 있다.
# 위 사진의 신경망 구현해보기
input_ = keras.layers.Input(shape=X_train.shape[1:])
hidden1 = keras.layers.Dense(30, activation='relu')(input_)
hidden2 = keras.layers.Dense(30, activation='relu')(hidden1)
concat = keras.layers.Concatenate()([input_, hidden2])
output = keras.layers.Dense(1)(concat)
model = keras.Model(inputs=[input_], outputs=[output])
코드 해석
-
Input 객체: shape과 dtype을 포함하여 모델의 입력을 정의한다. 여러 개의 입력을 가질 수 있다.
-
30개의 뉴런과 ReLU 활성화 함수를 가진 Dense 층을 만든다. 이 층은 만들어지자마자 입력과 함께 함수처럼 호출된다. (함수형API로 불리는 이유)
-
두 번째 은닉층을 만들고, 함수처럼 호출한다.
-
Concatenate() 함수를 호출하여 두 번째 은닉층의 출력과 입력을 연결한다.
-
하나의 뉴런과 활성화 함수가 없는 출력층을 만들고 Concatenate 층이 만든 결과를 사용해 호출한다.
-
마지막으로 사용할 입력과 출력을 지정하여 케라스 Model을 만든다.
또 다른 신경망
-
일부 특성은 짧은 경로로 전달하고 다른 특성은 깊은 경로로 전달하고 싶다면?
- 여러 입력을 사용하자
input_A = keras.layers.Input(shape=[5], name='wide_input')
input_B = keras.layers.Input(shape=[6], name='deep_input')
hidden1 = keras.layers.Dense(30, activation='relu')(input_B)
hidden2 = keras.layers.Dense(30, activation='relu')(hidden1)
concat = keras.layers.Concatenate()([input_A, hidden2])
output = keras.layers.Dense(1)(concat)
model = keras.Model(inputs=[input_A, input_B], outputs=[output])
- 모델 컴파일은 이전과 동일하지만 fit() 메서드를 호출할 때, 입력마다 하나씩 행렬의 튜플 (X_train_A, X_train_B)을 전달해야한다. X_valid, X_test, X_new에도 동일하게 적용된다.
model.compile(loss='mse', optimizer=keras.optimizers.SGD(learning_rate=1e-3))
X_train_A, X_train_B = X_train[:, :5], X_train[:, 2:]
X_valid_A, X_valid_B = X_valid[:, :5], X_valid[:, 2:]
X_test_A, X_test_B = X_test[:, :5], X_test[:, 2:]
X_new_A, X_new_B = X_test_A[:3], X_test_B[:3]
history = model.fit((X_train_A, X_train_B), y_train, epochs=20,
validation_data = ((X_valid_A, X_valid_B), y_valid))
mse_test = model.evaluate((X_test_A, X_test_B), y_test)
y_pred = model.predict((X_new_A, X_new_B))
여러 개의 출력이 필요한 경우
-
그림에서 회귀 작업(물체 중심의 좌표와 너비, 높이를 찾는다)과 분류 작업을 함께하는 경우
-
동일한 데이터에서 독립적인 여러 작업을 수행할 때 -> 다중 작업 분류 수행
-
규제 기법으로 사용하는 경우
-
과대 적합을 감소하고 모델의 일반화 성능을 높이도록 훈련에 제약을 가한다.
-
ex) 신경망 구조에 보조 출력을 추가한다. = 적절한 층에 연결하고 모델의 출력 리스트에 추가하면 된다.
-
# 보조 출력 추가한 모델 만들기
input_A = keras.layers.Input(shape=[5], name='wide_input')
input_B = keras.layers.Input(shape=[6], name='deep_input')
hidden1 = keras.layers.Dense(30, activation='relu')(input_B)
hidden2 = keras.layers.Dense(30, activation='relu')(hidden1)
concat = keras.layers.Concatenate()([input_A, hidden2]) # 여기까지는 이전과 동일하다
output = keras.layers.Dense(1, name="main_output")(concat)
aux_output = keras.layers.Dense(1, name='aux_outout')(hidden2)
model = keras.Model(inputs=[input_A, input_B], outputs=[output, aux_output])
-
각 출력은 자신만의 손실 함수 필요 => 컴파일할 때 손실의 리스트를 전달해야한다.
-
케라스는 나열된 손실을 모두 더하여 최종 손실을 구해 훈련에 사용한다.
-
또한 더 중요한 출력의 손실에 가중치를 부여할 수 있다.
# 컴파일 (+ 출력의 손실 가중치 지정)
model.compile(loss=['mse', 'mse'], loss_weights=[0.9, 0.1], optimizer='sgd')
# 모델 훈련
history = model.fit(
[X_train_A, X_train_B], [y_train, y_train], epochs=20,
validation_data=([X_valid_A, X_valid_B], [y_valid, y_valid])
)
# 결과: 개별 손실 & 총 손실 반환
total_loss, main_loss, aux_loss = model.evaluate(
[X_test_A, X_test_B], [y_test, y_test]
)
# 각 출력에 대한 예측 반환하기
y_pred_main, y_pred_aux = model.predict([X_new_A, X_new_B])
y_pred_main, y_pred_aux
10.2.5 서브클래싱 API로 동적 모델 만들기
시퀀셜 API & 함수형 API
- 선언적이다 => 사용할 층과 연결 방식을 먼저 정의해야하고 모델에 데이터를 주입하여 훈련/예측을 할 수 있다.
장점
-
모델을 저장하거나 복사, 공유하기 쉽다.
-
모델의 구조를 출력하거나 분석하기 쉽다
-
모델에 데이터가 주입되기 전에 모델의 에러를 일찍 발견할 수 있다.
-
정적이므로 디버깅하기 쉽다.
단점
- 반복문을 포함하고 다양한 크기를 다루며, 조건문을 가지는 등 동적인 구조가 필요할 때가 많다. => 해결: 서브클래싱 API를 사용하면 된다!
# 서브클래싱 API로 동적 모델 만들기
class WideAndDeepModel(keras.Model):
def __init__(self, units=30, activation='relu', **kwargs):
super().__init__(**kwargs) # 표준 매개변수를 처리한다.
self.hidden1 = keras.layers.Dense(units, activation=activation)
self.hidden2 = keras.layers.Dense(units, activation=activation)
self.main_output = keras.layers.Dense(1)
self.aux_output = keras.layers.Dense(1)
def call(self, inputs):
input_A, input_B = inputs
hidden1 = self.hidden1(input_B)
hidden2 = self.hidden2(hidden1)
concat = keras.layers.concatenate([input_A, hidden2])
main_output = self.main_output(concat)
aux_output = self.aux_output(hidden2)
return main_output, aux_output
model = WideAndDeepModel()
참고 - 파이썬 함수 선언부(*args, **kwargs)
args: 정해지지 않은 수의 (일반)파라미터 받음
kwargs: 정해지지 않은 수의 키워드 파라미터를 받는다. 키워드 파라미터 예시: Func(x=100, y=200, z=’b’)
코드 설명
-
함수형 API와 유사하지만 Input객체를 만들지 않고 call() 메서드의 input 매개변수를 사용하였다.
-
장점
call() 메서드에서는 for, if문 등 원하는 계산이 가능하다. => 연구자에게 잘 맞는 API이다. -
단점
모델 구조가 call() 메서드 안에 숨겨져있기 때문에 모델을 저장하거나 복사할 수 없다. => summary() 메서드를 호출하면 층의 목록만 나열되고 층 간의 연결 정보를 얻을 수 없다.
타입과 크기를 미리 알 수 없어 실수가 발생할 수 있다.
=>따라서 일반적인 경우 (높은 유연성이 필요하지 않는다면) 시퀀셜 API와 함수형 API를 사용하는 것이 좋다.
10.2.6 모델 저장과 복원
지금까지 케라스를 사용하여 신경망을 만들고 훈련하는 법을 배웠다. 모델을 저장하는 법을 알아보자.
-
저장 형식: HDF5 포맷 (.h5)
-
저장 대상: 모델 구조와 층의 모든 모델 파라미터(연결 가중치, 편향), 옵티마이저를 저장한다.
-
사용 방식: 하나의 파이썬 스크립트에서 모델을 훈련하고 저장한 다음 하나 이상의 스크립트(또는 웹)에서 모델을 로드하고 예측을 만드는데 활용한다.
# 시퀀셜 API를 이용해 모델 만들기
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')
# 모델 저장하기 => 간단 & 쉬움
model.save("my_keras_model.h5")
# 모델 로드하기
model = keras.models.load_model('my_keras_model.h5')
CAUTION
위의 모델 저장/로드 방식은 시퀀셜 API와 함수형 API에서만 사용가능하며 서브클래싱API에서는 사용 불가하다.
10.2.7 콜백 사용하기
훈련 도중 일정 간격으로 체크포인트를 저장하기 위해 콜백을 사용한다.
케라스가 훈련의 시작이나 끝 검증 또는 예측, 에포크의 시작이나 끝, 각 배치 처리 전후에 호출할 수 있다.
# ... 위에서 했던 방식대로 모델 만들고 컴파일 하기
# 체크포인트 저장하기
checkpoint_cb = keras.callbacks.ModelCheckpoint("my_keras_model.h5")
history = model.fit(X_train, y_train, epochs=10, callbacks=[checkpoint_cb])
save_best_only=True로 하면 최상의 검증 세트 점수에서만 모델을 저장한다. (단, 검증세트를 사용할 때!)
=> 과대적합 걱정 안해도 된다!
조기종료 첫 번째 방식
# 조기종료 방식1 & 최상의 모델 저장
checkpoint_cb = keras.callbacks.ModelCheckpoint("my_keras_model.h5", save_best_only=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") # 저장된 최상의 모델로 복원
조기종료 두 번째 방식
-
EarlyStopping 콜백 사용한다. 일정 에포크동안 검증 세트에 대한 점수가 향상되지 않으면 훈련을 멈춘다.
=> 에포크의 숫자를 크게 지정해도 된다. -
선택적으로 최상의 모델을 복원할 수 있다.
-
체크포인트 저장 콜백과 EarlyStopping 콜백 함께 사용 가능하다
-
이전 코드이 경우와 다르게 훈련이 끝난 후 최상의 가중치를 복원해주기 때문에 저장된 모델을 따로 복원할 필요가 없다.
# 조기종료 방식2
early_stopping_cb = keras.callbacks.EarlyStopping(patioence=10, restore_best_weights=True)
history = model.fit(X_train, y_train, epochs=100,
validation_data=(X_valid, y_valid),
callbacks=[checkpoint_cb, early_stopping_cb])
그 밖에도 사용자 정의 콜백을 만들 수 있다.
사용자 정의 콜백
class PrintValTrainRatioCallback(keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs): # 메서드 이름 그대로 에포크가 끝날 때 호출한다
print("\n val/train: {:.2f}".format(logs["val_loss"]/logs["loss"]))
코드 설명
훈련하는 동안 검증 손실과 훈련 손실의 비율 출력한다
10.2.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()
### 이전과 같은 모델 구성과 컴파일
# 시퀀셜 API를 이용해 모델 만들기
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=keras.optimizers.SGD(learning_rate=0.001))
# 텐서보드 -> 로그 기록하기
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])
learning_rate=0.05으로 두고 한번 더 실행해보자
run_logdir2 = get_run_logdir()
model2 = keras.models.Sequential([
keras.layers.Dense(30, activation='relu', input_shape=X_train.shape[1:]),
keras.layers.Dense(1)
])
# 모델 컴파일
model2.compile(loss="mean_squared_error",
optimizer=keras.optimizers.SGD(learning_rate=0.05))
# 텐서보드 -> 로그 기록하기
tensorboard_cb = keras.callbacks.TensorBoard(run_logdir2)
# 훈련
history = model2.fit(X_train, y_train, epochs=30,
validation_data = (X_valid, y_valid),
callbacks=[tensorboard_cb])
코드 설명
위 코드를 실행하면 TensorBoard() 콜백이 로그 디렉터리를 생성한다. 훈련하는 동안 이벤트 파일을 만들고 서머리를 기록한다. (서머리: 시각화하려는 각각의 이진 데이터 레코드)
위와 같이 디렉토리와 파일이 생성된다.
-
my_logs - 루트 로그디렉터리
-
run_연도_월_일_시_분_초 - 서브디렉터리
-
train - 훈련 로그를 위한 서브디렉터리; 이벤트 파일, 프로파일링 트레이스 파일(모델의 각 부분에서 시간이 얼마나 소요되었는지 보여주는 요) 포함
-
validation - 검증 로그를 위한 서브디렉터리
텐서보드 서버를 실행해보자.
%load_ext tensorboard
%tensorboard --logdir=./my_logs --port=6006
실행 결과를 보면, lr = 0.05인 모델의 훈련 손실이 더 빠르게 감소한다.
텐서보드를 이용한 스칼라, 히스토그램, 이미지, 오디오, 텍스트 시각화
create_file_writer() 함수를 사용해 SummaryWriter를 만들고 with 블럭 안에서 텐서보드를 사용해 스칼라, 히스토그램, 이미지, 오디오, 텍스트를 기록하고 시각화해보자.
test_logdir = get_run_logdir()
writer = tf.summary.create_file_writer(test_logdir)
with writer.as_default():
for step in range(1, 1000 + 1):
tf.summary.scalar("my_scalar", np.sin(step/10), step=step)
data = (np.random.randn(100)+2)*step/100
tf.summary.histogram("my_hist", data, buckets=50, step=step)
images = np.random.rand(2, 32, 32, 3) # 32x32 RGB 이미지
tf.summary.image("my_images", images*step/1000, step=step)
text = ["The step is"+str(step), "Its square is"+str(step**2)]
tf.summary.text("my_text", text, step=step)
sine_wave = tf.math.sin(tf.range(12000)/48000*2*np.pi*step)
audio = tf.reshape(tf.cast(sine_wave, tf.float32), [1, -1, 1])
tf.summary.audio("my_audio", audio, sample_rate=48000, step=step)
%load_ext tensorboard
%tensorboard --logdir=./my_logs --port=6006
배운 내용 요약
-
신경망의 유래와 다츰 퍼셉트론의 개념
-
분류와 회귀 문제를 위해 다층 퍼셉트론 사용하는 방법
-
시퀀셜 API, 함수형 API, 서브클래싱 API 사용하는 방법
-
모델 저장 & 복원
-
콜백: 체크포인트 저장, 조기 종료 등
-
텐서보드를 사용한 시각화 방법
지금까지 케라스 API를 사용하여 다층 퍼셉트론을 구현하는 방법에 대해 알아보았다. 다음 포스트에서는 신경망 하이퍼파라미터를 조정하여 모델의 성능을 높이는 방법을 다뤄볼 것이다.
댓글남기기