


# 데이터를 가져오기 위해서
# (우리에게 제공된 이미지 파일로부터 pixel데이터를 추출하기위해)
# Keras가 제공하는 ImageDataGenerator를 사용할꺼예요!
import os
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
# 학습하기위해서는 train data와 validation data가 필요해요!
# 지금까지는 학습할때 train data 중 일부(30%)를 띄어서 validation에 사용했어요
# validation_split=0.3 <- 이런식의 option을 이용해서 처리했었어요!
# 이렇게 해도 되지만 아예 validation data를 별도로 사용할 수 있어요!
train_dir = '/content/drive/MyDrive/[AI_SCHOOL_9기]/data/cat_dog_small/train'
validation_dir = '/content/drive/MyDrive/[AI_SCHOOL_9기]/data/cat_dog_small/validation'
# ImageDataGenerator 객체를 생성해요!
# pixel값(RGB)은 각각 0~255사이의 값을 가져요!
# 정규화처리를 한 pixel 데이터를 가져오기 위해서 rescale을 사용해요!
train_data_gen = ImageDataGenerator(rescale=1/255)
validation_data_gen = ImageDataGenerator(rescale=1/255)
train_generator = train_data_gen.flow_from_directory(
train_dir, # 어떤폴더에서 이미지를 가져올지 설정
classes=[ 'cats', 'dogs'], # 폴더명을 명시해요!
# cats 폴더에서 가져온 픽셀데이터의 label을 0으로
# dogs 폴더에서 가져온 픽셀데이터의 label을 1로
target_size=(150,150), # 이미지 size를 똑같이 resize
batch_size=20, # 한번에 20개의 이미지를 가져와서 pixel데이터로
# 변환해요. 조심할거는..label에 상관없이 가져와요!
# 멍멍이 10개, 고양이 10개 이렇게 가져오는게
# 아니라.. 둘 합쳐서 20개 가져와요!
class_mode = 'binary' # 이진분류인 경우 bianry
# 다중분류인 경우 categorical
)
validation_generator = validation_data_gen.flow_from_directory(
validation_dir, # 어떤폴더에서 이미지를 가져올지 설정
classes=[ 'cats', 'dogs'],
target_size=(150,150),
batch_size=20,
class_mode = 'binary'
)
# generator를 만들었으니 실제로 한번 동작시켜서 데이터를 잘 추출하는지
# 확인해 보아요!
# x_data는 당연히 이미지의 pixel data
# t_data는 이미지의 label(0(고양이) 혹은 1(멍멍이))
for x_data, t_data in train_generator:
print(f'x_data의 shape : {x_data.shape}') # (20,150,150,3)
print(f't_data의 shape : {t_data.shape}') # (20,)
break;
# 가져온 pixel data가 진짜 이미지의 pixel data인지 확인해보아요!
# pixel데이터를 이용해서 그림을 그려보면 되겠죠!
fig = plt.figure()
axs = [] # subplot들이 저장되는 list
for i in range(20):
axs.append(fig.add_subplot(4,5,i+1))
for x_data, t_data in train_generator:
# (20, 150, 150, 3)
for idx, img_data in enumerate(x_data):
axs[idx].imshow(img_data)
break;
plt.tight_layout()
plt.show()

import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras.optimizers import Adam
model = Sequential()
# CNN을 구현할꺼니까..처음에는 Feature Extraction부분이 나와요!
model.add(Conv2D(filters=32,
kernel_size=(3,3),
strides=(1,1),
activation='relu',
input_shape=(150,150,3)))
# filter의 shape => (3,3,3,32) 필터의 channel은 입력 데이터의 channel과 동일
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(filters=64,
kernel_size=(3,3),
strides=(1,1),
activation='relu'))
model.add(Conv2D(filters=128,
kernel_size=(3,3),
strides=(1,1),
activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(filters=128,
kernel_size=(3,3),
strides=(1,1),
activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
# model.summary()
# FC Layer(DNN 학습) - input, hidden, output 부분
model.add(Flatten()) # 4차원을 펴준다는 의미
# hidden layer(선택사항)
# 1개만 넣어도 되고 여러개 넣어도 되고 안넣어도 됨!!
model.add(Dense(units=512,
activation='relu'))
# output layer
model.add(Dense(units=1,
activation='sigmoid'))
model.compile(optimizer=Adam(learning_rate=1e-4),
loss='binary_crossentropy',
metrics=['acc'])
model.summary()

# 우선, 조기종료 설정
from tensorflow.keras.callbacks import EarlyStopping
es_cb = EarlyStopping(monitor='val_loss',
patience=5,
restore_best_weights=True)
# 학습 데이터와 val 데이터는 각각 generator 안에 있음
# 학습 데이터의 경우 한번에 20개 불러옴 but 한 epoch당 총 개수인 2000개 학습 필요
# 20*100 = 2000이므로 steps_per_epoch = 100
# validation_steps 역시 위와 동일, val 데이터는 총 1000개
# 따라서 20*50 = 1000이므로 validation_step = 50
model.fit(train_generator,
steps_per_epoch=100, # 한 epoch 당 generator를 몇 번 실행할 것인지
epochs=50,
validation_data = validation_generator,
validation_steps = 50,
callbacks=[es_cb],
verbose=1
)
# Epoch 12/50
# 100/100 [==============================] - 9s 89ms/step - loss: 0.1033 - acc: 0.9660 - val_loss: 0.9144 - val_acc: 0.7080
# 정확도가 70% 정도 -> 사용할 수 없는 모델이라는 의미
# 둘 중 하나 고르는건데도 10개 중 7개만 맞는거면 뭐..

# Image Augmentation(이미지 증식)
# 데이터를 살짝 변형시켜 데이터를 늘려서 학습을 시키는 것
# 주의점!! 살짝 변형시키는 것이지 새로운 데이터를 만들어내는 것은 아님
# 회전, 이미지 이동, 확대/축소, Flip
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
datagen = ImageDataGenerator(rescale=1/255,
rotation_range=20, # 회전 각도 범위 설정(0~20 사이 값 랜덤하게 실행됨)
width_shift_range = 0.1, # 0.1 = 10%
height_shift_range=0.1,
shear_range = 0.1,
zoom_range=0.1,
horizontal_flip = True,
vertical_flip=True,
fill_mode='nearest'
)
# width_shift_range = 가로 방향 얼만큼 움직일지(왼쪽 or 오른쪽),
img = image.load_img('/content/drive/MyDrive/AI스쿨 파일/ML/cat_dog_small/train/cats/cat.3.jpg',
target_size=(150,150))
x = image.img_to_array(img)
x.shape
# ImageGenerator를 이용해서 이 파일로부터 증식된 이미지를 추출!
# 기본적으로 ImageDataGenerator는 4차원을 사용
# 우리 이미지도 역시 4차원으로 표현해야!
x = x.reshape((1,) + x.shape)
x.shape
# 직접 그려서 확인
fig = plt.figure()
axs = []
for i in range(20):
axs.append(fig.add_subplot(4,5,i+1))
idx=0
for batch in datagen.flow(x,batch_size=1):
axs[idx].imshow(image.array_to_img(batch[0])) # batch[0]는 픽셀 데이터(변형된 이미지)
idx += 1
if idx%20==0:
break
plt.tight_layout()
plt.show()

import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_dir = '/content/drive/MyDrive/AI스쿨 파일/ML/cat_dog_small/train'
validation_dir = '/content/drive/MyDrive/AI스쿨 파일/ML/cat_dog_small/validation'
# ImageDataGenerator 생성
train_datagen = ImageDataGenerator(rescale=1/255,
rotation_range=20,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
# validation data는 증식을 사용하면 안되요! (평가용 데이터이기 때문)
validation_datagen = ImageDataGenerator(rescale=1/255)
train_generator = train_datagen.flow_from_directory(
train_dir,
classes=['cats', 'dogs'],
target_size=(150,150),
batch_size=20,
class_mode='binary'
)
validation_generator = validation_datagen.flow_from_directory(
validation_dir,
classes=['cats', 'dogs'],
target_size=(150,150),
batch_size=20,
class_mode='binary'
)
# model 생성
model = Sequential()
model.add(Conv2D(filters=32,
kernel_size=(3,3),
strides=(1,1),
activation='relu',
input_shape=(150,150,3)))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(filters=64,
kernel_size=(3,3),
strides=(1,1),
activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(filters=128,
kernel_size=(3,3),
strides=(1,1),
activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(filters=128,
kernel_size=(3,3),
strides=(1,1),
activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
# 여기까지가 Feature Extraction 부분이에요! 이미지의 특징을 추출하는 부분
# 이렇게 이미지의 특징을 추출한 후 2차원으로 변경해서 학습을 진행
model.add(Flatten()) # 4차원데이터를 2차원으로 변경(이미지 3차원을 1차원으로 변경)
model.add(Dropout(rate=0.5))
# hidden layer
model.add(Dense(units=512,
activation='relu'))
# output layer
model.add(Dense(units=1,
activation='sigmoid'))
model.compile(optimizer=Adam(learning_rate=1e-4),
loss='binary_crossentropy',
metrics=['acc'])
# overfitting 정도를 확인하기 위해 EarlyStopping은 설정하지 않았어요!
history = model.fit(train_generator,
steps_per_epoch=100,
epochs=100,
validation_data=validation_generator,
validation_steps=50,
verbose=1)
import matplotlib.pyplot as plt
train_loss = history.history['loss']
valid_loss = history.history['val_loss']
train_acc = history.history['acc']
valid_acc = history.history['val_acc']
plt.plot(train_loss, color='r')
plt.plot(valid_loss, color='b')
plt.show()
plt.plot(train_acc, color='r')
plt.plot(valid_acc, color='b')
plt.show()

