본문 바로가기
딥러닝

강아지 VS 고양이(Cat vs Dog), 강아지 고양이 구분

by 짱태훈 2024. 11. 9.
728x90

1. 프로젝트 목표

  1. 프로젝트 목표 및 분석 대상에 대한 이해
  2.  데이터셋의 전반적인 구성

2. 기대 효과

  1. 딥러닝 모델의 성능 검증과 비교
  2. 딥러닝 학습 과정 이해

3. 요약

  1. 프로젝트 흐름도
  2. 결과

4. 분석 대상 확인

  1. 이미지 샘플 확인

5. 모델 훈련

  1. 직접 설계한 모델
  2. 사전 훈련 모델
  3. 결과

6. 결론


1. 프로젝트 목표

1. 프로젝트 목표 및 분석 대상에 대한 이해

고양이(김쫀떡, https://www.youtube.com/@%EA%B9%80%EC%AB%80%EB%96%A1), 강아지(소녀의행성, https://www.youtube.com/@%EC%86%8C%EB%85%80%EC%9D%98%ED%96%89%EC%84%B1Girlsplanet)

 

프로젝트의 목표는 Kaggle에서 제공하는 강아지와 고양이 사진 데이터셋을 이용해 두 동물을 정확히 분류할 수 있는 머신러닝 모델을 만드는 것이다. 사람은 강아지와 고양이를 구분하는 것이 비교적 쉬운 일이지만, 컴퓨터는 그렇지 않다. 강아지와 고양이는 모두 눈, 코, 귀, 수염, 네 발, 털, 꼬리를 가지고 있어 비슷한 특징을 공유하며, 이러한 이유로 컴퓨터가 둘을 구별하는 것은 어려울 수 있다.

머신러닝 모델이 이러한 시각적 유사성에도 불구하고 강아지와 고양이를 효과적으로 구별하기 위해서는 이미지의 세부적인 차이점을 학습할 수 있어야 한다. 예를 들어, 고양이와 강아지는 귀 모양, 얼굴 구조, 체형에서 차이를 보이지만, 강아지의 품종 간에도 큰 차이가 있어 모델이 이러한 다양한 특성을 학습해야 한다. 이를 통해 컴퓨터 비전 모델이 다양한 변이를 고려하여 이미지 인식에서 섬세한 차이를 얼마나 잘 학습하고 구별할 수 있는지 확인할 수 있다.

또한, 강아지와 고양이에 대한 이미지는 인터넷에서 풍부하게 구할 수 있어 대규모 데이터셋을 확보하는 데 용이하다. 이를 바탕으로 딥러닝 모델을 학습시켜 강아지와 고양이를 구분하는 능력을 높이는 것이 이 프로젝트의 핵심 목표이다.

 

2. 데이터셋의 전반적인 구성

kaggle에서 다운로드받아 사용한 강아지와 고양이 사진 데이터셋은 cat-and-dog, catndog, dogs-cats-images 총 3개이다. 데이터의 구성은 아래 표와 같다.

cat-and-dog catndog dogs-cats-images
10,028개 37,500개 20,000개
label: cat / dog label: cat / dog / N/A label: cat / dog

catndog 데이터셋의 경우 kaggle 대화에서 사용된 데이터셋으로 test 이미지 데이터셋은 라벨링이 되어있지 않다. 따라서 test 이미지 데이터셋은 제외하고 25,000개의 이미지를 이용했다. 특히 catndog의 이미지 중 라벨링이 되어 있는 25,000개 중 20,000는 train 데이터로 5000개는 test, validation 데이터로 이용했다. 최종적으로 train 데이터 30,028개, validation 데이터 12,5000개, test 데이터 12,500개로 나누었다.

train data validation data test data
30,028 12,500 12,500

 

2. 기대 효과

1. 데이터셋 처리 및 모델 최적화 기술 강화

다양한 데이터셋을 통합하고 이를 학습에 맞게 전처리하는 과정에서 데이터셋 처리 기술을 강화할 수 있다. 또한, 여러 유형의 데이터로 학습하면서 모델을 최적화하는 기술을 배울 수 있다.

 

2. 실제 응용 사례 적용 가능성

강아지와 고양이와 같은 반려동물 분류 모델은 실제 응용 사례에서 유용하게 활용될 수 있다. 예를 들어, 반려동물 관련 앱에서 사진을 통해 반려동물의 종류를 자동으로 분류하거나, 유기동물 보호소에서 자동 분류 시스템을 구축하는 데 도움이 될 수 있다.

 

3. 이미지 인식 기술의 발전

강아지와 고양이의 구별처럼 이미지 내에서 미세한 차이를 구분하는 문제는 더 넓은 범위의 이미지 인식 기술의 발전에 기여할 수 있다. 이 프로젝트를 통해 개발된 기술은 다른 이미지 분류 문제에도 적용될 수 있다.

 

3. 요약

1. 프로젝트 흐름도

 

2. 결과

그림1
그림2

직접 만든 모델과 사전 훈련된 모델 2개를 이용해서 훈련을 진행했다. 훈련 성능에서 사전 훈련 모델인 Xception 모델은 98.97%에 도달하며 훈련 데이터에 매우 잘 맞추고 있다. 뿐만 아니라 검증 성능에서도 Xception 모델이 0.9897로 가장 높은 검증 정확도를 보여주었으며, 검증 손실에서는 Xception 모델이 가장 낮은 검증 손실을 보여준다. 각각 모델이 test 데이터셋을 통해 검증을 했을 때 점수는 아래 표와 같다.

make_model xception MobileNetV2
accuracy: 0.9388 accuracy: 0.9953 accuracy: 0.9830
loss: 0.1642 loss: 0.0125 loss: 0.0492

 

결론적으로 Xception 모델이 훈련과 검증 성능에서 높은 정확도와 낮은 손실을 보여줄 뿐만 아니라 검증 데이터에서의 성능 역시 Xception 모델이 여전히 가장 높은 정확도와 가장 낮은 손실을 보여준다. 즉, Xception이 cat vs dog 데이터셋에 가장 잘 맞는 모델이라고 볼 수 있다.

 

4. 분석 대상 확인

1. 이미지 샘플 확인

[SchubertSlySchubert, "Cat and Dog", Kaggle, 2017년 수정, 2024년 11월 접속, https://www.kaggle.com/datasets/tongpython/cat-and-dog]

 

Cat and Dog

Cats and Dogs dataset to train a DL model

www.kaggle.com

[Kaggle · Playground Prediction Competition, "Dogs vs. Cats", Kaggle, 2013년 수정, 2024년 11월 접속, https://www.kaggle.com/competitions/dogs-vs-cats]

 

Dogs vs. Cats

Create an algorithm to distinguish dogs from cats

www.kaggle.com

 

[chetanimravan, "Dogs & Cats Images", Kaggle, 2017년 수정, 2024년 11월 접속, https://www.kaggle.com/datasets/chetankv/dogs-cats-images]

 

Dogs & Cats Images

image classification

www.kaggle.com

 

이미지는 앞에서 확인했 듯 훈련 세트 30,028, 검증 세트 12,500, 테스트 세트 12,500개로 구성되어 있다. 훈련 세트 이미지를 강아지, 고양이 각각을 확인하면 아래와 같다. 

그림3

훈련 세트, 검증 세트, 테스트 세트를 통해 모델의 성능을 확인해 보고 필자가 직접 수집한 아래의 사진들을 모델을 이용해 예측해보고자 한다. 총 56개의 강아지와 고양이 사진으로 구성되어 있다.

그림4(출처: 유튜브 뭉치의 개팔상팔, 소녀의행성, 뚜비, 재롱잔치, 김쫀떡)

 

5. 모델 훈련

1. 직접 만든 모델

IMAGE_SIZE: 224, BATCH_SIZE: 32

모델 구성: 5개의 컨볼루션 블록으로 구성, BatchNormalization 사용, Max_Pooling 대신 strides를 (2, 2)로 적용

데이터 증식: albumentations 적용

def make_model():
    input_tensor = Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3))
    
    # Conv Block 1
    x = Conv2D(filters=16, kernel_size=(3, 3), padding='same', kernel_initializer='he_normal')(input_tensor)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    x = Conv2D(filters=16, kernel_size=(3, 3), padding='same', strides=(2, 2), kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    # Conv Block 2
    x = Conv2D(filters=32, kernel_size=(3, 3), padding='same', kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    x = Conv2D(filters=32, kernel_size=(3, 3), padding='same', strides=(2, 2), kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    # Conv Block 3
    x = Conv2D(filters=64, kernel_size=(3, 3), padding='same', kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    x = Conv2D(filters=64, kernel_size=(3, 3), padding='same', strides=(2, 2), kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    # Conv Block 4
    x = Conv2D(filters=128, kernel_size=(3, 3), padding='same', kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    x = Conv2D(filters=128, kernel_size=(3, 3), padding='same', strides=(2, 2), kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    # Conv Block 5
    x = Conv2D(filters=256, kernel_size=(3, 3), padding='same', kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    x = Conv2D(filters=256, kernel_size=(3, 3), padding='same', strides=(2, 2), kernel_initializer='he_normal')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    
    # Flatten and Fully Connected Layers
    x = Flatten(name='flatten')(x)
    x = Dropout(rate=0.5)(x)
    x = Dense(512, activation='relu', name='fc1')(x)
    x = Dropout(rate=0.3)(x)
    output = Dense(1, activation='sigmoid', name='output')(x)
    
    model = Model(inputs=input_tensor, outputs=output)
    
    model.summary()
    return model
accuracy: 0.9086 - loss: 0.2713 - val_accuracy: 0.8532 - val_loss: 4.1474

데이터 증강 기법을 적용 했으며, learning_rate는 0.001로 진행했다. ReduceLROnPlateau과 EarlyStopping을 각각 patience=3, patience=5 적용했기에 총 15 epoch 중 6번 째 epoch가 완료된 후 early 조기 종료(Early Stopping)가 적용되어 학습이 중단되었다. make_model은 양호한 훈련 성능을 보여준다. 하지만, 검증 성능은 훈련 성능에 비해 낮고, 검증 손실이 매우 높다. 이는 모델이 학습 데이터에는 잘 맞지만, 검증 데이터에는 일반화되지 않고 있음을 보여준다. 즉, 모델이 학습 데이터에 과적합되었을 가능성이 있다.

테스트 세트를 이용해 평가(evaluate)를 진행했을 때 아래와 같은 점수가 나왔다. 또한, 직접 수집한 새로운 강아지 고양이 사진을 대상으로는 그림5를 통해 56개의 테스트 세트에서 10개의 이미지를 예측하는데 실패한 것을 확인할 수 있다.

accuracy: 0.8906 - loss: 3.5280

그림5

2. 사전 훈련 모델

1. MobileNetV2

accuracy: 0.9186 - loss: 0.2372 - val_accuracy: 0.8764 - val_loss: 0.5800

데이터 증강 기법을 적용 했으며, learning_rate는 0.001로 진행했다. ReduceLROnPlateau과 EarlyStopping을 각각 patience=3, patience=5 적용했기지만 총 15 epoch를 모두 완료한 후 종료되었다. MobileNetV2은 make_model 보다 양호한 훈련 성능을 보여준다. 하지만, 검증 성능은 훈련 성능 보다 낮고, 검증 손실은 훈련 손실에 비해 매우 높다. 이 결과는 학습 데이터에 비해 검증 데이터에서의 성능 차이가 나타나는 과적합임을 알 수 있다.

테스트 세트를 이용해 평가(evaluate)를 진행했을 때 아래와 같은 점수가 나왔다. 또한, 직접 수집한 새로운 강아지 고양이 사진을 대상으로는 그림6을 통해 56개의 테스트 세트에서 5개의 이미지를 예측하는데 실패한 것을 확인할 수 있다.

accuracy: 0.8701 - loss: 0.4364

그림6

 

2. Xception

Xception 모델은 가장 좋은 성능을 보여준 모델로 앞의 모델들과 달리 더 자세하게 다뤄보려고 한다.

accuracy: 0.9980 - loss: 0.0056 - val_accuracy: 0.9897 - val_loss: 0.0380

Xception 모델은 매우 좋은 스코어를 보여준다. 학습과 검증 모두에서 높은 정확도와 낮은 손실을 기록하고 있어 과적합 문제도 거의 없다고 볼 수 있다. 즉, 데이터에 잘 맞고 일반화 성능도 뛰어나다고 볼 수 있다. 그림7을 보면 더 정확하게 확인할 수 있다. 

그림7

 

학습 정확도와 검증 정확도가 높은 수준으로 수렴하고 있다. 학습 초기부터 높은 정확도를 보이며, 에포크가 진행될수록 안정화되는 모습을 보여준다. 또한, 학습과 검증 정확도의 차이가 거의 없어, 모델이 학습 데이터에 과적합되지 않고 일반화 성능이 매우 좋다고 볼 수 있다. 하지만 특정 에포크에서는 검증 정확도에 약간의 변동이 있지만, 전체적으로는 높은 정확도를 유지하며 안정적인 성능을 나타내고 있다.

학습 손실과 검증 손실이 학습 초기에 빠르게 줄어들어 0.05 이하의 낮은 손실 값을 유지하고 있다. 에포크 2 때 검증 손실이 높아졌지만 이후 학습과 검증 손실 모두 낮은 수준에서 거의 변동이 없는 상태를 보여준다. 즉, 손실 그래프가 거의 수평에 가깝게 유지되고 있는 점은 모델이 과적합 없이 잘 학습되었다고 볼 수 있다.

테스트 세트를 이용해 평가(evaluate)를 진행했을 때 아래와 같은 점수가 나왔다. 또한, 직접 수집한 새로운 강아지 고양이 사진을 대상으로는 그림8을 통해 56개의 테스트 세트에서 2개의 이미지를 예측하는데 실패한 것을 확인할 수 있다.

accuracy: 0.9953 - loss: 0.0125

 

그림8

1) Xception 모델 전체 예측 결과

 

3. 결과

앞의 결과를 통해 make_model은 강아지를 대상으로 예측에 실패한 것을 확인할 수 있다. 즉, 다른 모델들에 비해 성능이 좋지 않다고 볼 수 있다. 반면 MobileNetV2은 강아지를 대상으로 모두 예측에 성공했다. 하지만 고양이를 대상으로 예측했을 때 5개를 예측에서 실패했다. Xception 역시 강아지를 대상으로 모두 예측에 성공했다. 하지만 고양이를 대상으로 예측했을 때 2개를 예측에서 실패했다.

모든 모델이 공통적으로 예측에 실패한 사진이 두 개가 있다. 아래 그림9로 모두 고양이 사진이다. 사람의 입장에서 쉽게 고양이로 구분할 수 있지만 두 사진은 고양이의 얼굴이나 귀 부분이 약간 가려져 있거나 분명하지 않아 모델이 고양이를 식별하는 데 사용하는 특징이 덜 보일 수 있다. 모델은 일반적으로 귀의 형태나 얼굴의 특정 특징을 통해 고양이와 강아지를 구분하는 경우가 많기 때문에, 이런 특징이 모호하면 잘못된 예측을 할 가능성이 있다.

그림9

 

6. 결론

이 프로젝트의 목표는 Kaggle에서 제공된 강아지와 고양이의 사진 데이터셋을 이용해 두 동물을 정확히 분류할 수 있는 딥러닝 모델을 개발하고 비교하는 것이다. 결론은 다음과 같다.

  1. 모델 성능 비교:
    • 직접 만든 make_model은 학습 데이터에서 양호한 성능을 보였지만, 검증 데이터와 테스트 데이터에서는 과적합 문제로 인해 상대적으로 낮은 성능을 보였다. 반면, 사전 훈련된 MobileNetV2와 Xception 모델은 높은 정확도와 낮은 손실을 기록했으며, 특히, Xception 모델이 가장 우수한 성능을 보였다.
    • Xception 모델은 학습, 검증, 테스트 데이터에서 높은 정확도와 낮은 손실을 유지하며, 과적합 없이 안정적으로 학습되었다. 즉,  Xception 모델이 강아지와 고양이를 구별하는 데 필요한 다양한 시각적 특징을 효과적으로 학습했음을 의미한다.
  2. 실제 데이터 적용 가능성:
    • 테스트 데이터셋에서 Xception 모델은 99.53%의 정확도와 0.0125의 낮은 손실을 기록하며, 강아지와 고양이를 높은 정확도로 구분하는 능력을 보여주었다. 이러한 성능은 실제 응용 사례에서도 반려동물을 높은 정확도로 분류할 수 있는 가능성을 시사한다.
    • 다만, 직접 수집한 추가적인 강아지와 고양이 이미지에서 모든 모델이 공통적으로 예측에 실패한 사례가 있었다. 특히, 고양이의 얼굴이나 귀가 가려진 이미지에서 예측이 어려웠다. 이는 모델이 특정한 특징(귀 모양, 얼굴 윤곽 등)을 통해 고양이를 인식하고 있음을 의미하며, 이러한 부분에서 예측 정확도를 높이기 위해 추가적인 데이터 증강이나 전처리 기법을 적용할 필요가 있다.
  3. 프로젝트의 기대 효과:
    • 반려동물 분류 모델은 반려동물 관리 앱, 유기동물 보호소의 자동 분류 시스템 등 실제 응용 사례에서도 유용하게 사용될 수 있다.
  4. 향후 개선 방향:
    • 향후, 더 다양한 상황에서 강아지와 고양이를 인식할 수 있도록 데이터셋을 보강하거나, 특정한 특징이 잘 드러나지 않는 이미지에서도 높은 성능을 발휘할 수 있도록 모델을 추가적으로 개선할 필요가 있다.
    • 다양한 배경과 조명 조건에서의 이미지 수집, 추가적인 하이퍼파라미터 튜닝 등을 통해 모델의 성능을 더욱 최적화할 수 있을 것이다.
728x90