본문 바로가기
  • 🦄 창민이 개발일지
딥러닝

Cat vs Dog 분류 모델 만들기

by 창민이 개발일지 2022. 6. 18.

Cat vs Dog 분류 모델 만들기

 
import tensorflow as tf
from tensorflow.keras import preprocessing
from tensorflow.keras import models, layers
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
import numpy as np
import cv2

데이터 전처리

데이터 증강(argument)

In [2]:
train_datagen = ImageDataGenerator(
    rescale=1./127.5,
    rotation_range= 40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
)
In [3]:
valid_datagen = ImageDataGenerator(
    rescale=1./127.5,
    rotation_range= 40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
)
  • rescale: 이미지의 스케일을 -1~1로 정규화
  • rotation_ragne: 최대 40 각도까지만 변경
  • width_shift_range: 전체 크기의 최대 2/10 까지 좌우 이동
  • height_shift_range: 전체 크기의 최대 2/10 까지 상하 이동
  • shear_range: 밀림의 정도를 최대 2/10 까지만 변경
  • zoom_range: 확대 축소를 최대 2/10 까지만 변경
  • horizontal_flip: 좌우 반전

각 데이터별 제너레이터 만들기

In [4]:
train_ds = train_datagen.flow_from_directory(
    '/jupyterNotebook/datasets/cats_and_dogs/train/',
    target_size=(150, 150),
    class_mode='binary',
    batch_size=100,
    interpolation="box"
)
 
In [5]:
valid_ds = train_datagen.flow_from_directory(
    '/jupyterNotebook/datasets/cats_and_dogs/validation/',
    target_size=(150, 150),
    class_mode='binary',
    batch_size=100,
    interpolation="box"
)

증강된 데이터 확인

In [6]:
x_train, y_train = next(iter(train_ds))
In [7]:
class_list = {j:i for i,j in train_ds.class_indices.items()}
In [9]:
num = np.random.randint(0,len(x_train))
plt.imshow(x_train[num])
plt.title(class_list[y_train[num]])
plt.show()
 

모델 만들기

In [10]:
model = models.Sequential()
model.add(layers.Input(shape=(150,150,3)))
model.add(layers.Conv2D(32,3,1,activation="relu",))
model.add(layers.MaxPool2D((2,2)))
model.add(layers.Conv2D(64,3,1,activation="relu"))
model.add(layers.MaxPool2D((2,2)))
model.add(layers.Conv2D(128,3,1,activation="relu"))
model.add(layers.MaxPool2D((2,2)))
model.add(layers.Conv2D(64,3,1,activation="relu"))
model.add(layers.MaxPool2D((2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(128,activation="relu"))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(64,activation="relu"))
model.add(layers.Dense(1,activation="sigmoid"))

모델 확인하기

In [11]:
model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 148, 148, 32)      896       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 74, 74, 32)       0         
 )                                                               
                                                                 
 conv2d_1 (Conv2D)           (None, 72, 72, 64)        18496     
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 36, 36, 64)       0         
 2D)                                                             
                                                                 
 conv2d_2 (Conv2D)           (None, 34, 34, 128)       73856     
                                                                 
 max_pooling2d_2 (MaxPooling  (None, 17, 17, 128)      0         
 2D)                                                             
                                                                 
 conv2d_3 (Conv2D)           (None, 15, 15, 64)        73792     
                                                                 
 max_pooling2d_3 (MaxPooling  (None, 7, 7, 64)         0         
 2D)                                                             
                                                                 
 flatten (Flatten)           (None, 3136)              0         
                                                                 
 dense (Dense)               (None, 128)               401536    
                                                                 
 dropout (Dropout)           (None, 128)               0         
                                                                 
 dense_1 (Dense)             (None, 64)                8256      
                                                                 
 dense_2 (Dense)             (None, 1)                 65        
                                                                 
=================================================================
Total params: 576,897
Trainable params: 576,897
Non-trainable params: 0
_________________________________________________________________
In [12]:
tf.keras.utils.plot_model(model,show_shapes=True,show_layer_activations=True)
Out[12]:

모델 학습 설정하기

In [13]:
model.compile(
    optimizer='adam',
    loss=tf.keras.losses.BinaryCrossentropy(),
    metrics=['accuracy']
)

학습하기

GPU 확인
!nvidia-smi
Sun Jun 19 13:23:20 2022       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 510.73.05    Driver Version: 510.73.05    CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  Off  | 00000000:01:00.0 Off |                  N/A |
| 50%   38C    P2   109W / 350W |  22732MiB / 24576MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+
In [16]:
historys = model.fit(
    train_ds,epochs=70,
    validation_data=valid_ds
)
 
In [19]:
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
plt.plot(historys.history['accuracy'],label="accuracy")
plt.plot(historys.history['val_accuracy'],label="val-accuracy")
plt.legend()

plt.subplot(1,2,2)
plt.plot(historys.history['loss'],label="loss")
plt.plot(historys.history['val_loss'],label='val-loss')
plt.legend()
plt.show()

모델 저장

In [2]:
file_path = "/jupyterNotebook/model_save/cats_vs_dogs/model/cat_vs_dogs.h5"
In [ ]:
model.save("/jupyterNotebook/model_save/cats_vs_dogs/model/cat_vs_dogs.h5")

모델 불러오기

model = models.load_model(file_path)
 

중간층 활성화 시각화

activation_model = models.Model(model.input, layer_output)
 
 
In [383]:
img = cv2.imread("/jupyterNotebook/datasets/dogs-vs-cats/cats_and_dogs/test/cats/cat.1222.jpg")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
img = cv2.resize(img,(150,150))
In [384]:
preprocess_img = img * (1/127.5)
In [385]:
plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)
plt.imshow(preprocess_img)
plt.show()
 
In [386]:
activations = activation_model.predict(np.expand_dims(preprocess_img,0))[:8]
 
In [390]:
fig = plt.figure(figsize=(10,10))
for i,layer_activation in enumerate(activations):
    transpose_layer = np.transpose(layer_activation[0,:,:,:10],axes=[2,0,1])

    for j,layer in enumerate(transpose_layer):
        fig.add_subplot(8,10,i*10+j+1)
        plt.imshow(layer)
        plt.axis("off")
    plt.title("activation %d"%i)
        
plt.show()

중간층 활성화 시각화 해석

  • 하위층으로 갈수록 여러 종류의 엣지 위주로 감지하고 있다. 하위층은 초기 사진에 있는 거의 모든 정보가 유지 됨(구체적)
  • 상위층으로 갈수록 활성화는 점점 더 추상적으로 되고 시각적을 이해하기 어려워진다. 상위 층의 표현은 이미지의 시각적 콘텐츠에 관한 정보가 점점 줄어들고 이미지의 클래스에 관한 정보가 점점 증가. 반복적인 변환을 통해 관계 없는 정보(여기서는 고양이 주변 사람이나 배경이미지)를 걸러내고 유용한 정보는 강조되고 개선된다(고양이 이미지->고양이 클래스).
  • 상위층으로 갈수록 비어 있는 활성화가 늘어난다. 첫번쨰 층에서는 거의 모든 필터가 입력 이미지에 활성화되었지만 층을 올라가면서 활성화 되지 않는 필터들이 늘어난다. 필터에 인코딩된 패턴이 입력 이미지에 나타나지 않았다는 것을 의미한다.

'딥러닝' 카테고리의 다른 글

GAN개념과 DCGAN 구현  (0) 2022.07.12
stanford dogs 분석 및 학습하기  (1) 2022.06.23
클래스 활성화의 히트맵 시각화  (0) 2022.06.23
컨브넷 필터 시각화  (0) 2022.06.23
Keras.1 Modeling  (0) 2022.06.18