grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_0.T.dot(grad_y_pred)
grad_h = grad_y_pred.dot(w2.T)
grad_w1 = x.T.dot(grad_h * h * (1 - h))
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
1. 정의
2-layer MLP (Multi-Layer Perceptron)은 두 개의 주요 층을 가진 신경망 모델이다.
여기서 "2-layer"는 일반적으로 입력층과 출력층 사이에 2개의 은닉층이 있는 구조를 의미합니다.
이 신경망은 비선형 변환을 통해 입력 데이터를 처리하고, 복잡한 패턴을 학습할 수 있습니다.
2. 2-layer MLP의 구성
- 입력층 (Input Layer):
- 입력층은 데이터의 특성(feature)을 신경망에 전달합니다.
- 입력층의 뉴런 수는 데이터의 차원과 같으며, 데이터의 각 특성(feature)을 나타냅니다.
- 은닉층 (Hidden Layers):
- 첫 번째 은닉층: 입력층과 두 번째 은닉층(또는 출력층) 사이에 위치합니다. 이 층에서는 비선형 변환을 적용하여 입력 데이터의 복잡한 패턴을 학습합니다. 각 뉴런은 활성화 함수(예: ReLU, 시그모이드, tanh 등)를 통해 출력값을 생성합니다.
- 두 번째 은닉층: 첫 번째 은닉층과 출력층 사이에 위치합니다. 이 층에서도 비선형 변환이 이루어지며, 복잡한 패턴을 학습하여 최종 출력을 결정합니다.
- 출력층 (Output Layer):
- 출력층은 모델의 최종 결과를 생성합니다.
- 출력층의 활성화 함수는 문제에 따라 다릅니다. 예를 들어, 다중 클래스 분류 문제에서는 소프트맥스(softmax) 함수를 사용하고, 이진 분류 문제에서는 시그모이드(sigmoid) 함수를 사용할 수 있습니다.
순방향 전파 (Forward Propagation)
- 입력 데이터가 입력층으로 들어옵니다.
- 입력층에서 첫 번째 은닉층으로 데이터가 전달됩니다.
- 데이터는 가중치와 편향을 곱한 후, 활성화 함수를 통해 변환됩니다.
- 첫 번째 은닉층의 출력이 두 번째 은닉층으로 전달됩니다.
- 이 과정도 같은 방식으로 진행됩니다.
- 두 번째 은닉층의 출력이 출력층으로 전달됩니다.
- 출력층에서 최종 예측값이 계산됩니다.
역전파 (Backpropagation)
- 손실 함수 (Loss Function) 계산: 모델의 예측값과 실제 값 간의 차이를 계산하여 손실을 측정합니다.
- 오차의 그래디언트 계산: 손실 함수에 대한 각 가중치의 그래디언트를 계산합니다.
- 가중치 업데이트: 계산된 그래디언트를 사용하여 가중치를 업데이트하여 모델을 개선합니다.
3. 수식 및 코드 이해
1. 모델 정의
import numpy as np
from numpy.random import randn
n, d, h, c = 64, 1000, 100, 10
x, y = randn(n, d), randn(n, c)
w1, w2 = randn(d, h), randn(h, c)
learning_rate = 1e-4
n : 데이터의 수
d: 입력차원
h: 히든차원
c : 클래스 수
x: (64, 1000) 64개의 데이터와 1000개 열(피쳐)
y: (64,10) 64개의 데이터 샘플이 각각의 10개의 클래스 또는 출력값을 가진 상태
w1, w2 정의
2. 순전파 코드
for t in range(1000):
# 순전파 계산
y_0 = x.dot(w1) # y = xw + b
h_0 = 1 / (1 + np.exp(-y_0)) # sigmoid
y_pred = h_0.dot(w2) # 마지막 결과값
1. y_0 = x.dot(w1) 편향 b 는 생략
2. 시그모이드 함수 작성
h_0 = 1 / (1 + np.exp(-y_0)
\begin{flalign*}
\sigma(z) = \frac{1}{1 + e^{-z}} &&
\end{flalign*}
3. 예측값 출력
y_pred = h_0.dot(w2)
3. Loss 코드
# loss
loss = np.square(y_pred - y).sum() # MSE 평균제곱오차
print(t, loss)
4. 역전파 (BackPropagation) 코드
최적의 기울기 (업데이트 뱡향 및 크기)를 구하는 것이 gradient 인데,
기울기를 구하기 위해서 뒤에서 부터 앞까지 미분을 해서 기울기를 업데이트 한다.
Chain rlue(Upsteam * Local) 를 이용해서 미분 한다.
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_0.T.dot(grad_y_pred)
grad_h = grad_y_pred.dot(w2.T)
grad_w1 = x.T.dot(grad_h * h * (1 - h))
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2
1. grad_y_pred = 2.0 * (y_pred - y)
\begin{flalign*}
MSE(L) = \frac{1}{n} \sum_{i=1}^{n} (y_{\text{pred},i} - y_i)^2 &&
\end{flalign*}
위의 식을 미분
\begin{flalign*}
\frac{\partial (\text{MSE})}{\partial y_{\text{pred},i}} = \frac{2}{n} (y_{\text{pred},i} - y_i) &&
\end{flalign*}
코드에서 배치크기 n에 대한 정규화가 없으므로 2.0 을 그대로 사용
2. grad_w2 = h_0.T.dot(grad_y_pred)
손실 함수 L을 w2에 대해 미분하여 그래디언트를 계산
\[\frac{\partial L}{\partial w2} = \frac{\partial L}{\partial y_{\text{pred}}} \cdot \frac{\partial y_{\text{pred}}}{\partial w2}\]
각각의 미분 값
\[\frac{\partial L}{\partial y_{\text{pred}}} = \frac{2}{n} \cdot (y_{\text{pred}} - y)\]
y_pred = h_0.dot(w2) 에서 미분
\[\frac{\partial y_{\text{pred}}}{\partial w2} = h_0\]
각 미분값을 곱해준 식
전치행렬을 한 이유는 차원을 맞춰주기 위해서
\[\frac{\partial L}{\partial w2} = h_0^T \cdot \frac{\partial L}{\partial y_{\text{pred}}}\]
3. grad_h = grad_y_pred.dot(w2.T)
출력층에서의 기울기(grad_y_pred)를 두 번째 은닉층으로 전파하여 grad_h를 계산
\begin{flalign*} \text{grad_h} &= \frac{\partial L}{\partial y_{\text{pred}}} \cdot \frac{\partial y_{\text{pred}}}{\partial h_0} && \end{flalign*}
\begin{flalign*} \frac{\partial y_{\text{pred}}}{\partial h_0} &= w2 && \end{flalign*} \begin{flalign*} \text{grad_h} &= \text{grad_y_pred} \cdot w2^T && \end{flalign*}
4. grad_w1 = x.T.dot(grad_h * h * (1 - h))
\( w1 \): \begin{flalign*} \frac{\partial L}{\partial w1} &= \frac{\partial L}{\partial y_0} \cdot \frac{\partial y_0}{\partial w1} && \end{flalign*}
Where:
\begin{flalign*} \frac{\partial L}{\partial y_0} &= \text{grad_h} \cdot (h \cdot (1 - h)) && \end{flalign*} \begin{flalign*} \frac{\partial y_0}{\partial w1} &= x && \end{flalign*}
Thus:
\begin{flalign*} \text{grad_w1} &= x^T \cdot \left(\text{grad_h} \cdot (h \cdot (1 - h))\right) && \end{flalign*}
역전파 미분하는 과정이다.
모든 코드 정리
import numpy as np
from numpy.random import randn
# 2-layer mlp (multi layer perceptron)
n, d, h, c = 64, 1000, 100, 10 # 데이터 input 수, 입력차원, 히든차원, 클래스수
x, y = randn(n, d), randn(n, c)
w1, w2 = randn(d, h), randn(h, c)
learning_rate = 1e-4
for t in range(1000):
# 순전파 계산
y_0 = x.dot(w1) # y = xw + b
h_0 = 1 / (1 + np.exp(-y_0)) # sigmoid
y_pred = h_0.dot(w2) # 마지막 결과값
# loss
loss = np.square(y_pred - y).sum() # MSE 평균제곱오차
print(t, loss)
# 역전파 (기울기 업데이트)
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_0.T.dot(grad_y_pred)
grad_h = grad_y_pred.dot(w2.T)
grad_w1 = x.T.dot(grad_h * h * (1 - h))
w1 = w1 - learning_rate * grad_w1
w2 = w2 - learning_rate * grad_w2
'AI Naver boost camp > [Week 02] ML LifeCycle' 카테고리의 다른 글
LSTM(Long Short-Term Memory Networks) (0) | 2024.08.18 |
---|---|
RNN - 순환신경망 이란?? (1) | 2024.08.18 |
활성화함수 (Activation funtion) (0) | 2024.08.16 |
Numpy - dot, @, * 차이점 (0) | 2024.08.16 |
경사하강법 - Gradient Desent (0) | 2024.08.13 |
댓글