8. 케라스 신경망 모델 구성법#
감사의 글
아래 내용은 프랑소와 숄레의 Deep Learning with Python(2판)의 소스코드 내용을 참고해서 작성되었습니다. 자료를 공개한 저자에게 진심어린 감사를 전합니다.
소스코드
여기서 언급되는 코드를 (구글 코랩) 신경망 모델 활용법에서 직접 실행할 수 있다.
슬라이드
본문 내용을 요약한 슬라이드를 다운로드할 수 있다.
주요 내용
다양한 신경망 모델 구성법
신경망 모델과 층의 재활용
신경망 모델 훈련 옵션: 콜백과 텍서보드
8.1. 신경망 모델 구성법 1: Sequential
모델 활용#
케라스를 이용하여 매우 간단한 방식부터 매우 복잡한 방식까지 다양한 방식으로 필요한 수준의 신경망 모델을 구성할 수 있다. 케라스를 이용하여 세 가지 방식으로 딥러닝 신경망 모델을 구성할 수 있다.
Sequential
모델 활용: 층으로 스택을 쌓아 만든 모델함수형 API 활용: 가장 많이 사용됨.
모델 서브클래싱: 모든 것을 사용자가 지정.
먼저 Sequential
모델은 층으로 스택을 쌓아 만든 모델이며 가장 단순하다.
Sequential
클래스
from tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
layers.Dense(64, activation="relu"),
layers.Dense(10, activation="softmax")
])
Sequential
모델은 한 종류의 입력값과 한 종류의 출력값만 사용 가능하며, 데이터 변환은 지정된 층의 순서대로 적용된다.
summary()
메서드
완성된 신경망 모델의 층의 구조와 각 층의 출력값의 모양 정보를 확인할 수 있다.
모델과 층의 이름: 특별히 지정하지 않으면 기본 이름 자동으로 할당됨.
층별 출력값의 모양(
Output Shape
): 유닛수 확인.None
은 임의의 배치크기를 가리킴.층별 파라미터 수(
Param #
): 훈련을 통해 학습되어야 하는 파라미터들의 개수가중치 행렬과 편향 벡터에 포함된 항목들의 수를 가리킴.
파라미터 수
Total params
: 파라미터의 총 개수Trainable params
: 가중치 행렬과 편향 벡터에 포함된 파라리터처럼 훈련을 통해 학습(업데이트)되는 파라미터 총 개수Non-trainable params
: 훈련에는 관여하지만 훈련을 통해 학습되지는 않는 파라미터. 지금까지 다룬 모델에서는 비학습 파라미터 사용되지 않았음. 나중에 비학습 파라미터 예제를 다룰 것임 (10장 참고).
그런데 위 모델의 요약이 정보를 제대로 전달하지 못한다.
>>> model.summary()
이유는 모델의 입력값의 모양을 모르기 때문이다. 사실 위 모델은 임의의 모양의 2차원 텐서를 입력값으로 사용할 수 있다.
Input()
함수
Input()
함수를 이용하여 모델 훈련에 사용될 입력값에 대한 정보를 모델에 미리 전달할 수 있다.
예를 들어 아래 코드는 훈련셋의 샘플이 784 개의 특성을 갖는 1차원 어레이로 지정한다.
즉, 이렇게 입력값의 정보를 미리 지정하면 지정된 모양의 훈련셋만 사용할 수 있다.
from tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
keras.Input(shape=(784,)),
layers.Dense(64, activation="relu"),
layers.Dense(10, activation="softmax")
])
그러면 모델 정보가 보다 구체적으로 요약된다.
>>> model.summary()
8.2. 신경망 모델 구성법 2: 함수형 API#
Sequential
클래스를 사용하면 한 종류의 입력값과 한 종류의 출력값만을 사용할 수 있다.
반면에 함수형 API를 이용하면 다중 입력과 다중 출력을 지원하는
모델을 구성할 수 있다.
즉, 모델이 서로 다른 종류의 입력값과 서로 다른 종류의 출력값을 지원한다.
기본 활용법
앞서 살펴 본 Sequential
모델을 함수형 API를 이용하여 구성하면 다음과 같다.
inputs = keras.Input(shape=(3,), name="my_input") # 입력층
features = layers.Dense(64, activation="relu")(inputs) # 은닉층
outputs = layers.Dense(10, activation="softmax")(features) # 출력층
model = keras.Model(inputs=inputs, outputs=outputs) # 모델 지정
사용된 단계들을 하나씩 살펴보자.
입력층: 여기서는 한 개만 사용
inputs = keras.Input(shape=(3,), name="my_input")
은닉층: 입력층의 값을 이어 받음. 여러 개의 은닉층을 자유 자재로 구성 가능.
features = layers.Dense(64, activation="relu")(inputs)
출력층: 최종 은닉층의 결과를 이어 받아 출력값 계산. 여기서는 한 개만 사용.
outputs = layers.Dense(10, activation="softmax")(features)
모델 빌드: 입력층과 출력층을 이용하여 모델 지정
model = keras.Model(inputs=inputs, outputs=outputs)
summary()
의 실행결과는 다음과 같다.
>>> model.summary()
8.2.1. 다중 입력, 다중 출력 모델#
다중 입력과 다중 출력을 지원하는 모델을 구성하는 방법을 예제를 이용하여 설명한다.
(고객 요구사항 접수 모델)
고객의 요구사항이 입력되었을 때 처리 우선순위와 담당부서를 지정하는 시스템을 구현하려 한다. 고객의 요구사항은 세 종류의 입력값으로 구성된다. 따라서 시스템에 사용될 딥러닝 신경망 모델은 세 개의 입력값과 두 개의 출력값을 사용한다.
입력 사항 세 종류는 다음과 같다.
title
: 요구사항 제목제목을 멀티-핫 인코딩한 0과 1로 구성된 길이가 1만인 벡터.
1만등 이내의 사용빈도를 갖는 단어만 사용됨.
6장의IMDB 영화 후기 멀티-핫 인코딩 참고
text_body
: 요구사항 내용요구사항 내용을 멀티-핫 인코딩한 0과 1로 구성된 길이가 1만인 벡터.
1만등 이내의 사용빈도를 갖는 단어만 사용됨.
6장의IMDB 영화 후기 멀티-핫 인코딩 참고
tags
: 사용자에 의한 추가 선택 사항100개 중 여러 개 선택.
멀티-핫 인코딩된 길이가 100인 벡터.
출력 사항 두 종류는 다음과 같다.
priority
: 요구사항 처리 우선순위.0에서 1사이의 값.
sigmoid
활성화 함수 활용.
department
: 네 개의 요구사항 처리 담당 부서 중 하나 선택.softmax
활성화 함수 활용.
고객 요구사항 접수 모델을 함수형 API를 이용하여 다음과 같이 구현할 수 있다.
입력층: 세 개
title
: 제목 입력 처리text_body
: 요구사항 내용 입력 처리tags
: 추가 선택사항 처리. 100개 중에 하나 선택.
은닉층: 두 개
Concatenate
층: 여러 개의 텐서를 좌우로 이어붙임. 여기서는 고객의 요구사항 제목, 내용, 추가 선택사항을 담고 있는 길이가 각각 1만, 1만, 100인 세 개의 벡터를 이어붙여서 길이가 총 2만1백인 하나의 벡터로 변환.Dense
층: 64 개의 유닛과 함께relu()
함수 사용
출력층: 두 개
priority
: 요구사항 처리 우선순위 판단. 0과 1사의 값을 계산하는Dense
층. 1개의 유닛과sigmoid()
활성화함수 지정.department
: 요구사항 처리 담당 부서 선택. 4 개의 부서 각각에 대한 처리 활률값을 계산하는Dense
층. 4개의 유닛과softmax()
활성화함수 지정.
vocabulary_size = 10000 # 사용빈도 1만등 인내 단어 사용
num_tags = 100 # 태그 수
num_departments = 4 # 부서 수
# 입력층: 세 개
title = keras.Input(shape=(vocabulary_size,), name="title")
text_body = keras.Input(shape=(vocabulary_size,), name="text_body")
tags = keras.Input(shape=(num_tags,), name="tags")
# 은닉층
features = layers.Concatenate()([title, text_body, tags]) # shape=(None, 10000+10000+100)
features = layers.Dense(64, activation="relu")(features)
# 출력층: 두 개
priority = layers.Dense(1, activation="sigmoid", name="priority")(features)
department = layers.Dense(
num_departments, activation="softmax", name="department")(features)
# 모델 빌드: 입력값으로 구성된 입력값 리스트와 출력값으로 구성된 출력값 리스트 사용
model = keras.Model(inputs=[title, text_body, tags], outputs=[priority, department])
모델 컴파일
손실함수와 평가지표 모두 출력층의 개수만큼 지정한다.
손실함수(loss)
priority
대상:mean_squared_error
department
대상:categorical_crossentropy
평가지표(metrics): 평가지표는 대상 별로 여러 개를 사용할 수 있기에 각각의 대상에 대해 평가지표 리스트를 작성함.
priority
대상:["mean_absolute_error", "mean_squared_error"]
department
대상:["accuracy", "AUC", "Precision"]
model.compile(optimizer="adam",
loss=["mean_squared_error", "categorical_crossentropy"],
metrics=[["mean_absolute_error", "mean_squared_error"], ["accuracy", "AUC", "Precision"]])
모델 훈련
모델 훈련은 fit()
함수에 세 개의 훈련 텐서로 이루어진 리스트와
두 개의 타깃 텐서로 이루어진 리스트를 지정한 후에 실행한다.
import numpy as np
# 샘플 수
num_samples = 1280
# 입력 텐서 3 개 무작위 생성
title_data = np.random.randint(0, 2, size=(num_samples, vocabulary_size))
text_body_data = np.random.randint(0, 2, size=(num_samples, vocabulary_size))
tags_data = np.random.randint(0, 2, size=(num_samples, num_tags)) # 멀티-핫-인코딩
# 타깃 텐서 2 개 무작위 생성
priority_data = np.random.random(size=(num_samples, 1))
department_data = np.random.randint(0, 2, size=(num_samples, num_departments)) # 멀티-핫-인코딩
model.fit([title_data, text_body_data, tags_data],
[priority_data, department_data]
epochs=10)
모델 평가
모델 평가도 훈련과 동일한 방식으로 구성된 인자가 사용된다.
model.evaluate([title_data, text_body_data, tags_data],
[priority_data, department_data])
모델 활용
예측값은 두 개의 출력층 각각에서 생성된 두 개의 어레이로 구성된 리스트이다.
priority_preds, department_preds = model.predict([title_data, text_body_data, tags_data])
우선 순위 예측값: 0과 1사이의 확률값
>>> priority_preds array([[1.], [1.], [1.], ..., [1.], [1.], [1.]], dtype=float32)
처리 부서 예측값: 각 부서별 적정도를 가리키는 확률값
>>> department_preds array([[1.0000000e+00, 5.0770291e-28, 4.8780390e-08, 1.4980437e-14], [1.0000000e+00, 8.9238867e-31, 4.3726455e-08, 1.0175944e-14], [1.0000000e+00, 1.6067065e-29, 5.4092455e-09, 2.2488301e-14], ..., [1.0000000e+00, 1.8711068e-29, 2.2684986e-08, 5.9480673e-14], [1.0000000e+00, 4.0235123e-29, 1.5713432e-08, 9.7684718e-14], [1.0000000e+00, 2.8694353e-30, 7.1231565e-10, 6.3928655e-15]], dtype=float32)
각각의 요구사항을 처리해야 하는 부서는
argmax()
메서드로 확인된다.>>> department_preds.argmax() array([0, 0, 0, ..., 0, 0, 0])
8.2.2. 신경망 모델 구조 그래프#
plot_model()
을 이용하여 층 연결 구조를 그래프로 나타낼 수 있다.
>>> keras.utils.plot_model(model, "ticket_classifier.png")
층 연결 그래프 그리기
keras.utils.plot_model()
함수가 제대로 작동하려면
pydot
파이썬 모듈과 graphviz 라는 프로그램이 컴퓨터에 설치되어 있어야 한다.
pydot
모듈 설치:pip install pydot
graphviz 프로그램 설치: https://graphviz.gitlab.io/download/
구글 코랩에서는 기본으로 지원됨.
입력 텐서와 출력 텐서의 모양을 함께 표기할 수도 있다.
>>> keras.utils.plot_model(model, "ticket_classifier_with_shape_info.png", show_shapes=True)
8.3. 신경망 모델 구성법 3: 서브클래싱#
keras.Model
클래스를 상속하는 모델 클래스를 직접 선언하여 활용하는 기법이
서브클래싱subclassing이다.
서브클래싱으로 모델 클래서를 선언하려면 아래 두 메서드를 목적에 맞추어 재정의overriding한다.
__init__()
메서드(생성자): 은닉층과 출력층으로 사용될 층 객체 지정call()
메서드: 층을 연결하는 과정 지정. 즉, 입력값으부터 출력값을 만들어내는 순전파 과정 묘사.
앞서 함수형 API로 구성한 고객 요구사항 접수 모델(두 종류의 출력값 생성 모델)을 서브클래싱을 기법을 이용하여 구현하면 다음과 같다.
class CustomerTicketModel(keras.Model):
def __init__(self, num_departments): # num_departments: 고객 요구사항 처리 부서 개수
super().__init__()
self.concat_layer = layers.Concatenate() # 은닉층
self.mixing_layer = layers.Dense(64, activation="relu") # 은닉층
self.priority_scorer = layers.Dense(1, activation="sigmoid") # 출력층 1
self.department_classifier = layers.Dense( # 출력층 2
num_departments, activation="softmax")
def call(self, inputs): # inputs: 사전 객체 입력값. 모양은 미정.
title = inputs["title"]
text_body = inputs["text_body"]
tags = inputs["tags"]
features = self.concat_layer([title, text_body, tags]) # 은닉층 연결
features = self.mixing_layer(features)
priority = self.priority_scorer(features) # 출력층 연결
department = self.department_classifier(features)
return priority, department # 두 종류의 출력값 지정
이전과 동일한 구성의 모델은 다음과 같이 선언한다.
>>> model = CustomerTicketModel(num_departments=4)
컴파일, 훈련, 평가, 예측은 이전과 완전히 동일한 방식으로 실행된다.
서브클래싱 기법의 장단점
장점
call()
함수를 이용하여 층을 임의로 구성할 수 있다.for
반복문 등 파이썬 프로그래밍 모든 기법을 적용할 수 있다.
단점
모델 구성을 전적으로 책임져야 한다.
모델 구성 정보가
call()
함수 외부로 노출되지 않아서 앞서 보았던 그래프 표현을 사용할 수 없다.
8.4. 혼합 신경망 모델 구성법#
모델 vs. 층
모델 서브클래싱은 keras.layers.Layer
를 상속하여 사용자 정의 층 클래스를 선언하는 방식과
거의 동일하다 (5장 참고).
사실 keras.Model
이 keras.layers.Layer
의 자식 클래스이다.
즉, 이미 선언된 모델을 다른 모델에서 하나의 층으로 활용할 수 있다.
층 클래스와는 다르게 모델 클래스는 fit()
, evaluate()
, predict()
메서드를 함께 지원하여
모델의 훈련, 평가, 활용을 담당하도록 한다.
모델 클래스가 층의 하위 클래스이기에 선언된/훈련된 모델을 다른 모델의 하나의 층으로 활용할 수도 있다. 아래 두 예제는 이 사실을 이용하여 앞서 소개된 세 가지 방식을 임의로 혼합할 수 있음을 보여준다.
예제: 서브클래싱 모델을 함수형 모델에 활용하기 (강추!!!)
먼저 서브클래싱으로 하나의 모델을 선언한다.
한 개의 밀집층만 사용
이진 분류인 경우: 하나의 유닛과
sigmoid
활성화 함수 사용다중 클래스 분류인 경우: 클래스(범주) 수 만큼의 유닛과
softmax
활성화 함수 사용
class Classifier(keras.Model):
def __init__(self, num_classes=2):
super().__init__()
if num_classes == 2:
num_units = 1
activation = "sigmoid"
else:
num_units = num_classes
activation = "softmax"
self.dense = layers.Dense(num_units, activation=activation)
def call(self, inputs):
return self.dense(inputs)
아래 코드는 함수형 API 형식으로 새로운 모델을 지정한다. 이때 위 모델 클래스의 객체를 출력층으로 사용한다.
inputs = keras.Input(shape=(3,)) # 입력층
features = layers.Dense(64, activation="relu")(inputs) # 은닉층
outputs = Classifier(num_classes=10)(features) # 출력층
model = keras.Model(inputs=inputs, outputs=outputs)
예제: 함수형 모델을 서브클래싱 모델에 활용하기
먼저 함수형 API 형식으로 하나의 모델을 선언한다.
inputs = keras.Input(shape=(64,))
outputs = layers.Dense(1, activation="sigmoid")(inputs)
binary_classifier = keras.Model(inputs=inputs, outputs=outputs)
아래 MyModel
클래스는 앞서 선언한 binary_classifier
모델을 출력층으로 활용한다.
class MyModel(keras.Model):
def __init__(self, num_classes=2):
super().__init__()
self.dense = layers.Dense(64, activation="relu")
self.classifier = binary_classifier
def call(self, inputs):
features = self.dense(inputs)
return self.classifier(features)
8.5. 신경망 모델의 구성, 훈련, 평가, 예측#
딥러닝 신경망 모델의 훈련은 한 번 시작되면 훈련이 종료될 때까지 어떤 간섭도 받지 않는다. 즉, 훈련 시작 이전의 컴파일 과정에서 지정된 설정을 훈련 중간에 변경할 수 없다. 다만, 훈련 진행과정을 관찰monitoring할 수 있을 뿐이다.
훈련 과정 동안 관찰할 수 있는 내용은 일반적으로 다음과 같다.
에포크별 손실값
에포크별 평가지표
손실값과 평가지표를 계산하는 방식은 모델을 컴파일할 때 지정된다. 케라스가 지원하는 방식 중에 하나를 선택하거나 필요에 따라 사용자가 직접 선언한 손실함수 또는 평가지표 클래스를 활용할 수 있다.
8.5.1. 콜백#
컴퓨터 프로그래밍에서 콜백callback은 하나의 프로그램이 실행되는 도중에 추가적으로 다른 API를 호출하는 기능 또는 해당 API를 가리킨다. 호출된 콜백은 자신을 호출한 프로그램과 독립적으로 실행된다.
신경망 모델 훈련 과정에서 사용될 수 있는 다양한 콜백 기능을 케라스가 제공한다. 일반적으로 손실값, 평가지표 등 훈련 중에 계산되는 기록을 저장하여 활용하며, 가장 많이 활용되는 콜백은 다음과 같다.
훈련 기록 작성
훈련셋, 검증셋에 대한 손실값, 평가지표 기록 및 출력
훈련 에포크마다 보여지는 손실값, 평가지표 등 관리
keras.callbacks.CSVLogger
클래스 활용.기본으로 지원되도록 설정되었음.
훈련중인 모델의 상태 저장
모델의 상태: 훈련 중인 모델에 저장된 가중치와 편향 등의 파라미터 정보
훈련 중 가장 좋은 성능의 모델(의 상태) 저장
keras.callbacks.ModelCheckpoint
클래스 활용
훈련 조기 종료
검증셋에 대한 손실이 더 이상 개선되지 않는 경우 훈련을 종료 시키기
keras.callbacks.EarlyStopping
클래스 활용
하이퍼 파라미터 조정
학습률 동적 변경 지원
keras.callbacks.LearningRateScheduler
또는keras.callbacks.ReduceLROnPlateau
클래스 활용
예제
콜백은 fit()
함수의 callbacks
라는 옵션 인자를 이용하여 지정한다.
예를 들어 아래 코드는 두 종류의 콜백을 지정한다.
EarlyStopping
: 검증셋에 대한 정확도가 2 에포크 연속 개선되지 않을 때 훈련 종료ModelCheckpoint
: 매 에포크마다 훈련된 모델 상태 저장save_best_only=True
: 검증셋에 대한 손실값이 가장 낮은 모델만 저장
callbacks_list = [
keras.callbacks.EarlyStopping(
monitor="val_accuracy",
patience=2,
),
keras.callbacks.ModelCheckpoint(
filepath="checkpoint_path.keras",
monitor="val_loss",
save_best_only=True,
)
]
지정된 콜백과 함께 모델을 훈련시키는 방법은 다음과 같다. 에포크를 50 정도로 크게 잡는다. 하지만 조기 종료 기능에 의해 10번 에포크 정도에서 훈련이 종료된다.
def get_mnist_model():
inputs = keras.Input(shape=(28 * 28,))
features = layers.Dense(512, activation="relu")(inputs)
features = layers.Dropout(0.5)(features)
outputs = layers.Dense(10, activation="softmax")(features)
model = keras.Model(inputs, outputs)
return model
model = get_mnist_model()
model.compile(optimizer="rmsprop",
loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
model.fit(train_images, train_labels,
epochs=50,
callbacks=callbacks_list,
validation_data=(val_images, val_labels))
Epoch 1/50
1563/1563 ━━━━━━━━ 4s 2ms/step - accuracy: 0.8635 - loss: 0.4526 - val_accuracy: 0.9594 - val_loss: 0.1473
Epoch 2/50
1563/1563 ━━━━━━━━ 2s 2ms/step - accuracy: 0.9526 - loss: 0.1668 - val_accuracy: 0.9671 - val_loss: 0.1173
Epoch 3/50
1563/1563 ━━━━━━━━ 3s 2ms/step - accuracy: 0.9616 - loss: 0.1319 - val_accuracy: 0.9718 - val_loss: 0.1117
Epoch 4/50
1563/1563 ━━━━━━━━ 3s 2ms/step - accuracy: 0.9674 - loss: 0.1145 - val_accuracy: 0.9736 - val_loss: 0.1019
Epoch 5/50
1563/1563 ━━━━━━━━ 2s 2ms/step - accuracy: 0.9709 - loss: 0.1056 - val_accuracy: 0.9750 - val_loss: 0.1051
Epoch 6/50
1563/1563 ━━━━━━━━ 3s 2ms/step - accuracy: 0.9745 - loss: 0.0950 - val_accuracy: 0.9750 - val_loss: 0.1033
Epoch 7/50
1563/1563 ━━━━━━━━ 2s 1ms/step - accuracy: 0.9768 - loss: 0.0834 - val_accuracy: 0.9780 - val_loss: 0.0891
Epoch 8/50
1563/1563 ━━━━━━━━ 3s 2ms/step - accuracy: 0.9776 - loss: 0.0792 - val_accuracy: 0.9792 - val_loss: 0.0872
Epoch 9/50
1563/1563 ━━━━━━━━ 3s 2ms/step - accuracy: 0.9792 - loss: 0.0714 - val_accuracy: 0.9786 - val_loss: 0.0929
Epoch 10/50
1563/1563 ━━━━━━━━ 2s 1ms/step - accuracy: 0.9804 - loss: 0.0733 - val_accuracy: 0.9782 - val_loss: 0.0957
Epoch 11/50
1563/1563 ━━━━━━━━ 2s 2ms/step - accuracy: 0.9816 - loss: 0.0685 - val_accuracy: 0.9782 - val_loss: 0.0924
<keras.src.callbacks.history.History at 0x7f3251f342f0>
조기종료 후 훈련과정에서 저장된 최고 성능의 모델을 불러온 다음에 활용하는 방법은 다음과 같다.
>>> model = keras.models.load_model("checkpoint_path.keras")
>>> test_metrics = model.evaluate(test_images, test_labels)
>>> test_metrics
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.9745 - loss: 0.1033
[0.08732542395591736, 0.9786999821662903]
8.5.2. 텐서보드#
텐서보드TensorBoard는 모델 훈련 과정을 시각적으로 실시간 관찰할 수 있는 도구를 제공하며 텐서플로우와 함께 설치된다.
신경망 모델 구조 시각화
손실값, 정확도 등의 변화 시각화
가중치, 편향 텐서 등의 변화 히스토그램
이미지, 텍스트, 오디오 데이터 시각화
기타 다양한 기능 제공
TensorBoard
콜백 클래스를 활용해서 텐서보드 서버 실행을 콜백으로 지정한다.
아래 코드에서 log_dir
는 텐서보드 서버 실행에 필요한 데이터 저장소를 가리킨다.
tensorboard = keras.callbacks.TensorBoard(
log_dir="./tensorboard_log_dir",
)
model.fit(train_images, train_labels,
epochs=10,
validation_data=(val_images, val_labels),
callbacks=[tensorboard])
모델 훈련 중 또는 이후에 텐서보드 서버를 다음 두 가지 방식을 이용하여 실행할 수 있다.
단, 현재 작업 디렉토리(cwd)에 tensorboard_log_dir
디렉토리가 포함되어 있다고 가정한다.
주피터 노트북에서
%load_ext tensorboard
%tensorboard --logdir ./tensorboard_log_dir
터미널에서
$ tensorboard --logdir ./tensorboard_log_dir