오차 역전파
신경망에서 가중치는 오차 역전파 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 |