[혼자 공부하는 머신러닝+딥러닝] 8-2. 합성곱 신경망을 사용한 이미지 분류

2025. 3. 11. 22:37·ML & DL/머신러닝 기초

 

Intro.

8-1장에서 합성곱 신경망의 주요 개념들을 살펴봤다.

필터 크기, 패딩, 스트라이드, 풀링 등 설정할 게 많았는데, 이걸 일일이 직접 계산할 필요는 없다.

복잡한 계산은 Keras API가 다 해주기 때문에, 우리는 직관적으로 층의 구조만 설계하면 된다.

이번엔 Fasion MNIST 데이터를 적용해서 합성곱 신경망을 실습해보자!

(과연 7장의 심층신경망보다 성능이 더 좋을지 지켜봅시다!) 

 

1. 데이터 준비

  • 7장에서 했던 것과 동일하게 데이터 불러옴 + 데이터 살펴보기

  • 이전과 유사하게 255로 나눠서 전처리하고, 훈련/검증세트 분리
  • ⭐단, `reshape` 할 때 1차원으로 펼치지 않음 + 깊이(채널) 차원 추가

훈련 세트의 차원 변화를 그림으로 그려보면 이렇다

 

 

2. 합성곱 신경망(CNN) 만들기

keras의 `Sequential()`클래스에다가 `add()`로 층을 하나씩 추가하면 됨

1) Conv2D

  • 32개의 필터, 커널(도장) 크기는 (3*3), 활성화는 Relu, 패딩은 Same padding
  • ⭐제일 첫 번째 layer니까 `input_shape` 지정해줘야 함 = 깊이(채널) 차원 추가했으니까 (28, 28, 1)
# Sequential 객체 (뼈대) 생성해두기! 여기다가 하나씩 쌓아보자!
model = keras.Sequential()

# 1번째 합성곱 층
model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu', padding='same',
                              input_shape=(28,28,1))) # 1번째 층이니까 입력 차원까지 전달해줘야 함!

2) MaxPooling2D

  • 풀링 사이즈는 전형적인 (2*2) 사용
# 맥스 풀링 층
model.add(keras.layers.MaxPooling2D(2))
✅중간점검

•  필터를 32개 썼으니, 특성 맵의 깊이는 32가 될 것
•  (2,2) 풀링 썼으니, 특성 맵의 크기는 절반으로 줄어들 것
⇒ 여기까지 통과한 특성맵 : (14, 14, 32)

3) Conv2D

  • 층을 더 쌓아보자!
    • ⭐커널의 깊이(채널)는 알아서 입력과 동일한 깊이로 설정됨. 즉, kernel_size는 엄밀히 말하면 (3, 3, 32)가 됨!
  • 64개의 필터, 나머지는 1)과 동일
# 2번째 합성곱 층 (이번엔 필터 64개!)
model.add(keras.layers.Conv2D(64, kernel_size=(3,3), activation='relu', padding='same'))

4) MaxPooling2D

  • 2)와 동일
# 풀링은 이번에도 (2,2) 맥스풀링!
model.add(keras.layers.MaxPooling2D(2))
✅중간점검

•  필터를 64개 썼으니, 특성 맵의 깊이는 64가 될 것
•  (2,2) 풀링 썼으니, 특성 맵의 크기는 절반으로 줄어들 것
⇒ 여기까지 통과한 특성맵 : (7, 7, 64)

 

5) Flatten - Dense - Dropout

  • 최종 출력층으로 가기 전에 은닉층을 하나 거쳐가도록 추가 
    • 완전연결층으로 연결하기 위해 `Flatten` 층을 추가 = 1차원으로 펼침
    • 은닉층 뉴런 개수는 100개로 설정 
    • Overfitting 막기 위해 `Dropout` 층도 추가. 40% 확률로 노드 off.
# 이제 최종 확률값을 구하기 위해, Dense층 거쳐야 함!!

model.add(keras.layers.Flatten()) # 3차원 특성맵을 1차원으로 펼침
model.add(keras.layers.Dense(100, activation='relu')) # 뉴런 100개짜리 "은닉층"
model.add(keras.layers.Dropout(0.4)) # 오버피팅 규제를 위해서 드롭아웃 층도 추가

 

6) Dense

  • 최종 출력층은 `softmax` 함수 사용 = 10개의 클래스에 대한 분류 확률을 출력!
# 10개로 구분하는 "출력층"으로 마무리! 
model.add(keras.layers.Dense(10, activation='softmax')) # 다중분류니까 softmax 함수

 

7) 모델 최종 구조

  • `summary()`로 전체 모델 구조를 출력해 봄
  • ✏️파라미터 개수 계산 (가중치 + 절편)
    • 1번째 합성곱 층 : 3*3*1*32 + 32 = 320개
    • 2번째 합성곱 층 : 3*3*32*64 + 64 = 18,496개
    • 은닉층 : (7*7*64를 1차원으로 펴준) 3316*100 + 100 = 313,700개
    • 출력층 : 100*10 + 10 = 1,010개

  • keras.utils 패키지의 `plot_model` 함수를 쓰면 모델 구조를 그림으로도 출력 가능
    • ❗그림에는 안 나오지만 InputLayer라는 층이 맨 앞에 자동으로 추가됨 (25년 2월 기준)
keras.utils.plot_model(model) # 출력 결과로 아래 그림이 나옴

# show_shapes 설정으로 입출력 크기도 같이 볼 수 있고, to_file로 모델 이미지 저장도 가능함!
keras.utils.plot_model(model, show_shapes=True, to_file='cnn-architecture.png', dpi=300)

  • 전체 구조를 그림으로 그려보면 아래와 같음

 

3. 모델 컴파일 & 훈련

  • 모델 구성을 완료했으니, 이제 컴파일 설정하고 훈련하자!
  • Keras의 장점: 모델 종류나 구성 방식에 상관없이 Compile & Fit 과정이 같아서 편리함!

모델 컴파일

  • 옵티마이저 : Adam
  • 손실함수 : sparse_categorical_crossentropy (타깃값이 정수로 되어있으므로 'sparse' 붙임!)
  • 평가 메트릭 : 정확도
    • 예전에는 'accuracy'라고 단일 문자열만 넣는 것도 가능했는데, 이제 keras에서 리스트나 튜플 형태로 넣으라고 바뀜
  • 콜백 : ModelCheckpoint, EarlyStopping
# 컴파일 단계에서 옵티마이저, 손실함수, 평가 메트릭 설정
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# 콜백 설정 준비
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-cnn-model.h5') # 콜백: 체크포인트
early_stopping_cb = keras.callbacks.EarlyStopping(patience=2,        # 콜백 : 조기종료
                                                  restore_best_weights=True) # 최적 가중치 저장

 

모델 훈련 & 평가

  • 역시 `fit` 함수로 훈련해서 결과를 `history` 객체에 저장
  • 검증 데이터와 콜백 함수들도 함께 입력해줌!
history = model.fit(train_scaled, train_target, epochs=20, # 에포크는 20번
                    validation_data=(val_scaled, val_target), # 검증 데이터셋
                    callbacks=[checkpoint_cb, early_stopping_cb]) # 콜백 설정

  • 검증세트 Accuracy가 92%까지 올라감! (7-3장의 최종 모델은 88%였음)
  • Loss 그래프 그려보면, 설정한 대로 조기종료(EarlyStopping)가 잘 이루어졌음을 확인 가능!
    • 7번째 에포크(=epoch 6) 이후로 2번 동안 loss가 줄어들지 않아서 종료됨 (`patience=2`)
    • 모델 객체의 파라미터는 7번째 에포크 때의 최적값으로 복원되어 있음 (`restore_best_weights=True`) ⇒ 그래서 'best-cnn-model.h5'를 굳이 다시 불러오지 않아도 됨

 

새로운 데이터에 적용(예측)

  • 👨‍🏫편의상 검증세트의 첫 번째 샘플을 새로운 데이터라고 가정합시다
    • `imshow`로 출력해보니 '가방'으로 보이는 이미지가 나옴 (원래 (28,28,1)이므로 (28,28)로 바꿔야 출력 가능)

  • 우리가 만든 모델로 이 샘플을 `predict` 해보자
    • 출력 결과, 9번째 확률값만 매우 높음 = 가방으로 잘 예측했다!

`classes = ['티셔츠', '바지', '스웨터', '드레스', '코트', '샌달', '셔츠', '스니커즈', '가방', '앵클 부츠']`

 

  • 테스트 세트로 최종 일반화 성능까지 평가
    • 훈련/검증세트에 한 것처럼 전처리 후, `evaluate` 함수로 평가 수행!
    • 91% 정확도를 보임! (당연히 검증세트보다는 약간 낮음)

 


🤔 Hmmmm...

455p. 코드 [22]에서 첫 번째 샘플을 전달할 때 왜 `val_scaled[0]` 이 아니라 `val_scaled[0:1]` 를 사용하나요?

👨‍🏫Keras의 fit, predict, evaluate는 모두 배치(batch) 형태의 입력을 기대합니다. (여러 개의 샘플을 한 번에 처리하는 게 일반적이기 때문) 그래서 하나의 샘플을 전달하더라도 리스트를 하나 더 감싸서 (=배치 차원을 그대로 유지한 상태로) 전달해야 합니다.
🆗 [0]은 단순히 첫 번째 원소를 선택하는 것이므로 차원이 하나 줄어듦. 반면 [0:1]는 첫 번째 원소만 포함하는 '부분집합'을 만드는 거니까 원래의 차원(shape)이 유지되면서 첫 번째 차원의 크기만 1이 됨. 아래의 간단한 예시로 이해할 수 있음.

 

🤓 To wrap up...

 

 

 

 

 

'ML & DL > 머신러닝 기초' 카테고리의 다른 글

[혼자 공부하는 머신러닝+딥러닝] 8-3. 합성곱 신경망의 시각화  (2) 2025.03.12
[혼자 공부하는 머신러닝+딥러닝] 8-1. 합성곱 신경망의 구성요소  (1) 2025.03.10
[혼자 공부하는 머신러닝+딥러닝] 🎊혼공학습단 완주 회고록🎊  (0) 2025.03.07
[혼자 공부하는 머신러닝+딥러닝] 7-3. 신경망 모델 훈련  (0) 2025.03.07
[혼자 공부하는 머신러닝+딥러닝] 7-2. 심층 신경망  (1) 2025.02.28
'ML & DL/머신러닝 기초' 카테고리의 다른 글
  • [혼자 공부하는 머신러닝+딥러닝] 8-3. 합성곱 신경망의 시각화
  • [혼자 공부하는 머신러닝+딥러닝] 8-1. 합성곱 신경망의 구성요소
  • [혼자 공부하는 머신러닝+딥러닝] 🎊혼공학습단 완주 회고록🎊
  • [혼자 공부하는 머신러닝+딥러닝] 7-3. 신경망 모델 훈련
simon919
simon919
개인적으로 공부한 내용을 기록하고 나누는 블로그입니다. 데이터 분석, 인공지능에 관한 내용을 주로 다룹니다.
  • simon919
    문과생의 AI 생존기
    simon919
  • 전체
    오늘
    어제
    • 분류 전체보기 (84)
      • ML & DL (38)
        • 머신러닝 기초 (23)
        • 딥러닝 기초 (6)
        • 데이터마이닝 (9)
      • Data structure & Algorithm (1)
      • SQL (21)
        • BigQuery (13)
        • MySQL (8)
      • Statistics (4)
        • 교육 연구를 위한 통계 (4)
        • Linear Algebra (0)
      • Python (17)
        • Pandas (16)
        • Matplotlib (0)
        • Numpy (0)
        • Web Crawling (1)
      • Projects (0)
      • Etc. (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 글자가 깨지면 새로고침 해주세요 :)
  • 인기 글

  • 태그

    SQL
    교육통계
    Functional API
    mysql
    혼공학습단
    최우수혼공족
    통계학 기초
    google cloud
    Conv2d
    kmooc
    리트코드
    BigQuery
    Bayesian Optimization
    agglomerative
    SQL코딩테스트
    kmeans
    pytorch
    Xai
    MaxPooling2D
    silhouette index
    혼공머신
    티스토리 스킨
    블로그 스킨
    pandas
    SQL문제풀이
    해커랭크
    ml기초
    특성맵 시각화
    데이터마이닝
    HELLO 스킨
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
simon919
[혼자 공부하는 머신러닝+딥러닝] 8-2. 합성곱 신경망을 사용한 이미지 분류
상단으로

티스토리툴바