본문 바로가기

VISION

Implementing convolution, padding, pooling, stride

framework 없이 convolution 구현하기.

 

Padding
array = np.random.randn(3,3)
pad = 1		#(3,3) shape array에 padding을 1씩 줌
np.pad(array, (pad,pad), mode='constant', constant_values=(0,1))

# output
[[ 0.          0.          0.          0.          1.        ]
 [ 0.          0.16003707  0.87616892  0.31563495  1.        ]
 [ 0.         -2.02220122 -0.30620401  0.82797464  1.        ]
 [ 0.          0.23009474  0.76201118 -0.22232814  1.        ]
 [ 0.          1.          1.          1.          1.        ]]

 

* constant_values는 optional. 명시하지 않으면 zero-padding이며, 명시할 경우 원하는 값으로 padding을 줄 수 있다.

 

 

Convolution with stride
def convolution(array, W, b, stride):
    (m, height_prev, width_prev, channel_prev) = array.shape
    (f, f, channel_prev, channel) = W.shape
    
    height = (height_prev + pad*2 - f)//stride + 1
    width = (width_prev + pad*2 - f)//stride + 1
    
    output = np.zeros((m, height, width, channel))	#output을 형태에 맞게 초기화
    
    for i in range(m):
        for h in range(height_prev):	#row 범위 지정
            h_start = h*stride
            h_end = h*stride+f
            
            for w in range(width_prev):	#column 범위 지정
                w_start = w*stride
                w_end = w*stride+f
                
                for c in range(channel_prev):	#필터 개수(channel)만큼 반복
                    array_slice = array[h_start:h_end, w_start:w_end]	#array에서 바라볼 영역 선택
                    output[i, h, w, c] = conv_single_step(array_slice, W[:,:,:,c],b[:,:,:,c])
                    Z = np.sum(array_slice*W[:,:,:,c]) + float(b[:,:,:,c])
    
    assert(Z.shape == (m, n_H, n_W, n_C))
    cache = (A_prev, W, b, hparameters)	#backprop을 위해 필요한 정보(사용된 값들)를 캐시에 저장해놓음
    
    return Z, cache

 

 

Pooling
array_slice = array[h_start:h_end, w_start:w_end,channel]	#채널별로 적용해야하므로 채널 선택
                    
np.max(array_slice)	#max pooling인 경우
np.mean(array_slice)	#average pooling인 경우