참조: 구글 Load and preprocess images
https://www.tensorflow.org/tutorials/load_data/images
※ ImageDataGenerator
https://www.tensorflohttps://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator
ImageDataGenerator 기법은 deprecicated 하므로 tf.keras.utils.image_dataset_from_directory 명령을 사용하자.
과거에는 tf.keras.preprocessing.image.ImageDataGenerator 명령을 사용했으나 이미 낡았으므로 앞으로는 tf.keras.utils.image_dataset_from_directory 명령을 사용하기로 하자.
이 둘울 비교해 보면 ImageDataGenerator 에는 batch_size 가 없으나 utils.image_dataset _from_directory 에는 있음을 알 수 있다. ImageDataGenerator에서 batch_size Default 값은 32 이지만 파라메터가 없으므로 고정된 값으로만 사용된다.
tf.keras.preprocessing.image.ImageDataGenerator( featurewise_center=False, samplewise_center=False, featurewise_std_normalization=False, samplewise_std_normalization=False, zca_whitening=False, zca_epsilon=1e-06, rotation_range=0, width_shift_range=0.0, height_shift_range=0.0, brightness_range=None, shear_range=0.0, zoom_range=0.0, channel_shift_range=0.0, fill_mode='nearest', cval=0.0, horizontal_flip=False, vertical_flip=False, rescale=None, preprocessing_function=None, data_format=None, validation_split=0.0, interpolation_order=1, dtype=None ) |
tf.keras.utils.image_dataset_from_directory( directory, labels='inferred', label_mode='int', class_names=None, color_mode='rgb', batch_size=32, image_size=(256, 256), shuffle=True, seed=None, validation_split=None, subset=None, interpolation='bilinear', follow_links=False, crop_to_aspect_ratio=False, **kwargs ) |
os 라이브러리는 listdir 명령 사용 시 필요하다.
time 라이브러리는 학습 시간과 평가시간 측정에 사용한다.
1 | import os import tensorflow as tf from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout from keras.layers import Flatten from keras.constraints import maxnorm from keras.optimizers import Adam from keras.layers.convolutional import Conv2D from keras.layers.convolutional import MaxPooling2D from keras.utils import np_utils import numpy as np import time import matplotlib.pyplot as plt |
처리해야 할 이미지 사이즈를 표준적으로 (224, 224) 로 설정하자.
2 | plt.figure() # 뒤에 나오는 matplotlib 사진 출력 data_root = ("D:/⦁⦁⦁/ImageClassfication/DataSet") # 6종의 식물 데이터 폴더 IMAGE_SHAPE = (224, 224) # 표준 이미지 사이즈 지정 INPUT_SHAPE = (224, 224, 3) # 커러 이미지 shape 지정 TRAINING_DATA_DIR = str(data_root) |
TRAINING_DATA_DIR 폴더에 들어 있는 6개의 식물 데이터 폴더들을 사용하여 검증용(valid) 데이터와 학습용(train) 데이터를 준비하자. ※ 폴더의 식물명이 라벨값이 된다. **kwargs 는 dict 형태 인수들의 입출력에 사용된다.
3 | kwargs = dict(rescale=1./255, validation_split=.20) valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(**kwargs) valid_generator = valid_datagen.flow_from_directory( TRAINING_DATA_DIR,subset="validation",shuffle=True,target_size=IMAGE_SHAPE ) train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(**kwargs) train_generator = train_datagen.flow_from_directory( TRAINING_DATA_DIR,subset="training",shuffle=True,target_size=IMAGE_SHAPE ) |
train_generator 에서 image_batch 와 label_batch 튜플 데이터를 뽑아내자.
4 | for image_batch, label_batch in train_generator: break print(image_batch.shape) print(label_batch.shape) for valid_image_batch, valid_label_batch in valid_generator: break print(valid_image_batch.shape) print(valid_label_batch.shape) print(label_batch[0:2]) |
식물별 폴더의 라벨 번호와 라벨 명을 합o dict 형태로 출력한다.
4 | print(train_generator.class_indices) plt.imshow(valid_image_batch[0]) |
Sequential 에 의해 신경망을 구성한다.
첫 번째 CNN 은닉층에서 (3,3) 디지털 필터 커늘을 64개 사용 후 (2,2) 로 MaxPooling 하여 이미지 크기를 축소한 후 한 줄로 펴서(flattening), 완전연결계층(fully connected layer)에 입력한다. 224->128->6 으로 크기를 줄인 후 softmax 처리한다.
옵티마이져는 Adam을 사용한다. loss 함수는 keras 의 categorical_crossentropy를 사용한다. 척도는 [‘acc’] 를 사용는 바 softmax 로 연산된 확률 중 가장 큰 값을 argmax 로 찾아내어 정답 라벨값과 비교하여 정오 수를 체크하여 인식률을 측정한다.
5 | model = Sequential([ Conv2D(64,(3,3),activation = 'relu', input_shape=INPUT_SHAPE), MaxPooling2D(2,2), Flatten(), Dense(128,activation = 'relu'), Dense(6, activation = 'softmax')]) model.summary() optimizer = Adam(learning_rate=1e-3) model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['acc']) |
학습용 샘플 수를 batch_size 로 나누어 epoch 별 반복 학습 회수를 결정하자.
6 | steps_per_epoch = np.ceil(train_generator.samples/train_generator.batch_size) val_steps_per_epoch=np.ceil(valid_generator.samples/valid_generator.batch_size) |
epochs = 100 일 때의 학습 완료 후 연산 소요 시간이 출력된다. GPU 없는 PC에서 663초 연산이 이루어졌다.
7 | start = time.time() hist = model.fit( train_generator, epochs=100, verbose=1, steps_per_epoch=steps_per_epoch, validation_data=valid_generator, validation_steps=val_steps_per_epoch).history end = time.time() print('train time', end-start, '초') |
학습과 검증용 인식률 계산결과를 참고하자. 학습용은 충분한 학습으로 학습용 데이터에 대해서 100 % 인식률을 보여주지만 검증용에 대해서는 72% 의 인식률을 보여준다. epochs 값을 100에서 120 으로 중가시키면 807 초로 연산시간이 소요되었으며 검증용 인식률이 77.7% 로 증가되었다.
![](https://blog.kakaocdn.net/dn/bPm942/btsiO5iApiM/IjbMPCHRLTrCe51sxRnXjK/img.png)
데이터 파일을 직접 준비하지 못한 경우에는 필자가 만들어 사용한 아래의 6개 압축파일을 다운받아 압축을 해제하여 DataSet 폴더를 만들어 집어 넣은 후 이 DataSet 폴더를 바로 위의 실행 파일이 들어 있는 폴더에 설치한 후 위 실행파일을 실행해 보자.
※ tistory 블로그에 압축파일 크기가 20M 로 제한되어 있어 6개로 나누어 압축파일을 올려두었음