article thumbnail image
Published 2021. 7. 24. 18:58

- 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)}%')

 

 

 

<실행 화면>

학습 진행중

 

 

cifar_cnn_E(64).h5 모델의 정확도

test data에 대해 정확도가 85.81% 가 나온 것을 확인할 수 있다.

 

 

 

- Just Do It -

 

반응형

'Python > Machine_learning' 카테고리의 다른 글

[Python] IRIS  (0) 2021.07.24
[Python] MNIST  (0) 2021.06.27
복사했습니다!