사용한 버전

  • tensorflow = 2.2.0

 

kaggle에서 개와 고양이 데이터셋을 다운로드하여 진행했습니다

 

해당 폴더 안에 (이름은 자유)

 

cat_and_dog

ㄴ training_set

    ㄴ cats

    ㄴ dogs

ㄴ test_set

    ㄴ cats

    ㄴ dogs

 

와 같이 구성해 놓아야 합니다

 

validation data 는 아래에서 따로 지정할 것입니다

 

 

import os
from tensorflow.keras.preprocessing.image import ImageDataGenerator

rootPath = './datasets/cat_and_dog'

imageGenerator = ImageDataGenerator(
    rescale=1./255,
    rotation_range=20,
    width_shift_range=0.1,
    height_shift_range=0.1,
    brightness_range=[0.2, 1.3],
    horizontal_flip=True,
    validation_split=.2
)

trainGen = imageGenerator.flow_from_directory(
    os.path.join(rootPath, 'training_set'),
    target_size=(64, 64),
    subset='training'
)

validationGen = imageGenerator.flow_from_directory(
    os.path.join(rootPath, 'training_set'),
    target_size=(64, 64),
    subset='validation'
)

Found 6404 images belonging to 2 classes.

Found 1601 images belonging to 2 classes.

 

 

ImageDataGenerator로 전처리와 이미지 증폭 설정

 

ImageDataGenerator에 대한 보다 자세한 설명은 아래 글 참조

https://blueberry-kyu.tistory.com/4

 

 

 

 

from tensorflow.keras.models import Sequential
from tensorflow.keras import layers

model = Sequential()

model.add(layers.InputLayer(input_shape=(64, 64, 3)))
model.add(layers.Conv2D(16, (3, 3), (1, 1), 'same', activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(rate=0.3))

model.add(layers.Conv2D(32, (3, 3), (1, 1), 'same', activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(rate=0.3))

model.add(layers.Conv2D(64, (3, 3), (1, 1), 'same', activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Dropout(rate=0.3))

model.add(layers.Flatten())
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(2, activation='sigmoid'))

model.summary()

CNN 구성

이진 분류이므로 마지막 layer에 sigmoid를 사용하였습니다

 

 

model.compile(
    optimizer='adam',
    loss='binary_crossentropy', 
    metrics=['acc'],
)

epochs = 50
history = model.fit(
    trainGen, 
    epochs=epochs,
    validation_data=validationGen,
)

optimizer는 일반적으로 많이 사용하는 adam

loss는 이진 분류 이므로 binary_crossentropy를 사용하였습니다

metrics는 acc (정확도, accuracy로 써도 똑같음!)

 

더보기
더보기

이전 포스트에선 x_train(이미지), y_train(레이블) 형태로 데이터를 다뤘는데

 

그쪽이 편하다면

x_train=np.concatenate([trainGen.next()[0] for i in range(trainGen.__len__())])
y_train=np.concatenate([trainGen.next()[1] for i in range(trainGen.__len__())])

의 방법으로 변환하여 사용하면 됩니다.

 

validation data와 test data도 같은 방법을 사용

 

 

...

대충 30분 정도 걸린 듯

 

 

 

 

history.history.keys()

dict_keys(['loss', 'acc', 'val_loss', 'val_acc'])

 

history_dict = history.history

loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(loss)+1)
fig = plt.figure(figsize=(12, 6))

ax1 = fig.add_subplot(1, 2, 1)
ax1.plot(epochs, loss, color='blue', label='train_loss')
ax1.plot(epochs, val_loss, color='red', label='val_loss')
ax1.set_title('Train ans Validation loss')
ax1.set_xlabel('Epochs')
ax1.set_ylabel('loss')
ax1.grid()
ax1.legend()

accuracy = history_dict['acc']
val_accuracy = history_dict['val_acc']

ax2 = fig.add_subplot(1, 2, 2)
ax2.plot(epochs, accuracy, color='blue', label='train_accuracy')
ax2.plot(epochs, val_accuracy, color='red', label='val_accuracy')
ax2.set_title('Train ans Validation Accuracy')
ax2.set_xlabel('Epochs')
ax2.set_ylabel('Accuracy')
ax2.grid()
ax2.legend()

plt.show()

 

 

testGenerator = ImageDataGenerator(
    rescale=1./255
)

testGen = imageGenerator.flow_from_directory(
    os.path.join(rootPath, 'test_set'),
    target_size=(64, 64),
)

#model.evaluate_generator(testGen)
model.evaluate(testGen)

Found 2023 images belonging to 2 classes.

64/64 [==============================] - 8s 122ms/step - loss: 0.4474 - acc: 0.7958

 

정확도는 거의 80 퍼

나쁘지 않다

 

 

※ model.evaluate_generator를 이용하는 경우 경고가 뜰 수 있습니다

evaluate_generator을 사용하여도 결과는 나오지만 evaluate로 바꾸려는 추세인 듯..?

 

 

 

from tensorflow.keras.preprocessing.image import array_to_img
import numpy as np

index = ['cat', 'dog']
imgs = testGen.next()
arr = imgs[0][0]
img = array_to_img(arr).resize((128, 128))
plt.imshow(img)
result = model.predict_classes(arr.reshape(1, 64, 64, 3))
print('예측: {}'.format(index[result[0]]))
print('정답: {}'.format(index[np.argmax(imgs[1][0])]))

예측: cat

정답: cat

역시 셀을 반복 실행하면 다른 데이터를 볼 수 있습니다~

 

model.save('cat_dog_model.h5')

모델 저장하기

 

 

image와 label 분리

더보기
더보기

위의 방법은 ImageDataGenerator 를 이용한 데이터를 가지고 진행하였는데

image와 label을 따로 진행하는게 편하시다면

 

x_train=np.concatenate([trainGen.next()[0] for i in range(trainGen.__len__())])

y_train=np.concatenate([trainGen.next()[1] for i in range(trainGen.__len__())])

x_val=np.concatenate([validationGen.next()[0] for i in range(validationGen.__len__())])

y_val=np.concatenate([validationGen.next()[1] for i in range(validationGen.__len__())])

x_test=np.concatenate([testGen.next()[0] for i in range(testGen.__len__())])

y_test=np.concatenate([testGen.next()[1] for i in range(testGen.__len__())])

 

와 같은 방법으로 분리하여 진행할 수있습니다

+ Recent posts