by museonghwang

퍼셉트론 (Perceptron)

|

Perceptron

이번 게시물에서는 모든 신경망(Neural net)의 기본이 되는 퍼셉트론(Perceptron) 에 대해서 알아보겠습니다. 신경망이 각광을 받게 된 지는 얼마되지 않았습니다만, 그보다 훨씬 전부터 신경망과 퍼셉트론에 대해서 많은 연구가 있어왔습니다. 퍼셉트론(perceptron) 알고리즘은 프랑크 로젠블라트(Frank Rosenblat)가 1957년에 고안한 알고리즘으로 신경망(딥러닝)의 기원이 되는 알고리즘이며, 신경망과 딥러닝으로 나아가는 데 중요한 아이디어를 배울 수 있습니다.

퍼셉트론(인공 뉴런, 단순 퍼셉트론)은 다수의 신호를 입력으로 받아 하나의 신호를 출력합니다. 여기서 말하는 신호란 전류나 강물처럼 흐름이 있는 것으로 전류가 전선을 타고 흐르는 전자를 내보내듯, 퍼셉트론 신호도 흐름을 만들고 정보를 앞으로 전달합니다. 퍼셉트론 신호는 ‘흐른다/안 흐른다(1이나 0)’의 두 가지 값을 가질 수 있습니다.

fig 2-1

이미지 출처 : 밑바닥부터 시작하는 딥러닝</a>

  • $x_1$과 $x_2$ : 입력 신호
  • $y$ : 출력 신호
  • $w_1$과 $w_2$ : 가중치
  • 그림의 원 : 뉴런 혹은 노드

위 그림은 입력으로 2개의 신호를 받은 퍼셉트론의 예입니다. 입력 신호가 뉴런에 보내질 때는 각각 고유한 가중치가 곱해집니다($w_1x_1$, $w_2x_2$). 그리고 뉴런에서 보내온 신호의 총합이 정해진 한계를 넘어설 때만 1을 출력합니다(뉴런이 활성화한다). 여기서 그 한계를 임계값이라 하며, $\theta$ 기호로 나타냅니다.

이미지 출처 : javapoint

위 퍼셉트론은 총 4개의 신호 $(x_1, \cdots, x_4)$ 를 입력받습니다. 각 신호는 연산을 위한 가중치 $(w_1, \cdots, w_4)$ 를 가지고 있습니다. 가중치는 각 신호가 주는 영향력을 조절하는 요소로 추후 학습 과정에서 이 값을 업데이트하게 됩니다. 퍼셉트론은 모든 연산의 합이 임계값 $\theta$ 를 넘으면 $1$ 을, 넘지 못하면 $0$ 을 출력합니다. 입력 신호를 2개로 단순화하여 퍼셉트론이 작동하는 방식을 수식으로 나타내면 아래와 같습니다.

\[y = \begin{cases} 0 \qquad (w_1x_1 + w_2x_2 + w_3x_3 + w_4x_4 \leq \theta) \\ 1 \qquad (w_1x_1 + w_2x_2 + w_3x_3 + w_4x_4 > \theta) \end{cases}\]

그리고 이를 신호가 $n$ 개인 경우로 일반화 하면 아래의 수식과 같이 나타낼 수 있습니다.

\[y = \begin{cases} 0 \qquad (\sum^n_{i=1} w_ix_i \leq \theta) \\ 1 \qquad (\sum^n_{i=1} w_ix_i > \theta) \end{cases}\]

정리하지면, 퍼셉트론은 복수의 입력 신호 각각에 고유한 가중치를 부여합니다. 가중치는 각 신호가 결과에 주는 영향력을 조절하는 요소로 작용합니다. 즉, 가중치가 클수록 해당 신호가 그만큼 더 중요함을 뜻합니다.


Logic gate

AND gate

이번에는 논리 게이트(Logic gate)에 대해 알아보겠습니다.

처음으로 알아볼 게이트는 AND 게이트입니다. AND 게이트는 입력이 둘이고 출력은 하나입니다. 다음 표는 AND 게이트의 진리표로, 두 입력이 모두 1일 때만 1을 출력하고, 그 외에는 0을 출력합니다.

x1 x2 y
0 0 0
1 0 0
0 1 0
1 1 1

이 AND 게이트를 퍼셉트론으로 표현하고 싶다면 진리표대로 작동하도록 하는 $w_1, w_2, \theta$의 값을 정해야 합니다. AND 게이트를 만족하는 매개변수 조합은 무한히 많습니다. 가령 $(w_1, w_2, \theta)$가 $(0.5, 0.5, 0.7)$일 때, 또 $(0.5, 0.5, 0.8)$이나 $(1.0, 1.0, 1.0)$ 때 모두 AND 게이트의 조건을 만족합니다. 매개변수를 이렇게 설정하면 $x_1$과 $x_2$모두가 1일 때만 가중 신호의 총합이 주어진 임계값을 웃돌게됩니다.

위 매개변수를 고려하여 AND gate를 파이썬으로 구현해보겠습니다. x1과 x2를 인수로 받는 AND라는 함수입니다.

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

매개변수 w1, w2, theta는 함수 안에서 초기화하고, 가중치를 곱한 입력의 총합이 임계값을 넘으면 1을 반환하고 그 외에는 0을 반환합니다.

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

NAND 게이트

NAND gate는 Not AND를 의미하며, 그 동작은 AND 게이트의 출력을 뒤집은 것이 됩니다. 진리표로 나타내면 아래 표처럼 $x_1, x_2$과 가 모두 1일 때만 0을 출력하고, 그 외에는 1을 출력합니다.

x1 x2 y
0 0 1
1 0 1
0 1 1
1 1 0

NAND 게이트를 표현하려면 예를 들어 $(w_1, w_2, \theta) = (-0.5, -0.5, -0.7)$ 조합이 있습니다. 사실 AND 게이트를 구현하는 매개변수의 부호를 모두 반전하기만 하면 NAND 게이트가 됩니다.

OR 게이트

OR 게이트는 입력 신호 중 하나 이상이 1이면 출력이 1이 되는 논리 회로입니다.

x1 x2 y
0 0 0
1 0 1
0 1 1
1 1 1

여기서 중요한 점은 퍼셉트론의 구조는 AND, NAND, OR 게이트 모두에서 똑같다는 것입니다. 세 가지 게이트에서 다른 것은 매개변수(가중치와 임계값)의 값 뿐입니다. 즉, 똑같은 구조의 퍼셉트론이 매개변수의 값만 적절히 조정하여 AND, NAND, OR로 변신하는 것입니다.

여기서 퍼셉트론의 매개변수 값을 정하는 것은 컴퓨터가 아니라 인간이 직접 진리표하는 ‘학습 데이터’를 보면서 매개변수의 값을 생각했습니다. 기계학습 문제는 매개변수의 값을 정하는 작업을 컴퓨터가 자동으로 하도록 합니다. 즉 학습이란 적절한 매개변수 값을 정하는 작업이며, 사람은 퍼셉트론의 구조(모델)를 고민하고 컴퓨터에 학습할 데이터를 주는 일을 합니다.


가중치(Weight)와 편향(Bias) 도입

앞에서 구현한 AND 게이트는 직관적이고 알기 쉽지만, 앞으로를 생각해서 다른 방식으로 수정해야 합니다. 첫번째 식의 $\theta$를 $-b$로 치환하면 퍼셉트론의 동작이 다음처럼 됩니다.

\[y = \begin{cases} 0 \qquad (b + w_1x_1 + w_2x_2 \leq 0) \\ 1 \qquad (b + w_1x_1 + w_2x_2 > 0) \end{cases}\]
  • $b$ : 편향($bias$)
  • $w_1$과 $w_2$ : 가중치

위 식의 관점에서 해석해보자면, 퍼셉트론은 입력신호에 가중치를 곱한 값과 편향을 합하여, 그 값이 0을 넘으면 1을 출력하고 그렇지 않으면 0을 출력합니다. 넘파이를 이용하여 위 식을 구현해 보겠습니다.

import numpy as np

x = np.array([0, 1])     # 입력
w = np.array([0.5, 0.5]) # 가중치
b = -0.7                 # 편향
np.sum(w*x) + b # 대략 -0.2(부동소수점 수에 의한 연산 오차)

[OutPut]
-0.19999999999999996

여기에서 $-\theta$가 편향 $b$로 치환되었고, 편향은 가중치 $w_1, w_2$와 기능이 다르다는 사실에 주의 해야합니다.

  • 가중치 $w_1$과 $w_2$ : 각 입력 신호가 결과에 주는 영향력(중요도)을 조절하는 매개변수
  • 편향$(b)$ : 뉴런이 얼마나 쉽게 활성화(결과로 1을 출력)하느냐를 조절하는 매개변수

예를 들어 $b$가 -0.1이면 각 입력 신호에 가중치를 곱한 값들의 합이 0.1을 초과할 때만 뉴런이 활성화합니다. 반면 $b$가 -20.0이면 각 입력 신호에 가중치를 곱한 값들의 합이 20.0을 넘지 않으면 뉴런은 활성화하지 않습니다.

이처럼 편향의 값$(bias)$은 뉴런이 얼마나 쉽게 활성화되는지를 결정합니다.

AND gate 구현

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

for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = AND(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))

[OutPut]
(0, 0) -> 0
(1, 0) -> 0
(0, 1) -> 0
(1, 1) -> 1

NAND gate 구현

def NAND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([-0.5, -0.5]) # AND 와는 가중치(w와 b)만 다르다.
    b = 0.7
    tmp = np.sum(w*x) + b
    if tmp <= 0:
        return 0
    else:
        return 1
    
for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = NAND(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))

[OutPut]
(0, 0) -> 1
(1, 0) -> 1
(0, 1) -> 1
(1, 1) -> 0

OR gate 구현

def OR(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5]) # AND 와는 가중치(w와 b)만 다르다.
    b = -0.2
    tmp = np.sum(w*x) + b
    if tmp <= 0:
        return 0
    else:
        return 1

for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = OR(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))

[OutPut]
(0, 0) -> 0
(1, 0) -> 1
(0, 1) -> 1
(1, 1) -> 1


퍼셉트론의 한계

XOR gate

XOR 게이트는 배타적 논리합이라는 논리 회로입니다. 다음 표와 같이 $x_1$과 $x_2$중 한쪽이 1일 때만 1을 출력합니다.

x1 x2 y
0 0 0
1 0 1
0 1 1
1 1 0

지금까지 본 퍼셉트론으로는 이 XOR 게이트를 구현할 수 없습니다. 다음 그림으로 XOR 게이트를 좌표평면에 표시했는데, 0을 원(O), 1을 삼각형(△)으로 표시했습니다. AND, NAND, OR 게이트처럼 직선 하나로 O와 △을 나누는 영역을 만들어낼 수 있을까라는 질문에는 답을 할 수 없습니다.

fig 2-7

이미지 출처 : 밑바닥부터 시작하는 딥러닝</a>

위 그림의 O과 △을 직선 하나로 나누는 방법은 아무리 생각해도 떠오르지 않습니다. 사실 직선 하나로 나누기란 불가능 합니다.

선형과 비선형

직선 하나로는 위 그림의 O과 △을 나눌 수 없습니다. 하지만 다음 그림처럼 ‘직선’ 이라는 제약을 없앤다면 가능합니다.

fig 2-8

이미지 출처 : 밑바닥부터 시작하는 딥러닝</a>

퍼셉트론은 직선 하나로 나눈 영역만 표현할 수 있다는 한계가 있습니다. 위 그림 같이 곡선은 표현할 수 없다. 위 그림과 같은 곡선의 영역을 비선형 영역, 직선의 영역을 선형 영역이라고 합니다. 퍼셉트론의 한계는 정확히 말하면 단층 퍼셉트론(single Layer perceptron) 으로는 XOR 게이트를 표현할 수 없다 또는 단층 퍼셉트론으로는 비선형 영역을 분리할 수 없다 가 됩니다. 앞으로 퍼셉트론을 조합하여, 즉 층을 쌓아서 XOR 게이트를 구현하는 모습을 보게 됩니다.


Multi-layer perceptron

퍼셉트론으로는 XOR 게이트를 표현할 수 없었습니다. 하지만 퍼셉트론의 아름다움은 ‘층을 쌓아’ 다층 퍼셉트론(multi-layer perceptron)을 만들 수 있다는데 있습니다. XOR 게이트를 만드는 방법은 다양합니다. 그중 하나는 앞서 만든 AND, NAND, OR 게이트를 조합하는 방법입니다.**

fig 2-9

fig 2-11

이미지 출처 : 밑바닥부터 시작하는 딥러닝</a>

위 그림과 같은 조합이라면 XOR 게이트를 구현할 수 있는데, $x_1$과 $x_2$가 입력 신호, $y$가 출력 신호입니다. $x_1$과 $x_2$는 NAND와 OR 게이트의 입력이 되고, NAND와 OR의 출력이 AND 게이트의 입력으로 이어집니다.

위 그림의 조합이 정말 XOR를 구현하는지 살펴보면, NAND의 출력을 $s_1$, OR의 출력을 $s_2$로 해서 진리표를 만들면 다음 표처럼 됩니다. $x_1, x_2, y$에 주목하면 분명히 XOR의 출력과 같습니다.

fig 2-12

이미지 출처 : 밑바닥부터 시작하는 딥러닝</a>

XOR gate 구현

XOR 게이트를 파이썬으로 구현해보겠습니다. 지금까지 정의한 함수 AND, NAND, OR를 사용하면 구현할 수 있습니다.**

def XOR(x1, x2):
    s1 = NAND(x1, x2)
    s2 = OR(x1, x2)
    y = AND(s1, s2)
    return y

print(XOR(0, 0)) # 0을 출력
print(XOR(1, 0)) # 1을 출력
print(XOR(0, 1)) # 1을 출력
print(XOR(1, 1)) # 0을 출력

이로써 XOR 게이트를 완성했습니다. 지금 구현한 XOR를 뉴런을 이용한 퍼셉트론으로 표현하면 다음 그림처럼 됩니다.

fig 2-13

이미지 출처 : 밑바닥부터 시작하는 딥러닝</a>

XOR는 위 그림과 같이 다층 구조의 네트워크입니다. 그런데 위의 퍼셉트론은 지금까지 본 AND, OR 퍼셉트론과 형태가 다릅니다. 실제로 AND, OR가 단층 퍼셉트론인데 반해, XOR는 2층 퍼셉트론입니다. 이처럼 층이 여러 개인 퍼셉트론을 다층 퍼셉트론이라 합니다.

위 그림과 같이 2층 퍼셉트론에서는 0층에서 1층으로 신호가 전달되고, 이어서 1층에서 2층으로 신호가 전달됩니다. 이 동작을 더 자세히 서술하면 다음과 같습니다.

  1. 0층의 두 뉴런이 입력 신호를 받아 1층의 뉴런으로 신호를 보낸다.
  2. 1층의 뉴런이 2층의 뉴런으로 신호를 보내고, 2층의 뉴런은 $y$를 출력한다.

이상으로 2층 구조를 사용해 퍼셉트론으로 XOR 게이트를 구현할 수 있게 되었습니다. 다시 말해 단층 퍼셉트론으로는 표현하지 못한 것을 층을 하나 늘려 구현할 수 있었습니다. 이처럼 퍼셉트론은 층을 쌓아(깊게 하여) 더 다양한 것을 표현할 수 있습니다.