CNN은 영상의 2차원 변환인 회전(Rotation), 크기(Scale), 밀림(Shearing), 반사(Reflection), 이동(Translation)와 같은 2차원 변환인 Affine Transform에 취약하다. 즉, Affine Tranform으로 변환된 영상은 다른 영상으로 인식한다.
또한 이 뿐만 아니라 Noise삽입, 색상, 밝기 변형 등을 활용하여 Data Augmentation 효과를 얻을 수 있다.
Data Augmentation을 위한 데이터 생성(generator)하는 방법으로 keras의 ImageDataGenerator을 사용할 수 있다. 이 Data Generator는 이미지에 변화를 주면서 컴퓨터의 학습자료로 이용하여 더욱 효과적이고 과적합을 방지하는 방식으로 학습할 수 있도록 한다.
(https://keraskorea.github.io/posts/2018-10-24-little_data_powerful_model/글에서 알려준 바에 따라)
ImageDataGenerator는
1. 학습 도중 이미지에 임의 변형 및 정규화를 적용해 주고
2. 변형된 이미지를 배치 단위로 불러올 수 있는 Generator을 생성해 준다.
- generator 생성 할 때, flow(data, label)과 flow_from_directory(directory) 두 가지 함수를 사용하며
- 이미지를 불러오고 모델을 학습 할 때, fit_generator와 evaluate_generator 함수를 사용한다.
3. genetor의 transformation parameter(이미지에 어떤 변화를 줄 수 있는지)는 매우 많으며, 그 중 대표적으로 많이 사용되는 것들은
- rotation_range
- width_shift_range
- height_shift_range
- brightness_range
- zoom_range
- horizontal_flip
- vertical_flip
- preprocessing_function
- rescale
- : transformation은 이미지에 변화를 주어서 학습 데이터를 많게 해서 성능을 높이기 위해 하는 것이기 때문에 train set만 해주고, test set에는 해 줄 필요가 없다. 그러나 주의할 것은 Rescale은 train, test 모두 해 주어야 한다.
train_datagenerator = ImageDataGenerator(
zoom_range = 0.7,
rescale = 1. /255.
)
test_datagenerator = ImageDataGenerator(
rescale = 1. /255.
)
등이 있다. (참고: www.keras.io/preprocessing/image/ )
2. 구현
1) flow(data, label) 사용하여 generator생성하는 경우
MNIST 데이터를 사용하여 datagenerator.flow(inputs) 형식으로 Data Augmentation을 진행한다.
# 0. 필요한 함수 import
import os
from glob import glob
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
#1. 데이터 파일 경로찾기 및 Read, Load Image
data_path = glob('/dataset/mnist_png/training/0/*.png')
path = data_path[0]
gfile = tf.io.read_file(path)
image = tf.io.decode_image(gfile)
image.shape #[28, 28, 1]
#2. Set Data Generator
import tensorflow.keras.preprocessing.imgae import ImageDataGenerator
#datagenerator 생성
datagenerator = ImageDataGenerator(
rotation_range = 20,
width_shift_range = 0.2,
height_shift_ragne = 0.2,
horizontal_flip = True
)
#생성한 datagenerator을 image에 적용
image = image[tf.newaxis, ...]
image.shape #[1, 28, 28, 1]
image_result = next(iter(datagenerator.flow(image)) #이러면 datagenerator에서 설정해준 것들이 하나씩 적용된다.
#original image와 transformation된 image 시각화해서 보기
plt.subplot(1, 2, 1)
plt.title('original')
plt.imshow(np.squeeze(image), 'gray')
plt.subplot(1, 2, 2)
plt.title('Transforms Image')
plt.imshow(np.squeeze(image_result), 'gray')
plt.show()
#####################.flow() 함수는 임의 변환된 이미지를 배치 단위로 생성해서 지정한 폴더에 저장할 수 있다.########
##################### 즉, 하나하나 적용해서 각 image_result로 만들고 batch로 묶고 싶다면,
i = 0
for batch in datagenerator.flow(image, batch_size=1,
save_to_dir=`preview`, save_prefix=`label`, save_format=`png`):
i += 1
if i > 20:
break # 이미지 20장을 생성하고 마칩니다
2) flow_from_directory(directory) 사용하여 generator생성하는 경우
MNIST 데이터를 사용하여 datagenerator.flow_from_directory(directory) 형식으로 Data Augmentation을 진행한다.
- datagenerator.flow(inputs)는 이미지를 load 후 => datagenerator을 적용
- datagenerator.flow_from_directory(directory)는 => 해당 경로에 있는 image load와 datagenerator 함께 가능
# 0. 필요한 함수 import
import os
from glob import glob
import tensorflow as tf
import numpy as np
#1. 데이터 파일 경로찾기
train_dir = 'dataset/mnist_png/training'
test_dir ='dataset/mnist_png/testing'
#2. Set Data Generator
import tensorflow.keras.preprocessing.imgae import ImageDataGenerator
#datagenerator 생성
train_datagenerator = ImageDataGenerator(
rescale = 1./255.,
width_shift_range = 0.3,
zoom_range = 0.7,
horizontal_flip = True
)
test_datagenerator = ImageDataGenerator(
rescale = 1./255.,
)
#train_datagenerator을 train image에 적용
train_result = train_datagenerator.flow_from_directory(
train_dir,
target_size = input_shape[:2],
batch_size = batch_size,
class_mode=`binary` # binary_crossentropy 손실 함수를 사용하므로 binary 형태로 라벨을 불러와야 합니다.
)
#test_datagenerator을 test image에 적용
test_result = test_datagenerator.flow_from_directory(
test_dir,
target_size = input_shape[:2],
batch_size = batch_size,
class_mode=`binary` # binary_crossentropy 손실 함수를 사용하므로 binary 형태로 라벨을 불러와야 합니다.
)
#3. model 생성 후,
inputs = layers.Input(input_shape)
net = layers.Conv2D(32, 3, padding = 'SAME')(inputs)
net = layers.Activation('relu')(net)
net = layers.Conv2D(32, 3, padding = 'SAME')(net)
net = layers.Activation('relu')(net)
net = layers.MaxPooling2D(pool_size = 2)(net)
net = layers.Dropout(dropout_rate)(net)
net = layers.Conv2D(64, 3, padding = 'SAME')(net)
net = layers.Activation('relu')(net)
net = layers.Conv2D(64, 3, padding = 'SAME')(net)
net = layers.Activation('relu')(net)
net = layers.MaxPooling2D(pool_size = 2)(net)
net = layers.Dropout(dropout_rate)(net)
net = layers.Flatten()(net)
net = layers.Dense(512)(net)
net = layers.Activation('relu')(net)
net = layers.Dense(num_classes)(net)
net = layers.Activation('softmax')(net)
model = tf.keras.Model(inputs = inputs, outputs = net, name = 'Basic_CNN')
model.compile(optimizer = tf.keras.optimizers.Adam(learning_rate), #Optimization
loss = 'categorical_crossentropy', #Loss function
metrics = ['accuracy']) #Metrics/Accuracy
#4. Training
model.fit_generator(
train_generator,
steps_per_epoch = len(train_generator),
epochs = num_epochs,
validation_data =validation_generator,
validation_steps = len(validation_generator))#steps_per_epoch : 한 epoch에 몇 개의 묶음의 이미지(batch)가 epoch에 돌아갈지
)
Test도 마찬가지
reference
fastcampus - 인공지능과 딥러닝 강의
https://www.kdnuggets.com/2018/05/data-augmentation-deep-learning-limited-data.html
https://keraskorea.github.io/posts/2018-10-24-little_data_powerful_model/
'Data Science > Deep Learning' 카테고리의 다른 글
2. 추가적인 손실 함수(Regularization) (0) | 2020.04.25 |
---|---|
1. Overfitting의 해결 (0) | 2020.04.25 |
2. 경사 하강 학습법 - 경사 하강 학습법 (0) | 2020.04.04 |
2. 경사 하강 학습법 - 모델의 학습과 경사하강 학습법과 최적화이론의 관계 (0) | 2020.04.04 |
1. 가장 단순한 신경망을 통한 작동원리 - Shallow Neural Network 수식적 이해 (0) | 2020.04.03 |