{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"**실습 목표**\n\n💡 딥러닝 모델 (MLP, CNN, VGG19)을 이용한 개 vs.고양이 이미지 분류\n\n💡 모델이 이미지의 어떤 특징을 추출하였는지 시각화 ","metadata":{}},{"cell_type":"markdown","source":"**필요 라이브러리 import 및 추가된 데이터 path 확인**","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport os\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**zip파일 압축 해제**","metadata":{}},{"cell_type":"code","source":"from zipfile import ZipFile\n\nbase_path = '/kaggle/input/dogs-vs-cats/'\nunzip_path = '/kaggle/working/' # 현재 디렉토리\n\n# 반복문 이용\nfor folder in os.listdir(path = base_path):\n    if folder.split(\".\")[1] == 'zip':\n        with ZipFile(base_path + folder, 'r') as zipfile:\n            zipfile.extractall(unzip_path)\n            print(f'{folder} 압축해제 완료!')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 데이터분석 및 전처리","metadata":{}},{"cell_type":"markdown","source":"모델에 입력하여 컴퓨터가 학습 할 수 있도록 전처리 해준다. ","metadata":{}},{"cell_type":"code","source":"train_dir = os.path.join(unzip_path, 'train')\ntest_dir = os.path.join(unzip_path, 'test1')\n\n# 파일리스트 가져오기\ntrain_img_names = os.listdir(train_dir)\ntest_img_names = os.listdir(test_dir)\n\nprint('total training images : ', len(train_img_names))\nprint('total test images : ', len(test_img_names))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_img_names[:5]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**이미지 이름과 분류 카테고리 정보를 갖는 dataframe 생성**","metadata":{}},{"cell_type":"code","source":"categories = list()\n\n# 반복문 이용\nfor image in train_img_names:\n    category = image.split('.')[0]\n    if category == 'dog':\n        categories.append('dog')\n    else:\n        categories.append('cat')\n        \ndf = pd.DataFrame({'Image':train_img_names, 'Category':categories})[:2000]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**📌Try it!!**","metadata":{}},{"cell_type":"code","source":"# 만들어진 데이터프레임 df를 출력해보자.\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**데이터 시각화**","metadata":{}},{"cell_type":"code","source":"# 필요 라이브러리 import\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f = plt.figure(figsize=(5, 5))\nax = f.add_subplot()\nsns.countplot(data=df, x='Category', ax=ax)\n\nfor patch in ax.patches:\n    label_x = patch.get_x() + patch.get_width()/2\n    label_y = patch.get_y() + patch.get_height()/2\n    text_msg = str(int(patch.get_height())) \n    ax.text(label_x, label_y, text_msg, horizontalalignment='center', verticalalignment='center')\n    \nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"random 함수를 이용하여 이미지 확인하기","metadata":{}},{"cell_type":"code","source":"import random\n\nsample = random.choice(train_img_names)\nsample_path = '/kaggle/working/train/' + sample\nplt.imshow(plt.imread(sample_path))\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**📌 Try it!!**\n\n실행할때마다 정말로 random하게 이미지가 출력되는지 확인해보자.","metadata":{}},{"cell_type":"code","source":"# 한번에 여러개의 이미지를 출력\npath = '/kaggle/working/train/'\nplt.figure(figsize=(10,10))\nfor i in range(25):\n    img_path = path + df.Image[i]\n    \n    plt.subplot(5,5,i+1)\n    plt.xticks([])\n    plt.yticks([])\n    plt.grid(False)\n    plt.imshow(plt.imread(img_path))\n    plt.xlabel(df.Category[i])\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 훈련데이터, 테스트데이터 나누기","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain, test = train_test_split(df, test_size=0.25, stratify=df['Category'])\n# dataframe의 기존 인덱스 제거\ntrain = train.reset_index(drop=True)\n# test = test.reset_index(drop=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"🎁 **Try it !!!**\n\ntrain, test 데이터를 각각 reset_index(drop=True) 처리를 했을 때와\n\n하지 않았을 때 데이터프레임 인덱스 차이를 확인하여 보세요.","metadata":{}},{"cell_type":"markdown","source":"**훈련데이터와 테스트데이터 갯수 시각화**","metadata":{}},{"cell_type":"code","source":"f, ax = plt.subplots(1, 2, figsize=(13,5))\nsns.countplot(data=train, x='Category', palette='magma', ax=ax[0])\nsns.countplot(data=test, x='Category', palette='magma', ax=ax[1])\n\nfor patch in ax[0].patches:\n    label_x = patch.get_x() + patch.get_width()/2\n    label_y = patch.get_y() + patch.get_height()/2\n    text_msg = str(int(patch.get_height())) \n    ax[0].text(label_x, label_y, text_msg, horizontalalignment='center', verticalalignment='center')\n\nfor patch in ax[1].patches:\n    label_x = patch.get_x() + patch.get_width()/2\n    label_y = patch.get_y() + patch.get_height()/2\n    text_msg = str(int(patch.get_height())) \n    ax[1].text(label_x, label_y, text_msg, horizontalalignment='center', verticalalignment='center')\n\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# keras의 ImageDataGenerator 라이브러리를 이용하여 이미지 전처리 진행\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\nheight, width, channel = (150, 150, 3)\n\ntrain_datagen = ImageDataGenerator(rescale=1. / 255.)\n\ntrain_generator = train_datagen.flow_from_dataframe(train,\n                                                   directory = './train',\n                                                   x_col='Image',\n                                                   y_col='Category',\n                                                   batch_size=32,\n                                                   class_mode='categorical',\n                                                   color_mode= 'rgb',\n                                                   target_size=(height, width))\n\ntest_datagen = ImageDataGenerator(rescale=1. / 255.)\ntest_generator = test_datagen.flow_from_dataframe(test,\n                                                   directory = './train',\n                                                   x_col='Image',\n                                                   y_col='Category',\n                                                   batch_size=32,\n                                                   class_mode='categorical',\n                                                   color_mode= 'rgb',\n                                                   target_size=(height, width))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 모델 훈련","metadata":{}},{"cell_type":"code","source":"# 필요 라이브러리 import\nimport tensorflow\n\nfrom tensorflow.keras.models import Sequential, Model\nfrom tensorflow.keras.layers import Input, InputLayer, Resizing\nfrom tensorflow.keras.layers import Conv2D, BatchNormalization\nfrom tensorflow.keras.layers import MaxPool2D, GlobalMaxPooling2D\nfrom tensorflow.keras.layers import Flatten\nfrom tensorflow.keras.layers import Dense, Dropout\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom tensorflow.keras.optimizers import SGD","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### MLP","metadata":{}},{"cell_type":"code","source":"# MLP 모델 정의\nmlp_model = Sequential()\n\nmlp_model.add(InputLayer((height, width, channel)))\nmlp_model.add(Resizing(48, 48, interpolation='bilinear'))\nmlp_model.add(Flatten()) \nmlp_model.add(Dense(2048, activation='relu'))\nmlp_model.add(Dense(1024, activation='relu'))\nmlp_model.add(Dense(512, activation='relu'))\nmlp_model.add(Dense(128, activation='relu'))\nmlp_model.add(Dense(2, activation='softmax'))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 모델 확인\nmlp_model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 모델 컴파일\nmlp_model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=[\"accuracy\"])\n\n# 모델 훈련\nmlp_history = mlp_model.fit(train_generator,\n                           validation_data=test_generator,\n                           epochs=20\n                           )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 정확도와 손실값 확인\n\nmlp_acc = mlp_history.history['accuracy']\nmlp_val_acc = mlp_history.history['val_accuracy']\nmlp_loss = mlp_history.history['loss']\nmlp_val_loss = mlp_history.history['val_loss']\n\nmlp_epochs = range(len(mlp_acc))\n\nplt.plot(mlp_epochs, mlp_acc, 'r', label='Training accuracy')\nplt.plot(mlp_epochs, mlp_val_acc, 'b', label='Validation accuracy')\nplt.title('Training and validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(mlp_epochs, mlp_loss, 'r', label='Training Loss')\nplt.plot(mlp_epochs, mlp_val_loss, 'b', label='Validation Loss')\nplt.title('Training and validation loss')\nplt.legend()\n\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ✅ 모델이 예측한 결과 시각화","metadata":{}},{"cell_type":"code","source":"class_names = ['cat','dogs']\ndef plot_image(i, predictions_array, true_label, img):\n    predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]\n    plt.grid(False)\n    plt.xticks([])\n    plt.yticks([])\n\n    plt.imshow(img)\n\n    predicted_label = np.argmax(predictions_array)\n    true_label = np.argmax(true_label)\n    if predicted_label == true_label:\n        color = 'blue'\n    else:\n        color = 'red'\n\n    plt.xlabel(\"{} {:2.0f}% ({})\".format(class_names[predicted_label],\n                                100*np.max(predictions_array),\n                                class_names[true_label]),\n                                color=color)\n\ndef plot_value_array(i, predictions_array, true_label):\n    predictions_array, true_label = predictions_array[i], true_label[i]\n    plt.grid(False)\n    plt.xticks([])\n    plt.yticks([])\n    thisplot = plt.bar(range(2), predictions_array, color=\"#777777\")\n    plt.ylim([0, 1])\n    predicted_label = np.argmax(predictions_array)\n    true_label = np.argmax(true_label)\n\n    thisplot[predicted_label].set_color('red')\n    thisplot[true_label].set_color('blue')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x, y = test_generator.next()\npredictions = mlp_model.predict(x)\n\nnum_rows = 5\nnum_cols = 3\nnum_images = num_rows*num_cols\nplt.figure(figsize=(4*num_cols, 2*num_rows))\nfor i in range(num_images):\n    plt.subplot(num_rows, 2*num_cols, 2*i+1)\n    plot_image(i, predictions, y, x)\n    plt.subplot(num_rows, 2*num_cols, 2*i+2)\n    plot_value_array(i, predictions, y)\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### CNN","metadata":{}},{"cell_type":"code","source":"# CNN 모델 정의\n\ncnn_model = Sequential()\n\ncnn_model.add(Conv2D(filters=32, kernel_size=3,activation=\"relu\", input_shape=(height, width, channel)))\ncnn_model.add(MaxPool2D(pool_size=2, strides=2))\ncnn_model.add(Conv2D(filters=64, kernel_size=3,activation=\"relu\"))\ncnn_model.add(MaxPool2D(pool_size=2, strides=2))\ncnn_model.add(Conv2D(filters=128, kernel_size=3, activation=\"relu\"))\ncnn_model.add(MaxPool2D(pool_size=2, strides=2))\ncnn_model.add(Flatten())\ncnn_model.add(Dense(units=512, activation=\"relu\"))\ncnn_model.add(Dropout(0.15))\ncnn_model.add(Dense(units=2, activation=\"softmax\"))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 모델 확인\ncnn_model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 모델 컴파일\ncnn_model.compile(optimizer=\"adam\", loss=\"categorical_crossentropy\", metrics=[\"accuracy\"])\n\n# 모델 훈련\ncnn_history = cnn_model.fit(train_generator,\n                            validation_data=test_generator,\n                            epochs=20)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 모델 저장\ncnn_model.save('cnn_model.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 정확도와 손실값 확인\n\ncnn_acc = cnn_history.history['accuracy']\ncnn_val_acc = cnn_history.history['val_accuracy']\ncnn_loss = cnn_history.history['loss']\ncnn_val_loss = cnn_history.history['val_loss']\n\ncnn_epochs = range(len(cnn_acc))\n\nplt.plot(cnn_epochs, cnn_acc, 'r', label='Training accuracy')\nplt.plot(cnn_epochs, cnn_val_acc, 'b', label='Validation accuracy')\nplt.title('Training and validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(cnn_epochs, cnn_loss, 'r', label='Training Loss')\nplt.plot(cnn_epochs, cnn_val_loss, 'b', label='Validation Loss')\nplt.title('Training and validation loss')\nplt.legend()\n\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ✅ CNN 모델이 예측한 결과 시각화","metadata":{}},{"cell_type":"code","source":"predictions = cnn_model.predict(x)\n\nnum_rows = 5\nnum_cols = 3\nnum_images = num_rows*num_cols\nplt.figure(figsize=(4*num_cols, 2*num_rows))\nfor i in range(num_images):\n    plt.subplot(num_rows, 2*num_cols, 2*i+1)\n    plot_image(i, predictions, y, x)\n    plt.subplot(num_rows, 2*num_cols, 2*i+2)\n    plot_value_array(i, predictions, y)\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### VGG19","metadata":{}},{"cell_type":"code","source":"# VGG 모델 정의\nimg_input = Input(shape = (height,width,channel))\n\n# Block 1\nx = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)\nx = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)\nx = MaxPool2D((2, 2), strides=(2, 2), name='block1_pool')(x)\nx = BatchNormalization()(x)\n\n# Block 2\nx = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)\nx = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)\nx = MaxPool2D((2, 2), strides=(2, 2), name='block2_pool')(x)\nx = BatchNormalization()(x)\n\n# Block 3\nx = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)\nx = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)\nx = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)\nx = MaxPool2D((2, 2), strides=(2, 2), name='block3_pool')(x)\nx = BatchNormalization()(x)\n\n# Block 4\nx = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)\nx = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)\nx = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)\nx = MaxPool2D((2, 2), strides=(2, 2), name='block4_pool')(x)\nx = BatchNormalization()(x)\n\n# Block 5\nx = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)\nx = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x)\nx = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)\nx = MaxPool2D((2, 2), strides=(2, 2), name='block5_pool')(x)\nx = BatchNormalization()(x)\n\nx = Flatten(name='flatten')(x)\nx = Dense(4096, activation='relu', name='fc1')(x)\nx = Dense(4096, activation='relu', name='fc2')(x)\nx = Dense(2, activation='softmax', name='predictions')(x)\n\nvgg_model = Model(img_input, x, name='vgg16')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 모델 확인\nvgg_model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 모델 컴파일\nvgg_model.compile(loss='categorical_crossentropy',\n                  optimizer='adam',\n                  metrics=['accuracy'])\n\n# 모델 학습\nvgg_history = vgg_model.fit(train_generator,\n                            validation_data=test_generator,\n                            epochs=20)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 정확도 및 손실값 확인\n\nvgg_acc = vgg_history.history['accuracy']\nvgg_val_acc = vgg_history.history['val_accuracy']\nvgg_loss = vgg_history.history['loss']\nvgg_val_loss = vgg_history.history['val_loss']\n\nvgg_epochs = range(len(vgg_acc))\n\nplt.plot(vgg_epochs, vgg_acc, 'r', label='Training accuracy')\nplt.plot(vgg_epochs, vgg_val_acc, 'b', label='Validation accuracy')\nplt.title('Training and validation accuracy')\nplt.legend()\n\nplt.figure()\n\nplt.plot(vgg_epochs, vgg_loss, 'r', label='Training Loss')\nplt.plot(vgg_epochs, vgg_val_loss, 'b', label='Validation Loss')\nplt.title('Training and validation loss')\nplt.legend()\n\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ✅ VGG 모델이 예측한 결과 시각화","metadata":{}},{"cell_type":"code","source":"x, y = test_generator.next()\npredictions = vgg_model.predict(x)\n\nnum_rows = 5\nnum_cols = 3\nnum_images = num_rows*num_cols\nplt.figure(figsize=(4*num_cols, 2*num_rows))\nfor i in range(num_images):\n    plt.subplot(num_rows, 2*num_cols, 2*i+1)\n    plot_image(i, predictions, y, x)\n    plt.subplot(num_rows, 2*num_cols, 2*i+2)\n    plot_value_array(i, predictions, y)\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 모델이 어떠한 특징으로 이미지를 분류 한 걸까!?\n\n👀시각화 해보자! ","metadata":{}},{"cell_type":"code","source":"# 저장한 cnn 모델 불러오기\nfrom tensorflow.keras.models import load_model\nsaved_model = load_model('cnn_model.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**🎁Try it!!**\n\n불러온 모델 정보를 표시해보자.","metadata":{}},{"cell_type":"code","source":"# 불러온 모델 정보 확인\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**훈련에 포함되지 않은 이미지 하나 가져오기**","metadata":{}},{"cell_type":"code","source":"# 리스트 형태이기 때문에 head()사용할 수 없으므로 [:5]로 확인\ntest_img_names[:5]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from  tensorflow.keras.preprocessing import image\n\nimg_path = './test1/8961.jpg'\n# 모델이 훈련될 때 입력에 적용한 전처리 방식을 동일하게 사용해줘야합니다. (color정보, 이미지 크기 등)\n\nimg = image.load_img(img_path, target_size=(150, 150), color_mode='rgb')\nimg_tensor = image.img_to_array(img)\nimg_tensor = np.expand_dims(img_tensor, axis=0)\nimg_tensor /= 255.\n\n# 이미지 크기 (1, 150, 150, 3)\nprint(img_tensor.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 불러온 이미지 확인\nplt.imshow(img_tensor[0])\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"모델이 사진을보고 각 층별로 어떤 특징을 추출했는지 살펴보자.","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras import models\n\n\n# 상위 8개 층의 출력을 추출합\nlayer_outputs = [layer.output for layer in saved_model.layers[:8]]\n# 입력에 대해 8개 층의 출력을 반환하는 모델을 생성\nactivation_model = models.Model(inputs=saved_model.input, outputs=layer_outputs)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 층의 활성화마다 하나씩 8개의 넘파이 배열로 이루어진 리스트를 반환합니다:\nactivations = activation_model.predict(img_tensor)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"first_layer_activation = activations[0]\nprint(first_layer_activation.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.matshow(first_layer_activation[0, :, :, 31], cmap='viridis')\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n다른 채널도 그려보자.","metadata":{}},{"cell_type":"code","source":"plt.matshow(first_layer_activation[0, :, :, 9], cmap='viridis')\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"채널 수를 바꾸어 가며 확인해보자\n\n강아지 얼굴 무늬 중 색이 구분되는 선이 뚜렷히 관찰된다.\n\n이제 네트워크의 모든 활성화층을 시각화 해봅시다.\n\n**특성맵 그리기**","metadata":{}},{"cell_type":"code","source":"# 층의 이름을 그래프 제목으로 사용\nlayer_names = []\nfor layer in saved_model.layers[:8]:\n    layer_names.append(layer.name)\n\nimages_per_row = 16\n\n# 특성 맵 그리기\nfor layer_name, layer_activation in zip(layer_names, activations):\n    # 특성 맵에 있는 특성의 수\n    n_features = layer_activation.shape[-1]\n\n    # 특성 맵의 크기 : (1, size, size, n_features)\n    size = layer_activation.shape[1]\n\n    # 활성화 채널을 위한 그리드 크기\n    n_cols = n_features // images_per_row\n    display_grid = np.zeros((size * n_cols, images_per_row * size))\n\n    # 각 활성화를 하나의 큰 그리드에 채웁니다\n    for col in range(n_cols):\n        for row in range(images_per_row):\n            channel_image = layer_activation[0,\n                                             :, :,\n                                             col * images_per_row + row]\n            # 그래프로 나타내기 좋게 특성을 처리합니다\n            channel_image -= channel_image.mean()\n            channel_image /= channel_image.std()\n            channel_image *= 64\n            channel_image += 128\n            channel_image = np.clip(channel_image, 0, 255).astype('uint8')\n            display_grid[col * size : (col + 1) * size,\n                         row * size : (row + 1) * size] = channel_image\n\n    # 그리드 출력\n    scale = 1. / size\n    plt.figure(figsize=(scale * display_grid.shape[1],\n                        scale * display_grid.shape[0]))\n    plt.title(layer_name)\n    plt.grid(False)\n    plt.imshow(display_grid, aspect='auto', cmap='viridis')\n\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}