DeepLearning - 퍼셉트론

변인 별로 가중치를 주고 결과를 판단할 거야

퍼셉트론 등장

맥컬럭-피츠(1943): 입력에 대해 일정치 이상이면 활성화(0과 1)하는 이진 장치 만들어보자

프랑크 로젠블랫(1957): 입력값 여러 개 각각에 가중치를 조절해봐, 이게 퍼셉트론이야.

  1. 입력값과 가중치를 곱해 더하고 편향을 더해 하나의 값을 만들기
    => z1=x1w11+x2w21+b1z_1 = x_1 w_{11} + x_2 w_{21} + b_1 => z2=x1w12+x2w22+b2z_2 = x_1 w_{12} + x_2 w_{22} + b_2
  2. 값을 활성화 함수에 넣어 최종 출력을 결정 => y=f(z)y = f(z)
  3. 최종 출력: 0 or 1

구분의 한계

퍼셉트론은 한계가 있다. 아래의 네 점이 있을 때, 점 사이의 직선 하나로 o와 x를 구분하는 선은 만들 수 없다.

o  x
x  o

하지만 모든 논리 문제가 그런 것은 아니다.

XOR이 문제다

AND는 직선 하나로 구분 가능

좌표계에서, 아래처럼 생각해보자.
(0, 0) -> 0
(0, 1) -> 0
(1, 0) -> 0
(1, 1) -> 1

위와 같은 AND 연산은 x1+x2=1.5x1 + x2 = 1.5 같은 경계로 분리가 가능하다.

OR도 직선 하나로 구분 가능

좌표계에서, 이번엔 OR을 생각해보면 이렇다
(0, 0) -> 0
(0, 1) -> 1
(1, 0) -> 1
(1, 1) -> 1

얘 또한 x1+x2=0.5x1 + x2 = 0.5 같은 경계로 분리 가능하다.

그런데 XOR은 다르다

(0, 0) -> 0
(0, 1) -> 1
(1, 0) -> 1
(1, 1) -> 0

음.. 안 된다.

-## 다층 퍼셉트론

풀리지 않는 문제는 아예 다른 차원으로 해석해보면 다시 답이 나오기도 한다.

이번 경우엔, 새로운 공간으로 변환해서 분리하도록 해보자. 즉, 평면 위에서 나누지 못했으니 중간 계산을 하나 더 둠으로써 새 기준을 만들어보는 거다.

아래의 NAND, OR를 다시 AND로 연산해버리면 내가 원한 XOR이 되니까!

(좀 전의 좌표처럼 대각선으로 같은 부류가 결정된다면, 이를 종이접기처럼 공간을 한 번 변형해 분리한다고 비유하기도 한다. 즉, 중간 퍼셉트론의 결과를 다시 다음 퍼셉트론의 입력으로 사용하는 방식이다.)

NAND (AND 연산의 반대)
(0, 0) -> 1
(0, 1) -> 1
(1, 0) -> 1
(1, 1) -> 0

OR
(0, 0) -> 0
(0, 1) -> 1
(1, 0) -> 1
(1, 1) -> 1

=> XOR=(x1ORx2)AND(NOT(x1ANDx2))XOR = (x_1 OR x_2) AND (NOT(x_1 AND x_2))

즉 여러 퍼셉트론을 층층히 연결해 계산해 나가는 다층 퍼셉트론이 시작된다. 이를 다층 퍼셉트론의 설계(ft.은닉층)로 다시 이어가자.

다층퍼셉트론

다층 퍼셉트론은 여러 개의 퍼셉트론을 층 형태로 연결한 구조임을 이해했다. 그러면 이때 입력층과 출력층 사이에 위치한 중간층을 은닉층(hidden layer)이라고 부르는 것도 외워두자.

은닉층

(1). 입력값 x1,x2x_1, x_2에 각각 가중치를 곱하고 편향(b, 바이어스)를 더해 은닉층 뉴런의 입력값을 만든다

xw+bx*w+b

(2). 은닉층에서 (1)에 대해 시그노이드 함수를 적용한다.

n1=σ(x1w11+x2w21+b1)n_1 = \sigma(x_1 \cdot w_{11} + x_2 \cdot w_{21} + b_1)
n2=σ(x1w12+x2w22+b2)n_2 = \sigma(x_1 \cdot w_{12} + x_2 \cdot w_{22} + b_2)

(3). (2)의 결과를 출력층으로 전달한다.
y=σ(n1w31+n2w32+b3)y = \sigma(n_1 \cdot w_{31} + n_2 \cdot w_{32} + b_3)

코드화

import numpy as np

w11 = np.array([-10, -10])  # NAND
w12 = np.array([10, 10])    # OR
w2 = np.array([20, 20])     # AND

b1 = 15   # NAND
b2 = -5   # OR
b3 = -30  # AND

def MLP(x, w, b):
    y = np.sum(w * x) + b
    
    if y <= 0:
        return 0
    else:
        return 1

def NAND(a, b):
    return MLP(np.array([a, b]), w11, b1)

def OR(a, b):
    return MLP(np.array([a, b]), w12, b2)

def AND(a, b):
    return MLP(np.array([a, b]), w2, b3)

def XOR(a, b):
    return AND(NAND(a, b), OR(a, b))

for x in [(0, 0), (1, 0), (0, 1), (1, 1)]:
    y = XOR(x[0], x[1])
    print(f"{x} -> {y}")