본문 바로가기

개념 정리/implement_python

backpropagation python 구현

2022.10.28 - [개념 정리] - 오차 역전파

 

오차 역전파

신경망에서 가중치는 오차 역전파 back propagation 방법을 사용한다. 이전에는 입력츠엥 값을 넣으면 은닉층을 거쳐 출력층에서 최종 결과를 볼 수 있었다. 더보기 오차 역전파 가중치 초기화 순전

teach-meaning.tistory.com

임의의 입력과 가중치 출력값의 지정

input = np.array([[1],[2],[3]])
target = np.array([[0.5],[0.1]])

w1 = np.array([[0.1,0.2],[0.3,0.4],[0.5,0.6]])
w2 = np.array([[0.7,0.8],[0.9,0.1]])

b1 = np.array([[0.5],[0.5]])
b2 = np.array([[0.3],[0.3]])

밀집층의 계산, 활성화 함수로 시그모이드 함수의 사용

def cal_dense(input, w, b):
  """
  밀집층의 계산
  Args:
    input : 입력값, 이전 층의 출력
    w : 해당 층의 가중치
    b : 해당 층의 가중치 편향 
  Return:
    다음 층의 출력 값 (활성화 함수 계산까지 했으므로)   
  """
  input_result = (w.T)@input+b
  hidden_output = 1/(1+np.exp(-input_result)) # 활성화 함수의 종류를 입력으로 받을 수 있음
  return hidden_output

은닉층의 계산

hidden_output = cal_dense(input, w1, b1)
hidden_output
>>>
array([[0.93702664],
       [0.96442881]])

출력층까지의 계산

predict = cal_dense(hidden_output, w2, b2)
predict
>>>
array([[0.86103399],
       [0.75879129]])

계산과 실젯 값의 차이 = 최소 제곱 오차 함수의 미분값 * 1/2

c_diff = predict-target
c_diff
>>>
array([[0.36103399],
       [0.65879129]])

역전파를 통한 1차 미분값의 계산, 출력층과 은닉층 사이

def w_c_diff(c_diff, output_result, input_result):
  """
  각 가중치들에 대한 비용 함수의 변화량을 계산하기 위한 함수
  Args:
    c_diff : 비용 함수의 미분식
    output_result : 해당 층의 출력
    input_result : 이전 층의 출력
  Result:
    가중치들에 대한 비용 함수의 변화량, 편향에 대한 비용 함수의 변화량
  """
  d_c_matrix = []
  a = (c_diff*(output_result*(1-output_result)))@(input_result.T) # 각 가중치 변화량에 따른 비용 함수 변화량의 행렬 생성
  b = (c_diff.T)@(output_result*(1-output_result)) # 편향 가중치 변화에 따른 비용 함수의 변화량 
  return a, b
w_c_diff2, b_c_diff2 = w_c_diff(c_diff, predict, hidden_output)
w_c_diff2
>>>
array([[0.04047892, 0.04166268],
       [0.11298352, 0.11628758]])
       
b_c_diff2
>>>
array([[0.16377596]])

입력층와 은닉층 사이의 계산

먼저 각 은닉층에 대한 비용 함수의 변화량 계산

def w1_c_diff(c_diff, output_result, weight):
  """
  각 은닉층에 대한 비용 함수의 변화량
  Args : 
    c_diff : 비용 함수 변화량, 오차 제곱 함수의 미분값
    output_result : 출력층의 계산 결과, 예측값
    weight : 은닉층의 가중치
  Return:
    a : 각 은닉층에 대한 비용 함수 변화량
    b : 
  """
  a = weight@(c_diff*(output_result*(1-output_result))) # 은닉층에 대한 연산

  b = (c_diff*(output_result*(1-output_result)))*weight
  return a, b
h1_c_diff, b_c_diff1 = w1_c_diff(c_diff, predict, w2)
h1_c_diff
>>>
array([[0.12670084],
       [0.05093706]])
       
b1_c_diff
>>>
array([[0.03023953, 0.03455946],
       [0.10851897, 0.01205766]])

두 행렬을 이용하여 각 입력층의 가중치, 가중치 편향 변화에 따른 비용 함수 변화량 계산

def input_c_diff(h_c_diff, hidden_output, input, weight, b, b_diff):
  """
  각 입력층의 가중치들에 대한 비용 함수 변화량
  Args :
    h_c_diff : 은닉층의 가중치별 변화에 따른 비용 함수 변화량
    hidden_output : 은닉층의 출력값
    input : 입력값
    weight : 입력층의 가중치
    b : 입력층의 가중치 편향
    b_diff : 밀집의 가중치 편향의 변화량에 따른 비용 함수 변화량
  Return:
    a : 입력층의 각 가중치들의 변화에 따른 비용 함수 변화량
    b_c : 입력층의 가중치 편향의 변화에 따른 비용 함수 변화량
  """
  a = h_c_diff*(hidden_output*(1-hidden_output))@(input.T) 
  
  b_c = b_diff*(hidden_output*(1-hidden_output)) * b
  return a, b_c
input_c_diff, b2_c_diff = input_c_diff(h1_c_diff, hidden_output,input, w1, b1, b_c_diff1)
input_c_diff
>>>
array([[0.00747633, 0.01495265, 0.02242898],
       [0.00174744, 0.00349488, 0.00524232]])
b2_c_diff_sum = 0
for i in range(b2_c_diff.shape[0]):
  sum += b2_c_diff[i,i]

b2_c_diff_sum
>>>
0.0010990070941353347

그런데 편향에 대한 변화는 왜 대각 행렬만의 합을 사용해야 하는지? 

수식을 보면 입력의 가중치 편향값의 계산은 일자로? 왜지

 

'개념 정리 > implement_python' 카테고리의 다른 글

python_matrix  (0) 2022.11.18
python_probablity_bayesian  (1) 2022.11.05
CNN_python_implement  (0) 2022.11.03