Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/ko/tensorboard/image_summaries.ipynb
25115 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

개요

TensorFlow Image Summary API를 사용하면 텐서와 임의의 이미지를 쉽게 로깅하고 TensorBoard에서 볼 수 있습니다. 이는 입력 데이터를 샘플링 및 검사하거나 레이어 가중치생성된 텐서를 시각화하는 데 대단히 유용할 수 있습니다. 또한, 진단 데이터를 이미지로 로깅하여 모델 개발 과정에서 도움을 받을 수 있습니다.

이 튜토리얼에서는 Image Summary API를 사용하여 텐서를 이미지로 시각화하는 방법을 알아봅니다. 또한, 임의의 이미지를 가져와서 텐서로 변환하고 TensorBoard에서 시각화하는 방법도 배웁니다. 이미지 요약을 사용하여 모델의 성능을 이해하는 데 도움을 주는 간단하지만 실용적인 예를 진행하겠습니다.

설정

try: # %tensorflow_version only exists in Colab. %tensorflow_version 2.x except Exception: pass # Load the TensorBoard notebook extension. %load_ext tensorboard
TensorFlow 2.x selected.
from datetime import datetime import io import itertools from packaging import version import tensorflow as tf from tensorflow import keras import matplotlib.pyplot as plt import numpy as np import sklearn.metrics print("TensorFlow version: ", tf.__version__) assert version.parse(tf.__version__).release[0] >= 2, \ "This notebook requires TensorFlow 2.0 or above."
TensorFlow version: 2.2

Fashion-MNIST 데이터세트 다운로드하기

Fashion-MNIST 데이터세트에서 이미지를 분류하기 위한 간단한 신경망을 구성하겠습니다. 이 데이터세트는 10개 범주의 패션 제품을 나타내는 70,000개의 28x28 회색조 이미지로 구성되며 범주당 7,000개의 이미지가 있습니다.

먼저 데이터를 다운로드합니다.

# Download the data. The data is already divided into train and test. # The labels are integers representing classes. fashion_mnist = keras.datasets.fashion_mnist (train_images, train_labels), (test_images, test_labels) = \ fashion_mnist.load_data() # Names of the integer classes, i.e., 0 -> T-short/top, 1 -> Trouser, etc. class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz 32768/29515 [=================================] - 0s 0us/step Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz 26427392/26421880 [==============================] - 0s 0us/step Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz 8192/5148 [===============================================] - 0s 0us/step Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz 4423680/4422102 [==============================] - 0s 0us/step

단일 이미지 시각화하기

Image Summary API의 동작 방식을 이해하기 위해, 이제 간단히 TensorBoard의 훈련 세트에 첫 번째 훈련 이미지를 로깅하겠습니다.

이를 위해 훈련 데이터의 형상을 살펴봅니다.

print("Shape: ", train_images[0].shape) print("Label: ", train_labels[0], "->", class_names[train_labels[0]])
Shape: (28, 28) Label: 9 -> Ankle boot

데이터세트에 있는 각 이미지의 형상은 높이와 너비를 나타내는 랭크-2 텐서 형상(28, 28)입니다.

그러나 tf.summary.image()(batch_size, height, width, channels)를 포함하는 랭크-4 텐서를 예상합니다. 따라서 텐서의 형상을 변경해야 합니다.

하나의 이미지만 로깅하므로 batch_size는 1입니다. 이미지는 회색조이므로 channels를 1로 설정합니다.

# Reshape the image for the Summary API. img = np.reshape(train_images[0], (-1, 28, 28, 1))

이제 이 이미지를 로깅하고 TensorBoard에서 볼 준비가 되었습니다.

# Clear out any prior log data. !rm -rf logs # Sets up a timestamped log directory. logdir = "logs/train_data/" + datetime.now().strftime("%Y%m%d-%H%M%S") # Creates a file writer for the log directory. file_writer = tf.summary.create_file_writer(logdir) # Using the file writer, log the reshaped image. with file_writer.as_default(): tf.summary.image("Training data", img, step=0)

이제 TensorBoard를 사용하여 이미지를 검사합니다. UI가 모두 표시될 때까지 몇 초 정도 기다리세요.

%tensorboard --logdir logs/train_data

"시계열" 대시보드에 방금 로깅한 이미지가 표시됩니다. 바로 "앵클 부츠"입니다.

더 쉽게 볼 수 있도록 이미지가 기본 크기로 조정됩니다. 크기가 조정되지 않은 원본 이미지를 보려면 오른쪽 '설정' 패널 하단에서 '실제 이미지 크기 표시'를 선택합니다.

밝기 및 대비 슬라이더를 사용하여 이미지 픽셀에 미치는 영향을 확인하세요.

여러 이미지 시각화하기

하나의 텐서를 로깅하는 작업은 잘 되었지만 여러 훈련 예를 로깅해야 한다면 어떨까요?

tf.summary.image()로 데이터를 전달할 때 로깅하려는 이미지의 수를 지정하기만 하면 됩니다.

with file_writer.as_default(): # Don't forget to reshape. images = np.reshape(train_images[0:25], (-1, 28, 28, 1)) tf.summary.image("25 training data examples", images, max_outputs=25, step=0) %tensorboard --logdir logs/train_data

임의의 이미지 데이터 로깅하기

matplotlib에 의해 생성된 이미지와 같이 텐서가 아닌 이미지를 시각화하려면 어떻게 해야 할까요?

플롯을 텐서로 변환하려면 몇 가지 상용구 코드가 필요하지만 그 후에는 문제가 없습니다.

아래 코드에서 matplotlib의 subplot() 함수를 사용하여 처음 25개의 이미지를 보기 좋은 격자로 로깅합니다. 그러면 TensorBoard에서 격자를 볼 수 있습니다.

# Clear out prior logging data. !rm -rf logs/plots logdir = "logs/plots/" + datetime.now().strftime("%Y%m%d-%H%M%S") file_writer = tf.summary.create_file_writer(logdir) def plot_to_image(figure): """Converts the matplotlib plot specified by 'figure' to a PNG image and returns it. The supplied figure is closed and inaccessible after this call.""" # Save the plot to a PNG in memory. buf = io.BytesIO() plt.savefig(buf, format='png') # Closing the figure prevents it from being displayed directly inside # the notebook. plt.close(figure) buf.seek(0) # Convert PNG buffer to TF image image = tf.image.decode_png(buf.getvalue(), channels=4) # Add the batch dimension image = tf.expand_dims(image, 0) return image def image_grid(): """Return a 5x5 grid of the MNIST images as a matplotlib figure.""" # Create a figure to contain the plot. figure = plt.figure(figsize=(10,10)) for i in range(25): # Start next subplot. plt.subplot(5, 5, i + 1, title=class_names[train_labels[i]]) plt.xticks([]) plt.yticks([]) plt.grid(False) plt.imshow(train_images[i], cmap=plt.cm.binary) return figure # Prepare the plot figure = image_grid() # Convert to image and log with file_writer.as_default(): tf.summary.image("Training data", plot_to_image(figure), step=0) %tensorboard --logdir logs/plots

이미지 분류자 빌드하기

이제 모든 내용을 실제 예와 결합하겠습니다. 여기서 하려는 것은 머신러닝을 배우는 것이지 예쁜 그림을 그리려는 것은 아니니까요!

이미지 요약을 사용하여 Fashion-MNIST 데이터세트에 대해 간단한 분류자를 훈련하는 동안 모델이 얼마나 잘 동작하는지 알아보겠습니다.

먼저, 매우 간단한 모델을 만들고 컴파일하여 옵티마이저와 손실 함수를 설정합니다. 이와 함께 컴파일 단계에 분류자의 정확성을 로깅하는 내용도 지정합니다.

model = keras.models.Sequential([ keras.layers.Flatten(input_shape=(28, 28)), keras.layers.Dense(32, activation='relu'), keras.layers.Dense(10, activation='softmax') ]) model.compile( optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'] )

분류자를 훈련할 때 혼동 행렬을 확인하는 것이 유용합니다. 혼동 행렬을 통해 분류자가 테스트 데이터에서 어떤 성능을 나타내는지 자세히 알아볼 수 있습니다.

혼동 행렬을 계산하는 함수를 정의합니다. 이를 위해 편리한 Scikit-learn 함수를 사용하고 matplotlib를 사용하여 플롯합니다.

def plot_confusion_matrix(cm, class_names): """ Returns a matplotlib figure containing the plotted confusion matrix. Args: cm (array, shape = [n, n]): a confusion matrix of integer classes class_names (array, shape = [n]): String names of the integer classes """ figure = plt.figure(figsize=(8, 8)) plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues) plt.title("Confusion matrix") plt.colorbar() tick_marks = np.arange(len(class_names)) plt.xticks(tick_marks, class_names, rotation=45) plt.yticks(tick_marks, class_names) # Compute the labels from the normalized confusion matrix. labels = np.around(cm.astype('float') / cm.sum(axis=1)[:, np.newaxis], decimals=2) # Use white text if squares are dark; otherwise black. threshold = cm.max() / 2. for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): color = "white" if cm[i, j] > threshold else "black" plt.text(j, i, labels[i, j], horizontalalignment="center", color=color) plt.tight_layout() plt.ylabel('True label') plt.xlabel('Predicted label') return figure

이제 분류자를 훈련하고, 동시에 혼동 행렬을 로깅할 준비가 되었습니다.

여기서 수행할 작업은 다음과 같습니다.

  1. 기본 메트릭을 로깅할 Keras TensorBoard 콜백을 만듭니다.

  2. epoch가 끝날 때마다 혼동 행렬을 로깅할 Keras LambdaCallback을 생성합니다.

  3. 두 콜백이 모두 전달되도록 하면서 Model.fit()으로 모델을 훈련합니다.

훈련이 진행되면 아래로 스크롤하여 TensorBoard가 시작되는지 확인합니다.

# Clear out prior logging data. !rm -rf logs/image logdir = "logs/image/" + datetime.now().strftime("%Y%m%d-%H%M%S") # Define the basic TensorBoard callback. tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir) file_writer_cm = tf.summary.create_file_writer(logdir + '/cm')
def log_confusion_matrix(epoch, logs): # Use the model to predict the values from the validation dataset. test_pred_raw = model.predict(test_images) test_pred = np.argmax(test_pred_raw, axis=1) # Calculate the confusion matrix. cm = sklearn.metrics.confusion_matrix(test_labels, test_pred) # Log the confusion matrix as an image summary. figure = plot_confusion_matrix(cm, class_names=class_names) cm_image = plot_to_image(figure) # Log the confusion matrix as an image summary. with file_writer_cm.as_default(): tf.summary.image("epoch_confusion_matrix", cm_image, step=epoch) # Define the per-epoch callback. cm_callback = keras.callbacks.LambdaCallback(on_epoch_end=log_confusion_matrix)
# Start TensorBoard. %tensorboard --logdir logs/image # Train the classifier. model.fit( train_images, train_labels, epochs=5, verbose=0, # Suppress chatty output callbacks=[tensorboard_callback, cm_callback], validation_data=(test_images, test_labels), )

정확성은 훈련 세트와 검증 세트 모두에서 상승 추세를 나타냅니다. 좋은 결과입니다. 그렇다면 데이터의 특정 하위 집합에서는 모델이 어떻게 동작할까요?

로깅된 혼동 행렬을 시각화려면 "이미지" 탭을 선택합니다. 혼동 행렬을 전체 크기로 보려면 '설정' 패널 하단의 '실제 이미지 크기 표시'를 선택합니다.

기본적으로, 대시보드에는 마지막으로 로깅된 스텝 또는 epoch에 대한 이미지 요약이 표시됩니다. 이전 혼동 행렬을 보려면 슬라이더를 사용합니다. 훈련이 진행됨에 따라 어두운 사각형이 대각선을 따라 합쳐지고 나머지 행렬이 0과 흰색을 향하는 추세를 나타내며 행렬에 큰 변화가 일어나고 있는 모습을 확인하세요. 이것은 훈련이 진행됨에 따라 분류자가 향상되고 있음을 의미합니다! 훌륭한 결과입니다!

혼동 행렬은 이 단순 모델에 몇 가지 문제가 있음을 보여줍니다. 큰 발전이 있기는 했지만 셔츠, 티셔츠, 풀오버는 서로 혼동되고 있습니다. 모델에 더 많은 작업이 필요합니다.

관심이 있다면 CNN(컨볼루셔널 네트워크)를 사용하여 이 모델을 개선해 보세요.