머신러닝/CustomFramework

Convolution 2D Layer

hwijin97 2022. 3. 26. 20:17

Foward

$x$ : $ ( N,  XH, XW, XC ) $

$w$ : $ ( KH, KW, XC, YC ) $

$ y $ : $ (  N, YH, YW, YC ) $

$ b $ : $ (1, 1, 1, YC ) $

 

$x$ : 입력 이미지 데이터

$y$ : 출력 이미지 데이터

$w$ : 가중치 행렬

$b$ : 편향 벡터

$N$ : 데이터 개수 (batch size)

$XH$ , $XW$ , $XC$ : 입력 이미지 높이, 너비, 채널 사이즈

$YH$ , $YW$ , $YC$ : 출력 이미지 높이, 너비, 채널 사이즈

$KH$, $KW$ : 커널 높이, 너비 사이즈

 

$SH$ , $SW$ : 높이, 너비  Stride 사이즈

$PH$ , $PW$ : 높이, 너비 Padding 사이즈

 

$$ \\ YH = \frac{XH - KH + 2PH}{SH} + 1 
\\ YW = \frac{XW - KW + 2PW}{SW} + 1 $$

 

 

$x'$ : padding 을 적용한 입력 이미지 데이터 - $ ( N, XH + 2PH, XW + 2PW, XC ) $

 

$ XH + 2PH = SH(YH - 1) + KH \\ XW + 2PW = SW(YW - 1) + KW $

 

 

$$ y_{h_y, w_y, c_y} = \sum_{h_k=1}^{KH}\sum_{w_k=1}^{KW}\sum_{c_x=1}^{XC} 
w_{h_k, w_k, c_x, c_y} x'_{(s_h(h_y-1)+h_k), (s_w(w_y-1) + w_k), c_x} $$

 


수식으로 이렇게 전개되지만, 실제 구현에서는 성능상의 문제가 존재한다.

반복문을 통해 forward 를 진행하면, x 위치를 y, k 좌표로 치환한다고 해도,

$N$, $YC$ , $KH$ , $KW$, $XC$ 를 순환해야되서 5중 반복문을 수행하게 된다.

따라서 이 방식을 피하기 위해, 두 행렬의 곱 형식으로 변환해서 구현한다. 이 방법이 반복문 보다 훨씬 빠르다.

 

결국 $y'$ = $x'$$w'$+$b'$ 형태로 나타내고, $y'$ 을 $y$ 로 reshape 하는 과정으로 forward 한다.

여기서 $x'$ 는 ( $N$ x $YH$ x $YW$ , $XC$ x $KH$ x $KW$ ) 차원, $w'$ 는 ( $XC$ x $KH$ x $KW$ , $YC$ ) 차원, $b'$ 는 ( $1$ x $1$ x $1$ , $YC$ ) 차원, $y'$ 는 ( $N$ x $YH$ x $YW$ , $YC$ ) 차원으로 구성된다.

$y'$ 을 $y$ = ( $N$ , $YH$, $YW$, $YC$ ) 의 형태로 reshape 하게 되면 행렬곱 방식의 forward output 이 만들어진다.

 

 


예시 ) x : 5x5x3, w : 3x3x3x5, y : 2x2x5 일 때 ( bias, batch 는 무시, stride 는 2 )

 

$x'$ 

$x_c$,$k_h$, $k_w$
$y_h$ , $y_w$ \
1,1,1 1,1,2 1,1,3 1,2,1 $x_c$, $k_h$, $k_w$ 3,2,3 3,3,1 3,3,2 3,3,3
1,1 $x_{1,1,1}$ $x_{1,2,1}$ $x_{1,3,1}$ $x_{2,1,1}$ $x_{s_h(y_h-1) + k_h, s_w(y_w-1) + k_w, x_c}$ $x_{2,3,3}$ $x_{3,1,3}$ $x_{3,2,3}$ $x_{3,3,3}$
1,2 $x_{1,3,1}$ $x_{1,4,1}$ $x_{1,5,1}$ $x_{2,3,1}$ $x_{2,5,3}$ $x_{3,3,3}$ $x_{3,4,3}$ $x_{3,5,3}$
2,1 $x_{3,1,1}$ $x_{3,2,1}$ $x_{3,3,1}$ $x_{4,1,1}$ $x_{4,3,3}$ $x_{5,1,3}$ $x_{5,2,3}$ $x_{5,3,3}$
2,2 $x_{3,3,1}$ $x_{3,4,1}$ $x_{3,5,1}$ $x_{4,3,1}$ $x_{4,5,3}$ $x_{5,3,3}$ $x_{5,4,3}$ $x_{5,5,3}$

 

$w'$

$y_c$
$x_c$,$k_h$, $k_w$ \
1 2 3 4 5
1,1,1 $w_{1,1,1,1}$ $w_{1,1,1,2}$ $w_{1,1,1,3}$ $w_{1,1,1,4}$ $w_{1,1,1,5}$
1,1,2 $w_{1,2,1,1}$ $w_{1,2,1,2}$ $w_{1,2,1,3}$ $w_{1,2,1,4}$ $w_{1,2,1,5}$
1,1,3 $w_{1,3,1,1}$ $w_{1,3,1,2}$ $w_{1,3,1,3}$ $w_{1,3,1,4}$ $w_{1,3,1,5}$
1,2,1 $w_{2,1,1,1}$ $w_{2,1,1,2}$ $w_{2,1,1,3}$ $w_{2,1,1,4}$ $w_{2,1,1,5}$
... $w_{k_h,k_w,x_c,y_c}$
3,2,3 $w_{2,3,3,1}$ $w_{2,3,3,2}$ $w_{2,3,3,3}$ $w_{2,3,3,4}$ $w_{2,3,3,5}$
3,3,1 $w_{3,1,3,1}$ $w_{3,1,3,2}$ $w_{3,1,3,3}$ $w_{3,1,3,4}$ $w_{3,1,3,5}$
3,3,2 $w_{3,2,3,1}$ $w_{3,2,3,2}$ $w_{3,2,3,3}$ $w_{3,2,3,4}$ $w_{3,2,3,5}$
3,3,3 $w_{3,3,3,1}$ $w_{3,3,3,2}$ $w_{3,3,3,3}$ $w_{3,3,3,4}$ $w_{3,3,3,5}$

 

$y'$

$y_c$
$y_h$, $y_w$ \
1 2 3 4 5
1,1 $y_{1,1,1}$ $y_{1,1,2}$ $y_{1,1,3}$ $y_{1,1,4}$ $y_{1,1,5}$
1,2 $y_{1,2,1}$ $y_{1,2,2}$ $y_{1,2,3}$ $y_{1,2,4}$ $y_{1,2,5}$
2,1 $y_{2,1,1}$ $y_{2,1,2}$ $y_{2,1,3}$ $y_{2,1,4}$ $y_{2,1,5}$
2,2 $y_{2,2,1}$ $y_{2,2,2}$ $y_{2,2,3}$ $y_{2,2,4}$ $y_{2,2,5}$

 

이 y' 을 y 으로 변형한다. 

 


코드 구현

 

입력 $x$ 를 통해 $x'$ 을 만드는 함수, y_shape 이 있는 이유는, $YH$ $YW$ 를 알기 위해서.

def img2col(x, y_shape, kernel_size, stride, padding_size):
    # x : N, XH, XW, XC
    # y : N, YH, YW, YC

    KH, KW = kernel_size
    SH, SW = stride
    PH, PW = padding_size

    N, XH, XW, XC = x.shape
    N, YH, YW, YC = y_shape
    
    # N, XH + 2PH, XW + 2PW, XC
    padded_x = np.pad(x, [(0, 0), (PH, PH), (PW, PW), (0, 0)], 'constant')

    # N, KH, KW, YH, YW, XC
    col = np.zeros((N, KH, KW, YH, YW, XC))

    for h in range(KH):
        h_max = h + SH * YH
        for w in range(KW):
            w_max = w + SW * YW
            col[:, h, w, :, :, :] = padded_x[:, h:h_max:SH, w:w_max:SW, :]
    
    # Transpose : N , YH , YW , XC , KH, KW
    # Reshape : N x YH x YW , XC x KH x KW
    col = col.transpose((0,3,4,5,1,2)).reshape(N*YH*YW, -1)
    return col

 

 

주의해야할 점은, 행렬이 1 부터가 아니라, 0 부터 시작하기 때문에 조금 다른점이 존재한다.

 

 

def forward(self, inputs):
        if inputs.dtype != self.dtype:
            warnings.warn("입력과 커널의 데이터 타입이 일치하지 않습니다. input dtype : {}, kernel dtype : {}".format(inputs.dtype, self.weight.dtype))
            inputs = inputs.astype(self.dtype)

        
        x = inputs

        # ( N x YH x YW , XC x KH x KW )
        flat_x = conv_utils.img2col(x, self.output_shape, self.kernel_size, self.strides, self.padding_size)
        

        # weight : KH x KW x XC x YC
        #Transpose : XC x KH x KW x YC
        #Reshape : ( XC x KH x KW , YC )
        flat_w = self.weight.transpose((2,0,1,3)).reshape(-1, self.filters)
        
        flat_b = self.bias.reshape(1, -1)
        # Dot : ( N x YH x YW , YC ) + ( 1 x 1 x 1, YC)
        flat_y = np.dot(flat_x, flat_w)
        if self.use_bias:
            flat_y += flat_b
            
        # Reshape : N x YH x YW x YC
        y = flat_y.reshape(*self.output_shape)
        
        if self.training:
            self.flat_x = conv_utils.average_flat_x(flat_x, y.shape)
            self.flat_w = flat_w
        return y

 

 

 

여기서 flat_x, flat_w 를 저장하는 이유는 backprop 시에 이용되기 때문이다. 

average_flat_x 는 upstream gradient $ \frac{\partial L}{\partial y} $ 가 batch 차원이 없는 행렬이라 $x$ 을 batch 차원기준 평균한것인데, 아직 정확한 방법인지는 분명하지 않다. 사실 구현하기 나름인데, 맨꼭대기 $ \frac{\partial L}{\partial y} $ 의 차원부터 batch를 유지한다고하면 그대로 사용하면 되긴하지만, 훈련시에 layer 가 깊어질수록 + batch size 가 커질수록 메모리에 대한 압박이 심해질 것같은 예상으로 이렇게 구현하게 되었다.

그런데 당연하게도 2차원 행렬로 변환하는 과정에서 데이터의 중복이 생기는데 ( stride 가 kernel size 보다 작다면 ), 아직 어쩔수 없는 부분이라고 생각하고 있다.

 


Backprop

$ \frac{\partial L}{\partial y} $ : ( $YH$ , $YW$ , $YC$ )

 

Weight

 

$$ \begin{matrix}
y_{h_y, w_y, c_y} = \sum_{h_k=1}^{KH}\sum_{w_k=1}^{KW}\sum_{c_x=1}^{XC} x_{s_h(h_y-1)+h_k, s_w(w_y-1)+w_k,c_x} w_{h_k, w_k, c_x, c_y} \\ \\
\frac{\partial y_{h_y, w_y, c_y}}{\partial w_{h_k, w_k, c_x, c_y}} = x_{s_h(h_y-1)+h_k, s_w(w_y-1)+w_k,c_x}
\end{matrix} $$

이때 $y$ 의 $c_y$ 와 $w$ 의 $c_y$ 가 동일하지 않은 경우는 모두 0 이된다. ( forward 참고, 고려안해도됨. )

 


 

$$ \frac{\partial y_{h_y, w_y, c_y}}{\partial w} = \frac{\partial y_{h_y, w_y, c_y}}{\partial w_{,,,c_y}} = \begin{bmatrix}
\frac{\partial y_{h_y, w_y, c_y}}{\partial w_{1,1,c_x,c_y}} & ... & \frac{\partial y_{h_y, w_y, c_y}}{\partial w_{1,KW,c_x,c_y}} \\
... & \frac{\partial y_{h_y, w_y, c_y}}{\partial w_{h_k,w_k,c_x,c_y}} & ... \\
\frac{\partial y_{h_y, w_y, c_y}}{\partial w_{KH,1,c_x,c_y}} & ... & \frac{\partial y_{h_y, w_y, c_y}}{\partial w_{KH,KW,c_x,c_y}} \\
\end{bmatrix}, (c_x = \text{1 to XC}) \\ = \begin{bmatrix}
x_{s_h(h_y-1)+1, s_w(w_y-1)+1, c_x} & ... & x_{s_h(h_y-1)+1, s_w(w_y-1)+KW, c_x} \\
... & x_{s_h(h_y-1)+h_k, s_w(w_y-1)+w_k, c_x} & ... \\
x_{s_h(h_y-1)+KH, s_w(w_y-1)+1, c_x} & ... & x_{s_h(h_y-1)+KH, s_w(w_y-1)+KW, c_x} \\
\end{bmatrix}, (c_x = \text{1 to XC}) $$

 

여기서 식을 자세히 들여다보면 위 $ \frac{\partial y_{h_y, w_y, c_y}}{\partial w} $ 은 $y_{h_y, w_y, c_y}$ 를 구하기 위해 $w$ 가 곱했던 $x$ 들을 의미한다. 그리고 $c_y$ 변수에 영향을 받지 않기때문에, $w$ 의 $c_y$ 차원에 대해서는 모두 동일한 값을 가지고, $ \frac{\partial L}{\partial y_{h_y, w_y, c_y}} $ 에 영향을 받는다.

 

이 $ \frac{\partial y_{h_y, w_y, c_y}}{\partial w}$ 를 1 차원으로 늘리게 되면, 위의 $x'$ 의 row 가 되고, $c_y$ 에 상관 없이 동일한 값을 가지기 때문에, $h_y$ , $w_y$ 에 관해서만 전부  펼치면 $x'$ 와 동일한 행렬이 만들어지고 이를 이용할 수 있다.

$x'$ 의 row 들은 $ \frac{\partial y_{h_y,w_y,c_y}}{\partial w_{,,,c_y}} $ 인데, col 들은 $ \frac{\partial y_{,,c_y}}{\partial w_{h_k,w_k,c_x,c_y}} $ 으로 볼 수 있다. 그래서 위에서 구했던 $x'^T$ 와 $ \frac{\partial L}{\partial y} $ 를 dot product 하면 우리가 원하는 $ \frac{\partial L}{\partial w} $ 을 구할 수 있다.


변수들의 연관관계를 이해하기 쉽게 위와 동일한 예시를 들어보자.

 

예시 ) x : 5x5x3, w : 3x3x3x5, y : 2x2x5 일 때 ( bias, batch 는 무시, stride 는 2 )

 

$ \frac{\partial L}{\partial y} $ : ($YH$, $YW$, $YC$ ) = ( 2, 2, 5 ) -> ( 2x2 , 5 )

$c_y$
$h_y$, $w_y$ \\
1 2 3 4 5
1,1 $\frac{\partial L}{\partial y_{1,1,1}}$ $\frac{\partial L}{\partial y_{1,1,2}}$ $\frac{\partial L}{\partial y_{1,1,3}}$ $\frac{\partial L}{\partial y_{1,1,4}}$ $\frac{\partial L}{\partial y_{1,1,5}}$
1,2 $\frac{\partial L}{\partial y_{1,2,1}}$ $\frac{\partial L}{\partial y_{1,2,2}}$ $\frac{\partial L}{\partial y_{1,2,3}}$ $\frac{\partial L}{\partial y_{1,2,4}}$ $\frac{\partial L}{\partial y_{1,2,5}}$
2,1 $\frac{\partial L}{\partial y_{2,1,1}}$ $\frac{\partial L}{\partial y_{2,1,2}}$ $\frac{\partial L}{\partial y_{2,1,3}}$ $\frac{\partial L}{\partial y_{2,1,4}}$ $\frac{\partial L}{\partial y_{2,1,5}}$
2,2 $\frac{\partial L}{\partial y_{2,2,1}}$ $\frac{\partial L}{\partial y_{2,2,2}}$ $\frac{\partial L}{\partial y_{2,2,3}}$ $\frac{\partial L}{\partial y_{2,2,4}}$ $\frac{\partial L}{\partial y_{2,2,5}}$

 

$ \frac{\partial y}{\partial w} $ : ( $YH$, $YW$, $XC$, $KH$, $KH$ ) = ( 2, 2, 3, 3, 3 ) -> ( 2x2, 3x3x3 )

$c_x$, $h_k$, $w_k$
$h_y$,$w_y$ \\
1,1,1 1,1,2 1,1,3 1,2,1 ... 3,2,3 3,3,1 3,3,2 3,3,3
1,1 $\frac{\partial y_{1,1,-}}{\partial w_{1,1,1,-}}$ $\frac{\partial y_{1,1,-}}{\partial w_{1,2,1,-}}$ $\frac{\partial y_{1,1,-}}{\partial w_{1,3,1,-}}$ $\frac{\partial y_{1,1,-}}{\partial w_{2,1,1,-}}$ $x_{s_h(h_y-1)+h_k, s_w(w_y-1)+w_k, c_x}$ $\frac{\partial y_{1,1,-}}{\partial w_{2,3,3,-}}$ $\frac{\partial y_{1,1,-}}{\partial w_{3,1,3,-}}$ $\frac{\partial y_{1,1,-}}{\partial w_{3,2,3,-}}$ $\frac{\partial y_{1,1,-}}{\partial w_{3,3,3,-}}$
1,2 $\frac{\partial y_{1,2,-}}{\partial w_{1,1,1,-}}$ $\frac{\partial y_{1,2,-}}{\partial w_{1,2,1,-}}$ $\frac{\partial y_{1,2,-}}{\partial w_{1,3,1,-}}$ $\frac{\partial y_{1,2,-}}{\partial w_{2,1,1,-}}$ ... $\frac{\partial y_{1,2,-}}{\partial w_{2,3,3,-}}$ $\frac{\partial y_{1,2,-}}{\partial w_{3,1,3,-}}$ $\frac{\partial y_{1,2,-}}{\partial w_{3,2,3,-}}$ $\frac{\partial y_{1,2,-}}{\partial w_{3,3,3,-}}$
2,1 $\frac{\partial y_{2,1,-}}{\partial w_{1,1,1,-}}$ $\frac{\partial y_{2,1,-}}{\partial w_{1,2,1,-}}$ $\frac{\partial y_{2,1,-}}{\partial w_{1,3,1,-}}$ $\frac{\partial y_{2,1,-}}{\partial w_{2,1,1,-}}$ ... $\frac{\partial y_{2,1,-}}{\partial w_{2,3,3,-}}$ $\frac{\partial y_{2,1,-}}{\partial w_{3,1,3,-}}$ $\frac{\partial y_{2,1,-}}{\partial w_{3,2,3,-}}$ $\frac{\partial y_{2,1,-}}{\partial w_{3,3,3,-}}$
2,2 $\frac{\partial y_{2,2,-}}{\partial w_{1,1,1,-}}$ $\frac{\partial y_{2,2,-}}{\partial w_{1,2,1,-}}$ $\frac{\partial y_{2,2,-}}{\partial w_{1,3,1,-}}$ $\frac{\partial y_{2,2,-}}{\partial w_{2,1,1,-}}$ ... $\frac{\partial y_{2,2,-}}{\partial w_{2,3,3,-}}$ $\frac{\partial y_{2,2,-}}{\partial w_{3,1,3,-}}$ $\frac{\partial y_{2,2,-}}{\partial w_{3,2,3,-}}$ $\frac{\partial y_{2,2,-}}{\partial w_{3,3,3,-}}$

 

$ \frac{\partial L}{\partial w} = \frac{\partial y}{\partial w}^T \cdot \frac{\partial L}{\partial y} $  : ( $KH$, $KW$, $XC$, $YC$ ) = ( 3, 3, 3, 5 ) -> ( 3x3x3, 5 )

$c_y$
$h_k$, $w_k$, $c_x$ \\
1 2 3 4 5
1,1,1 $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,w_y,1}}{\partial w_{1,1,1,1}}\frac{\partial L}{\partial y_{h_y,w_y,1}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,w_y,2}}{\partial w_{1,1,1,2}}\frac{\partial L}{\partial y_{h_y,w_y,2}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,w_y,3}}{\partial w_{1,1,1,3}}\frac{\partial L}{\partial y_{h_y,w_y,3}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,w_y,4}}{\partial w_{1,1,1,4}}\frac{\partial L}{\partial y_{h_y,w_y,4}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,w_y,5}}{\partial w_{1,1,1,5}}\frac{\partial L}{\partial y_{h_y,w_y,5}}$
1,2,1 $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,1}}{\partial w_{1,2,1,1}}\frac{\partial L}{\partial y_{h_y,h_w,1}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,2}}{\partial w_{1,2,1,2}}\frac{\partial L}{\partial y_{h_y,h_w,2}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,3}}{\partial w_{1,2,1,3}}\frac{\partial L}{\partial y_{h_y,h_w,3}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,4}}{\partial w_{1,2,1,4}}\frac{\partial L}{\partial y_{h_y,h_w,4}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,5}}{\partial w_{1,2,1,5}}\frac{\partial L}{\partial y_{h_y,h_w,5}}$
1,3,1 $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,1}}{\partial w_{1,3,1,1}}\frac{\partial L}{\partial y_{h_y,h_w,1}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,2}}{\partial w_{1,3,1,2}}\frac{\partial L}{\partial y_{h_y,h_w,2}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,3}}{\partial w_{1,3,1,3}}\frac{\partial L}{\partial y_{h_y,h_w,3}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,4}}{\partial w_{1,3,1,4}}\frac{\partial L}{\partial y_{h_y,h_w,4}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,5}}{\partial w_{1,3,1,5}}\frac{\partial L}{\partial y_{h_y,h_w,5}}$
2,1,1 $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,1}}{\partial w_{2,1,1,1}}\frac{\partial L}{\partial y_{h_y,h_w,1}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,2}}{\partial w_{2,1,1,2}}\frac{\partial L}{\partial y_{h_y,h_w,2}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,3}}{\partial w_{2,1,1,3}}\frac{\partial L}{\partial y_{h_y,h_w,3}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,4}}{\partial w_{2,1,1,4}}\frac{\partial L}{\partial y_{h_y,h_w,4}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,1}}{\partial w_{2,1,1,1}}\frac{\partial L}{\partial y_{h_y,h_w,1}}$
... ... ... $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,w_y,c_y}}{\partial w_{h_k,w_k,c_x,c_y}}\frac{\partial L}{\partial y_{h_y,w_y,c_y}}$
... ...
2,3,3 $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,1}}{\partial w_{2,3,3,1}}\frac{\partial L}{\partial y_{h_y,h_w,1}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,2}}{\partial w_{2,3,3,2}}\frac{\partial L}{\partial y_{h_y,h_w,2}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,3}}{\partial w_{2,3,3,3}}\frac{\partial L}{\partial y_{h_y,h_w,3}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,4}}{\partial w_{2,3,3,4}}\frac{\partial L}{\partial y_{h_y,h_w,4}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,5}}{\partial w_{2,3,3,5}}\frac{\partial L}{\partial y_{h_y,h_w,5}}$
3,1,3 $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,1}}{\partial w_{3,1,3,1}}\frac{\partial L}{\partial y_{h_y,h_w,1}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,2}}{\partial w_{3,1,3,2}}\frac{\partial L}{\partial y_{h_y,h_w,2}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,3}}{\partial w_{3,1,3,3}}\frac{\partial L}{\partial y_{h_y,h_w,3}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,4}}{\partial w_{3,1,3,4}}\frac{\partial L}{\partial y_{h_y,h_w,4}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,5}}{\partial w_{3,1,3,5}}\frac{\partial L}{\partial y_{h_y,h_w,5}}$
3,2,3 $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,1}}{\partial w_{3,2,3,1}}\frac{\partial L}{\partial y_{h_y,h_w,1}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,2}}{\partial w_{3,2,3,2}}\frac{\partial L}{\partial y_{h_y,h_w,2}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,3}}{\partial w_{3,2,3,3}}\frac{\partial L}{\partial y_{h_y,h_w,3}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,4}}{\partial w_{3,2,3,4}}\frac{\partial L}{\partial y_{h_y,h_w,4}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,5}}{\partial w_{3,2,3,5}}\frac{\partial L}{\partial y_{h_y,h_w,5}}$
3,3,3 $\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,1}}{\partial w_{3,3,3,1}}\frac{\partial L}{\partial y_{h_y,h_w,1}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,2}}{\partial w_{3,3,3,2}}\frac{\partial L}{\partial y_{h_y,h_w,2}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,3}}{\partial w_{3,3,3,3}}\frac{\partial L}{\partial y_{h_y,h_w,3}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,4}}{\partial w_{3,3,3,4}}\frac{\partial L}{\partial y_{h_y,h_w,4}}$
$\sum_{h_y=1}^{YH}\sum_{w_y=1}^{YW} $
$\frac{\partial y_{h_y,h_w,5}}{\partial w_{3,3,3,5}}\frac{\partial L}{\partial y_{h_y,h_w,5}}$

아, 다 작성하고나서 $y$ 첨자가 잘못작성되어있는걸 확인했는데, 귀찮아서 첫번째 row 만 바꿨다,, $y_{h_y, w_y, c_y}$ 가 맞는 첨자이다.

이렇게 두 행렬의 곱을 수행하면 위 행열을 얻고, 이를 reshape 해주면 $\frac{\partial L}{\partial w}$ 를 구할 수 있다.

 

 


코드구현

def backprop(self, dLdy, optimizer):
        # dLdy : YH x YW x YC
        # dydw : ( YH x YW x YC ) x ( KH x KW x XC x YC )
        # dLdw : KH x KW x XC x YC
        YH, YW, YC = dLdy.shape
        KH, KW, XC, YC =  self.weight.shape
        
        # Reshape : ( YH x YW , YC )
        flat_dLdy = dLdy.reshape(-1, YC)
        
        # flat_x.T : ( XC x KH x KW , YH x YW )
        # flat_dLdy : ( YH x YW , YC )
        # Dot : ( XC x KH x KW , YC )
        # Reshape : XC x KH x KW x YC
        # Transpose : KH x KW x XC x YC

        dLdw = np.dot(self.flat_x.T, flat_dLdy).reshape(XC, KH, KW, YC).transpose((1, 2, 0, 3))

        kernel_regularize_term = self.kernel_regularizer(self.weight) if self.kernel_regularizer is not None else 0
        kernel_delta = dLdw + kernel_regularize_term

        self.weight = self.weight - optimizer.learning_rate * kernel_delta

        
        if self.use_bias:
            bias_regularize_term = self.bias_regularizer(self.bias) if self.bias_regularizer is not None else 0
            bias_delta = dLdy + bias_regularize_term
            self.bias = self.bias - optimizer.learning_rate * bias_delta

        # flat_dLdy : ( YH x YW , YC )
        # flat_w.T : ( YC , XC x KH x KW )
        # Dot : ( YH x YW , XC x KH x KW )
        flat_dLdx = np.dot(flat_dLdy ,self.flat_w.T)
        dLdx = conv_utils.col2img(flat_dLdx, self.input_shape, self.output_shape, self.kernel_size, self.strides, self.padding_size)

        return dLdx

 

'머신러닝 > CustomFramework' 카테고리의 다른 글

Residual Connection  (0) 2022.04.04
Batch Normalization  (0) 2022.04.03
Dropout  (0) 2022.04.03
L1 L2 Regularizer  (0) 2022.04.03
Dense (Fully Connect) Layer  (0) 2022.03.21