본문 바로가기
  • You find inspiration to create your own path !
업무 자동화/AI

'개와 고양이 분류' 실습 #2

by ToolBOX01 2026. 5. 14.
반응형

3. 데이터 전처리

def format_image(image, label):
    image = tf.cast(image, tf.float32)
    image = image / 255.0  # 정규화
    image = tf.image.resize(image, (150, 150))
    return image, label

# map: 모든 데이터에 format_image 함수를 적용해라!
# batch(32): 데이터를 32개씩 묶어서 가져와라!

train_batches = train_data.map(format_image).batch(32)
test_batches = test_data.map(format_image).batch(32)

위 코드를 실행하고,  "train_batches"에 데이터가 있는지 확인을 합니다

for image_batch, label_batch in train_batches.take(1):
    print("배치 이미지 형태:", image_batch.shape)  # (batch_size, 150, 150, 3)
    print("배치 라벨 형태:", label_batch.shape)    # (batch_size,)
    print("첫 번째 이미지 형태 (정규화 및 리사이즈 후):", image_batch[0].shape)

배치 이미지 형태: (32, 150, 150, 3)
배치 라벨 형태: (32,)
첫 번째 이미지 형태 (정규화 및 리사이즈 후): (150, 150, 3)

4. CNN 모델 설계 (Convolutional Neural Network)

model = models.Sequential([
    # 특징 추출 (Convolution & Pooling)
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)),
    layers.MaxPooling2D(2, 2),
    
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D(2, 2),
    
    layers.Conv2D(128, (3, 3), activation='relu'),
    layers.MaxPooling2D(2, 2),

    # 분류 (Dense Layers)
    layers.Flatten(),
    layers.Dense(512, activation='relu'),
    layers.Dense(1, activation='sigmoid') # 개/고양이 이진 분류이므로 sigmoid 사용
])

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

/usr/local/lib/python3.12/dist-packages/keras/src/layers/convolutional/base_conv.py:113: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead. super().__init__(activity_regularizer=activity_regularizer, **kwargs)
  1. 데이터셋 로드 및 확인 (Cells FtziPCNs0Oqs, BaPQkAx00YPW, mZcpDzwl0-JN):
    • tensorflow_datasets를 사용하여 'cats_vs_dogs' 데이터셋을 불러왔습니다. 이 데이터셋은 고양이와 개의 이미지로 구성되어 있습니다.
    • 전체 데이터 중 80%는 훈련 데이터로, 나머지 20%는 테스트 데이터로 분리했습니다.
    • 데이터셋에 대한 기본적인 정보(전체 이미지 개수, 라벨 종류)를 확인했으며, 훈련 데이터에서 몇 개의 샘플 이미지를 시각화하여 확인했습니다.
    • 개별 이미지의 형태와 라벨 값(고양이: 0, 개: 1)도 확인했습니다.
  2. 이미지 전처리 및 배치 처리 (Cells bnOrbkEp1Cl5, 335086da):
    • format_image 함수를 정의하여 이미지를 전처리했습니다. 이 함수는 이미지를 0과 1 사이로 정규화하고, 모든 이미지를 150x150 픽셀 크기로 조정합니다.
    • map과 batch 함수를 사용하여 훈련 및 테스트 데이터에 이 전처리 함수를 적용하고, 데이터를 32개씩 묶어 배치(batch) 형태로 만들었습니다.
    • train_batches에서 하나의 배치를 가져와 이미지와 라벨의 형태를 확인하여, 배치가 32개의 150x150 크기 이미지로 구성되어 있음을 확인했습니다.
  3. 모델 정의 및 컴파일 (Cell 8ibqQtCD393X):
    • 케라스(Keras)의 Sequential API를 사용하여 컨볼루션 신경망(CNN) 모델을 정의했습니다.
    • 모델은 특징 추출을 위한 여러 개의 Conv2D  MaxPooling2D 레이어와, 분류를 위한 Flatten  Dense 레이어로 구성됩니다.
    • 마지막 레이어는 개/고양이 이진 분류를 위해 sigmoid 활성화 함수를 사용했습니다.
    • adam 옵티마이저와 binary_crossentropy 손실 함수를 사용하여 모델을 컴파일했습니다.
    발생한 UserWarning에 대한 설명: UserWarning: Do not pass an input_shape/input_dim argument to a layer. When using Sequential models, prefer using an Input(shape) object as the first layer in the model instead.

    이 메시지는 오류(Error)가 아니라 **경고(Warning)**입니다. 모델은 정상적으로 컴파일되었습니다. 케라스 Sequential 모델을 사용할 때, 첫 번째 레이어에 input_shape 인자를 직접 전달하는 대신, Input(shape=(150, 150, 3))과 같은 Input 객체를 모델의 첫 번째 레이어로 명시적으로 추가하는 것을 권장한다는 의미입니다. 이는 Functional API 스타일에서 모델을 구성할 때 더 유연하고 명확한 방법이지만, 현재 코드 방식도 동작하는 데 문제는 없습니다. 지금은 이 경고를 무시하고 다음 단계로 진행하셔도 됩니다.

5. 모델 학습 및 결과 확인

history = model.fit(train_batches, epochs=10, validation_data=test_batches)

# 학습 결과 시각화
plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
plt.show()

 

학습 결과 그래프와 로그를 보니, 아주 전형적인 과적합(Overfitting) 현상이 나타나고 있습니다. 인공지능이 공부를 한 게 아니라 답안지를 통째로 외워버린 상태

1. 주요 지표 분석

구분 훈련 데이터 (accuracy) 검증 데이터 (val_accuracy) 상태
최종 수치 99.17% (거의 완벽) 79.49% (정체 중) 격차 매우 큼
추세 계속해서 매끄럽게 상승 Epoch 2 이후로 정체 또는 하락 전형적인 과적합

 

  • 훈련 정확도 (accuracy): 1.00에 가까워질 정도로 매우 높습니다. 모델이 주어진 훈련 데이터 안에서는 개와 고양이를 완벽하게 구별한다는 뜻입니다.
  • 검증 정확도 (val_accuracy): 그래프의 주황색 선을 보시면, 초반에 잠깐 오르다가 어느 순간부터는 더 이상 오르지 않고 80% 근처에서 머물고 있습니다.
  • 손실값 (val_loss): 로그를 보면 val_loss가 Epoch 3(0.4383) 이후로 계속 커져서 마지막에는 1.2180까지 치솟았습니다. 이는 모델이 새로운 데이터를 봤을 때 점점 더 엉뚱한 대답을 하며 확신을 잃어가고 있다는 강력한 신호입니다

 

 

2. 왜 이런 결과가 나왔을까요?

모델이 학습 데이터의 특징(귀 모양, 털 색깔 등)을 배우는 대신, 학습 데이터에 포함된 노이즈나 특정 사진의 배경까지 통째로 외워버렸기 때문입니다. 이로 인해 "시험 공부는 열심히 해서 연습 문제는 다 맞히는데, 실제 시험(새로운 데이터)에서는 점수가 안 나오는" 상황이 된 것입니다.

 

3. 어떻게 해결하면 좋을까요? (개선 팁)
이 성능을 80% 이상으로 끌어올리기 위해서는 다음과 같은 방법들을 시도해 볼 수 있습니다.

10 데이터 증강 (Data Augmentation): 사진을 살짝 돌리거나(Rotation), 좌우를 반전(Flip)시켜서 모델이 사진을 외우지 못하게 방해합니다.

2) 드롭아웃 (Dropout) 추가: 학습 중에 무작위로 일부 신경망을 꺼버리는 기법입니다. 특정 경로에만 의존하지 않게 만들어 과적합을 방지합니다.

예: layers.Dropout(0.5)를 Dense 층 앞에 추가

3) L2 규제 (Regularization): 가중치가 너무 커지지 않게 제한을 두어 모델을 더 단순하게 만듭니다.

4) 조기 종료 (Early Stopping): val_loss가 더 이상 줄어들지 않고 늘어나기 시작할 때(이 그래프에서는 Epoch 2~3 지점) 학습을 스스로 멈추게 설정합니다.

현재 모델은 훈련 데이터에 너무 과하게 맞춰져 있습니다. val_accuracy를 높이기 위해 모델 구조에 Dropout을 추가하거나 데이터 증강 기법을 적용해 보시는 것을 추천


 

 

 

 

반응형