CNN 딥러닝 과제
-패션 MNIST는 10개의 카테고리로 구성된 의류 이미지 데이터셋으로, 각 이미지는 28x28 픽셀의 흑백 이미지입니다.
과제 :
패션 MNIST 분류 예제 퀴즈
- 데이터 로드 및 전처리: keras.datasets.fashion_mnist.load_data()를 사용하여 데이터를 로드하고, 픽셀 값을 0과 1 사이로 정규화합니다.
- CNN 모델 구성:
- Conv2D: Convolutional Layer (합성곱 층)으로, 이미지에서 특징을 추출합니다.
- MaxPooling2D: Max Pooling Layer (최대 풀링 층)으로, 특징 맵의 크기를 줄여 계산량을 줄이고 과적합을 방지합니다.
- Flatten: Flatten Layer (평탄화 층)으로, 2차원 특징 맵을 1차원 벡터로 변환합니다.
- Dense: Fully Connected Layer (완전 연결 층)으로, 모든 뉴런이 서로 연결되어 있습니다.
- softmax: 출력층의 활성화 함수로, 각 클래스에 대한 확률을 반환합니다.
- 모델 컴파일: 손실 함수, 옵티마이저, 평가 지표를 설정합니다.
- 모델 훈련: model.fit() 함수를 사용하여 모델을 훈련합니다.
- 모델 평가: model.evaluate() 함수를 사용하여 모델의 성능을 평가합니다.
- 예측 및 시각화 (선택 사항): 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
클래스 이름 정의한 코드
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()
클래스 이름 정의한 출력 결과
테스트 정확도: 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을 실제 이미지 분류 문제에 적용하여 학습하는 좋은 기회를 되었습니다.