본문 바로가기
IT/[Everyday]Coding

딥러닝_Neural Network_퍼셉트론3

by Jang HyunWoong 2014. 12. 19.

지금까지 한 방법은 우리가 이미 알고 있는 답을 input값으로 뉴럴 네트워크에 넣고 값을 예측했다. 

이러한 방법을 지도학습(supervised learning) 이라고 한다. 

 

간단하게

1. 지도학습(supervised learning)

: 우리가 이미 알고있는 훈련데이터로부터 뉴럴 네트워크가 이것을 정확하게 판별하는지 시도하는 것이다. 

예를 들어, 얼굴인식으로 보면, 훈련데이터로 정확한 얼굴 모양과 이름 등 데이터를 가지고 뉴럴 네트워크를 학습시킨다. 

그 후에 데이터를 넣어서 답을 구한다. 이 답이 가지고 있는 훈련데이터와 맞는지, 정확하게 예측했는지 아닌지를 판별한다. 그리고 에러를 조정하 나간다. 

 

2. 자율학습(unsupervised learning)

: 이것은 우리가 알지 못하는 데이터들을 가지고 기계가 스스로 학습해서 찾아가는 것이다. 예를 들어, 사진이라고 한다면, 사진에서 일정한 패턴을 클러스터링(clustering)한다. 이러한 클러스터링해서 나눈 데이터 집단을 통해 우리가 알지 못했던 패턴을 찾아내는 것이다. 

요즘 빅데이터가 뜨면서 자율학습이 효과적으로 증가했다. 많은 데이터가 있을 수록 비슷한 확률을 찾을 수 있기 때문이다. 

 

 

다시 돌아와서...

앞에서 했던 코드를 통해 예측된 값을 얻을 수 있다. 만약에 이 답이 틀린 답이면, 다시 weight를 조정해 가면서 에러를 줄일 수 있다. 

과정을 보면

1. 우리가 알고 있는 데이터 값을 input으로 넣는다.

2. 퍼셉트론으로 예측한 결과를 얻는다. 

3. 예측값이 맞는지 틀린지 에러를 계산한다. 

4. 에러값에 따라 weight를 다시 조정한다. 

5. 1번부터 다시 반복한다. 

 

1번부터 4번까지는 앞의 코드와 같다. 하지만 3번과 4번을 설명하는 코드는 없다. 

그럼 먼저 어떻게 퍼셉트론의 에러를 정의해야 하는 것일까? 또 그 값에 따라 어떻게 weight를 조정해야 할까?

 

먼저 에러의 정의를 보면

 

Error = Desired output - Guessed output / 에러 = 우리가 요구한 output - 퍼셉트론이 예측한 output 

 

이 될 수 있다. 

 

 퍼셉트론에서 나올 수 있는 값은 +1 또는 -1이다. 이 의미는 가능한 에러의 값은 3개이다. 

 

 Desired (요구 값)

Guessed (예측 값)

Error (에러)

-1

-1 

-1

+1 

-2 

+1 

-1 

+2 

+1 

+1 

 

만약 퍼셉트론이 예측한 답이 맞으면, error = -1 - (-1) 에러는 0, 예측한 답이 다르면 -2 or +2가 나올 것이다. 

우리는 이 퍼셉트론의 에러를 통해 weight값을 조정할 수 있다. 

weight의 변화는 델타 weight 라고 부른다Δweight

그래서 새로운 weight 값은

New weight = weight + Δweight

Δweight는 에러와 input값의 곱으로 계산된다. 

Δweight = error * input

그래서

New weight = weight + error * input

으로 정리할 수 있다. 

 

New weight를 통해 올바른 방향(요구 값)으로 가져갈 수 있다. 

 

여기서
New weight = weight + error * input 여기에 추가적으로 learning constant 값을 추가한다. 

곧 새로운 식은

New weight = weight + error * input * learning constant

learning constant를 더하는 이유는 결론적으로 learning rate를 빠르고 정확하게 해주기 위해서 이다. (only my opinion)

높은 learning constant값은 weight의 변화를 급격하게 변화시킨다. 아마도 조금 떠 빠르게 결과 값에 다가갈 수 있을 것이다. 그러나 너무 큰 weight의 변화는 weight overshoot결과를 초래할 수 있다.

반변 작은 learning constant 값이 들어가게 되면 weight를 조정하는데 시간이 걸릴 수 있따. 그 의미는 변화량을 적게 가져가고 연산을 많이 하는것이다. 그렇게 되면 아마도 전체적인 정확도를 높일 수 있을 것이다. 

 

new weight, learning constant 변수를 추가해서 코드를 업데이트 시켜보겠다. 

  1. #include <iostream>
  2. #include <random>
  3. using namespace std;
  4.  
  5. class Perceptron{
  6. float *weights;
  7. float c; 
  8. public:
  9. Perceptron(int n)
  10. {
  11. weights = new float[n];
  12. c = 0.01;
  13. random_device rd;
  14. mt19937_64 mt(rd());
  15. uniform_real_distribution<double> distribution(-1.0, 1.0);
  16. for(int i=0; i<sizeof(weights)-1; i++)
  17. {
  18. weights[i] = distribution(mt);
  19. }
  20. }
  21. int feedforward(float inputs[]){
  22. float sum = 0;
  23. for(int i=0; i<sizeof(weights)-1; i++){
  24. sum += inputs[i]*weights[i];
  25. }
  26. return activate(sum);
  27. }
  28. int activate(float sum){
  29. if(sum>0) return 1;
  30. else return -1;
  31. }
  32. void train(float inputs[], int desired){
  33. int guess = feedforward(inputs);
  34. float error = desired - guess;
  35. for(int i=0; i < sizeof(weights)-1; i++)
  36. {
  37. weights[i] += error * inputs[i] * c;
  38. }
  39. }
  40. };
  41. int main() {
  42. // your code goes here
  43. Perceptron p(3);
  44. float point[] = {10, -15, 1};
  45. int result = p.feedforward(point);
  46. cout << result << endl;
  47. return 0;
  48. }

 

line 7 : learning constant 를 변수 c로 추가했다. 

line 12 : 생성자에서 값을 0.01로 정했다. 

line 32-39 : new weight를 train시키기 위한 함수를 만들었다. 우리가 알고 있는 데이터에 대해서 새로운 weight값을 맞춰나가는 것이다. 

 

퍼셉트론을 훈련시키기 위해서는 우리는 이미 알고 있는 값을 input으로 넣어 주어야 한다. 그래서 새로운 클래스를 하나 만들었다. 

  1. class Trainer{
  2. float *inputs;
  3. int answer;
  4.  
  5. Trainer(float x, float y, int a){
  6. inputs = new float[3];
  7. inputs[0] = x;
  8. inputs[1] = y;
  9. inputs[2] = 1;
  10. answer = a;
  11. }
  12. };
  13.  

 

이 코드는 supervised learning으로 미리 값을 넣어 둔 상태이다. 

 

반응형