Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Tags
more
Archives
Today
Total
관리 메뉴

archive

[코드 리뷰 프로젝트] 2레이어 인공신경망 구현 백업 본문

ML_AI/네이버 부클 AI 엔지니어 기초 다지기 : AI Tech 준비과정

[코드 리뷰 프로젝트] 2레이어 인공신경망 구현 백업

안정민 2024. 6. 6. 14:56

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. 연산에 필요한 함수 구현하기 - 어파인 함수 및 시그모이드 함수

-하나의 레이어에서 수행되는 연산은 두 가지이며, 이 두 연산은 연속적으로 수행된 후 다음 레이어로 결과값을 넘긴다.

  1. 어파인 변환(affine transform): 가중치 매트릭스인 W를 곱하고(선형변환) 여기에 바이어스인 B를 더하는 연산입니다. 변환결과는 원점이 이동된(바이어스 덧셈연산으로 인해) 선형변환이라고 보시면 됩니다. 이를 어파인 변환이라고 합니다.
  2. 비선형 활성화 함수 : 어파인 변환된 결과에 비선형 연산을 추가하게 됩니다. 어파인 변환으로는 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 준비과정> 강의 내용을 바탕으로 작성되었습니다.