티스토리 뷰

딥러닝

딥러닝 - 03. 퍼셉트론

김한성 2019. 2. 12. 23:48

1. 퍼셉트론


퍼셉트론은 프랑크 로젠블라트가 1957년에 고안한 알고리즘입니다. 고대 화석 같은 이 알고리즘을 지금 시점에 왜 배우는가 하면, 퍼셉트론이 신경망(딥러닝)의 기원이 되는 알고리즘이기 때문입니다.


퍼셉트론은 다수의 신호를 입력으로 받아 하나의 신호를 출력합니다. 신호는 '1이나 0' 두가지 값을 가질 수 있습니다.

[그림 1]

[그림 1]은 입력으로 2개의 신호를 받은 퍼셉트론의 예입니다. x1과 x2는 입력신호, y는 출력 신호, w1과 w2는 가중치를 뜻합니다.

그림의 원을 뉴런 혹은 노드라고 부릅니다.

입력 신호가 뉴런에 보내질 때는 각각 고유한 가중치가 곱해집니다(w1* x1, w2 * x2)

뉴런에서 보내온 신호의 총합이 정해진 한계를 넘는다면? 1을 출력합니다.


이를 [공식 1]으로 풀면 아래처럼 아주 간단하게 나옵니다.


[공식 1]

               

2. 퍼셉트론을 이해하는데 필요한 논리 회로


2-1. AND 게이트

논리 회로를 알아보는 첫걸음으로 AND 게이트를 살펴보겠습니다. AND 게이트는 입력이 둘이고 출력은 하나입니다. [그림 2]와 같은 입력 신호와 출력 신회의 대응 표를 진리표라고 합니다. 


x1

x2 

0

 0 

 0 

1

0

0

 0 

 1 

 0 

1

 1 

 1 

[그림 2]


AND 게이트를 퍼셉트론으로 표현하고 싶을때 진리표대로 작동하는 w1, w2, 임계값을 정해야 합니다. 즉, 가중치 및 임계값을 정해야 합니다.

가령 (w1, w2, 임계값)가 (0.5, 0.5, 0.7)일 때, (0.5, 0.5, 0.8), (1.0, 1.0, 1.0)일 때, 모두 AND 게이트의 조건을 만족합니다.


2-2. NAND 게이트와 OR 게이트

NAND는 Not AND를 의미하며, 그 동작은 AND 게이트의 출력을 뒤집은 것이 됩니다. 진리표를 나타내면 [그림 3]처럼 x1, x2가 모두 1일 때만 0을 출력 그외에는 1을 출력합니다. NAND 게이트를 표현하려면 예를 들어 (w1, w2, 임계값) = (-0.5, -0.5, -0.7) 조합이 있습니다.


x1 

x2 

y 

0 

0 

1 

1 

0 

1 

0 

1 

1 

1 

1 

[그림 3]


OR 게이트는 입력 신호 중 하나 이상이 1이면 출력이 1이 되는 논리 회로입니다. OR 게이트의 진리표는 [그림 4] 처럼 볼 수 있고 매개변수는 (1.0, 0.5, 1.0)이 될 수 있겠네요.


x1 

x2 

y 

0 

0 

0 

1 

0 

1 

0 

1 

1 

1 

1 

[그림 4]


퍼셉트론은 AND, NAND, OR 논리 회로 게이트 모두에서 똑같습니다. 세 가지 게이트에서 다른 것은 매개변수(가중치와 임계값)의 값뿐입니다.


3. 퍼셉트론 구현하기


def AND(x1, x2):

    w1, w2, theta = 0.5, 0.5, 0.7

    tmp = x1 * w1 + x2 * w2

    if tmp <= theta:

        return 0

    elif tmp > theta:

        return 1


if __name__ == "__main__":

    print(AND(0, 0)) # 0 출력

    print(AND(1, 0)) # 0 출력

    print(AND(0, 1)) # 0 출력

    print(AND(1, 1)) # 1 출력


3-1. 가중치와 편향 도입

앞에서 구현한 AND 게이트는 단순하지만 [공식 2]를 보면 theta를 -b로 치환하면 아래의 식처럼 됩니다.

[공식 2]


위의 [공식 1] 과 [공식 2]는 기호만 바꿨을 뿐 의미는 같습니다. 여기에서 b를 편향(bias)이라 하고 w1, w2는 가중치 그대로입니다. [공식 2]에서 퍼셉트론은 입력 신호에 가중치를 곱한 값과 편향을 합하여 그 값이 0을 넘으면 1출력 그렇지 않으면 0을 출력합니다.


입력값과 가중치 +b(bias)라고 불리우는 추가적인 보정치값을 합했을 때, 0(지정값인 임계치는 개발자 혹은 설계자 마음인데 bias로 조정이 가능하니, 0으로 하는것이 일반적)보다 높으면 True라고 인지, 0이하일 경우, 버리기 위해서 False값을 전달하게 됩니다.


위의 식을 구현해 보겠습니다.


import numpy as np


x = np.array([0, 1]) #입력

w = np.array([0.5, 0.5]) #가중치

b = -0.7

print(w * x) #출력: [0, 0.5]

print(np.sum(w * x)) #출력: 0.5

print(np.sum(w * x) + b) #출력: 대략 -0.2


x = np.array([1, 1]) #입력

w = np.array([0.5, 0.5]) #가중치

b = -0.7

print(w * x)

print(np.sum(w * x)) #출력: 1.0

print(np.sum(w * x) + b) #출력: 대략 0.3


numpy 배열끼리 곱셈은 두 배열의 원소 수가 같다면 각 원소끼리 곱합니다. 그래서 w * x 에서 ([0, 1] * [0.5, 0.5] => [0, 0.5]), np.sum() 메서드는 입력한 배열의 결과값 총 합 [0 + 0.5] = [0.5]

입력을 0, 1말고 1, 1 하면 0보다 큰 값 이나올겁니다.


3-2. 가중치와 편향 구현하기


import numpy as np


def AND(x1, x2):

    x = np.array([x1, x2])

    w = np.array([0.5, 0.5])

    b = -0.7

    tmp = np.sum(w * x) + b

    if tmp <= 0:

        return 0

    else:

        return 1


if __name__ == "__main__":

    print(AND(0, 0)) #출력: 0

    print(AND(1, 0)) #출력: 0

    print(AND(0, 1)) #출력: 0

    print(AND(1, 1)) #출력: 1


여기에서 -theta가 b로 치환되었습니다. 그리고 편향은 가중치 w1, w2와 기능이 다릅니다. w1과 w2는 각 입력 신호가 결과에 주는 영향력(중요도)을 조절하는 매개변수이고, 편향(bais)은 뉴런이 얼마나 쉽게 활성화(결과로 1을 출력)하느냐를 조정하는 매개변수입니다.

예를 들어 b가 -0.1이면 각 입력 신호에 가중치를 곱한 값(x1 * w1 + x2 * w2)들의 합이 0.1를 초과할 때만 뉴런이 활성화합니다.

반면, b가 -20.0이면 각 입력 신호에 가중치를 곱한 값들의 합이 20.0을 넘지 않으면 뉴런은 활성화되지 않습니다.


즉, 위의 코드상에서 b의 값이 1.0만 되어도 AND(1,1) 출력이 0이 된다는 것입니다. 왜냐하면 1을 넘어야 뉴런이 활성화되기 때문에


이어서 NAND와 OR 게이트 구현

import numpy as np


def NAND(x1, x2):

    x = np.array([x1, x2])

    w = np.array([-0.5, -0.5])

    b = 0.7

    tmp = np.sum(w * x) + b

    if tmp <= 0:

        return 0

    else:

        return 1


if __name__ == "__main__":

    print(NAND(0, 0)) #출력: 1

    print(NAND(1, 0)) #출력: 1

    print(NAND(0, 1)) #출력: 1

    print(NAND(1, 1)) #출력: 0 


import numpy as np


def OR(x1, x2):

    x = np.array([x1, x2])

    w = np.array([0.5, 0.5])

    b = -0.2

    tmp = np.sum(w * x) + b

    if tmp <= 0:

        return 0

    else:

        return 1


if __name__ == "__main__":

    print(OR(0, 0)) #출력: 1

    print(OR(1, 0)) #출력: 1

    print(OR(0, 1)) #출력: 1

    print(OR(1, 1)) #출력: 0 


4. XOR 게이트 퍼셉트론


[그림 4-1]은 1이 하나라도 들어가있으면 1이라는 XOR 진리표입니다.


x1

x2 

y 

0 

0 

0 

1 

0 

1 

0 

1 

1 

1 

1 

[그림 4-1]


하지만 XOR 게이트는 퍼셉트론으로는 한계가 있습니다.

아래 [그림 5]에서 직선 하나로 동그라미와 세모를 나눌 방법은 없습니다. 직선 하나로는 나눌 수 없지만 '직선'이라는 제약을 없애면 가능합니다.


[그림 5]



아래 [그림 6] 처럼 곡선으로는 표현되지만 퍼셉트론은 직선 하나로 나눈 영역만 표현할 수 있습니다.

[그림 6] 같은 곡선의 영역을 비선형 영역, [그림 5] 같은 직선의 영역을 선형 영역이라 합니다.


[그림 6]



5. 다층 퍼셉트론(Multi Layer Perceptron)


다충 퍼셉트론이 나타나면서 '층을 쌓아' 만들 수 있다는것입니다. 층을 하나 더 쌓아서 XOR를 표현해볼 것입니다.

AND, NAND, OR 게이트를 합쳐서 표현해 보겠습니다.



x1 

x2 

y 

0 

0 

1 

1 

0 

1 

0 

1 

1 

1 

1 

[NAND 진리표]



x1 

x2 

y 

0 

0 

1 

1 

0 

1 

0 

1 

1 

1 

1 

[OR 진리표]


XOR 진리표는 x1값과 x2값이 동일해야지, y값이 1이 나오는 진리표이다. 그럼 위의 진리표 2개를 AND로 합치면 우선, 위의 표를 보기 쉽게 합쳐보겠습니다.


x1 

x2 

NAND

OR 

0 

0 

1 

0 

1

0 

1 

1 

0 

1 

1 

1 

1 

1 

0 

[NAND + OR 진리표]


여기서 왼쪽 2개의 값을 Input 값, 우측 2개의 값은 Output값 

Output 값을 다시 Input 값으로 생각하고, 이 값들을 AND 값으로 만들어보자


 NAND

OR 

AND 

1 

0 

0 

1 

1 

1 

1 

1 

1 

0 

1 


위의 표를 보면 NAND값과 OR값을 AND로 연결하니, XOR의 값을 출력할 수 있게 되었다.


파이썬 코드로 구현해보면


def XOR(x1, x2):

    s1 = NAND(x1, x2)

    s2 = OR(x1, x2)

    y = AND(s1, s2)

    return y


아래의 [그림 7] 이 다층 구조의 네트워크입니다. 왼쪽부터 0층, 1층, 2층 이처럼 XOR은 2층 퍼셉트론이고 층이 여러 개인 퍼셉트론을 다층 퍼셉트론이라 합니다.

2층 퍼셉트론에서는 0층에서 1층으로 신호가 전달되고, 이어서 1층에서 2층으로 신호가 전달됩니다.

1. 0층의 두 뉴련이 입력 신호를 받아 1층의 뉴련으로 신호를 보낸다

     2. 1층의 뉴련이 2층의 뉴련으로 신호를 보내고, 2층의 뉴련은 출력한다.


참고한 블로그

https://needjarvis.tistory.com/182?category=678065

https://m.blog.naver.com/cjswo9207/221058968925


참고한 책

밑바닥 부터 시작하는 딥러닝 (한빛 미디어)

댓글
«   2024/05   »
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