CNN-2단계(Data Augment)

joooon na·2023년 9월 15일
0

CNN

목록 보기
1/3
  • 지금까지는 tensorflow에서 제공된 이미지 데이터를 사용했는데, 실제 환경에서는 원하는 데이터를 충분히 확보하기는 힘들다. 그래서 필요한 방법이 데이터 증폭이다.

  • 해당 방법은 제한된 데이터셋에 회전, 늘림, 방향 조정 등과 같이 조작을 하여, 많은 데이터셋을 확보하는 방법이다.

Data Augment

  • from tensorflow.keras.preprocessing.image import ImageDataGenerator 으로 라이브러리를 불러온다.

  • 기본적으로 사용되는 매개변수

aug = ImageDataGenerator(rotation_range=50,      # 이미지 회전
                         width_shift_range=0.3,  # 이미지 좌우 이동
                         height_shift_range=0.3, # 이미지 상하 이동
                         zoom_range=0.5,         # 확대/축소 범위
                         shear_range=0.4,        # 비스듬히 늘림
                         horizontal_flip=True,   # 가로 전환
                         vertical_flip=True,     # 세로 전환
                         fill_mode='nearest')    # 마지막 옵션 주의하자. 이미지 회전, 이동, 축소할 때 발생하는 공간을 채우는 방식
  • 매개변수 중, zca_whitening = True를 입력하면, fit을 추가적으로 해줘야 한다.

  • data augment를 사용한다면, train 데이터 셋에서 validation data를 따로 형성해줘야 한다.

    • 원래는 model.fit(validation_size=0.2)이렇게 해줬는데, train_test_split를 통해서 처음에 쪼개줘야 한다.
  • model.fit(x_train, y_train)이 들어갔지만, model.fit(trainIDG, validation_data=valIDG) 가 대신해서 들어간다.

실습 1

    1. 데이터 준비
# 1) 데이터 확인
x.shape, y.shape

<출력>
((28, 28, 18724), (18724,))

# 2) 데이터 reshape
r, w, c = x.shape

x = x.reshape(c, r, w, -1)
<출력>
(18724, 28, 28, 1)

    1. 데이터셋 생성
# 1) 데이터 분리
from sklearn.model_selection import train_test_split

x_train, test_x, y_train, test_y = train_test_split(x, y, test_size=0.2, random_state=2023)

train_x, validation_x, train_y, validation_y = train_test_split(x_train, y_train, test_size=0.2, random_state=2023)


# 2) minmax스케일링
max_n, min_n = train_x.max(), train_x.min()

train_x = (train_x - min_n) / (max_n - min_n)
test_x = (test_x - min_n) / (max_n - min_n)
validation_x = (validation_x - min_n) / (max_n - min_n)


# 3) 원핫인코딩

- 주의할 점이 하나 있는데, class_n이 100과 같이 너무 크다면,
- 원핫인코딩을 하지 않고 model.compile(loss = 'sparse_categorical_crossentropy')로 두는 것이 더 좋다.

from keras.utils import to_categorical
class_n = len(np.unique(train_y))

train_y = to_categorical(train_y, class_n)
test_y = to_categorical(test_y, class_n)
validation_y = to_categorical(validation_y, class_n)

train_x.shape, validation_x.shape, train_y.shape,test_y.shape

<출력>
((11983, 28, 28, 1), (2996, 28, 28, 1), (11983, 100), (3745, 100))

    1. Image Data Augment
# 1) 데이터 제너레이터 선언(x_train)
from tensorflow.keras.preprocessing.image import ImageDataGenerator

trainIDG = ImageDataGenerator(rescale=1./255,         # 사실 이 부분은 전처리 과정에서 했다. 0~1 사이로 만들어줌
                              zca_whitening=True,     # apply ZCA whitening
                              rotation_range=30,      # randomly rotate images in the range (degrees, 0 to 180)
                              zoom_range = 0.2,       # randomly zoom image
                              width_shift_range=0.1,  # randomly shift images horizontally (fraction of total width)
                              height_shift_range=0.1, # randomly shift images vertically (fraction of total height)
                              horizontal_flip=True,   # randomly flip images
                              vertical_flip=True)     # randomly flip images

- 매개변수는 너무 과하면 오히려 학습에 좋지 않다.
- 특히 flip의 경우 안쓴만 못할 수 있다.

# 2) fit ( whitening이 없으면 안함)
trainIDG.fit(train_x)

# 3) flow(x_train)
- 학습 할 때마다, '실시간'으로 데이터를 생성하여 학습에 활용하고, 버리고를 반복할 준비!
flow_trainIDG = trainIDG.flow(train_x, train_y,
                              batch_size=128,
                              # save_to_dir='output',    # 생성하면 저장하는 거임.
                              # save_prefix='train',
                              # save_format='png'
                              )

# 4) 데이터 제너레이터 선언(x_val)
valIDG = ImageDataGenerator(rescale=1./255)

# 5) flow(x_val)
flow_valIDG = valIDG.flow(validation_x, validation_y)   # 위에 처럼 저장 변수 넣을 수 있음.

    1. modeling
# 1. 메모리 초기화
tf.keras.backend.clear_session()

# 2. 입력
il = tf.keras.layers.Input(shape=[32, 32, 3])

# 3. 입력-2
h = tf.keras.layers.Conv2D(filters=64,
                          kernel_size=(3,3),
                          strides=(1,1),
                          padding='same',
                          activation='relu')(il)
h = tf.keras.layers.BatchNormalization()(h)

h = tf.keras.layers.Conv2D(filters=64,
                          kernel_size=(3,3),
                          strides=(1,1),
                          padding='same',
                          activation='relu')(h)
h = tf.keras.layers.BatchNormalization()(h)

h = tf.keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2))(h)
h = tf.keras.layers.Dropout(0.25)(h)

h = tf.keras.layers.Conv2D(filters=128,
                          kernel_size=(3,3),
                          strides=(1,1),
                          padding='same',
                          activation='relu')(h)
h = tf.keras.layers.BatchNormalization()(h)

h = tf.keras.layers.Conv2D(filters=128,
                          kernel_size=(3,3),
                          strides=(1,1),
                          padding='same',
                          activation='relu')(h)
h = tf.keras.layers.BatchNormalization()(h)

h = tf.keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2))(h)
h = tf.keras.layers.Dropout(0.25)(h)

h = tf.keras.layers.Conv2D(filters=256,
                          kernel_size=(3,3),
                          strides=(1,1),
                          padding='same',
                          activation='relu')(h)
h = tf.keras.layers.BatchNormalization()(h)

h = tf.keras.layers.Conv2D(filters=256,
                          kernel_size=(3,3),
                          strides=(1,1),
                          padding='same',
                          activation='relu')(h)
h = tf.keras.layers.BatchNormalization()(h)

h = tf.keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2))(h)
h = tf.keras.layers.Dropout(0.25)(h)

h = tf.keras.layers.Conv2D(filters=512,
                          kernel_size=(3,3),
                          strides=(1,1),
                          padding='same',
                          activation='relu')(h)
h = tf.keras.layers.BatchNormalization()(h)

h = tf.keras.layers.Conv2D(filters=512,
                          kernel_size=(3,3),
                          strides=(1,1),
                          padding='same',
                          activation='relu')(h)
h = tf.keras.layers.BatchNormalization()(h)
h = tf.keras.layers.Dropout(0.25)(h)

# 4. 출력
h = tf.keras.layers.Flatten()(h)
h = tf.keras.layers.Dense(1024, activation='relu')(h)
ol = tf.keras.layers.Dense(100, activation='softmax')(h)

# 5. 모델
model= tf.keras.models.Model(il, ol)
model.compile(optimizer='adam', loss = tf.keras.losses.categorical_crossentropy, metrics='accuracy')

model.summary()

    1. Early stopping
# early stopping 설정

from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(patience = 3, verbose = 1, restore_best_weights=True)

model.fit(flow_trainIDG,
         verbose=1, epochs=1,
         validation_data=flow_valIDG,
         callbacks=[es],)

- train_x, train_y를 안넣고 DataGenerator한 변수를 넣어준다.

- model 평가는 동일함.
profile
배고프다

0개의 댓글