끵뀐꿩긘의 여러가지

[밑바닥부터 시작하는 딥러닝]활성화 함수, 손실함수 미분 & 구현 본문

Naver boostcamp -ai tech/책

[밑바닥부터 시작하는 딥러닝]활성화 함수, 손실함수 미분 & 구현

끵뀐꿩긘 2022. 9. 26. 07:51

시그모이드 함수:

$$sigmoid(x) = \frac{1}{1+e^{-x}}$$

시그모이드 함수

시그모이드 함수의 미분: 

$$ \frac{\mathrm{d} sigmoid(x)}{\mathrm{d} x} = \frac{\mathrm{d} }{\mathrm{d} x}\frac{1}{1+e^{-x}}\\
 =(1)(1+e^{-x})^{-2}(e^{-x})\\
 = \frac{e^{-x}}{(1+e^{-x})^2}\\
 = \frac{1+e^{-x}-1}{(1+e^{-x})^2}\\
 = \frac{1+e^{-x}}{(1+e^{-x})^2} - \frac{1}{(1+e^{-x})^2}\\
 = \frac{1}{(1+e^{-x})} - \frac{1}{(1+e^{-x})^2}\\
 = \frac{1}{(1+e^{-x})}(1-\frac{1}{(1+e^{-x})})\\
 = sigmoid(x)(1-sigmoid(x))$$

 

$$\therefore \frac{\mathrm{d} }{\mathrm{d} x}sigmoid(x) = sigmoid(x)(1-sigmoid(x))$$

시그모이드 함수의 도함수

시그모이드 layer 구현:

class Sigmoid:
    def __init__(self):
        self.out = None

    def forward(self, x):
        out = sigmoid(x)
        self.out = out
        return out

    def backward(self, dout):
        dx = dout * (1.0 - self.out) * self.out # sigmoid 미분 = sigmoid(x)(1-sigmoid(x))

        return dx

 

소프트맥스 함수 with CE:

softmax:

sigmoid 함수의 일반화 함수이며, 각 idx의 값이 정답일 확률을 나타낸다

ex.(0.2,0.7,0.1) # 1번이 정답일 확률(0.2), .... 3번이 정답일 확률(0.1)이라고 예상

softmax 구현:

softmax함수는 exp안의 항에 상수를 더해도 값이 같기 때문에 계산 overflow를 방지하기 위해서 x값 중 최대값을 빼준다.

def softmax(x):
	# x.ndim == 2이면 sigmoid
    
    # 왜 뒤집고 다시 뒤집는거임??
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0) # 오버플로 대책
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T 

	# flatten한 x(x.ndim == 1)가 들어왔을때만 사용한다
    x = x - np.max(x) # 오버플로 대책
    return np.exp(x) / np.sum(np.exp(x))

CrossEntropy:

CrossEntropy 구현:

def cross_entropy_error(y, t):
	# 차원 맞추기
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        
    # 훈련 데이터가 원-핫 벡터라면 정답 레이블의 인덱스로 반환
    if t.size == y.size:
        t = t.argmax(axis=1)
             
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t])) / batch_size # CE 적용

cross entropy를 적용한 softmax 미분

계산 그래프 방식:

$$\therefore SoftmaxwithLoss = \hat{y}_k - y_k$$

 

 

 

SoftmaxwithLoss layer 구현:

class SoftmaxWithLoss:
    def __init__(self):
        self.loss = None # 손실함수
        self.y = None    # softmax의 출력
        self.t = None    # 정답 레이블(원-핫 인코딩 형태)
        
    def forward(self, x, t):
        self.t = t
        self.y = softmax(x)
        self.loss = cross_entropy_error(self.y, self.t)
        
        return self.loss

    def backward(self, dout=1):
        batch_size = self.t.shape[0]
        if self.t.size == self.y.size: # 정답 레이블이 원-핫 인코딩 형태일 때
            dx = (self.y - self.t) / batch_size
        else:
            dx = self.y.copy()
            dx[np.arange(batch_size), self.t] -= 1 
            # ex. dx[0,5], 5번째 idx가 정답 레이블이므로 -1을 해주어 y-t한것처럼 만들어줌
            dx = dx / batch_size
        
        return dx
Comments