상세 컨텐츠

본문 제목

[Kaggle] Four Shape

AI/Kaggle

by cepiloth 2022. 1. 1. 18:42

본문

728x90
반응형

 

Four Shapes

16,000 images of four basic shapes (star, circle, square, triangle)

www.kaggle.com

 

오늘은 캐글 데이터 세트에 있는 Four Shapes을 이용하여 분류(인식) 모델을 만들어 보려고 합니다. 별, 동그라미, 세모 사각형 4개의 이미지가 총 16000개 있으면 이를 정확하기 분류하는 모델을 만들어 보려고 합니다.

 

접근 아이디어

별, 동그라미, 세모, 사각형 4 가지의 도형은 모두 특색이 있어 회전이나 Affine Transform을 하더라도 데이터 간에 겹치는 부분이 생기지 않을 거 판단이 듭니다. 만약 마름모와 네모가 있다면 네모를 45도 회전을 하면 마름모로 추정될 수 있는데 4가지 도형에서는 변환에 의해서 같아지는 경우가 없어 보입니다. 

 데이터가 16000개 도형별로 4000개 정도로 있으니 따로 데이터 증강은 할 필요없어 보이고 기본 CNN으로도 충분히 분류 가능하다고 판단 하였습니다.

 

코드 설명

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the "../input/" directory.
# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory

import os
#print(os.listdir("../input/shapes/*"))

import glob
import cv2
from sklearn.utils import shuffle

import keras
from keras.models import Sequential
from keras.layers import Dense,Conv2D,MaxPooling2D,Flatten,Dropout
from keras.layers.normalization import BatchNormalization

 기본 패키지를 import를 합니다 numpy는 수치 계산을 효율적으로 하는 라이브러리입니다. pandas는 데이터 조작 및 분석을 위해 Python 프로그래밍 언어 용으로 작성된 소프트웨어 라이브러리 입니다. 특히 숫자 테이블과 시계열 데이터를 조작할때 편리합니다. os, glob 은 파이썬에서 파일처리를 할때 사용됩니다. sklearn.utils 의 shuffle은 입렵된 배열을 섞어주는 역할을 하는 라이브러리 입니다.

 

import keras
from keras.models import Sequential
from keras.layers import Dense,Conv2D,MaxPooling2D,Flatten,Dropout
from keras.layers.normalization import BatchNormalization

Keras는 파이썬으로 작성된 오픈 소스 신경만 라이브러리이며 MXNet, Deeplearning4J, Tensorflow, Microsoft Cognitive Toolkit 또는 Theano 위에서 수행할 수 있는 라이브러리입니다.

Sequential 모델을 생성할 때 순차적으로 레이어 층을 더할 때 사용합니다. Dense는 이전 네트워크 계층의 모든 뉴런과 결합된 형태의 Layer(fully-connectd layer)이며 활성 함수를 설정할 수 있습니다.

Conv2D는 합성곱 계층으로서 Convolution Layer를 의미합니다. 합성곱 신경망에서 핵심이자 가장 중요한 구성 요소이며 데이터의 형상을 유지하면서 학습시키기 위한 뉴런의 형태로 달라지는데 이를 Filter 혹은 kernel이라고 부르며 이 필터가 바로 합성곱 계층에서의 가중치에 해당하며, 유사한 이미지의 영역을 강조하는 특성 맵(feature map)을 출력하여 다음 계층으로 전달하는 역할을 수행합니다.

MaxPooling2D은 폴링 계층(Pooling Layer)라고도 불리며 사용하는 이유는 이미지의 크기를 줄이면서 데이터의 손실을 막기 위해 합성곱 계층에서 스트라이드 값을 1로 지정하는 대신, 폴링 계층을 사용하기도 합니다. 또 다른 이유로는 합성곱 계층의 과적합(Overfitting)을 막기 위해 폴링 계층이 사용되기도 합니다. Max pooling과 Averge pooling 두 가지의 기법을 주로 사용합니다.

Flattern은 컨볼루션 층이나 풀링 레이어에서 주어진 이미지를 2차원 배열로 다루게 되는데 이때 1차원으로 바꿔주는 역할을 합니다.

Dropout은 노드가 많아지거나 층이 많아진다고 해서 학습이 좋아지는 것이 아니고 오히려 과적합에 빠질 수 있고, 이것을 얼마나 효과적으로 피해 가는지가 중요하다고 볼 수 있습니다. 그중 간단하지만 효과가 큰 기법이 드롭아웃이며 은닉층에 배치된 노드 중 일부를 임의로 삭제해주는 역할을 합니다.

 

#Define a path to our data
circle_train_path = '../input/shapes/*circle'
square_train_path = '../input/shapes/*square'
star_train_path = '../input/shapes/*star'
triangle_train_path = '../input/shapes/*triangle'

cir_path = os.path.join(circle_train_path,'*g')
sq_path = os.path.join(square_train_path,'*g')
str_path = os.path.join(star_train_path,'*g')
trg_path = os.path.join(triangle_train_path,'*g')
#create train array
x_train = []
y_train = []

훈련을 진행할 각 도형 이미지의 경로를 설정합니다. 

 

print("Reading Training Data")
#reading data to memory
file_1 = glob.glob(cir_path)
for f1 in file_1:
    img = cv2.imread(f1)
    x_train.append(img)
    y_train.append([1,0,0,0])
    
print("25% Complete")
    
file_2 = glob.glob(sq_path)
for f2 in file_2:
    img = cv2.imread(f2)
    x_train.append(img)
    y_train.append([0,1,0,0])
    
print("50% Complete")
    
file_3 = glob.glob(str_path)
for f3 in file_3:
    img = cv2.imread(f3)
    x_train.append(img)
    y_train.append([0,0,1,0])
    
print("75% Complete")
    
file_4 = glob.glob(trg_path)
for f4 in file_4:
    img = cv2.imread(f4)
    x_train.append(img)
    y_train.append([0,0,0,1])
    
x_train = np.array(x_train)
y_train = np.array(y_train)

x_train, y_train = shuffle(x_train,y_train)

print("Finished Reading Training Data")

glob 함수를 이용해 각 도형의 경로를 읽어 x_train에 이미지를 삽입 y_train은 결과 값은 지정하는데 여기서 사용된 방법은 레이블을 따로 사용하지 않고 결괏값을 이용하는 방법을 사용하였습니다.

동그라미 - [1, 0, 0, 0] / 네모 - [0, 1, 0, 0] / 별 - [0, 0, 1, 0] /  삼각형 - [0, 0, 0, 1]

 

#create a model
model = Sequential()
model.add(Conv2D(32,(3,3),activation='relu',input_shape = (200,200,3)))
model.add(MaxPooling2D((2,2),strides = (2,2)))
model.add(BatchNormalization())
model.add(Conv2D(64,(2,2),activation='relu'))
model.add(MaxPooling2D((2,2),strides = (2,2)))
model.add(Conv2D(128,(2,2),activation='relu'))
model.add(MaxPooling2D((2,2),strides = (2,2)))
model.add(BatchNormalization())
model.add(Conv2D(256,(5,5),activation='relu'))
model.add(MaxPooling2D((2,2),strides = (2,2)))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(4096,activation = 'relu'))
model.add(Dropout(0.5))
model.add(Dense(4,activation='softmax'))

Sequential를 이용하여 순차 모델을 만듭니다. input_shape의 값이 200, 200, 3 인 이유는 입력으로 들어오는 훈련용 이미지가 200x200 크기이며 RGB(3 채널) 데이터만 사용한다는 의미입니다. Conv2D, MaxPooling2D, BatchNormalization 순서로 레이어가 구성 된 것을 확인할 수 있습니다. 배치 정규화(Batch Normalization)는 가중치의 scale을 정규화하여 gradient exploding을 방지하는 역할을 수행합니다.

자세한 사항은 https://eehoeskrap.tistory.com/430 참고하시면 됩니다.

 

#model compile, fit and save
model.compile(loss=keras.losses.categorical_crossentropy,
             optimizer=keras.optimizers.SGD(lr=0.00001),
             metrics = ['accuracy'])

model.fit(x_train,y_train,batch_size = 1,epochs = 2,verbose = 1,validation_split = 0.0)
model.save('shape_recg.h5')
#del model

이제 모델을 훈련합니다. 분류할 이미지의 종류가 적고 해서 epoch는 2회만 수행합니다.

Epoch 1/2
14970/14970 [==============================] - 304s 20ms/step - loss: 0.1116 - acc: 0.9655
Epoch 2/2
14970/14970 [==============================] - 302s 20ms/step - loss: 0.0147 - acc: 0.9974

epoch 당 훈련시간은 약 5분 손실 1%, 정확도가 99%가 나왔습니다.

 

이제 모델을 저장하고 테스트해보겠습니다.

#load our model again
from keras.models import load_model
model = load_model('shape_recg.h5')
import cv2
import numpy as np
#test model on image
dir_path = '../input/shapes/circle/2.png'
test_img = cv2.imread(dir_path)
test_img = test_img.reshape(1,200,200,3)

Y = model.predict(test_img)[0]
val = np.argmax(Y)
if(val == 0):
    print("Circle")
elif(val == 1):
    print("Square")
elif(val == 2):
    print("Star")
else:
    print("Triangle")

출력 결과

Circle

 

해당 데이터셋과 문제는 딥러닝을 조금만 공부하더라도 실습할 수 있는 문제입니다. 처음 캐글을 시작할 때 타이타닉 문제라던지 기본 예제 문제를 풀어보는 것도 좋지만 해당 문제가 저는 더 심플해서 입문용으로 추천합니다. 

 

전체 소스코드는 https://www.kaggle.com/cepiloth/four-shapes 에서 확인할 수 있습니다.

728x90
반응형

댓글 영역