01. 컨볼루션 신경망 이해
📘
CNN은 이미지나 음성, 시계열 데이터를 처리하는 데 적합한 딥러닝 신경망 구조임.
이미지의 공간 구조를 그대로 활용하며 특징을 추출하는 데 효과적임.
✅ 정의
컨볼루션 신경망(CNN, Convolutional Neural Network)은 이미지나 영상처럼 구조가 있는 데이터를 처리하기 위한 인공신경망임.
입력 이미지에서 중요한 특징을 자동으로 추출하고 학습하는 방식임.
✅ 사용하는 이유
- 이미지 전처리 없이 특징을 자동으로 추출할 수 있음.
- 위치 변화에 영향을 적게 받음 (위치 불변성 존재함).
- 연산량이 적고 파라미터가 공유되어 학습이 효율적임.
- 완전연결층에 비해 과적합 위험이 줄어듦.
✅ Dense Layer와 CNN Layer 비교
| 항목 | Dense Layer | Convolution Layer |
| 입력 처리 방식 | 1D 벡터화 필요 | 2D 이미지 구조 유지 |
| 학습 방식 | 전역 특징 학습 | 지역 특징 학습 |
| 파라미터 수 | 매우 많음 | 상대적으로 적음 |
| 공간 정보 유지 | 불가능 | 가능 |
| 오버피팅 위험 | 높음 | 낮음 |
예시로 햄버거 이미지의 구성요소(패티, 빵, 치즈 등)가 위치가 바뀌더라도 CNN은 동일한 이미지로 인식함. 반면, Dense Layer는 위치가 바뀌면 다르게 인식함.
✅ 구성 요소 정의
- Convolution Layer: 필터(커널)를 사용해 특징 추출을 수행함.
- Activation (ReLU): 비선형성을 추가해 모델이 복잡한 패턴을 학습하도록 도와줌.
- Pooling Layer: 특징의 위치를 줄이면서 중요한 정보만 유지하는 역할을 함.
- Flatten: 2D 이미지 데이터를 1D 벡터로 변환하여 Dense Layer에 전달함.
- Dense Layer: 최종 출력을 위한 분류기 역할을 수행함.
✅ 전이학습 정의 및 이유
**전이학습(Transfer Learning)**이란, 사전학습된 모델을 활용하여 새로운 작업을 빠르게 학습하는 기법임.
- 큰 데이터셋으로 학습된 모델을 기반으로 하여, 데이터가 부족한 상황에서도 효과적인 학습이 가능함.
- 일부 레이어는 고정하고, 상위 레이어만 재학습하여 시간과 자원을 절약함.
- 단점은 원래 학습된 데이터와 새로운 데이터의 특성이 너무 다르면 성능이 떨어질 수 있음.
02. 사전학습 모델을 사용하여 개과 고양이 이미지 이진 분류모델
🐶
✅ 목적
개와 고양이를 구분하는 이진 분류 문제를 해결하기 위함.
사전학습 모델 MobileNetV2를 사용함.
✅ MobileNetV2 특징
- 경량 모델로 모바일 환경에서도 빠르게 작동함.
- 깊은 층으로 갈수록 더욱 추상적인 특징을 추출함.
- ImageNet 같은 대규모 데이터셋으로 사전학습되어 있음.
✅ 모델 구성
- feature extractor로 MobileNetV2 사용함.
- 출력층만 사용자 정의 Dense Layer로 교체함.
- binary_crossentropy 손실 함수 사용함.
- 성능 평가는 confusion matrix와 classification report를 활용함.
✅ 장단점
- 적은 수의 이미지로도 높은 성능을 낼 수 있음.
- 학습 시간 단축 및 과적합 방지에 효과적임.
- 단점은 사전학습 모델이 특정 도메인에 특화되어 있으면 일반화가 떨어질 수 있음.
코드
1. 데이터 준비 및 전처리
🔧 주요 코드
!wget --no-check-certificate \
https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip \
-O /tmp/cats_and_dogs_filtered.zip
- Google에서 데이터셋 다운로드
- wget은 외부 URL에서 데이터를 가져오는 명령어임.
zip_ref.extractall('/tmp')
- 압축 해제
train_dir = os.path.join(rootPath, 'train')
validation_dir = os.path.join(rootPath, 'validation')
- 훈련용/검증용 이미지 디렉터리 경로 설정
🔄 이미지 데이터 로드
image_dataset_from_directory(...)
- 자동으로 폴더명을 클래스 레이블로 인식
- image_size=(160, 160): 이미지 크기 통일
- batch_size=32: 한 번에 처리할 이미지 수
✨ image_size나 batch_size를 변경하면 학습 속도 및 정확도에 영향을 줄 수 있음.
- 너무 큰 이미지: 학습 느려짐, 성능 ↑ 가능
- 너무 작은 이미지: 학습 빠르지만 정보 손실
2. 모델 구성 및 설정
🔧 주요 코드
base_model = tf.keras.applications.MobileNetV2(input_shape=(160, 160, 3),
include_top=False,
weights='imagenet')
- MobileNetV2: 경량화된 CNN 모델 (성능 좋고 빠름)
- include_top=False: 기존 분류층 제거하고 우리가 새로 덧붙임
- weights='imagenet': ImageNet 데이터셋으로 학습된 사전 가중치 사용
base_model.trainable = False
- 특징 추출기로만 사용하고 학습은 하지 않음
→ 빠르게 수렴하고 오버피팅 방지 가능
→ 🔁 바꾸면: True로 하면 fine-tuning 가능 (성능↑ or 오버피팅↑)
📐 전체 모델 구조
model = models.Sequential([
base_model,
layers.GlobalAveragePooling2D(),
layers.Dense(1, activation='sigmoid')
])
- GlobalAveragePooling2D: 특징 맵의 평균값으로 압축 → 파라미터 감소
- Dense(1, sigmoid): 이진 분류 → 확률값 반환
🎯 이진 분류 → sigmoid
다중 분류라면 → softmax로 바꿔야 함.
3. 모델 학습
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
- optimizer='adam': 학습을 빠르고 안정적으로
- loss='binary_crossentropy': 이진 분류용 손실 함수
history = model.fit(train_ds, validation_data=val_ds, epochs=20)
- epochs=20: 학습 반복 횟수
- 🔁 늘리면: 성능 개선 가능 (단, 오버피팅 위험 있음)
4. 성능 평가
✅ 평가 지표 계산
confusion_matrix(y_true, y_pred)
classification_report(y_true, y_pred)
metrics.accuracy_score(...)
- accuracy: 전체 정확도
- precision: 예측한 것 중 실제 정답 비율
- recall: 실제 정답 중 예측이 맞은 비율
- f1: precision과 recall의 조화 평균
❗ 클래스 불균형 시에는 accuracy만으로 판단하지 않고 f1을 참고해야 정확
✅ 예측 실패 이미지 확인
wrong_images.append(images[i].numpy()) # 실제 이미지
wrong_preds.append(pred_label) # 잘못 예측한 값
wrong_labels.append(true_label) # 정답
- 혼동 행렬이나 성능 지표 외에 실제 어떤 이미지를 잘못 예측했는지 시각화하여 문제 파악
5. 이미지 예측 함수
🔧 주요 함수
def predict_image(img_path, model, class_names, img_size=(160, 160)):
...
img_array = img_array / 255.0 # 정규화
...
prediction = model.predict(img_array)[0][0]
- 입력 이미지 전처리 후 예측
- 결과 시각화 (imshow, title에 확률 표시)
✅ 교체 가능한 부분
- img_size=(160, 160)
→ 사전학습 모델마다 입력 크기 다름
(ex. EfficientNetB0은 224, InceptionV3은 299 등) - model.predict()
→ 다른 모델로 교체 시 아키텍처만 맞춰주면 동일 방식으로 예측 가능
✅ 랜덤 시드 설명
seed=123
- image_dataset_from_directory()의 셔플 재현성 확보
- 같은 이미지 분할, 같은 순서로 반복되게 함
- 실험 재현성과 성능 비교를 위해 반드시 고정하는 것이 좋음
🔁 seed를 변경하면: 이미지 순서, 훈련/검증 비율이 달라지며 성능 변화 가능성 있음
✅ 다른 사전학습 모델로 교체하는 방법
from tensorflow.keras.applications import EfficientNetB0
base_model = EfficientNetB0(input_shape=(224, 224, 3),
include_top=False,
weights='imagenet')
- EfficientNet, ResNet, Inception 등으로 쉽게 교체 가능
- 단, 입력 이미지 크기와 모델에 맞는 전처리 필요
03. 사전학습 모델을 사용하여 분리수거 이미지 다중 분류하기
♻️
✅ 목적
캔, 플라스틱, 종이 등 다양한 분리수거 품목을 자동으로 분류하는 다중 분류 문제임.
사전학습 모델 EfficientNetB0를 사용함.
✅ EfficientNetB0 특징
- 성능과 연산 효율성 사이의 균형이 뛰어남.
- 적은 연산량으로도 높은 정확도를 유지할 수 있음.
- 파라미터 수가 적고 경량 모델이므로 실제 서비스에 적합함.
✅ 모델 구성
- EfficientNetB0의 feature extractor만 사용하고, 상위 분류층(Dense Layer)은 새로 구성함.
- 출력층은 softmax를 사용하여 다중 클래스 확률을 반환함.
- 손실 함수는 sparse_categorical_crossentropy를 사용함 (정수 인덱스를 사용하는 다중분류에 적합함).
✅ 장단점
- 학습 데이터가 부족해도 전이학습으로 높은 정확도를 낼 수 있음.
- 빠른 수렴이 가능하고 실용성이 높음.
- 단점은 사전학습 모델이 원래 학습된 도메인과 너무 다르면 특성 전이 효과가 줄어들 수 있음.
✅ 요약 비교
| 항목 | 개·고양이 이진 분류 | 분리수거 다중 분류 |
| 사용 모델 | MobileNetV2 | EfficientNetB0 |
| 분류 유형 | 이진 분류 | 다중 분류 |
| 손실 함수 | binary_crossentropy | sparse_categorical_crossentropy |
| 출력층 활성화 | sigmoid | softmax |
| 활용 목적 | 가볍고 빠른 분류 | 높은 정확도의 정밀 분류 |
코드
🔹 01. 라이브러리 설치 및 임포트
!pip install koreanize-matplotlib
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.preprocessing import image
import numpy as np
from sklearn.metrics import confusion_matrix, classification_report
import seaborn as sns
import matplotlib.pyplot as plt
import koreanize_matplotlib
import os
import warnings
warnings.filterwarnings('ignore')
설명
- 필요한 패키지 설치 및 불러오기
- warnings는 불필요한 경고 숨기기
- koreanize_matplotlib: 한글 깨짐 방지
🔹 02. 데이터 업로드 및 경로 설정
path = '/content/drive/MyDrive/.../recycle_data'
설명
- 구글 드라이브에 업로드된 폴더를 불러올 경로
🔹 03. 데이터셋 로딩 (Training / Validation 분리)
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
path, validation_split=0.3, subset="training", seed=123, image_size=img_size, batch_size=batch_size
)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
path, validation_split=0.3, subset="validation", seed=123, image_size=img_size, batch_size=batch_size
)
설명
- 폴더 구조에서 자동으로 클래스 분류
- validation_split=0.3: 전체의 30%는 검증용
- seed=123: 고정된 분할을 위함
🟡 변경 가능:
- validation_split: 예) 0.2 → 더 많은 학습데이터 확보
- seed: 바꾸면 분할이 달라져 성능 영향 가능
🔹 04. 데이터 확인 및 시각화
for class_folder in sorted(os.listdir(path)):
...
for images, labels in train_ds.take(1):
...
설명
- 각 클래스당 이미지 개수 출력
- 훈련 데이터에서 9장 샘플 출력
🔹 05. 성능 향상을 위한 전처리
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(100).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
설명
- .cache(): 메모리에 적재 → 속도 향상
- .shuffle(100): 순서 섞기 → 과적합 방지
- .prefetch: CPU-GPU 병렬처리로 학습 효율 향상
🔹 06. EfficientNet 모델 구성 및 학습
6-1 모델 구성
base_model_effnet = tf.keras.applications.EfficientNetV2M(...)
model_effnet = models.Sequential([
base_model_effnet,
layers.GlobalAveragePooling2D(),
layers.Dense(len(class_names), activation='softmax')
])
설명
- EfficientNetV2M: ImageNet으로 사전학습된 모델
- include_top=False: FC 레이어 제거
- trainable=False: 전이학습(freeze)
🟡 다른 모델로 교체 가능:
- 예: EfficientNetB0, ResNet50, MobileNetV2, VGG16
6-2 모델 설정 (Compile)
model_effnet.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
설명
- adam: 최적화 알고리즘
- sparse_categorical_crossentropy: 정수 label용 다중분류 손실 함수
6-3 모델 학습
설명
- epochs=20: 20번 반복 학습
- history: 학습 및 검증 손실·정확도 저장
🔹 07. 모델 평가 및 시각화
7-1 학습 정확도 및 손실 시각화
plt.plot(history_effnet.history['accuracy'], ...)
설명
- 학습/검증 정확도 및 손실 시각화
- 오버피팅 여부 확인
7-2 Confusion Matrix
for images, labels in val_ds:
preds = model_effnet.predict(images)
...
cm_effnet = confusion_matrix(...)
sns.heatmap(...)
설명
- 예측 결과를 실제 클래스와 비교
- Confusion Matrix로 오차 분포 확인
7-3 Precision / Recall / F1-score 계산
report_effnet = classification_report(...)
print(report_effnet)
설명
- 다중분류에 대한 정밀도, 재현율, F1-score 계산
- 불균형 클래스에 대해 정확도보다 유용함
🔹 08. 사용자 이미지로 예측
uploaded = files.upload()
img = image.load_img(..., target_size=img_size)
...
pred_class_index = np.argmax(preds, axis=1)[0]
설명
- 사용자가 업로드한 이미지를 예측
- 결과는 한글 클래스명 매핑하여 출력
🔹 09. 모델 저장
model_effnet.save('model_effnetB0.h5')
설명
- .h5 포맷으로 모델 저장
- 나중에 불러와서 load_model()로 재사용 가능
마무리

이번 실습을 통해 CNN의 구조와 작동 방식을 직접 체험하며 추상적인 개념이 구체적으로 이해되었습니다. 특히, Dense Layer와 Convolution Layer의 차이, 위치 불변성과 파라미터 공유의 장점이 실제 예제를 통해 체감되었는데요. 단순히 이미지를 분류하는 것이 아니라, 이미지 속 패턴과 특징을 모델이 어떻게 추출하고 학습하는지에 대한 원리를 익힐 수 있어 좋았습니다. 또한 전이학습의 개념을 통해, 기존에 학습된 모델을 활용하여 적은 데이터로도 좋은 성능을 얻을 수 있다는 점이 실무에 매우 유용하게 느껴졌습니다.
개와 고양이 이진 분류 예제를 통해 사전학습 모델을 효율적으로 활용하는 방법을 배웠고, 분리수거 이미지 다중 분류에서는 실제 생활 문제에 딥러닝을 적용하는 가능성을 확인할 수 있었습니다. 모델 구성, 학습, 평가, 예측 및 저장까지 전 과정을 실습하며 프로젝트 단위의 머신러닝 흐름을 익힌 점도 저에게 큰 배움이었습니다!!! 특히 confusion matrix, classification report 등의 평가 방법을 통해 단순 정확도뿐 아니라 모델의 정밀한 성능을 확인하는 방법을 알게 되었답니다.
마지막으로 이미지 업로드 후 직접 분류해보는 기능을 구현하며 인공지능 기술이 사용자와 어떻게 상호작용할 수 있는지도 알 수 있었고, 앞으로 실생활 문제 해결에 AI를 적극 활용할 수 있을 거라 생각하며 내일도 뺘샤!!!
'ABC부트캠프' 카테고리의 다른 글
| [20일차] ESG포럼 & 세미나(3) (7) | 2025.07.20 |
|---|---|
| [19일차] ABC 부트캠프 진로컨설 기관 탐방 (14) | 2025.07.17 |
| [17일차]이진 분류 모델 실습 (타이타닉 생존자 예측) 및 인공지능 활용 신경망 실습 (0) | 2025.07.15 |
| [16일차] 인공지능 머신러닝 딥러닝 개요 (2) | 2025.07.14 |
| [15일차] ESG포럼 & 세미나(2) (6) | 2025.07.13 |