정보공간_1

[6기 부산 박천경] 신경회로망 오류역전파 (Backpropagation) 본문

IT 놀이터/Elite Member Tech & Talk

[6기 부산 박천경] 신경회로망 오류역전파 (Backpropagation)

알 수 없는 사용자 2014. 11. 28. 11:28

안녕하세요 부산 멤버십 박천경 입니다.

저는 마지막 엘리트멤버 포스팅으로 조금 주제를 바꿔서 요즘 인공지능 분야에 각광받는 

기술인 신경회로망을  포스팅 하려고 합니다.

그 중 에서도 오류역전파 (Backpropagation) 알고리즘에 대한 이야기를 들려 드리겠습니다.


앞서 Elite 2기의 이동욱님의 인공신경망 Network에 대한 글과 4기 김한남의 패턴인식에 

대한 글을 읽은 후에 글을 읽어 주신다면 좀더 쉽게 다가올 것이라고 생각됩니다.

저는 이번 신경회로망 오류역전파(Backpropagation) 포스팅에서는 교사학습을 이용한 

단층 정적 신경망과 이것의 단점을 보완 할 수 있는 다층 정적 신경망인 오류역전파에 

대해서 다루어 보겠습니다.


1.단층 정적 신경망 퍼셉트론

1957년 로젠블럿에 의해 소개된 비교적 정확히 기술된 최초의 신경회로망 모델이며 ,

단층 신경망의 기본구조 입니다.

위 그림은 일반적인 퍼셉트론의 기본 구조입니다.

퍼셉트론의 알고리즘  순서도는 다음과 같습니다.


1. 웨이트를 초기화 하고, Learning rate η(0<η<1) 를 설정한다

2. 각 패턴에 대한 패턴쌍(x,D)가 주어진다

3. 신경망의 출력을 계산한다

 

4. O=D이면 다음 2번 과정으로 돌아간다(다음 패턴)

5. 웨이트를 업데이트 한 이후 2번 과정으로 돌아간다(다음 패턴)

6. 전체 패턴이 과정을 거친 후 5번 과정에서 웨이트 변화가 없으면 학습 종료

웨이트 변화가 있을 경우 2번으로 돌아가서 처음 패턴부터 재 학습 한다.



이 단층 정적 신경망에게는 단점이 있습니다 다음과 같은 선형 분리 가능한 

벡터의 집합만을 분리 가능하다는 단점입니다. 

이러한 경우들을 보완하고자 다음 다층 정적 신경망이 나오게 되었습니다.


2. 다층 정적 신경망 오류역전파

오류 역전파 알고리즘은 피드포워드 신경망을 훈련시키는 방법 중 하나로 널리 쓰이는 알고리즘입니다.
피드포워드 신경망은 인공신경망의 한 형태로 입력층, 은닉층, 출력층으로 이루어져 있고,
각 층은 한 개 이상의 뉴런으로 이루어져 있습니다.
선형 분리 불가능한 문제를 선형 분리 가능한 형태로 변환 될 수 있도록 합니다.
또한 3층 구조를 가진 다층 정적 신경망 입니다.
모든 정보는 순방향 신경망의 웨이트에 저장되며, 학습과정 동안 웨이트 행렬 에 저장합니다.


은닉층의 학습을 위해 출력층에서 발생한 오류를 이용하여 은닉층 오차계산 하고,
다시 이 값을 입력층으로 역전파시켜 출력층의 오차가 원하는 수준이 될 때까지 반복합니다.

실제 적용시 고려사항
-최소평균제곱 비용함수의 국부 최적해를 위해 뉴런수를 증가 해야 합니다.
-이득항을 낮출 필요 있습니다.
-초기 가중치를 다르게 하여 여러 번 학습해야 좋은 output 값이 나옵니다.
이렇듯 지도 학습에서 효율성을 나타내기때문에 보편적으로 사용하는 신경회로망입니다.

학습은 크게 3단계로 구성됩니다.
1) 학습 패턴을 입력하여 신경망의 출력을 계산합니다.
2) 출력과 목표값과의 오차를 계산합니다.
3) 오차값을 역방향으로 전파시키면서 연결강도를 변경합니다.



이번에는 출력 산출하는 과정에 대해서 식과 함께 나타내 보겠습니다.
단계 1. 연결강도를 초기화 하고 학습패턴쌍(입력패턴X, 목표치 d)들을 선정한다.
단계 2. 학습률 α 를 설정, 오차의 최대 한계치 Emax를 설정
단계 3. 학습 패턴쌍을 차례로 입력하여 학습
단계 3-1. 은닉층의 NETz을 구한다. 
단계 3-2. 단극성 시그모이드 활성화 함수로 출력 Z를 구한다.

단계 3-3. 출력층의 NETy 을 구한다.
단계 3-4. 단극성 시그모이드 활성화 함수로 출력 Y를 구한다.


단계 3-5. 목표치와 출력값을 비교하여 제곱 오차를 구한다. 
(만약, 모든 출력 노드에서의 오차의 합이 Emax보다 작으면 학습을 종료한다.)
단계 3-6. 출력층의 오차 신호 δy 를 구한다. 
단계 3-7. 은닉층에 전파되는 오차 신호 δz 를 구한다
단계 3-8. 출력층의 오차 신호 δy 를 이용하여 출력층과 은닉층 간의 연결강도 W를 변경한다. 


단계 3-9. 은닉층의 오차 신호 δz 를 이용하여 은닉층과 입력층 간의 연결강도 V를 변경한다. 


단계 4. 더 이상 연결강도가 변경되지 않을 때까지 단계 3을 반복한다. 

이번엔 Backpropagation을 이용하여 AND 연산과 XOR 연산을 C++을 통해서 보여드리겠습니다.

void 훈련(int 훈련개수, double 상한오차, double 학습계수, double **입력, double **목표출력){
int 반복횟수 = 0;

double 오차;

double *은닉 = new double[은닉개수]; // 은닉층 뉴런
double *출력 = new double[출력개수]; // 출력층 뉴런
srand(0);
for(int i = 0;i < 은닉개수;i++){
for(int j = 0;j < 입력개수 + 1;j++){
은닉가중치[i][j] = 2.0 * rand() / RAND_MAX - 1;
}
}
for(int i = 0;i < 출력개수;i++){
for(int j = 0;j < 은닉개수 + 1;j++){
출력가중치[i][j] = 2.0 * rand() / RAND_MAX - 1;
}
}

do{
오차 = 0;
for(int i = 0;i < 훈련개수;i++){
출력계산(입력[i], 은닉, 출력);

// 은닉-출력층 가중치 갱신
for(int j = 0;j < 출력개수;j++){
double 미분값 = (출력[j] - 목표출력[i][j]) * (1 - 출력[j]) * 출력[j];

for(int k = 0;k < 은닉개수;k++){
출력가중치[j][k] -= 학습계수 * 미분값 * 은닉[k];
}
출력가중치[j][은닉개수] -= 학습계수 * 미분값;
}

// 입력-은닉층 가중치 갱신
for(int j = 0;j < 출력개수;j++){
for(int k = 0;k < 은닉개수;k++){
double 미분값 = (출력[j] - 목표출력[i][j]) *
 (1 - 출력[j]) * 출력[j] * 출력가중치[j][k] * 은닉[k] * (1 - 은닉[k]);
for(int l = 0;l < 입력개수;l++){
은닉가중치[k][l] -= 학습계수 * 미분값 * 입력[i][l];
}
은닉가중치[k][입력개수] -= 학습계수 * 미분값;
}
}

// 오차 계산
for(int j = 0;j < 출력개수;j++){
오차 += 0.5 * (출력[j] - 목표출력[i][j]) * (출력[j] - 목표출력[i][j]);
}
}
printf("반복횟수: %d, 오차: %lf\n", ++반복횟수, 오차);
}while(오차 > 상한오차);

delete[] 은닉;
delete[] 출력;
}


신경망을 훈련시키기 위한 함수와 입력과 목표출력에 대한 진리표 입니다.
훈련을 시작할때, 가중치 조절에 출력층 뉴런의 값이 필요하기 때문에 임시로 사용할 은닉층과 출력층을 
생성하고 , 가중치를 무작위 값으로 초기화합니다.
신경망을 훈련시키기 위해서 여러개의 은닉층 뉴런이 필요할 수 있는데, 모든 가중치가 같은 값으로 초기화 
되면 가중치 조정식에 따라 모든 은닉층 뉴런은 같은 위치로 이동하게 됩니다. 
이것은 은닉층 뉴런이 하나 있는 것과 같은 상태이므로, 모든 가중치는 반드시
서로 다른 값으로 초기화 되어야 합니다.


보시는 그림과 같이 위의 진리표와 흡사하게 나타 낼수 있는 것을 확인할 수 있습니다.

마치며, 신경회로망에 대해서 학교에서 공부하고 더욱 궁금한점이 생겨 찾아 봤던 부분이었습니다.

찾아볼수록 재미있었고, Backpropagation 뿐만 아니라 다양한 신경회로망 알고리즘에 대해서

공부해보면 좀 더 재미있는 프로젝트를 할 수 있겠다는 생각이 들었습니다.

제 포스팅은 이것으로 마치겠습니다. 모두들 수고하셨습니다.


Reference

-http://hub-ai.com/annhmmcrt/17009 (HUB AI)