퍼셉트론이란?
`퍼셉트론(perceptron)`은 다수의 신호를 입력으로 받아 하나의 신호를 출력한다. 퍼셉트론의 신호는 '신호가 흐른다'를 의미하는 1, '신호가 흐르지 않는다'를 의미하는 0의 두 가지 값을 가질 수 있다.
- 입력 신호가 뉴런에 보내질 때는 각각 고유한 가중치가 곱해짐(W1X1, W2X2)
- 뉴런에서 보내온 신호의 총합이 정해진 한계를 넘어설 때만 1을 출력되며 '뉴런이 활성화한다'라고 표현
- 정해진 한계를 `임계값`이라고 하며 세타로 표현
- 퍼셉트론은 복수의 입력 신호 각각에 고유한 가중치를 부여하며, 가중치는 각 신호가 결과에 주는 영향력을 조절하는 요소로 작용
- 가중치가 클수록 해당 신호가 그만큼 더 중요함을 의미
단순한 논리 회로
AND 게이트
`AND 게이트`는 입력이 둘이고 출력은 하나이다. 두 입력이 모두 1일 때만 1을 출력하고, 그 외에는 0을 출력한다. 다음은 입력 신호와 출력 신호의 대응 표를 나타내는 진리표이다.
X1 | X2 | y |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
이러한 AND 게이트를 퍼셉트로 표현하는 방법은 매우 다양하다. 순서대로 x1, x2, 세타가 (0.5, 0.5, 0.7), (0.5, 0.5, 0.8), (1.0, 1.0, 1.0)로 표현되면 모두 x1과 x2가 모두 1일 때만 가중 신호의 총합이 주어진 임계값을 웃돌게 된다.
NAND 게이트와 OR 게이트
`NAND 게이트`는 Not And를 의미하며 AND 게이트의 출력을 뒤집은 것이다. 즉, x1과 x2가 모두 1일 때만 0을 출력하고, 그 외에는 1을 출력한다. 퍼셉트론을 구현할 때에도 AND 게이트를 구현하는 매개변수의 부호를 모두 반전하기만 하면 NAND 게이트가 된다. `OR 게이트`는 입력 신호 중 하나 이상이 1이면 출력이 1이 되는 논리 회로이다. 두 게이트의 진리표는 다음과 같다.
x1 | x2 | y |
0 | 0 | 1 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
x1 | x2 | y |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
여기서 중요한 점은 퍼셉트론의 구조는 AND, NAND, OR 게이트 모두에서 똑같다. 세 가지 게이트에서 다른 것은 매개변수(가중치와 임계값)의 값이다. 즉, 똑같은 구조의 퍼셉트론이 매개변수의 값만 적절히 조정하여 AND, NAND, OR 게이트로 변한다.
퍼셉트론 구현하기
AND 게이트 간단한 구현
# AND 게이트
def AND(x1, x2):
w1, w2, theta = 0.5, 0.5, 0.7
tmp = x1*w1 + x2*w2
if tmp <= theta:
return 0
if tmp > theta:
return 1
x1, x2를 인수로 받는 AND라는 함수를 구현했다. 매개변수 w1, w2, theta는 함수 내에서 초기화되며, 가중치를 곱한 입력의 총합이 임계값을 넘으면 1을 반환하고 그 외에는 0을 반환한다.
가중치와 편향 도입
전에 보았던 퍼셉트론 식에서 임계값 세타를 -b로 치환하면 다음과 같이 식이 변화한다.
여기에서 b는 `편향(bias)`라고 한다. 해당 식에서 퍼셉트론을 해석하면, 퍼셉트론은 입력 신호에 가중치를 곱한 값과 편향을 합하여 그 값이 0을 넘으면 1을 출력하고 그렇지 않으면 0을 출력한다.
가중치와 편향 구현하기
가중치와 편향을 도입한 AND 게이트는 다음과 같이 구현할 수 있다.
# 가중치와 편향이 도입된 AND 게이트
def AND(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.7
tmp = np.sum(x*w) + b
if tmp <= 0:
return 0
else:
return 1
편향 b와 가중치 w1, w2의 기능은 다음과 같다.
- 가중치(w1, w2) : 각 입력 신호가 결과에 주는 영향력(중요도)을 조절하는 매개변수
- 편향(b) : 뉴런이 얼마나 쉽게 활성화(결과로 1을 출력)하느냐를 조정하는 매개변수
- b가 -0.1이면 각 입력 신호에 가중치를 곱한 값들의 합이 0.1을 초과할 때만 뉴런 활성화
- b가 -20.0이면 각 입력 신호에 가중치를 곱한 값들의 합이 20을 초과할 때만 뉴런 활성화
가중치와 편향을 도입한 NAND 게이트와 OR 게이트는 다음과 같이 구현된다.
# NAND 게이트
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
# OR 게이트
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
AND, NAND, OR 게이트는 모두 같은 구조의 퍼셉트론이며, 각각 가중치 매개변수와 편향 매개변수에만 차이가 있다.
퍼셉트론의 한계(XOR 게이트)
`XOR 게이트`는 배타적 논리합이라는 논리 회로이다. 이는 X1과 X2 중 한쪽이 1일 때만 1을 출력한다. XOR 게이트의 진리표는 다음과 같다.
x1 | x2 | y |
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
지금까지 본 퍼셉트론으로는 XOR 게이트를 구현할 수 없다. 이에 대한 시각적 설명은 다음과 같다.
0을 출력하는 경우에는 동그라미로, 1을 출력하는 경우는 세모로 표현했다. 좌측에 OR 게이트의 경우 해당 직선으로 0과 1의 출력을 제대로 나누고 있다. 색이 칠해져 있는 영역이 0을 출력하는 영역이다. 그러나 XOR 게이트의 경우 동그라미와 세모를 나눌 수 있는 영역을 직선 하나로 나누기는 불가능하다.
앞서 직선 하나로는 XOR 게이트의 동그라미와 세모를 구분할 수 없었지만, 곡선으로는 표현이 가능하다. 이를 `비선형` 영역이라고 하며, 직선의 영역은 `선형` 영역이라고 표현한다. 결론적으로, 퍼셉트론은 직선 하나로 나눈 영역만 표현할 수 있다는 한계를 가지고 있다.
다층 퍼셉트론이 출동한다면
기존 게이트 조합하기
앞에서 설명한 퍼셉트론의 한계는 정확히 말하면 `단층 퍼셉트론(Single-layer perceptron)`으로는 XOR 게이트를 표현할 수 없다, 또는 비선형 영역을 분리할 수 없다는 것이다. 이러한 한계점은 퍼셉트론의 층을 쌓아 `다층 퍼셉트론(Multi-layer perceptron)`을 구현하여 표현할 수 있다.
예를 들어 다음과 같이 NAND의 출력을 s1, OR의 출력을 s2로 해서 진리표를 만들면 다음과 같다. X1, X2, y를 보면 XOR의 출력과 동일하다. 즉, X1과 X2는 NAND와 OR 게이트의 입력이 되고, NAND와 OR의 출력이 AND 게이트의 입력이 된다.
X1 | X2 | S1 | S2 | y |
0 | 0 | 1 | 0 | 0 |
1 | 0 | 1 | 1 | 1 |
0 | 1 | 1 | 1 | 1 |
1 | 1 | 0 | 1 | 0 |
XOR 게이트 구현하기
def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
XOR 게이트를 뉴런을 이용한 퍼셉트론으로 표현하면 다음과 같다.
AND, OR 퍼셉트론은 단층 퍼셉트론이지만 XOR 퍼셉트론은 2층 퍼셉트론, 즉 다층 퍼셉트론이다. 여기서 XOR 퍼셉트론은 0층과 1층 사이, 1층과 2층 사이에서만 가중치를 갖기 때문에 가중치를 갖는 층이 2개여서 2층 퍼셉트론이라고 한다. 하지만 때에 따라 구성 층의 수를 기준으로 3층 퍼셉트론이라 하는 경우도 있다.
- 0층의 두 뉴런이 입력 신호를 받아 1층의 뉴런으로 신호를 보낸다.
- 1층의 뉴런이 2층의 뉴런으로 신호를 보내고, 2층의 뉴런은 y를 출력한다.
결론적으로 단층 퍼셉트론으로는 표현하지 못한 것을 층을 하나 늘려 구현하였으며, 퍼셉트론은 층을 쌓아(깊게 하여) 더 다양한 것을 표현할 수 있다.
이 포스팅은 '밑바닥부터 시작하는 딥러닝' 교재를 공부하고 작성한 글입니다. 해당 포스팅에 포함된 코드들은 깃허브에서 확인하실 수 있습니다.