목차
구현하기 전 읽어 볼 지식
아래의 👀정답 코드 보기 를 누르기 전 코드를 한번 짜보고 답을 보길 바란다!!
목표
- CNN 모델을 위한 데이터 준비
- 세련된 형태의 CNN 모델 생성, 다양한 layer들의 이해
- CNN 모델 학습 및 성능 관찰
데이터 준비
수화 데이터세트는 csv 형식으로 되어있음.
- 상단에 레이블이 있는 행과 열로 이루어진 그리드
- 데이터를 로드하여 작업하기 위해 데이터 로드 및 조작을 위한 고성능 툴인 Pandas라는 라이브러리를 사용
- CSV 파일은 DataFrame이라는 형식으로 읽음
import pandas as pd
Pandas에는 csv 파일을 예상하고 DataFrame을 반환하는 read_csv 메서드가 존재
- 이를 통해 데이터를 불러 올 것임
👀 정답 코드 보기
# Load in our data from CSV files
train_df = pd.read_csv("data/asl_data/sign_mnist_train.csv")
valid_df = pd.read_csv("data/asl_data/sign_mnist_valid.csv")
레이블 추출
트레이닝 및 검증 레이블을 y_train 및 y_valid 변수에 저장하는 법
1️⃣ 해당 변수를 생성
2️⃣ 다음 레이블이 더 이상 필요없는 데이터프레임 원본에서 레이블을 삭제
👀 정답 코드 보기
# label 이라는 열이 정답열임
y_train = train_df['label']
y_valid = valid_df['label']
del train_df['label']
del valid_df['label']
이미지 추출
트레이닝 및 검증 이미지를 x_train 및 x_valid 변수에 저장
👀 정답 코드 보기
x_train = train_df.values
x_valid = valid_df.values
레이블 분류
keras.utils.to_categorical
메서드를 사용하여 여기에 인코딩할 값과 값을 인코딩할 범주 수를 전달해 범주 인코딩keras를 가져와 범주 수(24)를 설정해둠
import tensorflow.keras as keras
num_classes = 24
이 다음 코드를 짜봐라
- Categorically encode y_train and y_valid
👀 정답 코드 보기
# TODO: Categorically encode y_train and y_valid.
y_train = keras.utils.to_categorical(y_train, num_classes)
y_valid = keras.utils.to_categorical(y_valid, num_classes)
이미지데이터 정규화
데이터의 픽셀 값이 현재처럼 0~255가 아닌 0~1의 부동 소수점 값이 되어야함
보기전에 코드 직접 쳐보고 정말 정답 확인용으로 봐라
👀 정답 코드 보기
x_train = x_train / 255
x_valid = x_valid / 255
❤ 여기까진 MNIST 모델 구현과 같다 ❤
CNN을 위한 이미지 변환 reshaping
현재 데이터 셋의 상태를 확인해보자
x_train.shape, x_valid.shape
# ((27455, 784), (7172, 784))
현재 데이터 셋의 특징
- 서로 가까운 픽셀(위치 정보)에 대한 모든 정보를 가지고 있지 않음
- feature를 탐지하는 컨볼루션(convolution)(합성곱 계층) 적용 불가
[변환]
컨볼루션 적용을 위해 데이터 셋을 28x28픽셀 형식으로 변경
➡ 컨볼루션에서 인접한 픽셀끼리 그룹을 짓고 중요한 feature들을 탐지가능
[모델의 첫번 째 컨볼루션 레이어]
자세한 설명 보러가기
- 이미지의 높이
- 이미지 너비
- 채널의 숫자
우리의 이미지는 Grayscale이기 때문에 채널은 1의 값을 갖음
즉,
(27455, 784) ➡ (27455, 28, 28, 1)
(이미지 개수, 픽셀 개수) ➡ (이미지 개수, 특징맵 가로, 특징맵 세로, 채널 수)
동일하게 유지하기를 원하는 모든 차원에 대해 reshape을 진행하는 경우,
‘-1’ 을 통해 표현할 수 있으므로 다음과 같이 구성
x_train = x_train.reshape(-1,28,28,1)
x_valid = x_valid.reshape(-1,28,28,1)
바뀐 데이터 확인
x_train.shape
# (27455, 28, 28, 1)
x_valid.shape
# (7172, 28, 28, 1)
x_train.shape, x_valid.shape
# ((27455, 28, 28, 1), (7172, 28, 28, 1))
합성곱 모델 생성
아래의 그림을 구현할 것임
필요한건 줄테니 계층을 하나하나 구현해 보자!
- padding=”same” 이다
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import (
Dense,
Conv2D,
MaxPool2D,
Flatten,
Dropout,
BatchNormalization,
)
먼저 인스턴스 부터 생성해라
👀 정답 코드 보기
model = Sequential()
model.add(Conv2D(75, (3, 3), strides=1, padding="same", activation="relu", input_shape=(28, 28, 1)))
model.add(BatchNormalization())
model.add(MaxPool2D((2, 2), strides=2, padding="same"))
model.add(Conv2D(50, (3, 3), strides=1, padding="same", activation="relu"))
model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(MaxPool2D((2, 2), strides=2, padding="same"))
model.add(Conv2D(25, (3, 3), strides=1, padding="same", activation="relu"))
model.add(BatchNormalization())
model.add(MaxPool2D((2, 2), strides=2, padding="same"))
model.add(Flatten())
model.add(Dense(units=512, activation="relu"))
model.add(Dropout(0.3))
model.add(Dense(units=num_classes, activation="softmax"))
그럼 이제 각 매서드를 설명해보자!!
Conv2D
작은 커널은 입력 이미지들을 훑으며, 분류에 중요한 특징들을 파악하는 단계
- 모델의 초기 컨볼루션: 선과 같은 간단한 특징을 탐지
- 그 이후 컨볼루션: 점점 더 복잡한 특징을 탐지
- 층 깊이에 따른 추출정보 변화 더 알아보기
커널 구현
- 75: 우리가 학습하게 될 필터(Filter)의 갯수
- (3,3): 필터의 크기
- strides: 필터가 이미지를 얼마만큼의 간격으로 이동할 것인지
- padding: 입력 이미지와 결과 이미지의 크기를 맞추기 위해서 사용
model.add(Conv2D(75 , (3,3) , strides = 1 , padding = 'same'...)
배치 정규화
입력을 정규화하는 것과 마찬가지로,
배치정규화는 hidden layer들의 값을 scaling하여 학습을 개선
MaxPool2D
풀링의 종류 중 최대 풀링
- 모델이 약간의 변화에 더욱 견고하게 만들기 가능
- 모델의 학습 및 추론 속도 향상
Dropout
과적합(Overfitting)을 방지하는 기술
- 무작위로 뉴런 중 일부를 선택하고 제외시켜, 뉴런들이 특정 경로에서 forward 혹은 backward progation에 참여하지 않도록 함
- 더 알아보기
Flatten
평탄화로 다차원 입력을 1차원으로 변환시켜 줌
- feature vector: Flatten의 결과, 분류를 위한 마지막 layer로 연결
Dense
첫 dense 레이어: (512 유닛)는 feature vector를 입력으로 받으며, 어떠한 Feature가 분류에 기여하는지를 학습
두 번째 dense 레이어: (24 유닛)는 우리의 분류 예측 결과를 위한 마지막 layer로 활용됨
모델 요약
👀 정답 코드 보기
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 28, 28, 75) 750
_________________________________________________________________
batch_normalization (BatchNo (None, 28, 28, 75) 300
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 75) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 50) 33800
_________________________________________________________________
dropout (Dropout) (None, 14, 14, 50) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 14, 14, 50) 200
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 7, 7, 50) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 7, 7, 25) 11275
_________________________________________________________________
batch_normalization_2 (Batch (None, 7, 7, 25) 100
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 4, 4, 25) 0
_________________________________________________________________
flatten (Flatten) (None, 400) 0
_________________________________________________________________
dense (Dense) (None, 512) 205312
_________________________________________________________________
dropout_1 (Dropout) (None, 512) 0
_________________________________________________________________
dense_1 (Dense) (None, 24) 12312
=================================================================
Total params: 264,049
Trainable params: 263,749
Non-trainable params: 300
_________________________________________________________________
모델 컴파일
실제로 데이터를 사용하여 모델을 트레이닝하기 전에 수행해야 할 마지막 단계
- 손실함수:
categorical crossentropy
사용 - 모델의 정확도를 측정
👀 정답 코드 보기
model.compile(loss="categorical_crossentropy", metrics=["accuracy"])
모델 트레이닝
모델의 fit
메서드를 사용하여 위에서 생성한 트레이닝 및 검증 이미지와 레이블로 20에포크 동안 트레이닝해라.
👀 정답 코드 보기
model.fit(x_train, y_train, epochs=20, verbose=1, validation_data=(x_valid, y_valid))
결과 해석
먼저 결과를 보자
Epoch 1/20
858/858 [==============================] - 5s 6ms/step - loss: 0.3107 - accuracy: 0.9055 - val_loss: 0.6278 - val_accuracy: 0.8240
Epoch 2/20
858/858 [==============================] - 4s 5ms/step - loss: 0.0192 - accuracy: 0.9940 - val_loss: 0.4390 - val_accuracy: 0.9131
Epoch 3/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0124 - accuracy: 0.9961 - val_loss: 0.2644 - val_accuracy: 0.9453
Epoch 4/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0085 - accuracy: 0.9973 - val_loss: 0.3846 - val_accuracy: 0.9186
Epoch 5/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0063 - accuracy: 0.9977 - val_loss: 0.3341 - val_accuracy: 0.9463
Epoch 6/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0053 - accuracy: 0.9986 - val_loss: 0.4166 - val_accuracy: 0.9366
Epoch 7/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0047 - accuracy: 0.9990 - val_loss: 0.5201 - val_accuracy: 0.9151
Epoch 8/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0041 - accuracy: 0.9989 - val_loss: 2.2097 - val_accuracy: 0.7839
Epoch 9/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0034 - accuracy: 0.9992 - val_loss: 0.3527 - val_accuracy: 0.9421
Epoch 10/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0024 - accuracy: 0.9993 - val_loss: 0.3070 - val_accuracy: 0.9516
Epoch 11/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0037 - accuracy: 0.9989 - val_loss: 0.3727 - val_accuracy: 0.9481
Epoch 12/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0025 - accuracy: 0.9993 - val_loss: 0.4154 - val_accuracy: 0.9423
Epoch 13/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0024 - accuracy: 0.9996 - val_loss: 0.5034 - val_accuracy: 0.9463
Epoch 14/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0024 - accuracy: 0.9995 - val_loss: 0.7400 - val_accuracy: 0.9296
Epoch 15/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0011 - accuracy: 0.9998 - val_loss: 0.3552 - val_accuracy: 0.9414
Epoch 16/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0011 - accuracy: 0.9997 - val_loss: 0.3995 - val_accuracy: 0.9520
Epoch 17/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0032 - accuracy: 0.9992 - val_loss: 0.4067 - val_accuracy: 0.9511
Epoch 18/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0022 - accuracy: 0.9995 - val_loss: 0.5415 - val_accuracy: 0.9508
Epoch 19/20
858/858 [==============================] - 4s 4ms/step - loss: 8.1472e-04 - accuracy: 0.9998 - val_loss: 0.3580 - val_accuracy: 0.9626
Epoch 20/20
858/858 [==============================] - 4s 4ms/step - loss: 0.0021 - accuracy: 0.9997 - val_loss: 0.5734 - val_accuracy: 0.9399
<tensorflow.python.keras.callbacks.History at 0x7f2323e1feb8>
CNN을 쓰지 않았을 때 보다 학습 정확도도 매우 높고, 검증 정확도도 향상
🚫 검증 정확도가 수렴하지 않음 ➡ 나중에 개선할 것임
메모리
넘어가기 전에 다음 셀을 실행하여 GPU 메모리를 지우기
이는 다음 노트북으로 넘어가기 위한 필수 작업
import IPython
app = IPython.Application.instance()
app.kernel.do_shutdown(True)