Colab으로 하루에 하나씩 딥러닝

합성곱 신경망_5.이미지 분류를 위한 신경망_1)LeNet-5 본문

딥러닝_개념

합성곱 신경망_5.이미지 분류를 위한 신경망_1)LeNet-5

Elleik 2023. 1. 6. 22:56
728x90

LeNet-5(르넷-5)

  •  얀 르쿤(Yann LeCun)이 7 계층 모델 구조를 가진 신경망을 통해 필기체로 쓰인 숫자를 인식하게 함
    • 7 계층 : 'CONV - POOL - CONV - POOL - FC - FC - FC'
    • 콘벌루션 계층(CONV)과 풀링 계층(POOL)을 2번씩 반복한 뒤 완전 연결 3 계층(FC)으로 연결
  •  콘벌루션 계층과 풀링 계층은 신경망의 시각 영역, 완전 연결 계층은 연관 영역을 모델링 함

LeNet-5(르넷-5) 실습

### 라이브러리 호출

%load_ext tensorboard

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

from tensorflow.keras import Model
from tensorflow.keras.models import Sequential
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.losses import categorical_crossentropy
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import Dense, Flatten, Conv2D, AveragePooling2D, Dropout

### LeNet-5 클래스 생성

num_classes = 2
class LeNet(Sequential):
  def __init__(self, input_shape, nb_classes):
    super().__init__()

    self.add(Conv2D(6, kernel_size=(5,5), strides=(1,1), activation='relu',
                    input_shape=input_shape, padding='same')) # 설명 1
    self.add(AveragePooling2D(pool_size=(2,2), strides=(2,2), padding='valid')) # 설명 2
    self.add(Conv2D(16, kernel_size=(5,5), strides=(1,1), activation='relu', padding='valid'))
    self.add(AveragePooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
    self.add(Flatten())
    self.add(Dense(120, activation='relu'))
    self.add(Dense(84, activation='relu'))
    self.add(Dense(nb_classes, activation='softmax'))

    self.compile(optimizer='adam', 
                 loss=categorical_crossentropy,
                 metrics=['accuracy'])

상세 설명

  • 설명 1: 
    • 6: 필터 개수
    • kernel_size: 커널의 행과 열
    • strides: 필터를 적용하는 간격
    • activation: 활성화 함수 설정
    • input_shape: 입력 이미지 형태를 정의(행, 열, 채널 개수)
    • padding: same일 경우, 출력 이미지 크기와 입력 이미지 크기가 동일
  • 설명 2:
    • pool_size: 연산 범위를 의미, 해당 범위 내 평균을 가져옴
    • strides: 필터가 계산 과정에서 한 스텝마다 이동하는 크기
    • padding: valid일 경우, 연산 전에 주변에 빈 값을 넣어 이미지 크기를 유지하는 것을 비활성화

### LeNet-5 모델 생성

model = LeNet((100,100,3), num_classes)
model.summary()

모델 생성 결과


### Git에서 데이터 가져오기

!git clone https://github.com/gilbutITbook/080263.git

데이터 클론 완료


### 파라미터 초기화 및 데이터 호출

EPOCHS = 100
BATCH_SIZE = 32
image_height = 100
image_width = 100
train_dir = "/content/080263/chap6/data/catanddog/train"
valid_dir = "/content/080263/chap6/data/catanddog/validation"

### 이미지 데이터 증가

train = ImageDataGenerator(
    rescale=1./255,
    rotation_range=10,
    width_shift_range=0.1,
    height_shift_range=0.1,
    shear_range=0.1,
    zoom_range=0.1)

train_generator = train.flow_from_directory(train_dir, target_size=(image_height, image_width),
                                                                  color_mode="rgb",
                                                                  batch_size=BATCH_SIZE,
                                                                  seed=1,
                                                                  shuffle=True,
                                                                  class_mode="categorical")
valid = ImageDataGenerator(rescale=1.0/255.0)
valid_generator = valid.flow_from_directory(valid_dir, 
                                            target_size=(image_height, image_width),
                                            color_mode="rgb",
                                            batch_size=BATCH_SIZE,
                                            seed=7,
                                            shuffle=True,
                                            class_mode="categorical")

train_num = train_generator.samples
valid_num = valid_generator.samples

개와 고양이에 대한 이미지 분류이므로 class 2개


### 텐서보드에서 모델 훈련 과정 살펴보기

log_dir = "/content"
tensorboard_callback=tf.keras.callbacks.TensorBoard(log_dir=log_dir,
                                                    histogram_freq=1, profile_batch=0)  # 설명1

model.fit(train_generator, 
          epochs=EPOCHS,
          steps_per_epoch=train_num // BATCH_SIZE,
          validation_data=valid_generator,
          validation_steps=valid_num // BATCH_SIZE,
          callbacks=[tensorboard_callback],
          verbose=1)  # 설명 2

모델 훈련시킨 결과

상세 설명

  • 설명 1: 
    • log_dir: 로그 파일이 기록될 위치
    • histogram_freq: 매 에포크마다 출력을 히스토그램으로 기록
    • profile_batch: 훈련이 진행되는 시간 및 시스템 자원 등에 대한 사용을 관리하는 것으로 기본적으로 두 번째 배치부터 계산 진행. 비활성화하기 위해 0 값을 부여
  • 설명 2:
    • train_generator: 입력 데이터
    • epochs: 학습 횟수를 의미. 과적합의 위험 때문에 적정 횟수 설정이 중요
    • steps_per_epoch: 한 에포크에서 사용한 스텝 개수를 지정
    • validation_data: 성능을 모니터링하는 데 사용하는 데이터셋 설정
    • validation_steps: 한 에포크가 종료될 때 사용되는 테스트 스텝 개수를 지정
    • callbacks=[tensorboard_callback]: 텐서보드라는 콜백 함수를 생성한 후 fit() 메서드의 파라미터로 넣어줌
    • verbose: 훈련의 진행과정을 보여줌. 
      • 0: 아무것도 안 보여줌
      • 1: 훈련의 진행도를 보여줌
      • 2: 미니 배치마다 훈련 정보를 출력

### 이미지 데이터셋 분류에 대한 예측

class_names=['cat','dog']
validation, label_batch = next(iter(valid_generator))
prediction_values = model.predict(validation)
prediction_values = np.argmax(prediction_values, axis=1)

fig = plt.figure(figsize=(12,8))
fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)

for i in range(8):
  ax = fig.add_subplot(2, 4, i+1, xticks=[], yticks=[])
  ax.imshow(validation[i,:], cmap=plt.cm.gray_r, interpolation='nearest')

  if prediction_values[i] == np.argmax(label_batch[i]):
    ax.text(3, 17, class_names[prediction_values[i]], color='yellow', fontsize=14)
  else:
    ax.text(3, 17, class_names[prediction_values[i]], color='red', fontsize=14)

모델의 예측 결과이지만 예측력이 좋지 못함

참고: 서지영, 『딥러닝 텐서플로 교과서』, 길벗(2022)