archive
[코드 리뷰 프로젝트] 2레이어 인공신경망 구현 백업 본문
XOR 문제에 대한 기계 학습을 진행하는 코드 리뷰 프로젝트
XOR연산은 eXclusion OR 의 줄임말이고, 출력의 특징은 두 입력이 같으면 0을, 다르면 1을 출력하는것 문제
1. 모델 세팅
import numpy as np # numpy import
X = np.array([0, 0, 1, 1, 0, 1, 0, 1]).reshape(2,4) # 입력
Y = np.array([0, 1, 1, 0]).reshape(1,4) # 정답
-학습셋으로 사용할 데이터셋 (입력값, 정답값) 행렬벡터를 numpy를 통해 정의
# 가중치 초기화 함수
def init_parameters(num_hidden_units = 2):
W1 = np.random.randn(2, num_hidden_units) # 첫번째 레이어 가중치
B1 = np.zeros((num_hidden_units,1)) # 첫번째 레이어 바이어스
W2 = np.random.randn(num_hidden_units, 1) # 두번째 레이어 가중치
B2 = np.zeros((1, 1)) # 두번째 레이어의 바이어스
return W1, B1, W2, B2 # 가중치 파라미터 리턴
-인공신경망의 각 층의 가중치 및 bias 초기화, numpy 라이브러리의 random.randn 사용
2. 연산에 필요한 함수 구현하기 - 어파인 함수 및 시그모이드 함수
-하나의 레이어에서 수행되는 연산은 두 가지이며, 이 두 연산은 연속적으로 수행된 후 다음 레이어로 결과값을 넘긴다.
- 어파인 변환(affine transform): 가중치 매트릭스인 W를 곱하고(선형변환) 여기에 바이어스인 B를 더하는 연산입니다. 변환결과는 원점이 이동된(바이어스 덧셈연산으로 인해) 선형변환이라고 보시면 됩니다. 이를 어파인 변환이라고 합니다.
- 비선형 활성화 함수 : 어파인 변환된 결과에 비선형 연산을 추가하게 됩니다. 어파인 변환으로는 XOR같은 직선으로 나눌 수 없는 분류 문제를 풀어내는데 한계가 있습니다. 비선형 변환을 통해 입력을 선형분리 가능한 형태로 변환 시켜줘야 합니다. (시그모이드)
-어파인 함수 구현
# Affine transform
def affine(W, X, B):
return np.dot(W.T, X) + B
-시그모이드 함수 구현
# sigmoid function
def sigmoid(z):
temp=np.exp(-z)
return 1 / (1 + temp)
3. 연산에 필요한 함수 구현하기 - 손실함수, 순전파, 역전파
-로지스틱 값이 출력값으로 활용되는 MLP에서는 LSE를 활용한 손실함수를 구현하지 않음(미분이 불가능), 따라서 LSE가 아닌 Log Loss 함수를 손실함수로 활용
-손실함수 구현
def binary_cross_entropy(Y, YHat):
N = Y.shape[1] # 총 샘플의 수
loss = -(1/N) * np.sum(Y * np.log(YHat) + (1 - Y) * np.log(1 - YHat))
return loss
-순전파 함수 구현
def forward_loss(X, Y, _params):
W1, B1, W2, B2 = _params
# 첫번째 레이어연산
Z1 = affine(W1, X, B1) # 1 affine 함수
H = sigmoid(Z1) # 2) sigmoid 함수
# 두번째 레이어 연산
Z2 = affine(W2, H, B2) # 3) affine 함수
YHat = sigmoid(Z2) # 4) sigmoid 함수
# 손실함수 계산
loss = binary_cross_entropy(Y, YHat) # 5) 이진크로스 엔트로피 함수
return Z1, H, Z2, YHat, loss
-역전파 함수 구현
def get_gradients(X, Y, _params):
W1, B1, W2, B2 = _params
m = X.shape[1] # 샘플의 수
# 포워드 함수 통과 후 출력
# - Z1 : 첫번재 레이어 affine 결과
# - H : 첫번재 레이어 sigmoid 통과한 결과
# - Z2 : 두번재 레이어 affine 통과한 결과
# - YHat : 두번재 레이어 sigmoid 통과한 결과
# - loss : 크로스엔트로피 손실값
Z1, H, Z2, YHat, loss = forward_loss(X, Y, _params)
# 1) dLoss/dZ2 구현. 손실함수가 각 샘플 손실의 평균으로 계산되기 때문에 그대로 구현
dLdZ2 = (1/m)*(YHat-Y)
# 2) dLoss/dW2의 구현
dLdW2 = np.dot(H, dLdZ2.T)
# 3) dLoss/dB2의 구현 - 샘플마다 gradient가 있음. 따라서 합쳐줘야 함.
dLdB2 = np.sum(dLdZ2, axis=1, keepdims=True)
# 4) dLoss/dH의 구현
dLdH = np.dot(W2, dLdZ2)
# 5) dLoss/dZ1의 구현
dLdZ1 = dLdH * H * (1-H)
# 6) dLoss/dW1의 구현
dLdW1 = np.dot(X, dLdZ1.T)
# 7) dLoss/dB2의 구현
dLdB1 =np.sum( dLdZ1, axis=1, keepdims=True)
return [dLdW1, dLdB1, dLdW2, dLdB2], loss
4. 모델 학습하기 -최적화 함수 정의 및 모델 학습
-최적화 함수 정의, Adam 활용해도 됨
def optimize(X, Y, _params, learning_rate=0.01, iteration=200000):
params = [np.copy(param) for param in _params]
loss_trace = []
for epoch in range(iteration):
dparams, loss = get_gradients(X, Y, params)
for i in range(len(params)):
params[i] += - learning_rate * dparams[i]
if (epoch % 100 == 0):
loss_trace.append(loss)
_, _, _, Y_hat_predict, _ = forward_loss(X, Y, params)
return params, loss_trace, Y_hat_predict
### Backpropagation 역전파 프로세스 개념이 아직 완벽하게 머리에 자리잡은 건 아닌 거 같다 아직 전체적인 프로세스를 이해하는 게 어려움... 여러 번 들여다봐야겠다
0. 전체 코드
TwoLayerNeuralNetwork.py
0.00MB
본 포스트의 학습 내용은 부스트클래스 <AI 엔지니어 기초 다지기 : 부스트캠프 AI Tech 준비과정> 강의 내용을 바탕으로 작성되었습니다.
'ML_AI > 네이버 부클 AI 엔지니어 기초 다지기 : AI Tech 준비과정' 카테고리의 다른 글
[7주차 (2)] Sequential Model - Transformer - 1 (0) | 2024.06.07 |
---|---|
[7주차 (1)] Sequential Model -RNN (0) | 2024.06.07 |
[코드 리뷰 프로젝트] 경사하강법 구현 백업 (0) | 2024.06.06 |
[6주차 (4)] 최적화 - 2 (0) | 2024.06.02 |
[6주차 (3)] 최적화 - 1 (0) | 2024.06.02 |