데이터 선정
데이터는 AI Hub에서 신청하면 무료로 받을 수 있는 한식이미지를 선정했고 총 15만개의 이미지 데이터 중 4000개만 사용했습니다.
(데이터 신청 시 서약서를 작성하는데 서약서에는 사용 기간을 명시해야 하고, 저는 사용기한이 6월 말까지였기 때문에 이미지를 따로 올리지 않는 점 양해바랍니다.)
개발 환경 및 라이브러리
개발 환경은 구글의 colab이며, 텐서플로우 케라스를 사용하였습니다.
코랩 환경 설정
이미지 데이터를 사용하기 때문에 이미지를 불러들일 필요가 있는데 저는 구글 드라이브에 이미지들을 올려놓고 사용했습니다.
from google.colab import drive # 코랩 구글드라이브 연동
drive.mount('/gdrive', force_remount=True)
* 참고로 새로 접속할 때마다 구글 드라이브와 연결해야하므로 한번 연결됐다고 주석처리하면 안됩니다. *
마운트 경로는 자신의 경로에 맞게 고쳐서 사용할 수 있습니다.
데이터 늘리기
또한 그냥 4000장만 사용했을 때는 데이터셋의 양이 작고 성능이 낮게 나오기 때문에 먼저 이미지들을 numpy 배열로 변환하고 ImageDataGenerator를 사용해 약 3만 7천개로 데이터를 늘렸습니다.
numpy배열 변환은 이 블로그(lsjsj92.tistory.com/357?category=792966)를 참고하였습니다. 코드를 그대로 사용한 게 아니라 저에게 맞게 변형하였기 때문에 제 코드를 올리기보단 블로그 주소를 남기는 것이 낫겠다고 생각하여 주소만 기입합니다.
ImageDataGenerator를 이용해 데이터셋을 늘리는 여러 코드들이 나와있지만 저는 이 블로그(jeongmin-lee.tistory.com/5)를 참고해서 경로와 데이터 생성 갯수만 수정해서 사용했습니다.
import numpy as np
import os
from os import listdir
from os.path import isfile, join
from PIL import Image
from google.colab import drive # 코랩 구글드라이브 연동
drive.mount('/gdrive', force_remount=True)
np.random.seed(3)
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
data_datagen = ImageDataGenerator(rescale=1./255)
data_datagen = ImageDataGenerator(rescale=1./255,
rotation_range=30,
shear_range=5.5,
# width_shift_range=0.1,
# height_shift_range=0.1,
zoom_range=0.,
horizontal_flip=True,
vertical_flip=True,
fill_mode='nearest')
filename_in_dir = []
for root, dirs, files in os.walk('/gdrive/My Drive/data/dataset/gobchang92'):
for fname in files:
full_fname = os.path.join(root, fname)
filename_in_dir.append(full_fname)
for file_image in filename_in_dir:
img = load_img(file_image)
x = img_to_array(img)
x = x.reshape((1,) + x.shape)
i = 0
for batch in data_datagen.flow(x,save_to_dir='/gdrive/My Drive/data/dataset/datagenerator/gobchang', save_prefix='gobchang', save_format='jpg'):
i += 1
if i > 16:
break
CNN 구조
가장 단순하다고 할 수 있는 CNN 구조입니다. 코드로 작성하면 아래와 같습니다.
with K.tf_ops.device('/device:GPU:0'):
model = Sequential()
model.add(Conv2D(64, (3,3), padding='same', activation='relu', input_shape=(64,64,3)))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Conv2D(128, (3,3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Conv2D(256, (3,3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Conv2D(512, (3,3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Conv2D(1024, (3,3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Conv2D(2048, (3,3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(nb_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
정확도는 5번 돌려봤을 때 95%정도가 나왔습니다.
'CNN' 카테고리의 다른 글
CNN 용어 정리 (0) | 2020.10.03 |
---|---|
ResNet 라이브러리 사용해보기 (0) | 2020.10.03 |