3 분 소요

본 글은 [핸즈온 머신러닝 2판 (Hands-On Machine Learning with Scikit-Learn, keras & TensorFlow)] - (박해선 옮김) 책을 개인공부하기 위해 요약, 정리한 내용입니다.
전체 코드는 https://github.com/ingu627/handson-ml2에 기재했습니다.(원본 코드 fork)
뿐만 아니라 책에서 설명이 부족하거나 이해가 안 되는 것들은 외부 자료들을 토대로 메꿔 놓았습니다.
오타나 오류는 알려주시길 바라며, 도움이 되길 바랍니다.

more info

1. 이미지 자료 : formal.hknu.ac.kr
2. 딥러닝을 위한 콘볼루션 계산 가이드





합성곱 신경망을 사용한 컴퓨터 비전


14.1 시각 피질 구조

  • 원숭이들은 시각 피질 안의 많은 뉴런이 작은 국부 수용장(local receptive field)을 가진다.
    • 즉, 뉴런들이 시야의 일부 범위 안에 있는 시각 자극에만 반응한다는 뜻
    • 시각 피질의 국부 수용장은 수용장이라 불리는 시야의 작은 영역에 있는 특정 패턴에 반응한다.
    • 시각 신호가 연속적인 뇌 모듈을 통과하면서 뉴런이 더 큰 수용장에 있는 더 복잡한 패턴에 반응한다.



14.2 합성곱 층

  • 합성곱 층은 완전연결층(fully-connected layer)과 달리 데이터의 형상을 유지하며 다음 계층으로 전달할 수 있다. 1
    • 이미지를 완전연결층으로 학습하면 과적합(overfitting)이 일어난다.2
    • 합성곱 레이어는 이미지 픽셀 사이의 관계를 고려한다.
    • 형상에 대해 특징(feature)만 뽑아서 효율적으로 이미지 학습이 가능하다.
  • 첫 번째 합성곱 층의 뉴런은 입력 이미지의 모든 픽셀에 연결되는 것이 아니라 합성곱 층 뉴런의 수용장 안에 있는 픽셀에만 연결된다.
    • 작은 저수준 특성에 집중
  • 두 번째 합성곱 층에 있는 각 뉴런은 첫 번째 층의 작은 사각 영역 안에 위치한 뉴런에 연결된다.
    • 더 큰 고수준 특성으로 조합해나가도록 도와줌


합성곱 : 한 함수가 다른 함수 위를 이동하면서 원소별 곱셈의 적분을 계산하는 수학 연산이다.
이 연산은 푸리에 변환(Fourier transform) 및 라플라스 변환(Laplace transform)과 깊은 관계가 있으며 신호 처리 분야에서 많이 사용된다.


  • 제로 패딩(zero padding) : 높이와 너비를 이전 층과 같게 하기 위해 입력의 주위에 0을 추가
    • 위의 그림은 층과 제로 패딩 사이의 연결, code= padding=SAME


  • 스트라이드(stride) : 한 수용장과 다음 수용장 사이 간격
    • 기능 : 출력 데이터의 출력 조정



14.2.1 필터

  • 필터 (합성곱 커널) : 입력뉴런에 사용될 가중치 역할 수행
    • 필터의 모양과 크기가 국부수용장의 모양과 크기를 지정
    • 결국 딥러닝은 학습하면서 필터의 값을 찾는 것이다.
  • 특성맵(feature map) : 필터 각각을 사용하여 생성된 출력값(=결과값)
    • 각 특성지도의 픽셀이 하나의 뉴런에 해당
    • 필터에 포함된 모든 뉴런은 동일한 가중치와 편향 사용
    • 이 맵은 필터를 가장 크게 활성화시키는 이미지의 영역을 강조한다.
  • 훈련하는 동안 합성곱 층이 자동으로 해당 문제에 가장 유용한 필터를 찾고 상위층은 이들을 연결하여 더 복잡한 패턴을 학습



14.2.2 여러 가지 특성 맵 쌓기

  • 각 특성 맵의 픽셀은 하나의 뉴런에 해당하고 하나의 특성 맵 안에서는 모든 뉴런이 같은 파라미터를 공유
    • 다른 특성 맵에 있는 뉴런은 다른 파라미터를 사용
    • 한 뉴런의 수용장은 이전 층에 있는 모든 특성 맵에 걸쳐 확장된다.
  • 하나의 합성곱 층이 입력에 따라 필터를 동시에 적용하여 입력에 있는 여러 특성을 감지


  • 합성곱 층에 있는 뉴런의 출력 계산
  • $z_{i,j,k}$
  • = $b_k+\sum_{u=0}^{f_h-1}\sum_{v=0}^{f_w-1}\sum_{k’=0}^{f_{n’}-1}x_{i’,j’,k’}\times w_{u,v,k’,k}$
    • 여기서 $i’=i\times s_h + u$, $\ j’=j\times s_w+v$
    • 컬러 채널 : 빨강, 초록, 파랑(RGB)으로 3개 | 흑백 채널 : 1개
    • $z_{i,j,k}$는 합성곱 층($l$층)의 $k$특성 맵에서 $i$행, $j$열에 위치한 뉴런의 출력
    • $s_h$, $s_w$ : 수직과 수평 스트라이드
    • $f_h$, $f_w$ : 수용장의 높이와 너비
    • $f_{n’}$ : 이전 층($l -1$층)에 있는 특성 맵의 수
    • $x_{i’,j’,k’}$ : $l-1$층의 $i’$행, $j’$열, $k’$특성 맵에 있는 뉴런의 출력
    • $b_k$ : ($l$레이어에 있는) $k$특성 맵의 편향
    • $w_{u,v,k’,k}$ : $l$층의 $k$ 특성 맵에 있는 모든 뉴런과 (뉴런의 수용장에 연관된) $u$행, $v$열, 그리고 $k’$ 특성 맵에 위치한 입력 사이의 연결 가중치



이미지출처3

  • 필터의 각 커널은 각각의 입력 채널을 합성곱 연산을 통해 처리한다.



이미지출처3

  • 채널별로 연산된 특성맵은 하나로 합쳐져서 하나의 채널을 형성한다.



이미지출처3

  • 여기에 편향(bias)를 추가하여 최종 출력 채널을 생성한다.



14.2.3 텐서플로 구현

  • 각 입력 이미지 : [높이, 너비, 채널]형태의 3D 텐서
  • 하나의 미니배치 : [미니배치 크기, 높이, 너비, 채널] 형태의 4D 텐서
  • 합성곱 층의 가중치 : [$f_h, f_w, f_{n’}, f_n$] 형태의 4D 텐서
  • 합성곱 층의 편향 : [$f_n$]형태의 1D 텐서
from sklearn.datasets import load_sample_image
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

# 샘플 이미지 로드
china = load_sample_image('china.jpg') / 255
flower = load_sample_image("flower.jpg") / 255
images = np.array([china, flower])
batch_size, height, width, channels = images.shape

filters = np.zeros(shape=(7, 7, channels, 2), dtype=np.float32)
filters[:, 3, :, 0] = 1 # 수직선
filters[3, :, :, 1] = 1 # 수평선

outputs = tf.nn.conv2d(images, filters, strides=1, padding='SAME') # 저수준 API에서 padding의 매개변수를 항상 대문자로!

plt.imshow(outputs[0, :, :, 1], cmap='gray') # 첫번째 이미지의 두 번째 특성 맵 선택
plt.show()


  • keras.layers.Conv2D 사용
# 3x3개의 필터 32개, padding='same'은 제로 패딩 사용
conv = keras.layers.Conv2D(filters=32, kernel_size=3, strides=1,
                           padding='same', activation='relu')



14.3 풀링 층

  • 풀링 층(pooling layer)의 목적 : 계산량과 메모리 사용량, 파라미터 수를 줄이기 위해 입력 이미지의 부표본(subsample)을 만들기 위해
    • 풀링 층의 각 뉴런은 이전 층의 작은 사각 영역의 수용장 안에 있는 뉴런의 출력과 연결되어 있다.
  • 최대 풀링 층(max pooling layer)을 통해 각 수용장에서 가장 큰 입력값이 다음 층으로 전달되고 다른 값은 버려진다.
    • 특징맵(feature map)의 크기를 절반으로 줄여준다.
    • 큰 특징들만 추출. 즉, 점점 샘플링해서 줄여주는 역할
    • 계산량, 메모리 사용량을 줄어준다.
    • 많은 정보를 잃게 되지만 그대로 잘 작동된다.


# 최대 풀링 층(2x2 풀링 커널, 스트라이드 2, 패딩 X)
tf.keras.layers.MaxPool2D(
    pool_size=(2, 2), strides=None, padding='valid', data_format=None
)


  • 최대 풀링은 작은 변화에도 일정 수준의 불변성(invariance)을 만들어준다.


  • 평균 풀링 층(average pooling layer) : AvgPool2D 사용
    • 하지만 최대 풀링층에 비해 성능이 떨어짐
  • 전역 평균 풀링 층(global average pooling layer) : 각 특성 맵의 평균을 계산

      global_avg_pool = keras.layers.GlobalAvgPool2D()
    



CNN Architecture

image
이미지출처4


image
이미지출처5

  • 출력 크기 계산 : (N-F+2P)/S + 1
    • N : input size
    • F : filter
    • P : padding
    • S : stride





References

댓글남기기