
- Convolution Neural Network를 활용한 CIFAR-10 머신러닝 -
<개요>
1. tensorflow 의 CIFAR-10 dataset 로드
2. cnn으로 모델 make
3. train dataset 활용해 학습
4. test dataset 활용해 테스트 및 정확도 도출
# CIFAR-10
CIFAR-10 32x32픽셀의 60,000개 컬러 이미지가 포함되어있으며,
각 이미지는 10개의 클래스로 라벨링이 되어있는 dataset이다.
60,000개 중, 50,000개 이미지는 트레이닝, 10,000개 이미지는 테스트 용도로 사용
# Conv2D
합성곱 레이어, 즉 컨벌루션 레이어는 합성곱을 통해,
3차원의 이미지를 그대로 입력층에 받고, 출력 또한 3차원 데이터로 출력하여 다음 Layer로 전달하는 방식으로,
형상을 가지는 데이터를 제대로 학습할 수 있게 된다.
# BatchNormalization
학습의 효율을 높이기 위해 도입되었다. 배치 정규화는 Regularization을 해준다고 볼 수 있음.
장점 :
학습 속도가 개선된다.
가중치 초깃값 선택의 의존성이 적어진다. (학습을 할 때마다 출력 값을 정규화하기 때문)
과적합(overfitting) 위험을 줄일 수 있다.
# MaxPooling2D
parameter를 줄여서 Overfitting을 억제한다.
Parameter를 줄이므로 computation이 줄어들어 속도를 향상한다.
# Dropout
Dropout은 네트워크의 일부를 생략하는 것으로,
일부 노드를 빼고 학습을 진행하여 생략한 네트워크는 영향을 끼치지 않게 하는 것이다.
이렇게 하면 학습 데이터에만 의존하는 정도가 좀 덜해짐으로 과적합(overfitting)을 줄일 수 있다.
<코드 설명>
import tensorflow as tf
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import *
from tensorflow.python.keras.models import load_model
dataset 로드를 위한 라이브러리와 모델 생성에 필요한 라이브러리를 import 한다.
def make_model():
model = Sequential()
# layer 1
model.add(Conv2D(32, (3, 3), padding='same', input_shape=(32, 32, 3), activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
# layer 2
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.3))
# layer 3
model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.4))
# layer 4
model.add(Conv2D(256, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(256, (3, 3), padding='same' ,activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.4))
# layer 5
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.4))
model.add(Dense(10, activation='softmax'))
model.summary()
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
Conv2D, BatchNormalization, MaxPooling2D, Dropout layer를 활용해 4개의 층과
Flatten, Dense layer를 활용하여 5번째 층으로 이루어진 모델을 만들었다.
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 32, 32, 32) 896
_________________________________________________________________
batch_normalization (BatchNo (None, 32, 32, 32) 128
_________________________________________________________________
conv2d_1 (Conv2D) (None, 30, 30, 32) 9248
_________________________________________________________________
batch_normalization_1 (Batch (None, 30, 30, 32) 128
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 15, 15, 32) 0
_________________________________________________________________
dropout (Dropout) (None, 15, 15, 32) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 15, 15, 64) 18496
_________________________________________________________________
batch_normalization_2 (Batch (None, 15, 15, 64) 256
_________________________________________________________________
conv2d_3 (Conv2D) (None, 13, 13, 64) 36928
_________________________________________________________________
batch_normalization_3 (Batch (None, 13, 13, 64) 256
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 6, 6, 64) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 6, 6, 64) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 6, 6, 128) 73856
_________________________________________________________________
batch_normalization_4 (Batch (None, 6, 6, 128) 512
_________________________________________________________________
conv2d_5 (Conv2D) (None, 6, 6, 128) 147584
_________________________________________________________________
batch_normalization_5 (Batch (None, 6, 6, 128) 512
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 3, 3, 128) 0
_________________________________________________________________
dropout_2 (Dropout) (None, 3, 3, 128) 0
_________________________________________________________________
conv2d_6 (Conv2D) (None, 3, 3, 256) 295168
_________________________________________________________________
batch_normalization_6 (Batch (None, 3, 3, 256) 1024
_________________________________________________________________
conv2d_7 (Conv2D) (None, 3, 3, 256) 590080
_________________________________________________________________
batch_normalization_7 (Batch (None, 3, 3, 256) 1024
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 1, 1, 256) 0
_________________________________________________________________
dropout_3 (Dropout) (None, 1, 1, 256) 0
_________________________________________________________________
flatten (Flatten) (None, 256) 0
_________________________________________________________________
dense (Dense) (None, 512) 131584
_________________________________________________________________
dropout_4 (Dropout) (None, 512) 0
_________________________________________________________________
dense_1 (Dense) (None, 10) 5130
=================================================================
Total params: 1,312,810
Trainable params: 1,310,890
Non-trainable params: 1,920
_________________________________________________________________
모델의 layer 와 params의 개수이다.
def train(model, x ,y):
# float 타입으로 변환 -> .
# 특징점을 보다 더 세밀하게 추출할 수 있도록 0.0~1.0 사이의 값으로 정규화
x = x / 255.
# label one hot encoding
y = tf.keras.utils.to_categorical(y, 10)
# fit 함수로 학습
history = model.fit(x, y, epochs=MY_EPOCH, batch_size=MY_BATCH)
# 모델 저장
model.save(filename)
return history
train dataset을 이용하여 학습시킨다.
train 함수의 파라미터(model, x, y)에는 make_model 함수로 생성한 모델, train_img, train_label을 넣어 줄 것이다.
def test(x, y):
model = load_model(filename)
# float 타입으로 변환 -> .
x = x / 255.
# label one hot encoding
y = tf.keras.utils.to_categorical(y, 10)
# evaluate 함수로 평가 -> 정확도 도출
test_loss, test_acc = model.evaluate(x, y)
return test_loss, test_acc
test dataset으로 테스트 및 정확도를 도출한다.
test 함수의 파라미터(x, y)에는 test_img, test_label 이 들어간다.
if __name__ == '__main__':
# dataset load
(train_img, train_label), (test_img, test_label) = cifar10.load_data()
# hyper parameters
MY_EPOCH = 64
MY_BATCH = 100
filename = f'cifar_cnn_E({MY_EPOCH}).h5'
# make a model
cifar_cnn = make_model()
# train
train(cifar_cnn, train_img, train_label)
main 문이다.
CIFAR-10 dataset 로드와 함께 각각의 변수에 저장한다.
hyper parameter 들을 설정한다.
위에서 만든 함수들을 이용해 모델을 불러오고 학습시키다.
# test
loss, acc = test(test_img, test_label)
print(f'"{filename}" 모델의 정확도 : {round(100 * acc, 2)}%')
마지막으로, test 함수를 이용해 정확도를 도출한다.
<전체 코드>
import tensorflow as tf
from tensorflow.keras.datasets import cifar10
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import *
from tensorflow.python.keras.models import load_model
def make_model():
model = Sequential()
# layer 1
model.add(Conv2D(32, (3, 3), padding='same', input_shape=(32, 32, 3), activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
# layer 2
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.3))
# layer 3
model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.4))
# layer 4
model.add(Conv2D(256, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(256, (3, 3), padding='same' ,activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.4))
# layer 5
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.4))
model.add(Dense(10, activation='softmax'))
model.summary()
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
def train(model, x ,y):
x = x / 255.
y = tf.keras.utils.to_categorical(y, 10)
history = model.fit(x, y, epochs=MY_EPOCH, batch_size=MY_BATCH)
model.save(filename)
return history
def test(x, y):
model = load_model(filename)
x = x / 255.
y = tf.keras.utils.to_categorical(y, 10)
test_loss, test_acc = model.evaluate(x, y)
return test_loss, test_acc
if __name__ == '__main__':
(train_img, train_label), (test_img, test_label) = cifar10.load_data()
# hyper parameters
MY_EPOCH = 64
MY_BATCH = 100
filename = f'cifar_cnn_E({MY_EPOCH}).h5'
cifar_cnn = make_model()
# train
train(cifar_cnn, train_img, train_label)
# test
loss, acc = test(test_img, test_label)
print(f'"{filename}" 모델의 정확도 : {round(100 * acc, 2)}%')
<실행 화면>
test data에 대해 정확도가 85.81% 가 나온 것을 확인할 수 있다.
- Just Do It -
'Python > Machine_learning' 카테고리의 다른 글
[Python] IRIS (0) | 2021.07.24 |
---|---|
[Python] MNIST (0) | 2021.06.27 |