이미지 데이터 증강(Image Data Augmentation)
기준의 이미지 데이터에 변형을 가하여 데이터 셋을 확장하는 기술
모델의 일반화 성능을 향상시키고, 과적합을 방지하는데 도움이 된다
변형 방법
RandomCrop: 이미지에서 무작위로 일부 영역을 자름으로써 이미지의 일반적인 특징을 유지하면서 새로운 관점에서 데이터를 제공RandomFlip: 이미지를 무작위로 수평 또는 수직으로 뒤집음으로써 대칭적인 변화를 시뮬레이션 함RandomTranslation: 이미지를 무작위로 이동시켜 객체가 다양한 위치에 나타나는 것을 시뮬레이션 함RandomRotation: 이미지를 무작위로 회전시켜 객체의 다양한 방향에서 보이도록 함RandomZoom: 이미지를 무작위로 확대 또는 축소하여 객체의 크기에 대한 불변성을 얻음RandomContrast: 이미지의 대조를 무작위로 조절하여 밝기 대비를 다양하게 만듦RandomBrightness: 이미지의 밝기를 무작위로 조절하여 다양성을 증가 시킴=> 기존의 가지고있는 데이터에서 양을 늘려 학습하여 더 좋은 성능을 얻기위해 진행하는 것
x와 y로 나눠진 상태
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(x, y,
test_size=0.2,
random_state=2024)
train_x, val_x, train_y, val_y = train_test_split(train_x, train_y,
test_size=0.2,
random_state=2024)
train_x = ( train_x - train_x.min() ) / ( train_x.max() - train_x.min() )
val_x = ( val_x - train_x.min() ) / ( train_x.max() - train_x.min() )
test_x = ( test_x - train_x.min() ) / ( train_x.max() - train_x.min() )
np.unique(train_y)
class_n = len( np.unique(train_y) )
from keras.utils import to categorical
train_y = to_categorical(train_y, class_n)
val_y = to_categorical(val_y, class_n)
test_y = to_categorical(test_y, class_n)
import keras
from keras.backend import clear_session
from keras.models import Model
from keras.layers import Input, Dense, Flatten, BatchNormalization, Dropout
from keras.layers import Conv2D, MaxPool2D
# 데이터 확인
train_x.shape, train_y.shape
# 1. 세션 클리어
clear_session
# 2. 레이어 엮기
il = Input(shape=28,28,1)
########################################################
# Augmentation Layers
al = keras.layers.RandomRotation(factor=(-0.1, 0.1))(il)
al = keras.layers.RandomTranslation(height_factor=(-0.1, 0.1),
width_factor=(-0.1, 0.1))(al)
al = keras.layers.RandomZoom(height_factor=(-0.1,0.1),
width_factor=(-0.1,0.1))(al)
# al = keras.layersRandomFlip(mode='horizontal_and_vertival')(al)
#################################################
hl = Conv2D(filters=64, # 새롭게 제작하는 feature map의 수
kernel_size=(3,3), # Conv 필터의 가로세로
strides=(1,1) # Conv 필터의 이동보폭
padding='same', # 1. 사이즈유지 | 2. 외곽 정보 더 반영
activation='relu'
)(al)
hl = Conv2D(filters=64,
kernel_size=(3,3),
strides=(1,1)
padding='same',
activation='relu'
)(al)
hl = MaxPool2D(pool_size=(2,2), # 풀링 필터의 가로 세로
strides=(2,2) # 풀링 필터의 이동 보폭
)(hl)
hl = BatchNormalization()(hl)
hl = Dropout(0.5)(hl)
hl = Conv2D(filters=128,
kernel_size=(3,3),
strides=(1,1)
padding='same',
activation='relu'
)(al)
hl = Conv2D(filters=128,
kernel_size=(3,3),
strides=(1,1)
padding='same',
activation='relu'
)(al)
hl = MaxPool2D(pool_size=(2,2),
strides=(2,2)
)(hl)
hl = BatchNormalization()(hl)
hl = Dropout(0.5)(hl)
hl = Flatten()(hl)
hl = Dense(1024, activation='relu')
ol = Dense(10, activation='softmax')(hl)
# 3. 모델의 시작과 끝 지정
model = Model(il, ol)
# 4. 컴파일
model.compile(optimizer='adam',
loss='categorical_crossentropy'),
metrics=['accuracy']
# 5. 요약
model.summary()
import keras
from keras.backend import clear_session
from keras.models import Model, Sequential
from keras.layers import Input, Dense, Flatten
from keras.layers import Conv2D, MaxPool2D, BatchNormalization, Dropout
# 데이터 확인
train_x.shape, train_y.shape
# 1. 세션 클리어
clear_session()
# 2. 모델 선언
model = sequential()
# 3. 레이어 블록 조립
model.add( Input(shape=(28,28,1)) )
###################################################
# Augmentation Layers
model.add( keras.layers.RandomRotation(factor=(-0.1,0.1)) )
model.add( keras.layers.RandomTranslation(height_factor=(-0.1,0.1),
width_factor=(-0.1,0.1)) )
model.add( keras.layers.RandomZoom(height_factor(-0.1, 0.1),
width_factor=(-0.1, 0.1)
# model.add( keras.layers.RandomFlip(mode='horizontal_and_vertical') )
###################################################
model.add( Conv2D(filters=64,
kernel_size=(3,3),
strides=(1,1),
padding='same',
activation='relu'
)
model.add( Conv2D(filters=64,
kernel_size=(3,3),
strides=(1,1),
padding='same',
activation='relu'
)
model.add( MaxPool2D(pool_size=(2,2)m
strides=(2,2)
)
model.add( BatchNormalization() )
model.add( Dropout(0.25) )
model.add( Conv2D(filters=128,
kernel_size=(3,3),
strides=(1,1),
padding='same',
activation='relu'
)
model.add( Conv2D(filters=128,
kernel_size=(3,3),
strides=(1,1),
padding='same',
activation='relu'
)
model.add( MaxPool2D(pool_size=(2,2)m
strides=(2,2)
)
model.add( BatchNormalization() )
model.add( Dropout(0.25) )
model.add( Flatten() )
model.add( Dense(1024, activation('relu') )
model.add( Dense(10, activation('softmax') )
# 4. 컴파일
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 5. 요약
model.summary()
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss',
min_delta=0,
patience=3,
verbose=1,
restore_best_weights=True
)
model.fit(train_x, train_y, validation_data=(val_x, val_y),
epochs=10000,
callbacks=[es]
)
model.evaluate(test_x, test_y)
y_pred = model.predict(test_x)
# 원핫 인코딩 한 것을 다시 묶어주는 코드
# 평가 지표 및 실제 데이터 확인을 위해 필요
y_pred_arg = np.argmax(y_pred, axis=1)
test_y_arg = np.argmax(test_y, axis=1)
# 라이브러리 불러옴
from sklearn.metrics import accuracy_score, classification_report
# 결과 출력
print( accuracy_score(test_y_arg, y_pred_arg) )
print( classification_report(test_y_arg, y_pred_arg) )
# keras 최신버전 업데이트
!pip install --upgrade keras
# keras 오류 개선
import os
os.environ['KERAS_BACKEND'] = 'tensorflow'
# 불러오기
from sklearn.model_selection import train_test_split
# train : validation set 8:2로 분할
train_x, val_x, train_y, val_y =\
train_test_split(train_x, train_y, test_size=0.2, random_state=2024)
# 확인
train_x.shape, val_x.shape, train_y.shape, val_y.shape
# 최대값 최소값 지정
min_n, max_n = train_x.max(), train_x.min()
# 스케일링
train_x = (train_x - min_n) / (max_n - min_n)
val_x = (val_x - min_n) / (max_n - min_n)
test_x = (test_x - min_n) / (max_n - min_n)
# 확인
train_x.min(), train_x.max()
이번엔 원핫인코딩을 시도하지 않고 loss에서 sparse_categorical_crossentropy 사용할 것임
## 100은 어디서 나왔냐~
# len(np.unique(train_y)) 확인하면 된다.
## 불러오기
# from keras.utils import to_categorical
## 인코딩
# train_y = to_categorical(train_y, 100)
# val_y = to_categorical(val_y, 100)
# test_y = to_categorical(test_y, 100)
## 확인
train_x.shape, train_y.shape
# 불러오기
import keras
from keras.utils import clear_session
from keras.models import Sequential, Model
from keras.layers import Input, Dense, Flatten, Dropout, BatchNormalization
from keras.layers import Conv2D, MaxPool2D, RandomFlip
# 1. 세션클리어
clear_session()
# 2. 레이어 연결
il = Input( shape=(32,32,3) )
#########################################
# Augmentation Layer
al = RandomFlip(mode='vertical')(il)
#########################################
hl = Conv2D(64, (3,3), (1,1), 'same', activation='relu')(hl)
hl = Conv2D(64, (3,3), (1,1), 'same', activation='relu')(hl)
hl = MaxPool2D( (2,2), (2,2) )(hl)
hl = BatchNormalization()(hl)
hl = Dropout(0.4)(hl)
hl = Conv2D(128, (3,3), (1,1), 'same', activation='relu')(hl)
hl = Conv2D(128, (3,3), (1,1), 'same', activation='relu')(hl)
hl = MaxPool2D( (2,2), (2,2) )(hl)
hl = BatchNormalization()(hl)
hl = Dropout(0.4)(hl)
hl = Conv2D(256, (3,3), (1,1), 'same', activation='relu')(hl)
hl = Conv2D(256, (3,3), (1,1), 'same', activation='relu')(hl)
hl = MaxPool2D( (2,2), (2,2) )(hl)
hl = BatchNormalization()(hl)
hl = Dropout(0.4)(hl)
hl = Flatten()(hl)
ol = Dense(100, activation='softmax')
# 3. 모델 시작 끝 지정
model = Model(il, ol)
# 4. 컴파일
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
# 5. 요약
model.summary()
그림으로 model 나타내기
from keras.utils import plot_model
plot_model(model, show_shapes=True)
# 불러오기
from keras.callbacks import EarlyStopping
#
es = EarlyStopping(monitor='val_loss',
min_delta=0,
patience=3,
verbose=1,
restore_best_weights=True
)
# 학습
model.fit(train_x, train_y, validation_data=(val_x, val_y),
epochs=10000, verbose=1,
callbacks=[es]
)
# 평가
model.evaluate(test_x, test_y)
# 예측
y_pred = model.predict(test_x)
# one-hot encoding을 다시 묶어주는 코드, 평가지표 및 실제데이터 확인을 위해 필요
y_pred_arg = np.argmax(y_pred, axis=1)
test_y_arg = np.argmax(test_y, axis=1)
from sklearn.metrics import accuracy_score, classification_report
accuracy_score(test_y_arg, y_pred_arg)
print( classification_report(test_y_arg, y_pred_arg,
target_names=list( label_dict.values() )) )