Linear Model Simplification


 

 

 

 

Backpropagation for Binary Cross Entropy


Node

Partial Derivative

Chain Rule

Backpropagation

Simgoid Activation Funcion


Node

Partial Derivatives

Chain Rule

Backpropagation

 

Tanh Activation Funcion


Node

Partial Derivatives

Chain Rule

Backpropagation

 

ReLU Activation Funcion


Node

Partial Derivatives

Chain Rule

Backpropagation

이번 포스트에서는 Deep Learning에서 가장 많이 사용되는 activation function들인 sigmoid, tanh, ReLU에 대해서 알아본다.

실제로는 상당히 다양한 종류의 activation function들이 존재하고 2017년 Google Brain에서 개발한 Swish activation function 등, 지금도 효유적인 backpropagation을 위한 activation function들이 개발되고 있다.

이때 이 모든 activation function들을 한 번에 다루는 것은 비효율적이기도 하고, 지겨우니까 대표적인 activation function들에 대해 배우고, learning process에 접목시켜본 뒤에 다른 activation function들의 특징을 파악하는 편이 더 좋을 것 같다.

 

따라서 몇 차례의 포스트를 걸쳐 기본적인 sigmoid, tanh, ReLU에 대해서 배워보도록 하자.

 

Sigmoid Activation Function


Deep learning을 배우는 사람들은 아마 logistic regression을 배우면서 처음 sigmoid라는 non-linear activation function을 접할 것이다. 그리고 이 sigmoid function은 logistic function의 subset인데 output이 0과 1사이이므로 확률로의 해석이 가능하며 x축으로의 bias가 없어서 learning에 효과적이므로 logistic funciton들 중 가장 많이 사용된다.

 

먼저 logistic function의 식은 다음과 같다.

이 logistic function에서 input의 boundary를 (0,1)로 맞추고 x축에 대한 bias도 없애면

우리가 알고있는 sigmoid function의 형태가 된다. 이 sigmoid function는 함수의 모양과 도함수를 그려보면 다음과 같다.

x_range = np.linspace(-5, 5, 300)
sigmoid = 1 / (1 + np.exp(-1*x_range))
sigmoid_d = sigmoid*(1 - sigmoid)

fig, ax = plt.subplots(2, 1, figsize = (15,10))
ax[0].set_title("Sigmoid Function", fontsize = 20)
ax[0].plot(x_range, sigmoid)
ax[0].grid()

ax[1].set_title("Derivative of Sigmoid", fontsize = 20)
ax[1].plot(x_range, sigmoid_d)
ax[1].grid()

 

극한을 이용하여 sigmoid의 수렴값을 구해보면

이므로 sigmoid의 output은 확률로 해석이 가능하며

전체 0부터 1사이의 output 중 90% 정도인 0.1과 0.9를 input이 실수 전체 중 -2부터 2일때가 차지한다. 따라서 [-2, 2] 이외의 값들은 outlier로 취급되어 sigmoid의 output에서는 0.1, 0.9와 큰 차이를 보이지 않는다.

 

그리고 이 sigmoid의 derivative는 다음과 같이 구할 수 있다.

 

따라서 sigmoid function에 대한 node는 다음과 같이 구현할 수 있다.

class sigmoid_node():
    def __init__(self):
        self.x, self.z = None, None
        
    def forward(self, x):
        self.x = x
        self.z = 1 / (1 + np.exp(-1*self.x))
        return self.z
    
    def backward(self, dJ):
        return self.z * (1 - self.z) * dJ

 

Tanh Activation Fucntion


위의 sigmoid보다 대부분의 경우에서 좋은 성능을 보여주는 activation function은 tanh이다. 따라서 hidden layer에서 sigmoid보다 tanh를 사용하는 경우가 많다. 하지만 마지막 layer에서 classification을 할 때는 tanh보다 sigmoid를 많이 사용한다.

이 tanh activation function은 다음과 같다.

 

이 tanh의 모양과 도함수의 모양은 다음과 같다.

x_range = np.linspace(-5, 5, 300)
tanh = (np.exp(x_range) - np.exp(-1*x_range))/(np.exp(x_range) + np.exp(-1*x_range))
tanh_d = (1 + tanh)*(1 - tanh)

fig, ax = plt.subplots(2, 1, figsize = (15,10))
ax[0].set_title("Tanh Function", fontsize = 20)
ax[0].plot(x_range, tanh)
ax[0].grid()

ax[1].set_title("Derivative of Tanh", fontsize = 20)
ax[1].plot(x_range, tanh_d)
ax[1].grid()

위의 식에서 극한을 이용하면 다음과 같은 결과를 얻을 수 있다.

 

이때 알 수 있는 것은, sigmoid와 달리 activation function의 output이 zero-centered라는 것이다. 즉, deep learning의 hidden layer에 이 tanh를 사용할 경우, 다음 layer의 input이 자동으로 zero-centered input이 되는 것을 알 수 있다. 이것이 tanh가 sigmoid보다 좋은 성능을 보여주는 첫 번째 이유가 된다.

 

sigmoid와 마찬가지로 tanh의 도함수를 구해보면 다음과 같다.

 

따라서 tanh는 다음과 같이 구현할 수 있다.

class tanh_node():
    def __init__(self):
        self.x, self.z = None, None
    
    def forward(self, x):
        self.x = x
        self.z = (np.exp(self.x) - np.exp(-1*self.x))/(np.exp(self.x) + np.exp(-1*self.x))
        return self.z
        
    def backward(self, dJ):
        return (1 + self.z) * (1 - self.z) * dJ

 

ReLU Activation Function


요즘 deep learning에서 가장 첫 번째로 시도되는 activation function은 ReLU일 것이다. 이 ReLU가 다른 activation function보다 좋은 성능을 내는지에 대한 논문도 다양하며 실제로 다양한 neural network에서 좋은 성능을 보여준다. 먼저 ReLU의 식은 다음과 같다.

 

즉, ReLU의 input이 양수일 경우엔 그 양수값을 내보내고, 음수일 경우 0을 내보낸다. ReLU가 좋은 성능을 내는 첫 번째 이유가 이 식에 있다. Sigmoid, Tanh는 여러 연산들을 하여 activation value를 만드는데 비해, 이 ReLU는 한 번의 비교연산만을 통하여 output을 내기 때문에 연산속도가 빠르다. 보통 tanh보다 5배정도 빠르다고 알려져있다.

 

이 ReLU의 그래프와 도함수를 보면 다음과 같다.

x_range = np.linspace(-5, 5, 300)
zero_arr = np.zeros_like(x_range)
relu = np.maximum(x_range, zero_arr)
relu_d = relu / (0.0001 + relu)
fig, ax = plt.subplots(2, 1, figsize = (15,10))
ax[0].set_title("Tanh Function", fontsize = 20)
ax[0].plot(x_range, relu)
ax[0].grid()

ax[1].set_title("Derivative of Tanh", fontsize = 20)
ax[1].plot(x_range, relu_d)
ax[1].grid()

이때, 코드를 보면 relu_d를 구현하는데 조금의 트릭이 들어간 것을 알 수 있다. 음수일 때 0, 양수일 때 1을 만들기 위하여 relu에 relu를 나눠주는데 0으로 나눠줄 수 없으므로 gradient에 영향을 주지 않는 0.0001 정도를 더해서 나눠준 것을 알 수 있다.

 

도함수는 어렵게 구할 것 없이, 양수일 때는 1이고 음수일 때는 0이 된다.

 

따라서 ReLU는 다음과 같이 구현할 수 있다.

class relu_node():
    def __init__(self):
        self.x, self.z = None, None
        
    def forward(self, x):
        self.x = x
        self.z = np.maximum(0, self.x)
        return self.z
    
    def backward(self, dJ):
        return self.z / (0.0001 + self.z)

Activation Functions Comparison


위의 3가지 activation function을 같이 그려보면 다음과 같다.

먼저 위의 그래프를 통해 알 수 있는 것은, sigmoid와 tanh는 output의 범위가 정해져있지만 ReLU는 output의 범위가 정해져있지 않다는 것이다.

그리고 도함수에서 sigmoid와 tanh는 1보다 작기 때문에 layer가 많아질수록 propagate되는 값들이 0에 가까워질 것을 알 수 있다. 즉, sigmoid와 tanh는 태생적으로 vanishing gradient problem을 야기할 수 있는 activation function들이다.

마지막 Linear Regression에 대한 Backpropagtion으로 Multivariate Linear Regression에 대한 Backpropagation 정리노트이다.

 

Backpropagation for One Sample


Model

Parital Derivative

Chain Rule

Backpropagation Visualization

Parameter Update

 

Backpropagation for Two Samples


Model

Parital Derivative

Chain Rule

Backpropagation Visualization

Parameter Update

 

Backpropagation Vectorized form


Model

Parital Derivative

Chain Rule

Backpropagation Visualization

Parameter Update

이번 포스트에서는 두 번째 model인 $y = \theta_{1} x + \theta_{0}$에 대한 backpropagation을 다뤄본다.

 

마찬가지로 하나의 Sample에 대한 backpropagation부터 살펴보자.

 

 

Backpropagation for One Sample


Model

 

Parital Derivative

 

Chain Rule

 

Backpropagation Visualization

 

Parameter Update

 

 

Backpropagation for Two Samples


Model

 

Parital Derivative

 

Chain Rule

 

 

Backpropagation Visualization

Parameter Update

 

 

Backpropagation Vectorized form


Model

 

Parital Derivative

 

Chain Rule

 

 

Backpropagation Visualization

Parameter Update

 

Linear Regression을 위한 Backpropagation은 다음과 같은 모델들을 사용하여 순서대로 진행될 것이다.

  1. $y = \theta x$
  2. $y = \theta_{1} x + \theta_{0}$
  3. $y = \theta_{2} x_{2} + \theta_{1} x_{1} + \theta_{0}$

그리고 각 단계에서도 첫 번째로는 하나의 sample에 대한 backpropagation, 두 번째로는 2개의 sample에 대한 backpropagation, 마지막으로 Vectorized form의 backpropagation으로 진행될 것이다.

 

그러면 이번 포스트에서는 첫 번째 model부터 살펴보도록하자.

 

Backpropagation for One Sample


먼저 forward-backward propagation을 위한 node들을 먼저 만들어보면 다음과 같다.

 

 

즉, $z_{1}$ node는 prediction value가 될 것이고, $L$는 loss를 구하게 된다. 그리고 각 node에서의 partial derivative를 구하면 다음과 같이 표시할 수 있다.

 

 

그리고 Chain rule에 의해 $\theta$까지의 backpropagation을 계산하면 다음과 같다.

 

$\frac{\partial L}{\partial z_{1}} = 

\frac{\partial L}{\partial z_{2}} \frac{\partial z_{2}}{\partial z_{1}}

=
2z_{2}*(-1) = -2z_{2}

=-2(y-z_{1})$

 

$\frac{\partial L}{\partial \theta} = 

\frac{\partial L}{\partial z_{2}}
\frac{\partial z_{2}}{\partial z_{1}}
\frac{\partial z_{1}}{\partial \theta}

=

\frac{\partial L}{\partial z_{1}}
\frac{\partial z_{1}}{\partial \theta}

=-2x(y-z_{1})
=-2x(y-\theta x)$

 

따라서 Backpropagation은 다음과 같이 일어난다.

 

$\theta = \theta - lr * \frac{\partial L}{\partial \theta}
=
\theta - lr * (-2x(y- \theta x))
=
\theta + lr * 2x(y- \theta x)$

 

Backpropagation for Two Samples


 

우리가 Learning 단계에서 mini-batch를 사용한다면 loss가 아닌 cost를 parameter update에 사용하게 된다. 

 

즉, loss들의 평균을 구하는 node가 추가된다. 그리고 mini-batch size가 2인 linear regression model은 다음과 같다.

 

그리고 각 node에서의 partial derivative를 표시하면

이 되고, Chain rule을 이용하여 backpropagation을 계산하면 다음과 같다.

 

$\frac{\partial J}{\partial z_{2}^{(1)}}=\frac{\partial J}{\partial L^{(1)}}\frac{\partial L^{(1)}}{\partial z_{2}^{(1)}}=\frac{1}{2} * 2z_{2}^{(1)}$

 

$\frac{\partial J}{\partial z_{2}^{(2)}}=\frac{\partial J}{\partial L^{(2)}}\frac{\partial L^{(2)}}{\partial z_{2}^{(2)}}=\frac{1}{2} * 2z_{2}^{(2)}$

 

$\frac{\partial J}{\partial z_{1}^{(1)}}=\frac{\partial J}{\partial L^{(1)}}\frac{\partial L^{(1)}}{\partial z_{2}^{(1)}}\frac{\partial z_{2}^{(1)}}{\partial z_{1}^{(1)}}=\frac{\partial J}{\partial z_{2}^{(1)}}\frac{\partial z_{2}^{(1)}}{\partial z_{1}^{(1)}}=-\frac{1}{2} * 2z_{2}^{(1)}=-\frac{1}{2} *2(y^{(1)} - z_{1}^{(1)})$

 

$\frac{\partial J}{\partial z_{1}^{(2)}}=\frac{\partial J}{\partial L^{(2)}}\frac{\partial L^{(2)}}{\partial z_{2}^{(2)}}\frac{\partial z_{2}^{(2)}}{\partial z_{1}^{(2)}}=\frac{\partial J}{\partial z_{2}^{(2)}}\frac{\partial z_{2}^{(2)}}{\partial z_{1}^{(2)}}=-\frac{1}{2} * 2z_{2}^{(2)}=-\frac{1}{2} *2(y^{(2)} - z_{1}^{(2)})$

 

$\frac{\partial J}{\partial \theta}=\frac{\partial J}{\partial L^{(1)}}\frac{\partial L^{(1)}}{\partial z_{2}^{(1)}}\frac{\partial z_{2}^{(1)}}{\partial z_{1}^{(1)}}\frac{\partial z_{1}^{(1)}}{\partial \theta}=\frac{\partial J}{\partial z_{1}^{(1)}}\frac{\partial z_{1}^{(1)}}{\partial \theta}=-\frac{1}{2} *2x^{(1)}(y^{(1)} - z_{1}^{(1)})=-\frac{1}{2} *2x^{(1)}(y^{(1)} - \theta x^{(1)})$

 

$\frac{\partial J}{\partial \theta}=\frac{\partial J}{\partial L^{(2)}}\frac{\partial L^{(2)}}{\partial z_{2}^{(2)}}\frac{\partial z_{2}^{(2)}}{\partial z_{1}^{(2)}}\frac{\partial z_{1}^{(2)}}{\partial \theta}=\frac{\partial J}{\partial z_{1}^{(2)}}\frac{\partial z_{1}^{(2)}}{\partial \theta}=-\frac{1}{2} *2x^{(2)}(y^{(2)} - z_{1}^{(2)})=-\frac{1}{2} *2x^{(2)}(y^{(2)} - \theta x^{(2)})$

 

이를 visualization하면 다음과 같다.

 

따라서 parameter update는 다음과 같이 된다.

 

$\theta = \theta - lr * (-\frac{1}{2} *2x^{(1)}(y^{(1)} - \theta x^{(1)}) -\frac{1}{2} *2x^{(2)}(y^{(2)} - \theta x^{(2)}))=\theta + lr * \frac{1}{2} \sum_{i=1}^{2} 2x^{(i)}(y^{(i)} - \theta x^{(i)})$

 

 

Backpropagation Vectorized form


위의 두 번째 단계는 실제 프로그래밍을 하기에도 힘들고, 같은 연산이 반복될 때 사용되는 vectorization을 이용하지 못한 모양이다. 따라서 mini-batch 사이즈가 임의의 n개일 때는 vectorization form을 이용하게 되고, 이 포스트에서는 3개의 mini-batch에 대한 backpropagation을 다룬다.

 

먼저 forward propgation을 포함한 model은 다음과 같다.

 

 

그리고 각 node에서 Jacobian을 이용한 partial derivative를 표시하면 다음과 같다.

 

 

그리고 각 node에서 실제로 backpropagationdmf 계산하면 다음과 같다.

따라서 Backpropagation은 다음과 같이 전체적으로 표시할 수 있다.

 

Plus Node


Node

Partial Derivatives

Chain Rule

Backpropagation

 

Minus Node


Node

Partial Derivatives

Chain Rule

Backpropagation

 

Multiplication Node


Node

Partial Derivatives

Chain Rule

Backpropagation

 

Square Node


Node

Partial Derivatives

Chain Rule

Backpropagation

 

Average Node


Node

Partial Derivatives

Chain Rule

Backpropagation

+ Recent posts