ABC부트캠프 데이터 탐험가 과정

[23일차] ABC 부트캠프 딥러닝과 CNN

hwibeenjeong 2024. 8. 5. 22:59

1. 딥러닝 개요

1-1. 딥러닝 라이브러리 (Keras)

딥러닝에 주로 사용되는 라이브러리인 Keras의 중요한 요소들을 살펴보자.

- 모델 (Model)

* 순차 모델(Sequential)을 비롯한 다양한 모델들이 존재한다. 이번 교육과정에서는 순차 모델을 주로 다루니 순차 모델에 대해서 자세히 알아보자.

  • compile(optimizer, loss, metrics): 훈련을 위해서 모델을 구성하는 메소드
  • fit(x, y, epochs, batch_size, verbose): 모델 훈련 메서드
  • evaluate(x, y): 테스트 모드에서 모델의 손실 함수 값과 측정 항목 값을 반환
  • predict(x, batch_size): 입력 샘플에 대한 예측값 생성
  • add(layer): 레이어 모델에 추가한다

- 레이어 (Layer)

 입력층과 출력층을 포함한 각 층들에 대한 설정들을 지정해주는 방법들을 제공한다.

  • Input(shape, batch_size, name): 입력을 받아서 케라스 텐서를 생성하는 객체
  • Dense(units, activation, use_bias, input_shape): 유닛(뉴런)들이 전부 연결된 레이어
  • Embedding(input_dim, output_dim): 문자 입력에 대해서 학습을 요할 때 필요한 레이어

- 입력 데이터(Input Data)

- 손실함수 (Loss Function)

  • MeanSquareError(MSE): 정답 레이블과 예측값 사이의 평균 제곱 오차를 계산
  • Binary_Crossentropy: 정답 레이블과 예측 레이블 간의 교차 엔트로피 손실을 계산
  • Categorical_Crossentropy: 정답 레이블과 예측 레이블 간의 교차 엔트로피 손실을 계산 (정답 레이블은 원핫 인코딩으로 제공)
  • Sparse_Categorical_Crossentropy: 정답 레이블과 예측 레이블 간의 교차 엔트로피 손실을 계산 (정답 레이블은 정수로 제공)

- 옵티마이저 (Optimizer)

  • SGD(Stochastic Gradiant Descent): 확률적 경사하강법. Nesterov 모멘텀을 지원
  • Adagrad: 가변 학습률을 사용하는 방법
  • Adadelta: 모멘텀을 이용하여 감소하는 학습률 문제를 처리하는 Adagrad의 변형
  • RMSprop: Adagrad에 대한 수정판
  • Adam: RMSprop + 모멘텀

- 활성화함수 (Activation Function)

  • sigmoid
  • tanH
  • relu
  • softmax
  • selu
  • softplus

하이퍼 매개변수 설정을 통해 모델의 속성들을 지정해준다. 하이퍼 매개변수란 위에서 살펴본 손실함수, 옵티마이저 등을 뜻하며, 최적의 모델을 위해 어떠한 손실함수를 사용할 것인지, 어떠한 옵티마이저를 사용할 것인지 선택하는 것이 중요하다. 하이퍼 매개변수 선택에는 4가지 방법이 있다.

  1. 기본값 사용: 라이브러리 설계자가 지정한 기본 값으로 사용
  2. 수동 검색: 사용자가 하이퍼 매개변수를 일일이 지정
  3. 그리드 검색: 격자 형태로 하이퍼 매개변수를 변경하면서 성능 측정
  4. 랜덤 검색: 랜덤 선택

1-2. 데이터의 정규화

신경망은 일련의 선형 조합과 비선형 활성화 함수를 통해 이러한 차이가 나는 입력을 결합하여 학습하게 되므로 각 입력과 관련된 매개 변수도 서로 다른 범위를 가지면서 학습된다. 부동 소수점 숫자 정밀도와 관련된 문제를 피하기 위해, 입력 값이 대략 -1.0에서 1.0 범위에 있도록 하는 것이 좋다. 

 

데이터의 정규화 방법

- MinMaxScaler: 모든 값들에 대해 0부터 1까지의 수로 치환하게 된다.

 

1-3. 과잉적합과 과소적합

과잉적합은 학습 횟수가 많아지면 많아질수록 다시 손실률이 올라가는 상태를 말한다. 그런 상황을 방지하기 위해 과잉 적합 방지 전략을 생각해야한다.

  1. 조기 종료: 검증 손실이 증가하면 훈련을 조기에 종료한다.
  2. 가중치 규제 방법: 가중치의 절댓값을 제한한다.
  3. 데이터 증강 방법: 데이터를 훨씬 더 많이 만든다.
  4. 드롭 아웃 방법: 일부의 뉴런의 동작을 멈춘다.

2. CNN (Convolution Neural Network)

2-1. CNN의 개요

CNN은 합성곱 신경망으로도 해석이 되며, 인간의 눈이 영상 정보를 처리하는 것을 모방하여 만든 신경망이다. 복잡하지만 기존의 신경망보다 성능이 우수하다.

 

신경망에서는 하위 레이어의 노드들과 상위 레이어의 노드들이 부분적으로만 연결되어 있다.

 

CNN의 동작 원리

1. 입력층

2. 입력층에서 컨벌루젼 연산을 통하여 특징을 뽑아내는 특징맵이 존재

3. 입력의 차원을 줄이는 연산인 풀링 연산을 적용

4. 2번과 3번 과정 반복

5. 신경망의 맨 끝에는 완전히 연결된 구조의 분류 신경망을 통해 물체를 인식한다.

 

Convolution 연산

 

3 X 3 구조의 커널의 중앙에 입력 레이어의 값들과 가중치 커널들의 곱셈을 진행한 결과 값을 입력한다. 

 

앞서 말했던 것과 같이 중앙에 결과 값을 입력하게 되면 연산이 거듭될수록 이미지의 크기는 줄어들게 된다. 그렇기 때문에 우리는 패딩 기법을 사용한다. 패딩 기법에는 두 가지가 존재한다.

  1. Valid: 커널을 입력 이미지 안에서만 움직이게 하는 것. (하지만, 해당 방법을 사용하면 이미지의 크기가 줄어들기 때문에 upscaling을 진행해야한다.)
  2. Same: 입력 이미지의 주변을 특정값(예를 들어 0, 이웃 픽셀 값)으로 채우는 것

위의 두가지 방법을 사용하여 Convolution 연산을 진행하게 된다.

 

특정 필셀에 대한 연산을 진행한 뒤, 다음 픽셀로 넘어가는 정도를 보폭(stride)이라고 한다. 보폭 값이 크면 빠르게 작업을 진행할 수 있겠지만, 정확도가 떨어지게 되고, 보폭 값이 작으면 시간이 오래 걸리는 대신 정확도가 높다는 특징이 있다.

 

Pooling

풀링이란, 서브 샘플링이라고도 하며, 입력 데이터의 크기를 줄이는 것이다. 보통 최대풀링을 사용하며, Convolution 연산처럼 윈도우(커널과 유사)를 움직이며 안에 있는 숫자 중 가장 큰 값만 출력하는 연산이다.

 

1. 최대 풀링 

 

2. 평균 풀링

풀링을 사용하는 이유는 다음과 같다.

  • 레이어의 크기가 작이지므로 계산이 빨라진다.
  • 신경망의 매개변수가 작아진다는 것을 의미하므로, 과적합이 나올 가능성이 줄어든다.
  • 공간에서 물체의 이동이 있어도 결과는 불변이다. 즉 물체의 공간이동에 대하여 둔감해지게 된다.

CNN을 이용한 예제를 살펴보자.

 

2-2. CNN 예제 1

import tensorflow as tf
import numpy as np
import keras


fashion_mnist = keras.datasets.fashion_mnist
# print(fashion_mnist)
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
print(x_train.shape)
print(x_test.shape)

x_train_CNN = x_train.reshape((-1, 28, 28, 1)) / 255.0 # 학습용 이미지 전처리
x_test_CNN = x_test.reshape((-1, 28, 28, 1)) / 255.0   # 테스트용 이미지 전처리

model_CNN = keras.Sequential([keras.layers.Conv2D(filters=32,   # 필터 사이즈 설정
                                      kernel_size= (3,3), # 커널 사이즈 설정
                                      padding='same',     # 패딩 설정
                                      activation='relu',  # 활성화함수 설정
                                      input_shape = (28, 28, 1)),
                keras.layers.MaxPool2D(pool_size=(2, 2),
                                       strides=2),
                keras.layers.Conv2D(filters=64,   # 필터 사이즈 설정
                                      kernel_size= (3,3), # 커널 사이즈 설정
                                      padding='same',     # 패딩 설정
                                      activation='relu',  # 활성화함수 설정
                                      input_shape = (28, 28, 1)),
                keras.layers.MaxPool2D(pool_size=(2, 2),
                                       strides=2),
                keras.layers.Conv2D(filters=32,   # 필터 사이즈 설정
                                      kernel_size= (3,3), # 커널 사이즈 설정
                                      padding='same',     # 패딩 설정
                                      activation='relu',  # 활성화함수 설정
                                      input_shape = (28, 28, 1)),
                keras.layers.MaxPool2D(pool_size=(2, 2),
                                       strides=2),
                # Convolution
                # DNN하기 전 flatten실행
                keras.layers.Flatten(),
                keras.layers.Dense(units=64, activation='relu', name='LAYER1'),
                keras.layers.Dense(units=32, activation='relu', name='LAYER2'),
                keras.layers.Dense(units=16, activation='relu', name='LAYER3'),
                keras.layers.Dense(units=10, activation='softmax', name='OUTPUT')],
                name = 'FASHION_CNN') 

print(model_CNN.summary())
model_CNN.compile(optimizer='adam', loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

model_CNN.fit(x_train, y_train, epochs=200)
model_CNN.save('2024-08-05_CNN.keras')
# model2 = keras.models.load_model('2024-08-05_CNN.keras')
# y_predicts = model2.predict(x_test_CNN)
# print(f'y_predict: {y_predicts[0]}')
# print(f'y_test   : {y_test[0]}')

import time
for i in range(30):
    print(f'{i+1}번째 예측: {np.round(y_predicts[i])}')
    print(f'{i+1}번째 정답: {y_test[i]}')
    time.sleep(3.0)

Conv2D 함수를 이용하여 Convolution 연산을 진행하고, MaxPool2D 함수를 이용하여 풀링 연산을 진행한다. 적절한 Convolution 연산과 Pooling 연산을 거치게 되면 Flatten함수를 이용하여 1차원으로 평탄화를 시킨다. 평탄화된 배열을 이용하여 이미지 분석을 진행하게 된다. 매번 학습하는 번거로움을 없애기 위해 save메서드를 통해 학습된 모델을 저장했다가 load_model 함수를 이용하여 모델을 불러온다.