기계학습

오류 역전파 알고리즘

Artificial Neural Network 조회 수 22554 추천 수 0 2014.08.14 17:03:58

오류 역전파 알고리즘은 피드포워드 신경망을 훈련시키기 위한 알고리즘 중 하나인데, 논문이나 글 등에서 신경망의 훈련방법에 대한 언급이 없으면 오류 역전파 알고리즘으로 훈련시켰다고 보면 될 정도로 지배적으로 쓰이는 알고리즘입니다.

 

피드포워드 신경망 1.png

 

피드포워드 신경망은 인공신경망의 한 형태로 입력 층, 은닉층, 출력층으로 이루어져 있고 각 층은 한 개 이상의 뉴런으로 이루어져 있습니다. 뉴런끼리는 가중치로 연결되는데, 이웃한 층에 있는 뉴런과 연결되며, 동일한 층에 있거나 두 층 이상 떨어져 있는 뉴런과는 연결되지 않습니다. 여기서 사용하는 신경망은 다층 퍼셉트론으로 이웃한 층의 모든 뉴런이 서로 연결되어 있는 것이 특징인 신경망입니다.

 

피드포워드 신경망은 입력층 -> 은닉층 -> 출력층으로 계산이 진행되는데, 은닉층의 각 뉴런의 값은 다음과 같이 구합니다.

 

%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%3D%5Csum%20_%7B%20i%3D1%20%7D%5E%7B%20I%20%7D%7B%20%5Ccombi%20_%7B%20i%20%7D%7B%20x%20%7D%20%7D%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20

%5Ccombi%20_%7B%20j%20%7D%7B%20h%20%7D%3Df%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20

 

여기서 I는 입력층에 있는 뉴런의 개수이고, f는 활성함수입니다.

활성함수는 신경망의 출력을 곡선의 형태로 바꾸어, 연속적이며 미분가능하도록 만들어주는 함수입니다.

이 함수를 사용하는 이유는 신경망을 훈련시킬 때 미분을 이용하기 때문입니다.

사용할 수 있는 활성함수로는 여러가지가 있지만, 여기서는 로지스틱 시그모이드 함수를 사용합니다.

 

f(x).png

 

f(x)%3D%5Cfrac%20%7B%201%20%7D%7B%201%2B%5Ccombi%20%5E%7B%20-x%20%7D%7B%20e%20%7D%20%7D%20

f%5Cquad%20'(x)%3D%5Cfrac%20%7B%20-g%5Cquad%20'(x)%20%7D%7B%20%5Ccombi%20%5E%7B%202%20%7D%7B%20g%20%7D(x)%20%7D%3D%5Cfrac%20%7B%20%5Ccombi%20%5E%7B%20-x%20%7D%7B%20e%20%7D%20%7D%7B%20%5Ccombi%20%5E%7B%202%20%7D%7B%20(1%2B%5Ccombi%20%5E%7B%20-x%20%7D%7B%20e%20%7D)%20%7D%20%7D%3D%5Cleft(%20%5Cfrac%20%7B%20%5Cleft(%201%2B%5Ccombi%20%5E%7B%20-x%20%7D%7B%20e%20%7D%20%5Cright)%20-1%20%7D%7B%201%2B%5Ccombi%20%5E%7B%20-x%20%7D%7B%20e%20%7D%20%7D%20%5Cright)%20%5Ccdot%20%5Cleft(%20%5Cfrac%20%7B%201%20%7D%7B%201%2B%5Ccombi%20%5E%7B%20-x%20%7D%7B%20e%20%7D%20%7D%20%5Cright)%20%3D%5Cleft(%201-%5Cfrac%20%7B%201%20%7D%7B%201%2B%5Ccombi%20%5E%7B%20-x%20%7D%7B%20e%20%7D%20%7D%20%5Cright)%20%5Ccdot%20%5Cleft(%20%5Cfrac%20%7B%201%20%7D%7B%201%2B%5Ccombi%20%5E%7B%20-x%20%7D%7B%20e%20%7D%20%7D%20%5Cright)%20%3D(1-f(x))%5Ccdot%20f(x)%20

 

각 출력층 뉴런의 값은 다음과 같이 구합니다.

 

%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%3D%5Csum%20_%7B%20j%3D1%20%7D%5E%7B%20J%20%7D%7B%20%5Ccombi%20_%7B%20j%20%7D%7B%20h%20%7D%20%7D%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20

%5Ccombi%20_%7B%20k%20%7D%7B%20y%20%7D%3Df%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20

 

여기서 J는 은닉층에 있는 뉴런의 개수입니다.

 

신경망의 입력층에 특정 벡터를 입력했을 때 원하는 출력 벡터를 얻으려면 가중치를 조정하여 신경망을 훈련시켜야 하는데, 이 때 오류 역전파 알고리즘이 사용됩니다.

오류 역전파 알고리즘은 가중치 조정량을 구하기 위해 주어진 입력에 대한 출력과 목표출력을 이용해서 오차 E를 구합니다.

 

E%3D%5Csum%20_%7B%20p%3D1%20%7D%5E%7B%20P%20%7D%7B%20%5Ccombi%20_%7B%20p%20%7D%7B%20E%20%7D%20%7D%20

 

여기서 P는 훈련에 사용 할 입력-목표출력 패턴의 개수입니다.

 

%5Ccombi%20_%7B%20p%20%7D%7B%20E%20%7D%3D%5Csum%20_%7B%20k%3D1%20%7D%5E%7B%20K%20%7D%7B%20%5Cfrac%20%7B%201%20%7D%7B%202%20%7D%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20%5Ccombi%20_%7B%20pk%20%7D%7B%20y%20%7D-%5Ccombi%20_%7B%20pk%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%20%7D%20

 

여기서 K는 출력층 뉴런의 개수이고, %5Ccombi%20_%7B%20pk%20%7D%7B%20y%20%7D%20는 p번째 패턴의 k번째 출력층 뉴런의 출력 값, %5Ccombi%20_%7B%20pk%20%7D%7B%20t%20%7D%20는 패턴 p의 k번째 출력층 뉴런의 목표출력입니다. 예를 들어, AND 연산과 XOR 연산을 동시에 할 수 있는 신경망을 만들고자 한다면,

 

 

패턴 입력 목표출력
1 (0, 0) (0, 0)
2 (0, 1) (0, 1)
3 (1, 0) (0, 1)
4 (1, 1) (1, 0)

 

이 표의 내용으로 신경망을 훈련시켜야 합니다.

패턴 1은 %5Ccombi%20_%7B%201%20%7D%7B%20i%20%7D%20에 0, %5Ccombi%20_%7B%202%20%7D%7B%20i%20%7D%20에 0을 입력값으로 넣고 계산했을 때,​ %5Ccombi%20_%7B%201%20%7D%7B%20y%20%7D%20 값으로 0, %5Ccombi%20_%7B%202%20%7D%7B%20y%20%7D%20의 값으로 0이 나오고,

패턴 2는 %5Ccombi%20_%7B%201%20%7D%7B%20i%20%7D%20에 0, %5Ccombi%20_%7B%202%20%7D%7B%20i%20%7D%20에 1을 입력값으로 넣고 계산했을 때,​ %5Ccombi%20_%7B%201%20%7D%7B%20y%20%7D%20 값으로 0, %5Ccombi%20_%7B%202%20%7D%7B%20y%20%7D%20의 값으로 1이 나오도록 하겠다는 의미입니다.

이 때, 입력층 뉴런의 개수 I는 3, 출력층 뉴런의 개수 K는 2, 훈련 패턴의 개수 P는 4가 됩니다.

 

입력값은 2개인데 왜 I가 3인가 하면, 피드포워드 신경망의 출력층을 제외한 층에는 bias 뉴런이 있기 때문입니다.

bias 뉴런은 모든 패턴에 대해 1의 고정된 값을 가진 추가적인 뉴런입니다.

이 뉴런은 입력 벡터에 상관없이 고정된 상수를 가지고 있기 때문에 함수의 모양에 영향을 주지 않으면서 위치를 조정할 수 있습니다. 

 

f(x-2).png f(x).png f(x+2).png

 

왼쪽부터 f(x-2), f(x), f(x+2)

 

bias 뉴런을 고려하여 위의 표의 패턴을 훈련시키기 위한 최적의 신경망은 다음과 같습니다.

 

 

 %5Ccombi%20_%7B%203%20%7D%7B%20x%20%7D%20과 %5Ccombi%20_%7B%203%20%7D%7B%20h%20%7D%20bias 뉴런입니다.​ bias 뉴런은 값이 이미 정해져 있으므로 이전 층의 뉴런과는 가중치로 연결되어 있지 않고,

다음 층의 bias 뉴런을 제외한 모든 뉴런의 값을 구하는데는 참여합니다.

 

그런데 우리는 은닉 층 뉴런의 개수를 정할 필요가 있습니다. 이것은 신경망을 훈련시키는데 있어서 중요한 요소인데,

각 은닉층 뉴런의 값을 구하는 식에서 시그모이드 함수에 대입하기 전의 식은 1차방정식임을 알 수 있습니다.

 

%5Ccombi%20_%7B%20j%20%7D%7B%20s%20%7D%3D%5Ccombi%20_%7B%201%20%7D%7B%20x%20%7D%5Ccombi%20_%7B%201j%20%7D%7B%20w%20%7D%2B%5Ccombi%20_%7B%202%20%7D%7B%20x%20%7D%5Ccombi%20_%7B%202j%20%7D%7B%20w%20%7D%2B...%2B%5Ccombi%20_%7B%20i%20%7D%7B%20x%20%7D%5Ccombi%20_%7B%20ij%20%7D%7B%20w%20%7D%20

 

이것은 선형 함수로써 신경망에서 공간을 분리하는 역할을 합니다.

예를들어, 다음의 매우 간단한 패턴을 훈련시키고자 한다면,

 

패턴

입력

목표출력

1

0

0

2

0.33

1

3

0.67

1

4

1

0

 

이것은 다음을 만족하는 함수를 만드는 것과 같습니다.

y = g(x)

0 = g(0), 1 = g(0.33), 1 = g(0.67), 0 = g(1)

 

이 패턴을 따르도록 신경망을 훈련시키기 위해서는 2개의 입력층 뉴런(값을 입력받는 뉴런과 bias 뉴런)과 하나의 출력층 뉴런을 가진 신경망이 필요합니다. 여기서 은닉층 뉴런은 bias 뉴런을 포함하여 3개가 필요한데, 위 표의 패턴을 그래프로 나타내 보면 다음과 같습니다.

 

패턴 1.png

 

 

만약 bias 뉴런을 제외한 은닉층 뉴런이 1개라면 신경망은 하나의 방정식으로 이 패턴을 따르도록 신경망을 훈련시킵니다.​

 

패턴 2.png

 

은닉층 뉴런은 방정식에 시그모이드 함수를 씌운 형태인데, 점 A와 B, C, D로 공간을 두개로 분리했으나 이것으로는 오차를 최소화 시킬 수 없습니다. 오차가 0이 아닌 값에 수렴하여 더 이상 감소하지 않는 경우에 지역 최소값에 수렴했다고 하는데, 이 경우에는 은닉층 뉴런의 개수를 늘려주어야 합니다.​

 


패턴 3.png

 

은닉층 뉴런을 하나 추가한 모습입니다.

검은색 선은 점 A와 점 B, C, D로 공간을 분리했고, 빨간색 선은 점 A, B, C와 D로 공간을 분리하여 최종적으로 (A), (B, C), (D)로 공간이 세개로 분리되었습니다. 여기가까지 입력-은닉층의 역할입니다.

 

검은색 선인 첫번째 은닉층 뉴런을 g(x)로 정의하고 빨간색 선인 두번째 은닉층 뉴런을 h(x)로 정의하겠습니다.

 

g(x)%3Df%5Cleft(%20%5Ccombi%20_%7B%201%20%7D%7B%20x%20%7D%5Ccdot%2040%2B1%5Ccdot%20%5Cleft(%20-6.5%20%5Cright)%20%20%5Cright)%20%20

h(x)%3Df%5Cleft(%20%5Ccombi%20_%7B%201%20%7D%7B%20x%20%7D%5Ccdot%20%5Cleft(%20-40%20%5Cright)%20%2B1%5Ccdot%2033.5%20%5Cright)%20%20

 

언뜻 보기에는 패턴을 따르는 듯 하지만 y(0) = g(0) + h(0) = 0 + 1 = 1로 우리가 원하는 목표출력은 0인데 1이 나와버립니다.

이것을 은닉-출력 층에서 조절합니다. 출력 뉴런은 각 은닉 뉴런에 가중치를 곱한 값을 얻기 때문에, 다음과 같은 형태로 나타낼 수 있습니다.

 

 

%5Ccombi%20_%7B%201%20%7D%7B%20y%20%7D(x)%3Df%5Cleft(%20g(x)%5Ccombi%20_%7B%2011%20%7D%7B%20w%20%7D%2Bh(x)%5Ccombi%20_%7B%2021%20%7D%7B%20w%20%7D%2B1%5Ccdot%20%5Ccombi%20_%7B%2031%20%7D%7B%20w%20%7D%20%5Cright)%20%20

 

적절한 가중치는 다음과 같습니다

%5Ccombi%20_%7B%201%20%7D%7B%20y%20%7D(x)%3Df%5Cleft(%20g(x)%5Ccdot%2010%2Bh(x)%5Ccdot%2010%2B1%5Ccdot%20(-15)%20%5Cright)%20%20

 

그래프로 나타내면 다음과 같습니다.


패턴 4.png

 

신경망이 패턴을 따르도록 성공적으로 훈련시켰습니다.

이렇듯 은닉 뉴런의 개수는 훈련에 중요한 요소이나, 성공적으로 훈련시키기 위해서 정확히 몇 개가 필요한지는 알 수 없습니다.

보통 개수를 늘려가면서 오차가 충분히 작은 결과가 나오는 신경망을 사용합니다.

 

다시 오차를 구한 시점으로 돌아와서, 오류 역전파 알고리즘은 위의 방법으로 구한 오차를 가중치로 미분하여 오차를 감소시키는 방향으로 가중치를 조정합니다.

 

w(t%2B1)%5Cgets%20w(t)-%5Ceta%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20w(t)%20%7D%20

여기서 %5Ceta%20%20는 학습률로 가중치 조정량의 크기를 결정합니다.

입력층과 은닉층을 연결하는 은닉층 가중치 %5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20은 다음과 같이 조정됩니다.

 

%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D(t%2B1)%3D%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D(t)-%5Ceta%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D(t)%20%7D%20

 

오차는 출력과 목표출력으로 이루어져 있어 바로 가중치로 미분할 수 없기 때문에 미분의 연쇄법칙을 이용합니다.​

 

 

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%5Cfrac%20%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%7D%5Cfrac%20%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20%7D%20

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Csum%20_%7B%20k%3D1%20%7D%5E%7B%20K%20%7D%7B%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%5Cfrac%20%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%5Cfrac%20%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%20%7D%20

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20%5Cfrac%20%7B%201%20%7D%7B%202%20%7D%5Cleft%5C%7B%20%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%201%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%201%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%2B%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%202%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%202%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%2B...%2B%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%20%5Cright%5C%7D%20%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20%5Cfrac%20%7B%201%20%7D%7B%202%20%7D%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3Df%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20

%5Cfrac%20%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%3Df%5Cquad%20'%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%3D%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cfrac%20%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%201%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccombi%20_%7B%201k%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%2Bf%5Cleft(%20%5Ccombi%20_%7B%202%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccombi%20_%7B%202k%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%2B...%2Bf%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20

 

%5Ctherefore%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Csum%20_%7B%20k%3D1%20%7D%5E%7B%20K%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cright)%20%5Ccdot%20%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccdot%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%20

%5Cfrac%20%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%7D%3Df%5Cquad%20'%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%3D%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20

%5Cfrac%20%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20%5Cleft(%20%5Ccombi%20_%7B%201%20%7D%7B%20x%20%7D%5Ccombi%20_%7B%201j%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%2B%5Ccombi%20_%7B%202%20%7D%7B%20x%20%7D%5Ccombi%20_%7B%202j%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%2B...%2B%5Ccombi%20_%7B%20i%20%7D%7B%20x%20%7D%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20%5Ccombi%20_%7B%20i%20%7D%7B%20x%20%7D%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20%7D%3D%5Ccombi%20_%7B%20i%20%7D%7B%20x%20%7D%20

 

%5Ctherefore%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20%7D%3D%5Cleft%5C%7B%20%5Csum%20_%7B%20k%3D1%20%7D%5E%7B%20K%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cright)%20%5Ccdot%20%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccdot%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%20%5Cright%5C%7D%20%5Ccdot%20%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccdot%20%5Ccombi%20_%7B%20i%20%7D%7B%20x%20%7D%20

 

이것이 %5Ccombi%20_%7B%20ij%20%7D%5E%7B%20H%20%7D%7B%20w%20%7D%20를 조정하기 위해 사용되는 식입니다.

다음으로, 은닉층과 출력층을 연결하는 출력층 가중치 %5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20은 다음과 같이 조정됩니다.

 

%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D(t%2B1)%3D%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D(t)-%5Ceta%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D(t)%20%7D%20

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%5Cfrac%20%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%5Cfrac%20%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20%5Cfrac%20%7B%201%20%7D%7B%202%20%7D%5Cleft%5C%7B%20%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%201%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%201%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%2B%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%202%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%202%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%2B...%2B%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%20%5Cright%5C%7D%20%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20%5Cfrac%20%7B%201%20%7D%7B%202%20%7D%5Ccombi%20%5E%7B%202%20%7D%7B%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cright)%20%20%7D%20%7D%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%3Df%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cfrac%20%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%3Df%5Cquad%20'%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%3D%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20

%5Cfrac%20%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%201%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccombi%20_%7B%201k%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%2Bf%5Cleft(%20%5Ccombi%20_%7B%202%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccombi%20_%7B%202k%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%2B...%2Bf%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%5Cright)%20%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%3Df%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20

 

 %5Ctherefore%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%3D%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cright)%20%5Ccdot%20%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%5Ccdot%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20H%20%7D%7B%20s%20%7D%20%5Cright)%20%20

 

이것은 %5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20조정하기 위해 사용되는 식입니다.​

 

여기서 우리는 한가지 특징을 발견할 수 있는데, 바로 은닉층 가중치의 조정식이 출력층 가중치의 조정식을 대부분 포함한다는 점입니다.

이 점을 이용하여 우리는 가중치 조정식을 미분의 연쇄법칙을 이용하여 일일이 계산하지 않고도 구할 수 있습니다.

그 예로 여기서 3개의 은닉층을 가진 신경망의 가중치 조정식을 구해보겠습니다.

먼저 출력층 가중치의 조정식은 다음과 같이 나타낼 수 있습니다.

 

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%3D%5Cleft(%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20-%5Ccombi%20_%7B%20k%20%7D%7B%20t%20%7D%20%5Cright)%20%5Ccdot%20%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%5Cright)%20%20

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%5Ccdot%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20

 

그러면 세번째 은닉층 가중치의 조정식은 다음과 같습니다.

 

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%7D%3D%5Cleft%5C%7B%20%5Csum%20_%7B%20k%3D1%20%7D%5E%7B%20K%20%7D%7B%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20k%20%7D%5E%7B%20O%20%7D%7B%20s%20%7D%20%7D%5Ccdot%20%5Ccombi%20_%7B%20jk%20%7D%5E%7B%20O%20%7D%7B%20w%20%7D%20%7D%20%5Cright%5C%7D%20%5Ccdot%20%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20H%20%7D%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%7D%5Ccdot%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20

 

두번째 은닉층 가중치의 조정식:

 

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%7D%3D%5Cleft%5C%7B%20%5Csum%20_%7B%20j%3D1%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20J%20%7D%20%7D%7B%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%7D%5Ccdot%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20%5Ccombi%20_%7B%203%20%7D%7B%20H%20%7D%20%7D%7B%20w%20%7D%20%7D%20%5Cright%5C%7D%20%5Ccdot%20%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20H%20%7D%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%7D%5Ccdot%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%201%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20

 

첫번째 은닉층 가중치의 조정식:

 

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%201%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%7D%3D%5Cleft%5C%7B%20%5Csum%20_%7B%20j%3D1%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20J%20%7D%20%7D%7B%20%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%7D%5Ccdot%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20%5Ccombi%20_%7B%202%20%7D%7B%20H%20%7D%20%7D%7B%20w%20%7D%20%7D%20%5Cright%5C%7D%20%5Ccdot%20%5Cleft(%201-f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%201%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20%5Cright)%20f%5Cleft(%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%201%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%5Cright)%20%20

%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20ij%20%7D%5E%7B%20%5Ccombi%20_%7B%201%20%7D%7B%20H%20%7D%20%7D%7B%20w%20%7D%20%7D%3D%5Cfrac%20%7B%20%5Cpartial%20E%20%7D%7B%20%5Cpartial%20%5Ccombi%20_%7B%20j%20%7D%5E%7B%20%5Ccombi%20_%7B%201%20%7D%7B%20H%20%7D%20%7D%7B%20s%20%7D%20%7D%5Ccdot%20%5Ccombi%20_%7B%20i%20%7D%7B%20x%20%7D%20

 

이 방법의 장점은 중복되는 계산을 하지 않기 때문에 컴퓨터가 가중치를 최대한 빠르게 조정할 수 있다는 것입니다.

 

이제 구한 식을 이용하여 오류 역전파 알고리즘을 C++로 구현해 보겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
 
class Feedforward_Neural_Networks{
private:
    int num_input;
    int num_hidden;
    int num_output;
 
    double **hidden_weight;
    double **output_weight;
 
    void Compute_Output(double input[], double hidden[], double output[]){...}
 
public:
    Feedforward_Neural_Networks(int num_input, int num_hidden, int num_output){...}
    ~Feedforward_Neural_Networks(){...}
 
    void Test(double input[], double output[]){...}
    void Train(int num_train, double learning_rate, double **input, double **target_output){...}
};
 
void main(){...}
cs

 

소스코드의 전체적인 모습니다.

신경망을 사용할 때는 입력층과 출력층만을 제시하며, 나머지 은닉층과 모든 가중치는 클래스 안에 있습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Feedforward_Neural_Networks(int num_input, int num_hidden, int num_output){
    this->num_input  = num_input;
    this->num_hidden = num_hidden;
    this->num_output = num_output;
 
    output_weight = new double*[num_output];
    for(int i = 0;i < num_output;i++){
        output_weight[i] = new double[num_hidden + 1];
    }
    hidden_weight = new double*[num_hidden];
    for(int i = 0;i < num_hidden;i++){
        hidden_weight[i] = new double[num_input + 1];
    }
}
cs

 

 

클래스를 생성할 때 사용자로부터 각 층 뉴런의 개수를 입력받고, 그 개수만큼 은닉층 뉴런과 가중치를 생성합니다.

개수를 입력받을 때, 사용자가 bias 뉴런을 고려하지 않았다고 가정하고 입력받은 개수에 1을 더해서 가중치를 생성합니다.

 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
void Train(int num_train, double learning_rate, double **input, double **target_output){
    int num_epoch = 0;
    int max_epoch = 10000;
 
    double *hidden            = new double[num_hidden];
    double *hidden_derivative = new double[num_hidden];
    double *output            = new double[num_output];
    double *output_derivative = new double[num_output];
 
    srand(0);
    for(int i = 0;i < num_hidden;i++){
        for(int j = 0;j < num_input + 1;j++){
            hidden_weight[i][j] = 0.2 * rand() / RAND_MAX - 0.1;
        }
    }
    for(int i = 0;i < num_output;i++){
        for(int j = 0;j < num_hidden + 1;j++){
            output_weight[i][j] = 0.2 * rand() / RAND_MAX - 0.1;
        }
    }
 
    do{
        double error = 0;
 
        for(int i = 0;i < num_train;i++){
            Compute_Output(input[i], hidden, output);
 
            // 출력미분값 계산
            for(int j = 0;j < num_output;j++){
                output_derivative[j] = learning_rate * (output[j] - target_output[i][j]) * (1 - output[j]) * output[j];
            }
 
            // 출력가중치 조정
            for(int j = 0;j < num_output;j++){
                for(int k = 0;k < num_hidden;k++){
                    output_weight[j][k] -= output_derivative[j] * hidden[k];
                }
                output_weight[j][num_hidden] -= output_derivative[j];
            }
 
            // 은닉미분값 계산
            for(int j = 0;j < num_hidden;j++){
                double sum = 0;
 
                for(int k = 0;k < num_output;k++){
                    sum += output_derivative[k] * output_weight[k][j];
                }
                hidden_derivative[j] = sum * (1 - hidden[j]) * hidden[j];
            }
 
            // 은닉가중치 조정
            for(int j = 0;j < num_hidden;j++){
                for(int k = 0;k < num_input;k++){
                    hidden_weight[j][k] -= hidden_derivative[j] * input[i][k];
                }
                hidden_weight[j][num_input] -= hidden_derivative[j];
            }
 
            // 오차 계산
            for(int j = 0;j < num_output;j++){
                error += 0.5 * (output[j] - target_output[i][j]) * (output[j] - target_output[i][j]);
            }
        }
        if(num_epoch % 500 == 0){
            printf("반복횟수: %d, 오차: %lf\n", num_epoch, error);
        }
    }while(num_epoch++ < max_epoch);
 
    delete[] hidden;
    delete[] output;
}
cs

 

훈련을 시작할 때, 가중치 조절에 은닉층과 출력층 뉴런의 값이 필요하기 때문에 임시로 사용할 층을 생성하고, 가중치를 무작위 값으로 초기화합니다. 신경망을 훈련시키기 위해서 여러 개의 은닉층 뉴런이 필요할 수 있는데, 뉴런이 서로 다른 가중치를 갖도록 초기화하지 않으면 가중치 조정식에 따라 모든 은닉층 뉴런은 계속해서 동일한 가중치를 갖게 됩니다. 이것은 은닉층 뉴런이 하나만 있는 것과 마찬가지로, 지역 최소값에 수렴하는 원인이 되므로 반드시 각각의 뉴런이 다른 가중치를 갖도록 초기화해야 합니다.

 

은닉층 뉴런과 출력층 뉴런의 값을 계산 한 뒤 가중치를 조정합니다. 가중치 조정식을 참고하시기 바랍니다.

bias 뉴런은 계산할 필요가 없어 만들어 두지 않았으므로 bias 뉴런과 연결된 가중치 'output_weight[j][num_hidden]', 'hidden_weight[j][num_input]'는 따로 계산합니다. 전체적인 식은 같고 단지 뉴런 값으로 1을 사용하면 됩니다.

가중치 조정하는 과정을 10,000번 반복합니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Compute_Output(double input[], double hidden[], double output[]){
    for(int i = 0;i < num_hidden;i++){
        double sum = 0;
 
        for(int j = 0;j < num_input;j++){
            sum += input[j] * hidden_weight[i][j];
        }
        sum += hidden_weight[i][num_input];
        hidden[i] = 1 / (1 + exp(-sum));
    }
    for(int i = 0;i < num_output;i++){
        double sum = 0;
 
        for(int j = 0;j < num_hidden;j++){
            sum += hidden[j] * output_weight[i][j];
        }
        sum += output_weight[i][num_hidden];
        output[i] = 1 / (1 + exp(-sum));
    }
}
cs

 

가중치 조정을 위해 은닉층 뉴런과 출력층 뉴런의 값을 계산합니다.

각 뉴런은 이전 층의 모든 뉴런과 가중치를 곱한 값의 합에 시그모이드 함수를 씌운 값을 가집니다.

 

 

1
2
3
4
5
6
7
void Test(double input[], double output[]){
    double *hidden = new double[num_hidden];
 
    Compute_Output(input, hidden, output);
 
    delete[] hidden;
}
cs

 

훈련이 끝난 뒤 시험해 보기 위해서는 입력을 제시한 뒤 출력을 계산하면 됩니다.

 

 

1
2
3
4
5
6
7
8
9
10
~Feedforward_Neural_Networks(){
    for(int i = 0;i < num_output;i++){
        delete[] output_weight[i];
    }
    for(int i = 0;i < num_hidden;i++){
        delete[] hidden_weight[i];
    }
    delete[] hidden_weight;
    delete[] output_weight;
}
cs

 

신경망을 제거할 때 할당한 메모리를 해제합니다.

 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
void main(){
    int num_input  = 2;
    int num_hidden = 2;
    int num_output = 2;
    int num_train  = 4;
 
    double learning_rate = 0.1;
 
    double **input         = new double*[num_train];
    double **target_output = new double*[num_train];
 
    Feedforward_Neural_Networks *FNN = new Feedforward_Neural_Networks(num_input, num_hidden, num_output);
 
    for(int i = 0;i < num_train;i++){
        input[i]         = new double[num_input];
        target_output[i] = new double[num_output];
    }
 
    input[0][0= 0;    input[0][1= 0;
    input[1][0= 0;    input[1][1= 1;
    input[2][0= 1;    input[2][1= 0;
    input[3][0= 1;    input[3][1= 1;
 
    target_output[0][0= 0;    target_output[0][1= 0;
    target_output[1][0= 0;    target_output[1][1= 1;
    target_output[2][0= 0;    target_output[2][1= 1;
    target_output[3][0= 1;    target_output[3][1= 0;
 
    FNN->Train(num_train, learning_rate, input, target_output);
 
    for(int i = 0;i < num_train;i++){
        double *output = new double[num_output];
 
        printf("입력: ", i);
        for(int j = 0;j < num_input;j++){
            printf("%lf ", input[i][j]);
        }
        FNN->Test(input[i], output);
 
        printf("출력:");
        for(int j = 0;j < num_output;j++){
            printf(" %lf", output[j]);
        }
        printf("\n");
 
        delete[] output;
    }
    for(int i = 0;i < num_train;i++){
        delete[] input[i];
        delete[] target_output[i];
    }
    delete[] input;
    delete[] target_output;
    delete FNN;
}
cs

 

main 함수입니다. 신경망을 이용하여 첫번째 출력층 뉴런에 AND연산을, 두번째 출력층 뉴런에 XOR연산을 훈련시키는 모습입니다.

 

 

 결과 출력.png

 

출력이 정확히 0과 1이 나오려면 오차가 0이 될 때까지 반복하면 되지만 훈련이 진행될수록 오차가 급격히 천천히 감소하기 때문에, 일반적으로 출력이 0에 가까우면 0으로 취급하고 1에 가까우면 1로 취급하는 방법을 사용합니다.

 

소스파일을 Feedforward Neural Networks.cpp로 파일 첨부하였습니다.

 

profile

HUB

2014.08.14 23:17:41
*.222.20.180

정말 좋은 강의 잘 봤습니다. 


사막의 오아시스같은 느낌입니다. ^^..


저도 열심히 글을 써 올려야 되는데 지금 하고 있는 프로젝트때문에 어쩔수 없이 잠시 활동을 못하고있네요 ... ㅜㅜ..


프로젝트 완료후 얼른 복귀해야겠어요 ㅎㅎ.. 감사합니다.

종이눈

2014.08.15 12:45:36
*.46.149.68

인공지능 관련된 커뮤니티는 지금도 여기밖에 없는 것 같지만...


이런 작은 지식이라도 계속 쌓아가다 보면 언젠가는 왠만한 인공지능 정보는 다 포함하고 있는 인공지능 커뮤니티가 될 수 있지 않을까 기대합니다.

profile

HUB

2014.08.15 14:07:09
*.222.20.180

그렇게 될 수 있도록 노력해야겠습니다.  :D


뿌우웅

2016.08.07 19:50:40
*.107.232.104

정말 좋은 글 감사드립니다. 질문이 있습니다.

위 예제 코드에서는 은닉층이 한층인것이 맞는지요?

종이눈

2016.10.08 12:03:46
*.161.255.7

네. 설명을 간단하게 하기 위해서 하나의 은닉층만을 사용했습니다.

구너도

2017.02.09 19:02:21
*.91.137.51

좋은 글 잘봤습니다. 한가지 궁금한게 있습니다.

중간에 아래와 같은 말이 잘이해가 안가는데요.

"검은색 선은 점 A와 점 B, C, D로 공간을 분리했고, 빨간색 선은 점 A, B, C와 D로 공간을 분리하여 최종적으로 (A), (B, C), (D)로 공간이 세개로 분리되었습니다.

좀 더 설명을 해주실 수 있나요?

List of Articles
번호 제목 글쓴이 날짜 조회 수
35 Artificial Neural Network lim님께서 올려주신 좋은 문제 풀이입니다. file [5] HUB 2014-11-02 1236
34 전체 기계학습을 이해하기 좋게 정리해 놓은 블로그 HUB 2014-09-18 1998
33 Hidden Markov Model HMM 쉽게 정리해놓은 글 HUB 2014-09-15 974
32 전체 DBN 작동원리 HUB 2014-09-03 1093
31 전체 DBN에 대한 설명 HUB 2014-08-29 1057
30 전체 Java로 작성된 머신러닝 라이브러리 HUB 2014-08-27 1610
» Artificial Neural Network 오류 역전파 알고리즘 file [6] 종이눈 2014-08-14 22554
28 전체 그래프의 비밀 (Programming Game AI by Example) [슬라이드 쉐어 펌] HUB 2014-07-10 1872
27 전체 단국대 교수님께서 인터넷에 공유하신 패턴 인식에 대한 PPT라고 합니다. file HUB 2014-07-10 1870
26 전체 패턴인식의 정의와 관련해 정리되어 있는 사이트[펌] HUB 2014-07-10 1466
25 전체 영상 데이터의 처리와 정보의 추출 [슬라이드쉐어 펌] HUB 2014-07-10 1403
24 Hidden Markov Model HMM이란? HUB 2014-07-09 1587
23 전체 1.2 기계학습(Machine Learning)이란? HUB 2014-07-07 2027
22 Artificial Neural Network 괜찮은 MLP 오픈소스 HUB 2014-07-07 1297
21 전체 딥러닝 관련 JAVA 소스코드 HUB 2014-07-06 3639
20 Support Vector Machine 자바 코드로 이루어진 SVM 라이브러리 + 오픈소스 HUB 2014-06-08 2759
19 Support Vector Machine SVM 설명 프리젠테이션 HUB 2014-06-08 2388
18 Support Vector Machine SVM 오픈소스 및 개요 file HUB 2014-06-08 3270
17 Support Vector Machine Support Vector Machine HUB 2014-06-08 2952
16 전체 1.1 패턴인식과 기계학습 HUB 2014-04-08 4847

로그인

로그인폼

로그인 유지