적은 datasets에 CNN 학습하는 경우
- Data의 수가 많지 않을 때 CNN을 통한 모형 학습이 어려울 수 있음
- 딥러닝은 많은 수의 데이터를 통해 feature engineering 과정 없이 feature를 찾을 수 있는데 있음
- 하지만 모델이 작고 regularization이 잘 되어 있다면 수백 개의 샘플로도 훈련 가능
- Data가 많지 않아 CNN 학습에 어려움이 있을 때 사용 가능한 방법
- Data augmentation 활용
- 이미지의 색깔, 각도 등을 약간씩 변형하여 data의 수를 늘림
- Pre-trained network의 활용
- ImageNet 등에서 학습된 기존의 모형과 weight를 불러온 후 목적에 맞게 약간 수정하여 모형 생성
- Data augmentation 활용
Data for cats vs. dogs
- 2013년 Kaggle의 computer vision competition data 활용 https://www.kaggle.com/c/dogs-vs-cats/data
- 개와 고양이를 구분하기 위한 문제로 각 12,500개의 이미지를 포함
- Medium-resolution color JPEGs
- 25000장의 사진 중 4000장의 cats/dogs 사진(2000 cats, 2000 dogs) 만을 사용하여 학습하여 좋은 모형을 만들어 낼 수 있을까?
- 학습: 2000, 검증: 1000, 테스트: 1000
# 이미지 다운로드
import gdown
url = 'https://drive.google.com/uc?id=1nBE3N2cXQGwD8JaD0JZ2LmFD-n3D5hVU'
fname = 'cats_and_dogs_small.zip'
gdown.download(url, fname, quiet=False)
#패키지 다운로드 및 데이터 압축 풀기
!mkdir data
!pip install zipfile
## 압축 풀기
!unzip -q ./cats_and_dogs_small.zip -d data/cats_and_dogs_small
- Input: 150 X150 픽셀의 RGB layer
- Output: cat or dog (binary classification)
- Hidden layers:
Conv2D
(withrelu
activation) +MaxPooling2D
import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers as layers
import numpy as np
np.random.seed(1)
tf.random.set_seed(1)
learning_rate = 0.001
dropout_rate = 0.5
N_EPOCHS = 50
N_BATCH=20
# 모델 정의
def create_model():
model = keras.Sequential()
# Feature Extraction(특성 추출-이미지의 특징을 추출하는 layer들.)
#Conv2D - kernel_size: 3, padding='SAME', stride=1(기본값)
#MaxPool2D - pool_size: 2(기본), padding='SAME'
model.add(layers.Conv2D(64, kernel_size=3, padding="SAME", activation='relu',
input_shape=(150,150,3)))
model.add(layers.MaxPool2D(padding='SAME'))
model.add(layers.Conv2D(64, kernel_size=3, padding="SAME", activation='relu'))
model.add(layers.MaxPool2D(padding='SAME'))
model.add(layers.Conv2D(128, kernel_size=3, padding="SAME", activation='relu'))
model.add(layers.MaxPool2D(padding='SAME'))
model.add(layers.Conv2D(128, kernel_size=3, padding="SAME", activation='relu'))
model.add(layers.MaxPool2D(padding='SAME'))
# classification layer (분류 - Dense)
model.add(layers.Flatten())
model.add(layers.Dropout(dropout_rate))
model.add(layers.Dense(512, activation='relu'))
# model.add(layers.Dropout(dropout_rate))
#출력
model.add(layers.Dense(1, activation='sigmoid')) #이진분류-unit수:1, 활성함수:sigmoid
return model
Data preprocessing(데이터전처리)
-
CNN 입력을 위한 이미지 전처리 단계
- 사진 파일 읽기
- JPEG content를 RGB 픽셀 값으로 디코딩
- floating point tensor 형태로 변환
- 0-255 사이의 값을 가지는 픽셀 값을 [0,1] 사이 값으로 변환
-
keras.preprocessing.image.ImageDataGenerator
를 사용하여 자동으로 입력 가능한 형태로 변환할 수 있음
Keras의 ImageDataGenerator 클래스
- 학습을 위해 이미지에 임의의 변형을 적용
- 변형된 이미지를 배치 단위로 생성하여 모형 학습시 사용하기 위한 generator를 생성
- 데이터 전체가 순환되어 배치 생성을 끝없이 함
flow_from_directory(directory)
메소드- 이미지가 특정 폴더 안에 분류 되어 있을 경우 subdirectory의 이름으로부터 target class를 자동으로 만들어냄
# train, validation, test 이미지가 들어있는 폴더 경로를 지정
train_dir = './data/cats_and_dogs_small/train'
validation_dir = './data/cats_and_dogs_small/validation'
test_dir = './data/cats_and_dogs_small/test'
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
# ImageDataGenerator 생성 - 각 pixel 을 0 ~ 1 사이로 범위 조정(scaling)
train_datagen = ImageDataGenerator(rescale=1/255) #각 픽셀에 1/255를 곱한다.
test_datagen = ImageDataGenerator(rescale=1/255) #각 픽셀에 1/255를 곱한다.
# 이미지와 연결 -> generator를 생성
# Train Set
train_generator = train_datagen.flow_from_directory(
train_dir, #이미지가 분류 되있는 디렉토리.
target_size=(150,150), #이미지들을 150 X 150으로 resizing
class_mode='binary', # output 클래스 형태
batch_size=N_BATCH #미니배치 사이즈
)
# Validation Set
validation_generator = test_datagen.flow_from_directory(
validation_dir, #이미지가 분류 되있는 디렉토리.
target_size=(150,150), #이미지들을 150 X 150으로 resizing
class_mode='binary', # output 클래스 형태
batch_size=N_BATCH #미니배치 사이즈
)
# Test Set
test_generator = test_datagen.flow_from_directory(
test_dir, #이미지가 분류 되있는 디렉토리.
target_size=(150,150), #이미지들을 150 X 150으로 resizing
class_mode='binary', # output 클래스 형태
batch_size=N_BATCH #미니배치 사이즈
)
# label의 클래스들을 확인
train_generator.class_indices # {'cats': 0, 'dogs': 1}
# step 수 (에폭당 몇번 weight 업데이트 할것인지)
len(train_generator), len(validation_generator), len(test_generator) # (100, 50, 50)
# 배치개수 만큼 이미지 조회
batch = train_generator.next() #2
len(batch), type(batch) #(2, tuple)
type(batch[0]), batch[0].shape # (numpy.ndarray, (20, 150, 150, 3))
# 이미지 확인
plt.figure(figsize=(10,10))
for i in range(4):
plt.subplot(2,2,i+1)
plt.imshow(batch[0][i])
plt.show()
Batch Generator를 이용한 Model Training(학습)
-
모델 훈련(학습)
-
모델.fit() 메소드
-
주요 매개변수
-
fit() 에 훈련데이터 셋으로 첫번째 매개변수에
Batch generator
(train_generator) 제공Batch generator
가 input 데이터와 output 라벨(label)을 제공한다.
-
steps_per_epoch
저- 한 epoch(전체 데이터셋학습)당 몇 step(파라미터 업데이트) 횟수 지정
- len(train_generator) 를 지정.
-
validation_data
- 검증 데이터셋 지정
Batch generator
지정(x_val, y_val)
과 같이 tuple 형태의 validation data를 지정할 수도 있음
-
validation_steps
- 몇 step마다 검증 할 것인지 지정.
- len(validation_generator) 를 지정
- validation data 개수를 batch_size로 나눈 값으로 지정
-
-
# 모델 생성, 컴파일
model = create_model()
model.compile(optimizer=keras.optimizers.Adam(learning_rate),
loss='binary_crossentropy', #개, 고양이 분류이니 이진분류
metrics=['accuracy'])
# 학습
histroy= model.fit(train_generator, #학습 데이터셋으로 Data(Batch) Generator 지정
epochs=N_EPOCHS,
steps_per_epoch=len(train_generator),
validation_data=validation_generator, #검증 데이터셋-Data Generator를 지정
validation_steps = len(validation_generator)
) #verbose = 0을 지정하면 학습내용을 보지 않을 수 있습니다.
model.evaluate(test_generator) #data generator
# loss: 1.4930 - accuracy: 0.7220
Data augmentation (데이터 증식)
-
학습 이미지의 수가 적어서 overfitting이 발생할 가능성을 줄이기 위해 기존 훈련 데이터로부터 그럴듯한 이미지를 랜덤하게 생성하여 데이터의 수를 늘리는 data augmentation 적용
rotation_range
: random rotation 각도 범위(0-180)width_shift_range,
height_shift_range`: 수평 혹은 수직 이동 범위(비율)shear_range
: 기울어지는 변환(shearing transformation)의 각도 범위(반시계방향)zoom_range
: 확대 비율([lower, upper] = [1-zoom_range, 1+zoom_range])horizontal_flip
: 수평으로 뒤집음(mirror image)fill_mode
: 변환된 이미지에서 생기는 빈 부분을 채우는 방법
-
이미지 변환을 통해서 이미지를 늘리는 작업(Image augmentation)
-
train_set에만 적용, validation, test set에는 적용하지 않는다. (rescaling만 한다.)
train_gen = ImageDataGenerator(
rescale = 1/255,
rotation_range= 40,
width_shift_range=0.2, #[-0.2, 0, +0.2] ex)[-1, -0.5, 0, 0.5, 1]
height_shift_range=0.2,
shear_range=0.2, #찌그리는 형태
zoom_range=0.2,
horizontal_flip=True
)
test_gen = ImageDataGenerator(rescale=1/255) #validation/test set 용(rescale만 진행)
train_generator = train_gen.flow_from_directory(train_dir,
target_size=(150,150),
class_mode='binary',
batch_size=N_BATCH)
validation_generator = test_gen.flow_from_directory(validation_dir,
target_size=(150,150),
class_mode='binary',
batch_size=N_BATCH)
test_generator = test_gen.flow_from_directory(test_dir,
target_size=(150,150),
class_mode='binary',
batch_size=N_BATCH)
model.evaluate(train_generator) # loss: 0.6930 - accuracy: 0.5000
# 확인
import os
from tensorflow.keras.preprocessing.image import load_img, img_to_array
image_path = os.path.join(train_dir, 'dogs', 'dog.0.jpg')
print(image_path)
img = load_img(image_path)
img
x = img_to_array(img)
x = x[np.newaxis, ...]
x.shape #(1, 375, 499, 3)
train_gen2 = ImageDataGenerator(
# rescale = 1/255,
rotation_range= 40,
width_shift_range=0.2, #[-0.2, 0, +0.2] ex)[-1, -0.5, 0, 0.5, 1]
height_shift_range=0.2,
shear_range=0.2, #찌그리는 형태
zoom_range=0.2,
horizontal_flip=True
)
gen = train_gen2.flow(x, batch_size=1) #Data Generator생성
plt.figure(figsize=(10,10))
for i in range(5):
plt.subplot(5, 1, i+1)
batch = gen.next()
img = batch[0].astype('uint8')
plt.imshow(img)
plt.show()
# 모델 생성 및 컴파일
model = create_model()
model.compile(optimizer=keras.optimizers.Adam(learning_rate),
loss='binary_crossentropy',
metrics=['accuracy'])
model.summary()
#학습
history=model.fit(train_generator,
epochs=N_EPOCHS,
steps_per_epoch=len(train_generator),
validation_data = validation_generator,
validation_steps=len(validation_generator))
model.evaluate(test_generator) #loss: 0.5078 - accuracy: 0.7590
loss가 대폭줄었고 정확도도 소폭 올라간 것을 볼 수 있다.
728x90
반응형
'Data Analysis & ML > Deep Learning' 카테고리의 다른 글
[Deep Learning][딥러닝] FunctionalAPI (0) | 2021.01.25 |
---|---|
[Deep Learning] 모델 저장하는 방법 (HDF5/tensorflow SaveModel/Callback) (0) | 2021.01.24 |
[Deep Learning][딥러닝] CNN MNIST 분류 (0) | 2021.01.24 |
[Deep Learning][딥러닝] CNN_MNIST분류 / 모델저장/ FunctionalAPI (0) | 2020.11.09 |
[Deep Learning][딥러닝] CNN 개요 (0) | 2020.11.09 |