퍼셉트론¶
퍼셉트론은 로젠 블렛이 1957년에 고안한 알고리즘입니다. 퍼셉트론은 입력 데이터를 2개의 부류중 하나로 분류하는 분류기(classifier)입니다.
신경세포와 퍼셉트론¶
사람의 뇌신경 세포의 동작과정을 흉내내어 만든 수학적 모델이 퍼셉트론입니다.
퍼셉트론은 학습이 가능한 초창기 신경망 모델로 현대적 의미로 보면 상당히 원시적인 신경망으로 볼 수 있습니다. 하지만 노드, 가중치, 층과 같은 개념이 도입되어 딥러닝을 포함하여 현대 신경망의 중요한 구성요소들을 이해하는데 의미가 있습니다.
퍼셉트론¶
퍼셉트론의 구조는 입력층과 출력층이라는 2개의 층으로 구성되는 단순한 구조로 이루어집니다.
그림 2-1 입력이 2개인 퍼셉트론
그림 2-1은 입력으로 2개의 신호를 받은 퍼셉트론의 예입니다. \(x_1\), \(x_2\)는 입력 신호, \(y\)는 출력신호, \(w_1\), \(w_2\)는 가중치(weight)를 뜻합니다. 그림에서 원은 뉴런 혹은 노드라고 부릅니다.
2개 입력에 대한 퍼셉트론은 다음과 같은 수식으로 나타낼 수 있습니다.
더 일반적으로 \(d\) 개의 입력을 가지는 퍼셉트론은 다음과 같이 나타낼 수 있습니다.
다음은 \(d=2\)일 때 예를 들어서 설명합니다.
단순한 논리연산¶
퍼셉트론을 활용한 간단한 문제를 살펴봅니다. 첫번째로 논리곱(AND) 진리표를 살펴봅니다. 두 입력이 모두 1일 때만 1을 출력하고 그 외에는 0을 출력합니다.
논리곱(AND 게이트)¶
\(x_1\) |
\(x_2\) |
\(y\) |
---|---|---|
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
위 표를 퍼셉트론으로 표현한다는 것은 \(w_1, w_2, \beta\)를 결정하는 것입니다. 위 조건을 만족하는 매개변수 조합은 무수히 많습니다. 가령 \((w_1, w_2, \beta) = (0.5, 0.5, 0.5)\)로 하거나 \((0.5, 0.5, 0.8)\)로 하는 등 무수히 많은 조합을 찾을 수 있습니다.
퍼셉트론 구현¶
간단한 구현¶
다음은 논리곱(AND 게이트)를 구현한 것입니다. \(x_1\), \(x_2\)를 입력받아 결과를 반환합니다.
In [1]: def AND(x1, x2):
...: w1, w2, beta = 0.5, 0.5, 0.7
...: tmp = x1 * w1 + x2 * w2
...: if tmp <= beta:
...: return 0
...: elif tmp > beta:
...: return 1
...:
In [2]: print("AND(0, 0)={}, AND(1, 0)={}, AND(0, 1)={}, AND(1, 1)={}".format(AND(0, 0), AND(1, 0), AND(0, 1), AND(1, 1)))
AND(0, 0)=0, AND(1, 0)=0, AND(0, 1)=0, AND(1, 1)=1
직접하기
NAND 게이트를 파이썬 함수로 구현해서 확인 해보세요. 여기서 \(w_1 = w_2 = -0.5\), \(\beta = -0.7\)을 사용해보고 가능한 다른 값들은 무엇이 있는지 생각해보세요.
OR 게이트를 구현하기 위해 필요한 \(w_1, w_2, \beta\)을 결정하고
OR
함수를 작성 하세요.
벡터 표현¶
퍼셉트론을 다르게 표현하면 다음과 같습니다. 위 식 (1)에서 \(-\beta\)를 \(b\)로 표현한 것입니다.
여기서 \(b\)는 입력 \(x_1, x_2\)이 모두 0일 때 퍼셉트론이 0으로부터 벗어난 정도를 나타낸다고 편향bias 이라고 합니다.
단순한 논리연산 퍼셉트론을 좌표평면 위에 기하적으로 표현하면 4개의 점을 분리하는 직선의 방정식을 찾는 문제와 같습니다. 이 직선은 벡터 \(\mathbf{w} = (w_1, w_2)\)에 수직인 직선이 됩니다.
또한 다음과 같이 3차원 공간 \((x, y, z)\)에서 표현하면 4점을 분리하는 평면의 방정식을 찾는 것과 같다고 할 수 있습니다.
\(z\)가 0보다 작거나 같으면 0
을 반환하고 그렇지 않으면 1
을 반환하는 알고리즘입니다. 즉 공간의 점 \((x,y,z)\)이 \(xy\) 평면 아래 있는 것과 위에 있는 것으로 분리하는 것과 마찬가지입니다.
넘파이를 이용해서 구현을 해봅니다.
In [5]: import numpy as np
...: x = np.array([0, 1])
...: w = np.array([0.5, 0.5])
...: b = -0.7
...: print(w * x)
...: print(np.sum(w * x))
...: print(np.sum(w * x) + b)
...:
[0. 0.5]
0.5
-0.19999999999999996
두 벡터 \(w = (w_1, w_2)\), \(x = (x_1, x_2)\)의 성분끼리 곱 w * x
을 한 후 b
를 더하여 구한 것입니다.
이것을 이용해서 AND
게이트를 다시 구현해봅니다.
In [6]: 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
...: elif tmp > 0:
...: return 1
...:
\(w_1, w_2\)는 입력 신호가 결과에 주는 영향력(중요도)을 조절하는 매개변수이고 편향은 뉴런이 얼마나 쉽게 활성화하느냐를 조정하는 매개변수입니다. 예를 들어 b
가 -0.1
이면 각 입력 신호에 가중치를 곱한 값들이 0.1
을 초과할 때만 뉴런이 활성화됩니다. 반면 b
가 -20.0
이면 각 입력신호에 가중치를 곱한 값들의 합이 20.0
을 넘지 않으면 뉴런은 활성화되지 않습니다. 이처럼 편향의 값은 뉴런(노드)이 얼마나 쉽게 활성화되는지를 결정합니다.
직접하기
NAND 게이트를 넘파이 배열을 이용해서 구현하고 테스트 해보세요. \(w_1 = w_2 = -0.5\), \(b = 0.7\)을 사용하세요.
OR 게이트를 넘파이 배열을 이용해서 구현하기 위한 \(w_1, w_2, b\)을 결정하고 OR 함수를 작성해서 확인해보세요.
다층 퍼셉트론¶
앞에서 봤던 퍼셉트론은 선형분리 가능한 문제에만 작동을 합니다. 다음과 같은 XOR 게이트 연산을 푸는데 사용할 수 없습니다.
XOR 게이트¶
XOR 게이트는 배타적 논리합(exclusive or)이라는 연산입니다.
\(x_1\) |
\(x_2\) |
\(y\) |
---|---|---|
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
앞에서 봤던 퍼셉트론은 좌표 평면에서 직선으로 분리하는 방법이었습니다. 그러나 XOR 게이트는 어떤 직선으로도 세모와 동그라미를 분리할 수 없는 것을 알 수 있습니다. 따라서 퍼셉트론으로는 해결할 수 없는 문제가 됩니다.
하지만 퍼셉트론을 한 층 더 쌓으면 이 문제를 해결할 수 있습니다. 우선 논리 게이트 표시에 대해 알아봅니다.
어떤 조합을 하면 XOR 게이트를 표현할 수 있을지를 생각해봅니다.
NAND, OR, AND를 다음과 같이 조합하면 XOR 게이트를 완성할 수 있습니다.
이것을 진리표로 나타내면 다음과 같습니다.
\(x_1\) |
\(x_2\) |
\(s_1(x_1\text{NAND}x_2)\) |
\(s_2(x_1\text{OR}x_2)\) |
\(y(s_1\text{AND}s_2)\) |
---|---|---|---|---|
0 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
0 |
XOR 게이트 구현¶
In [7]: def XOR(x1, x2):
...: s1 = NAND(x1, x2)
...: s2 = OR(x1, x2)
...: y = AND(s1, s2)
...: return y
...:
실행해보면 다음과 같이 맞게 출력되는 것을 볼 수 있습니다.
In [8]: print(XOR(0, 0))
...: print(XOR(1, 0))
...: print(XOR(0, 1))
...: print(XOR(1, 1))
...:
0
1
1
0
그림으로 나타내면 다음과 같습니다.
\(x_1, x_2\)를 입력층, NAND, OR 계산이 1층, AND 계산을 2층이라고 하며 다층 퍼셉트론이라고 합니다.
연습문제¶
다음 표를 만족하는 퍼셉트론을 구현해 보세요. 즉, 다음 식을 만족하는 \(w_1, w_2, b\)를 구해서 파이썬 함수로 만들어 보세요.
\[\begin{split}y = \begin{cases} 0, & \text{if} \quad w_1 x_1 + w_2 x_2 + b <= 0 \\ 1, & \text{if} \quad w_1 x_1 + w_2 x_2 + b > 0 \end{cases}\end{split}\]\(x_1\)
\(x_2\)
\(y\)
0
0
0
-1
0
1
-1
1
1
0
1
1
다음 표를 만족하는 퍼셉트론을 구현해 보세요. 즉, 다음 식을 만족하는 \(w_1, w_2, b\)를 구해서 파이썬 함수로 만들어 보세요.
\[\begin{split}y = \begin{cases} 0, & \text{if} \quad w_1 x_1 + w_2 x_2 + b <= 0 \\ 1, & \text{if} \quad w_1 x_1 + w_2 x_2 + b > 0 \end{cases}\end{split}\]\(x_1\)
\(x_2\)
\(y\)
-1
-1
0
-1
1
1
1
-1
1
1
1
1
다음 표를 만족하는 퍼셉트론이 가능한지를 판단하고, 가능하다면 다음 식을 만족하는 \(w_1, w_2, b\)를 구해서 파이썬 함수로 만들어 보세요.
\[\begin{split}y = \begin{cases} -1, & \text{if} \quad w_1 x_1 + w_2 x_2 + b <= 1 \\ 1, & \text{if} \quad w_1 x_1 + w_2 x_2 + b > 1 \end{cases}\end{split}\]\(x_1\)
\(x_2\)
\(y\)
0.3
0.6
-1
0.5
0.1
1
0.7
2
1
1.2
0.5
1