cnn층의 가중치는 필터인데 이 필터가 학습이 되면서 점점 원본 이미지를 잘 설명하는 형태로 변경되어감.
그동안 신경망 학습할 때 입력값과 가중치와의 "내적"을 했었는데 이 내적은 무슨 역할인가?
입력 신호와 가중치가 얼마나 유사한지를 나타내는 수치를 출력함
ㅇconvolution계층에서 일어나는 일 4가지
이미지의 특징을 추출하기 위해서 코드로 어떻게 구현했는가?
1. 원본 이미지를 im2col 함수로 2차원 행렬로 변경
2. filter를 넘파이의 reshape의 -1옵션을 이용해서 2차원 행렬로 변경
3. 2개의 2차원 행렬 내적
4. 내적한 결과 2차원 행렬을 다시 4차원으로 변경
class Convolution:
def __init__(self, W, b, stride=1, pad=0):
self.W = W #필터행렬, 학습되면서 이 필터행렬이 원본이미지의 특징을 잘 살릴 수 있도록 변경됨
self.b = b #신경망에 흘러가는 값들을 잘 활성화 시키게끔 도와주는 행렬인 바이어스를 셋팅
self.stride = stride #원본 이미지를 몇 칸 간격으로 필터가 스캔할 지를 지정
self.pad = pad #이미지의 가장자리 정보가 없어지지 않도록 채우는 것
def forward(self, x): #이미지를 흘려보내서 피처맵을 생성하는 함수(순전파)
FN, C, FH, FW = self.W.shape #4차원배열(필터 갯수, 색조, 높이, 가로)
N, C, H, W = x.shape #입력 이미지 4차원 배열(입력이미지의 갯수, 색조, 높이, 가로)
out_h = int(1 + (H + 2*self.pad - FH) / self.stride) #피처맵의 높이 사이즈 계산
out_w = int(1 + (W + 2*self.pad - FW) / self.stride) #피처맵의 가로 사이즈 계산
col = im2col(x, FH, FW, self.stride, self.pad) #입력이미지를 필터사이즈에 맞춰서 2차원 행렬로 변환
col_w = self.W.reshape(FN, -1).T #4차원 가중피(필터)행렬을 2차원으로 변경하고 전치
out = np.dot(col, col_w) + self.b #2차원 행렬 2개를 내적하고 바이어스를 더함
#내적계산의 결과값은 입력이미지와 필터의 유사성
out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) #2차원을 4차원으로 변경
#동시에 transpose함
return out
transpose(0, 3, 1, 2)는 (갯수, 높이, 넓이, 색조) ---> (갯수, 색조, 높이, 넓이)로 변경
문제177. 28x28의 사진 1개를 생성합니다.
import numpy as np
x1 = np.random.randn(1,3,28,28) #사진 1장 생성
x1
문제178. 5x5의 RGB필터 10개와 바이어스를 생성하시오.
ft = np.random.randn(10,3,5,5)
b1 = 1
문제179. 위에서 만든 설계도 Convolution을 가지고 conv1이라는 객체를 생성하고 입력값 x1을 넣어 피처맵 10개를 생성하시오.(피처맵은 필터 사이즈만큼 생성됨)
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
class Convolution:
def __init__(self, W, b, stride=1, pad=0):
self.W = W #필터행렬, 학습되면서 이 필터행렬이 원본이미지의 특징을 잘 살릴 수 있도록 변경됨
self.b = b #신경망에 흘러가는 값들을 잘 활성화 시키게끔 도와주는 행렬인 바이어스를 셋팅
self.stride = stride #원본 이미지를 몇 칸 간격으로 필터가 스캔할 지를 지정
self.pad = pad #이미지의 가장자리 정보가 없어지지 않도록 채우는 것
def forward(self, x): #이미지를 흘려보내서 피처맵을 생성하는 함수(순전파)
FN, C, FH, FW = self.W.shape #4차원배열(필터 갯수, 색조, 높이, 가로)
N, C, H, W = x.shape #입력 이미지 4차원 배열(입력이미지의 갯수, 색조, 높이, 가로)
out_h = int(1 + (H + 2*self.pad - FH) / self.stride) #피처맵의 높이 사이즈 계산
out_w = int(1 + (W + 2*self.pad - FW) / self.stride) #피처맵의 가로 사이즈 계산
col = im2col(x, FH, FW, self.stride, self.pad) #입력이미지를 필터사이즈에 맞춰서 2차원 행렬로 변환
col_w = self.W.reshape(FN, -1).T #4차원 가중피(필터)행렬을 2차원으로 변경하고 전치
out = np.dot(col, col_w) + self.b #2차원 행렬 2개를 내적하고 바이어스를 더함
#내적계산의 결과값은 입력이미지와 필터의 유사성
out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) #2차원을 4차원으로 변경
#동시에 transpose함
return out
conv1 = Convolution(ft, b1)
feature_map = conv1.forward(x1)
feature_map.shape #(1, 10, 24, 24)
원본이미지 (1,3,28,28) ---> 피처맵 10장(1,10,24,24)
문제180. 이번에는 다른 필터를 생성하는데 필터의 갯수를 100개로 해서 생성하고, 필터사이즈는 5x5로 하세요.
ft2 = np.random.randn(100,3,5,5)
conv2 = Convolution(ft2, b1)
feature_map2 = conv2.forward(x1)
feature_map2.shape #(1, 100, 24, 24)
반응형
'Study > class note' 카테고리의 다른 글
딥러닝 / CNN구현 (0) | 2022.04.18 |
---|---|
딥러닝 / 풀링계층 구현하기 (0) | 2022.04.18 |
딥러닝 / 3차원 데이터의 합성곱 연산 (0) | 2022.04.15 |
딥러닝 / 합성곱 신경망(Convolution Neural Network) (0) | 2022.04.14 |
딥러닝 / 오버피팅 방지(드롭아웃, L2규제) (0) | 2022.04.14 |