CNN 딥러닝 과제

이 과제는 CNN을 사용하여 패션 MNIST 데이터셋의 이미지를 분류하는 딥러닝 모델을 구현하는 것입니다.

-패션 MNIST는 10개의 카테고리로 구성된 의류 이미지 데이터셋으로, 각 이미지는 28x28 픽셀의 흑백 이미지입니다.

과제 :

패션 MNIST 분류 예제 퀴즈

  1. 데이터 로드 및 전처리: keras.datasets.fashion_mnist.load_data()를 사용하여 데이터를 로드하고, 픽셀 값을 0과 1 사이로 정규화합니다.
  2. CNN 모델 구성:
    • Conv2D: Convolutional Layer (합성곱 층)으로, 이미지에서 특징을 추출합니다.
    • MaxPooling2D: Max Pooling Layer (최대 풀링 층)으로, 특징 맵의 크기를 줄여 계산량을 줄이고 과적합을 방지합니다.
    • Flatten: Flatten Layer (평탄화 층)으로, 2차원 특징 맵을 1차원 벡터로 변환합니다.
    • Dense: Fully Connected Layer (완전 연결 층)으로, 모든 뉴런이 서로 연결되어 있습니다.
    • softmax: 출력층의 활성화 함수로, 각 클래스에 대한 확률을 반환합니다.
  3. 모델 컴파일: 손실 함수, 옵티마이저, 평가 지표를 설정합니다.
  4. 모델 훈련: model.fit() 함수를 사용하여 모델을 훈련합니다.
  5. 모델 평가: model.evaluate() 함수를 사용하여 모델의 성능을 평가합니다.
  6. 예측 및 시각화 (선택 사항): model.predict() 함수를 사용하여 테스트 이미지에 대한 예측을 수행하고, 결과를 시각화합니다.

<참고 자료 : import 라이브러리, 데이터 로드> // 0: 티셔츠/탑 (T-shirt/top) 1: 바지 (Trouser) 2: 풀오버 (Pullover) 3: 드레스 (Dress) 4: 코트 (Coat) 5: 샌들 (Sandal) 6: 셔츠 (Shirt) 7: 스니커즈 (Sneaker) 8: 가방 (Bag) 9: 앵클 부츠 (Ankle boot) import tensorflow as tf from tensorflow import keras import numpy as np import matplotlib.pyplot as plt // 데이터 로드 fashion_mnist = keras.datasets.fashion_mnist (train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data() // 클래스 이름 정의 class_names = [‘T-shirt/top’, ‘Trouser’, ‘Pullover’, ‘Dress’, ‘Coat’, ‘Sandal’, ‘Shirt’, ‘Sneaker’, ‘Bag’, ‘Ankle boot’] // 이미지 픽셀 값을 0과 1사이로 정규화 train_images = train_images / 255.0 test_images = test_images / 255.0

import tensorflow as tf  # 딥러닝 라이브러리
from tensorflow.keras import layers, models  # 신경망 계층  모델 설계
from tensorflow.keras.datasets import fashion_mnist  # fashion_mnist 데이터셋
import matplotlib.pyplot as plt  # 시각화 도구
// 2. 데이터 로드 및 전처리
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

// 이미지는 28x28 크기, 채널 정보 추가 (흑백 이미지는 채널 1개, 컬러는 3개)
train_images = train_images.reshape((train_images.shape[0], 28, 28, 1)).astype('float32') / 255.0  # 0~1 정규화, 픽셀은 0에서 255까지 값을 가짐
test_images = test_images.reshape((test_images.shape[0], 28, 28, 1)).astype('float32') / 255.0
// astype : 형변환

 레이블을 One-Hot Encoding (숫자 0~9 벡터로 변환)
// One-Hot Encoding : 범주형 데이터를 수치형 데이터로 변환하는 방법
if len(train_labels.shape) == 1:  # shape이 (n,)인지 확인
    train_labels = tf.keras.utils.to_categorical(train_labels, 10)  # to_categorical(원핫인코딩 대상, 클래스 갯수)
if len(test_labels.shape) == 1:  # shape이 (n,)인지 확인
    test_labels = tf.keras.utils.to_categorical(test_labels, 10)


// 3. CNN 모델 정의
model = models.Sequential()  # 순차적 모델 선언

// 첫 번째 합성곱 계층: 필터 크기 3x3, 필터 수 32, 활성화 함수 ReLU
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
// 풀링 계층: 2x2 크기로 다운샘플링
model.add(layers.MaxPooling2D((2, 2)))

// 두 번째 합성곱 계층: 필터 수 64
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

// 세 번째 합성곱 계층: 필터 수 64
model.add(layers.Conv2D(64, (3, 3), activation='relu'))

// Fully Connected Layer를 연결하기 위해 Flatten 처리
model.add(layers.Flatten())

// Fully Connected Layer 1: 뉴런 수 64, 활성화 함수 ReLU
model.add(layers.Dense(64, activation='relu'))

// 출력층: 뉴런 수 10(클래스 수), 활성화 함수 Softmax
model.add(layers.Dense(10, activation='softmax'))

// 모델 요약 출력 (구조 확인용)
model.summary()

// 4. 모델 컴파일
model.compile(optimizer='adam',               # 최적화 알고리즘 (손실값을 최소화하면서 모델이 최적의 가중치를 찾도록 안내하는 역할)
              loss='categorical_crossentropy', # 다중 클래스 분류 손실 함수
              metrics=['accuracy'])           # 평가 지표: 정확도
// 5. 모델 학습
history = model.fit(train_images, train_labels, epochs=5, batch_size=64, validation_split=0.2)

// 6. 모델 평가
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f"테스트 정확도: {test_acc:.4f}")
print(f"테스트 손실율: {test_loss:.4f}")

// 7. 결과 확인: 테스트 데이터에서 임의의 이미지 예측
import numpy as np

// 테스트 데이터에서 첫 번째 샘플을 가져옴
sample_image = test_images[0]   # 첫번  이미지 저장
sample_label = np.argmax(test_labels[0])   # y_test[0] 배열에서 가장  값을 가지는 요소의 인덱스를 찾아 sample_label 변수에 저장

// 모델로 예측 수행
predicted_label = np.argmax(model.predict(sample_image.reshape(1, 28, 28, 1)))

// 결과 출력
plt.imshow(sample_image.reshape(28, 28), cmap='gray')
plt.title(f"real value: {sample_label}, forcast value: {predicted_label}")
plt.show()

클래스 이름 정의를 안한 출력 결과

테스트 정확도: 0.8968
테스트 손실율: 0.2893

출력 결과1

클래스 이름 정의한 코드

import tensorflow as tf  # 딥러닝 라이브러리
from tensorflow.keras import layers, models  # 신경망 계층  모델 설계
from tensorflow.keras.datasets import fashion_mnist  # fashion_mnist 데이터셋
import matplotlib.pyplot as plt  # 시각화 도구
import numpy as np
from sklearn.metrics import classification_report

// 1. 클래스 이름 정의
class_names = [
    "T-shirt/top", "Trouser", "Pullover", "Dress", "Coat",
    "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot"
]

// 2. 데이터 로드 및 전처리
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

// 이미지 크기 조정 및 정규화
train_images = train_images.reshape((train_images.shape[0], 28, 28, 1)).astype('float32') / 255.0
test_images = test_images.reshape((test_images.shape[0], 28, 28, 1)).astype('float32') / 255.0

// 레이블을 One-Hot Encoding
if len(train_labels.shape) == 1:
    train_labels = tf.keras.utils.to_categorical(train_labels, 10)
if len(test_labels.shape) == 1:
    test_labels = tf.keras.utils.to_categorical(test_labels, 10)

// 3. CNN 모델 구성
model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),  # 합성곱
    layers.MaxPooling2D((2, 2)),  # 풀링
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Flatten(),  # Flatten 변환
    layers.Dense(64, activation='relu'),  # 완전 연결층
    layers.Dense(10, activation='softmax')  # 출력층 (10 클래스)
])

// 모델 구조 확인
model.summary()

// 4. 모델 컴파일
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

// 5. 모델 훈련
history = model.fit(train_images, train_labels, epochs=7, batch_size=64, validation_split=0.2)

// 6. 모델 평가
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f"테스트 정확도: {test_acc:.4f}")
print(f"테스트 손실율: {test_loss:.4f}")

// 7. 모델 예측 및 클래스별 성능 평가
predictions = model.predict(test_images)
predicted_labels = np.argmax(predictions, axis=1)  # 예측값
true_labels = np.argmax(test_labels, axis=1)  # 실제값

// 클래스별 정밀도, 재현율, F1-score 출력
print("\n 클래스별 성능 평가:")
print(classification_report(true_labels, predicted_labels, target_names=class_names))

// 8. 예측 결과 시각화 (랜덤 5개)
fig, axes = plt.subplots(1, 5, figsize=(12, 4))

for i, ax in enumerate(axes):
    idx = np.random.randint(len(test_images))  # 랜덤 인덱스 선택
    ax.imshow(test_images[idx].reshape(28, 28), cmap='gray')

    real_label = class_names[true_labels[idx]]
    predicted_label = class_names[predicted_labels[idx]]

    ax.set_title(f"Real: {real_label}\nPred: {predicted_label}")
    ax.axis("off")

plt.tight_layout()
plt.show()

출력 결과2

클래스 이름 정의한 출력 결과

테스트 정확도: 0.8959
테스트 손실율: 0.2850
Class Precision Recall F1-score Support
T-shirt/top 0.91 0.78 0.84 1000
Trouser 1.00 0.98 0.99 1000
Pullover 0.75 0.94 0.83 1000
Dress 0.88 0.94 0.91 1000
Coat 0.89 0.77 0.82 1000
Sandal 0.96 0.99 0.97 1000
Shirt 0.74 0.70 0.72 1000
Sneaker 0.96 0.94 0.95 1000
Bag 0.95 0.98 0.97 1000
Ankle boot 0.96 0.95 0.96 1000

주요 단계

데이터 로드 및 전처리:
Keras API를 통해 패션 MNIST 데이터셋 로드
픽셀 값을 0~1 사이로 정규화
이미지 데이터 형태 조정 (채널 추가)
레이블을 원-핫 인코딩으로 변환


CNN 모델 구성:
Conv2D 층: 이미지에서 특징 추출
MaxPooling2D 층: 특징 맵 크기 축소로 과적합 방지 및 계산량 감소
Flatten 층: 2D 특징 맵을 1D 벡터로 변환
Dense 층: 완전 연결 층으로 분류 수행
출력층: Softmax 활성화 함수로 10개 클래스에 대한 확률 출력


모델 컴파일 및 훈련:
손실 함수: categorical_crossentropy
최적화 알고리즘: Adam
평가 지표: 정확도(accuracy)
epochs와 batch_size 조정을 통한 모델 훈련


모델 평가 및 시각화:
테스트 데이터에 대한 정확도 및 손실률 측정
클래스별 성능 평가(정밀도, 재현율, F1-score)
랜덤 샘플에 대한 예측 결과 시각화

구현된 CNN 모델은 약 89.6%의 테스트 정확도를 달성했습니다. 
'Trouser', 'Sandal', 'Bag', 'Sneaker', 'Ankle boot' 등의 카테고리에서 높은 정확도를 보인 반면, 
'Shirt'와 같은 카테고리에서는 상대적으로 낮은 성능을 보였습니다. 이는 유사한 의류 
아이템(예: 셔츠와 티셔츠, 코트와 풀오버) 간의 구분이 더 어렵기 때문으로 분석됩니다.
이 과제는 딥러닝의 핵심 개념인 CNN을 실제 이미지 분류 문제에 적용하여 학습하는 좋은 기회를 되었습니다.