안녕하세요 오랜만이에요~
오늘은 딥러닝의 꽃! CNN에 대해 알아보겠습니다!
CNN이란 Convolution Neural network로 합성곱 신경망이라고 부릅니다.
CNN은 이미지, 동영상 등을 분석하는데 사용됩니다.
(음성 인식, 자연어 처리와 같은 다른 작업에도 많이 사용하지만 여기서는 시각적인 부분에 초점을 맞췄습니다.)
[기존계층과 합성곱 계층 비교]
먼저, 기존 신경망과 다른 점에 대해 알아보겠습니다.
기존에 구현했던 완전 연결 계층, 즉 기존 신경망은 데이터의 형상이 무시됩니다.
따라서 글자의 크기가 달라지거나 글자가 회전되거나,
글자에 변형이 조금만 생기더라도
다른 글자로 인식하기 때문에
새로운 학습 데이터를 넣어주지 않으면
좋은 결과를 기대하기 어렵습니다.
즉, 본질적인 패턴을 읽지 못하기 때문에
인식을 위해
다양한 데이터가 많이 필요합니다.
하지만, 합성곱 계층은
원본 이미지를 가지고 여러개의 feature map (특징맵)을 만들어 분류하는
완전 연결 계층으로,
이미지의 특징을 추출하기때문에 이미지가 변형이되더라도
잘 인식할 수 있습니다.
<기존 계층>
<합성곱 계층>
합성곱 연산이란?
이미지 3차원(세로, 가로, 색상) data의 형상을 유지하면서 연산하는 작업
입력 데이터에 필터를 적용한 것을 합성곱 연산이라고 합니다.
[합성곱 연산]
<구현 예시>
# 위의 그림을 파이썬으로 출력하시오
import numpy as np
input_ = np.array([[1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1]]) filter_ = np.array([[2,0,1],[0,1,2],[1,0,2]]) bias=3 a = input_.shape[0]-filter_.shape[0] + 1 b = input_.shape[1]-filter_.shape[1] + 1 result2 = []
for rn in range(a): for cn in range(b): result1 = input_[rn:rn+filter_.shape[0],cn:cn+filter_.shape[1]] * filter_ result2.append(np.sum(result1)+bias) result = np.array(result2).reshape(a,b)
패딩이란?
합성곱 연산을 수행하기 전에 데이터 주변을 특정값으로 채워 늘리는 것을 말합니다.
※ 패딩이 필요한 이유는 무엇일까요?
패딩을 하지 않을경우 data의 크기는 합성곱 계층을 지날 때마다 작아지게 되므로
가장자리 정보들이 사라지는 문제가 발생하기 때문에 패딩을 사용합니다.
<구현 예시>
# 위의 그림을 파이썬으로 출력하시오 import numpy as np input_ = np.array([[1,2,3,0],[0,1,2,3],[3,0,1,2],[2,3,0,1]]) input_pad = np.pad(input_, pad_width=1, mode='constant', constant_values=0) # padding method filter_ = np.array([[2,0,1],[0,1,2],[1,0,2]]) a = input_pad.shape[0]-filter_.shape[0] + 1 b = input_pad.shape[1]-filter_.shape[1] + 1 result2 = [] for rn in range(a): for cn in range(b): result1 = input_pad[rn:rn+filter_.shape[0],cn:cn+filter_.shape[1]] * filter_ result2.append(np.sum(result1)) result = np.array(result2).reshape(a,b)
스트라이드란?
input데이터에 filter를 적용하는 위치의 간격을 스트라이드라고 합니다.
[출력크기 공식]
(입력크기를 H(Height),W(Width), 필터크기를 FH, FW, 출력크기를 OH, OW, 패딩을 P, 스트라이드를 S라고 한다.)
3차원 합성곱 연산
이미지의 색은 보통 흑백이 아니라 RGB(Red, Green, Blue)컬러 이므로
RGB컬러에 대해서 합성곱을 해야합니다.
3차원 합성곱 구현 이론
[사진 한장을 RGB 필터로 합성곱하여 2차원 출력행렬(Feature map) 1을 출력한 그림]
위의 그림은 Feature map이 한 개가 나오는데
실제로는 사진 한 장에 대해서 여러개의 Feature map이 필요합니다.
Filter의 갯수를 늘리면 여러개의 Feature map을 출력할 수 있습니다.
하나의 Filter에 하나의 Feature map을 출력할 수 있습니다.
이미지를 한 장씩 학습시키는 것은 학습속도가 느립니다.
따라서 100장의 이미지를 묶음으로 나눠서 한번에 학습시킵니다.
이를 mini batch라고 합니다.
+ 합성곱 연산에 편향(bias)을 더해줍니다.
하지만 합성곱 계층을 미니 배치로 구현할 때 4차원 행렬의 연산이 됩니다.
따라서 연산의 속도가 느려지므로
행렬 연산을 빠르게 하기 위해 4차원이 아닌 2차원으로 차원을 축소해야할 필요가 있습니다.
※ 이때 im2col함수를 이용합니다.
원리: 각 4차원 블럭을 R,G,B로 각각 나누어 2차원으로 변환 후 합쳐줍니다.
※ 배치를 사용할 때 위의 방법을 여러번 하여 나온 결과인 2차원 행렬을 합쳐줍니다.
[im2col 함수]
def im2col(input_data, filter_h, filter_w, stride=1, pad=0): """다수의 이미지를 입력받아 2차원 배열로 변환한다(평탄화). Parameters ---------- input_data : 4차원 배열 형태의 입력 데이터(이미지 수, 채널 수, 높이, 너비) filter_h : 필터의 높이 filter_w : 필터의 너비 stride : 스트라이드 pad : 패딩 Returns ------- col : 2차원 배열 """
N, C, H, W = input_data.shape out_h = (H + 2 * pad - filter_h) // stride + 1 # 위의 출력크기 공식을 이용하여 구현 out_w = (W + 2 * pad - filter_w) // stride + 1 img = np.pad(input_data, [(0, 0), (0, 0), (pad, pad), (pad, pad)], 'constant') col = np.zeros((N, C, filter_h, filter_w, out_h, out_w)) for y in range(filter_h): y_max = y + stride * out_h for x in range(filter_w): x_max = x + stride * out_w col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N * out_h * out_w, -1)
return col
※ 2차원으로 변경해야할 행렬 2가지
1. 원본이미지를 필터 사이즈에 맞게 2차원으로 변경한 행렬
-> im2col 함수 이용
2. 4차원 필터 행렬을 2차원으로 변경
-> reshape 함수를 이용 (FN, -1)
[CNN 구현하기]
"Convolution 계층에서 일어나는 일"
1. 원본이미지를 im2col을 사용하여 2차원 행렬로 변경한다.
2. filter를 reshape을 사용하여 2차원 행렬으로 변경한다.
3. 2차원 행렬로 변환한 두 행렬을 내적한다.
4. 내적한 결과인 2차원 행렬을 다시 4차원으로 변환한다.
CNN층 구조
" conv -> pooling -> fully connected "
- conv: 이미지 특징(feature map)을 추출하는 층
- pooling: 추출한 feature map을 선명하게 하는 층
pooling 계층의 역활
출력 값에서 일부만 취하여 사이즈가 작은 이미지를 만든다.
마치 사진을 축소하면 해상도가 좋아지는 듯한 효과와 비슷하다.
※ 풀링 종류 3가지
1. 최대 풀링
: 컨볼루션 데이터에서 가장 큰 값을 대표값으로 선정
2. 평균 풀링
: 컨볼루션 데이터에서 평균값을 대표값으로 선정
3. 확률적 풀링
: 컨볼루션 데이터에서 임의 확률로 한 개를 선정
※ 그림출처: '밑바닥부터 시작하는 딥러닝'
생각보다 내용이 길어져서
파이썬으로 Convolution 계층 구현하는 것은
다음 포스팅에서 하겠습니다!
궁금하신 부분은 댓글 남겨주세요!!
'PYTHON으로 딥러닝하기' 카테고리의 다른 글
현업에서 많이 사용하는 Python 모듈 | Pandas (Series, DataFrame) (0) | 2019.02.27 |
---|---|
파이썬으로 딥러닝하기| CNN(Convolution Neural Network) Part2. 구현하기(FULL CODE) (4) | 2018.09.27 |
파이썬으로 딥러닝하기 | 신경망 학습의 효율과 정확도 올리기! (1) | 2018.09.04 |
파이썬으로 딥러닝하기 | 오차역전파란? & MNIST 신경망 구현하기 (0) | 2018.08.31 |
파이썬으로 딥러닝하기 | 손실함수 평균제곱오차(MSE) & 교차 엔트로피 오차(CEE) (1) | 2018.08.29 |