ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [딥러닝] CNN 활용하여 MNIST 예제 쉽게 따라하기
    딥러닝 공부하기 2023. 12. 27. 00:09

    ▶︎ CNN(Convolutional Neural Network) 란? 

    이름에서 알 수 있듯이 합성곱(새로운 연산)을 활용한 신경망 딥러닝 모델입니다.

    필터가 상하좌우 이동하면서 데이터와 convolution을 하여 특징을 추출합니다. 일반적인 Dense layer보다 적은 수의 파라미터θ로 데이터의 주요 특징을 찾아낼 수 있습니다. 

     

    ▶︎ 합성곱을 쓰는 이유는 무엇이고, 어떤 데이터에 적합해

    합성곱을 쓰는 이유는 "적은 수의 파라미터θ로 데이터의 주요 특징을 찾아낼 수 있기 때문." 입니다 

    필터를 이동시키면서 서로 다른 데이터의 특성을 추출하기 때문에 공간적(지역적, 위치적, 계층적) 패턴을 가지고 있는 이미지, 신호 데이터에 적합합니다.

    필터는 우리가 원하는 목적에 맞게 선정하거나 컴퓨터가 그 특징을 잘 찾을 수 있는 필터를 찾아줍니다. 이를 통해 데이터를 분해하고 변환하면서 일반화할 수 있고, 물체가 어디에 있든 필터를 이동하면서 위치를 파악할 수 있습니다.

    레이어가 쌓일수록 국소적인 특징에서 추상적인 특징을 인식합니다.

     

    ※ 이미지의 Hello World인 MNIST 데이터를 사용하겠습니다. MNIST 데이터는 0~9까지의 손글씨 데이터인데, 이미지를 학습하여 어떤 숫자인지 맞추는 것입니다. 28*28픽셀로 구성된 흑백 손글씨로, 학습 데이터는 6만 개, 테스트 데이터는 1만 개로 이루어져있습니다. 

    https://kr.mathworks.com/discovery/convolutional-neural-network-matlab.html

     

    1. 필요한 라이브러리들을 불러옵니다.

    import tensorflow as tf
    from tensorflow.keras import datasets, utils
    from tensorflow.keras import models, layers, activations, initializers, losses, optimizers, metrics
    
    import numpy as np
    import pandas as pd
    
    import os
    os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

     

    2. 데이터를 불러와서 알맞은 크기로 정규화를 시키고, 정답인 라벨 데이터는 to_categorical로 원핫벡터로 바꿔주어 나중에 손실함수 계산할 수 있도록 데이터를 준비해줍니다.

    # train, test data split
    (train_data, train_label), (test_data, test_label) = datasets.mnist.load_data()
    
    # Normalization
    train_data = train_data.reshape(60000, 28, 28, 1) / 255.0 
    test_data = test_data.reshape(10000, 28, 28, 1) / 255.0
    
    # 정답 데이터 원핫 인코딩으로 변환
    train_label = utils.to_categorical(train_label) # 0~9 -> one-hot vector
    test_label = utils.to_categorical(test_label) # 0~9 -> one-hot vector

     

    3. 모델을 설계하고 구축하고 정의합니다. Convolution, Batch Normalization, 활성화함수, Pooling을 활용하여 히든 레이어를 만들고 마지막에 fully-connected network(+ 모델 성능에 따라 Dropout 추가)를 펼쳐주며 output layer 분류를 위한 준비를 합니다.

    model = models.Sequential() 
    
    # Conv2D 파라미터 : Filter의 갯수(32), Filter의 shape(3,3), X data 1장의 shape(28,28,1) 
    model.add(layers.Conv2D(32, (3, 3), input_shape=(28, 28, 1))) 
    model.add(layers.BatchNormalization())
    model.add(layers.Activation('relu'))
    
    model.add(layers.Conv2D(32, (3, 3)))
    model.add(layers.BatchNormalization())
    model.add(layers.Activation('relu'))
    
    model.add(layers.MaxPooling2D(pool_size=(2, 2)))
    
    
    model.add(layers.Conv2D(64, (3, 3)))
    model.add(layers.BatchNormalization())
    model.add(layers.Activation('relu'))
    
    model.add(layers.Conv2D(64, (3, 3)))
    model.add(layers.BatchNormalization())
    model.add(layers.Activation('relu'))
    
    model.add(layers.MaxPooling2D(pool_size=(2, 2)))
    
    
    # Fully-connected network
    model.add(layers.Flatten()) # 전체 차원 펼치기.
    
    model.add(layers.Dense(512))
    model.add(layers.BatchNormalization())
    model.add(layers.Activation('relu'))
    model.add(layers.Dropout(rate=0.3)) # 오버피팅, 언더피팅에 따라 조정하기
    
    # output layer label 클래스의 갯수 : 10개
    model.add(layers.Dense(10, activation='softmax'))
    
    # 모델 구조 확인하기
    model.summary()

     

    4. 실 함수, 옵티마이저의 종류를 설정하여 기준을 설계하고 정의합니다.

    # 라벤을 원핫인코딩했기 때문에 sparse 사용하지 않음
    model.compile(optimizer=optimizers.Adam(), 
                  loss=losses.categorical_crossentropy, 
                  metrics=[metrics.categorical_accuracy]) # Precision / Recall / F1-Score 적용해보기

     

    5. Data Augumentation 활용하여 변형을 주고 노이즈를 주면서 오버피팅을 줄이고 일반화 성능을 높입니다. 또한 데이터를 늘리면서 클래스의 불균형을 해소시킬 수도 있습니다.

    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    
    
    gen_train = ImageDataGenerator(rotation_range=8,        # Degree range for random rotations.
                                   shear_range=0.3,         # Shear Intensity (Shear angle in counter-clockwise direction in degrees)
                                   width_shift_range=0.08,  # Fraction of total width
                                   height_shift_range=0.08, # Fraction of total height
                                   zoom_range=0.08)         # Range for random zoom ([lower, upper] = [1-zoom_range, 1+zoom_range])
    
    # 랜덤으로 변형해서 학습에 사용합니다
    train_generator = gen_train.flow(train_data, train_label, batch_size=64) # flow_from_directory() 활용 가능
    
    gen_test = ImageDataGenerator() # Test data에는 Augmentation을 적용하지 않습니다. 단순 통과하는 빈껍데기
    
    test_generator = gen_test.flow(test_data, test_label, batch_size=64)

     

    6. 모델을 학습합니다

    history = model.fit(train_generator, 
                        steps_per_epoch=60000 // 64, # == 배치 갯수
                        epochs=5)

     

    7. evaluate로 모델을 채점합니다.

    result = model.evaluate(test_data, test_label)
    
    print('loss (cross-entropy) :', result[0])
    print('test accuracy :', result[1])
    # 모델 예측 결과
    np.argmax(model.predict(test_data[:10]), axis=1)
    
    # 실제 정답
    np.argmax(test_label[:10], axis=1)

     

    꽤 높은 정확도를 보이는 것을 확인할 수 있었습니다. 

     

    참조 : https://kr.mathworks.com/discovery/convolutional-neural-network-matlab.html

Designed by Tistory.