밑바닥부터 시작하는 딥러닝 2장 - 퍼셉트론

shyoon·2023년 9월 24일
0

시작하기에 앞서, 본 시리즈는 '밑바닥부터 시작하는 딥러닝 - 파이썬으로 익히는 딥러닝 이론과 구현' 책의 내용을 정리하였음을 밝힙니다.
https://github.com/kchcoo/WegraLee-deep-learning-from-scratch


퍼셉트론


퍼셉트론이란?

다수의 신호를 입력으로 받아 하나의 신호를 출력하는 것으로 퍼셉트론 신호는 흐름을 만들고 정보를 앞으로 전달함. 1은 신호가 흐르는 것, 0은 흐르지 않는 것

위 그림은 2개의 입력 신호를 받은 간단한 퍼셉트론의 구조이다. x1,x2x_1, x_2는 입력 신호이며 yy는 출력 신호, w1,w2w_1, w_2는 각 가중치를 의미한다. 각 xxww를 곱한 값들을 더한 신호가 특정 threshold를 넘어설 때 1을 출력(신호 o). 이를 '뉴런이 활성화한다' 라고 한다. 수식으로 나타내면 아래와 같다.

y={0(w1x1+w2x2θ)1(w1x1+w2x2>θ)y = \begin{cases} {0 (w_1x_1 + w_2x_2 \le \theta)} \\ {1 (w_1x_1 + w_2x_2 > \theta)} \end{cases}

단순한 논리 회로


AND 게이트

입력이 둘이고 출력은 하나. 두 입력이 모두 1일 때만 1을 출력

AND 게이트의 진리표

x1x1x2x2yy
000
100
010
111



NAND 게이트

Not And 게이트. AND 게이트의 출력 결과를 뒤집은 것이라고 생각하면 된다.

NAND 게이트의 진리표

x1x1x2x2yy
001
101
011
110



OR 게이트

입력 신호 중 하나 이상이 1이면 출력이 1. 둘 다 0일 때만 0이라고 생각하면 된다.

OR 게이트의 진리표

x1x1x2x2yy
000
101
011
111



퍼셉트론 구현하기

간단한 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
  elif tmp > theta:
    return 1
print(AND(0, 0))
print(AND(1, 0))
print(AND(0, 1))
print(AND(1, 1))

출력 결과


가중치와 편향 도입


y={0(w1x1+w2x2θ)1(w1x1+w2x2>θ)y = \begin{cases} {0 (w_1x_1 + w_2x_2 \le \theta)} \\ {1 (w_1x_1 + w_2x_2 > \theta)} \end{cases}

위 식에서 θ\thetab-b로 치환하면 다음과 같은 식으로도 표현할 수 있다.

y={0(w1x1+w2x2+b0)1(w1x1+w2x2+b>0)y = \begin{cases} {0 (w_1x_1 + w_2x_2 + b \le 0)} \\ {1 (w_1x_1 + w_2x_2 + b > 0)} \end{cases}

여기서 bb를 편향(bias) 라고 표현하기도 한다. θ\thetab-b로 치환한 AND게이트는 다음과 같이 구현할 수 있다.

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
print(AND(0, 0))
print(AND(1, 0))
print(AND(0, 1))
print(AND(1, 1))
  • 넘파이를 이용하여 x,wx, w 두 배열 간 벡터 연산을 시행하고 합을 구한 다음, bias를 더하여 0보다 크면 1을, 0보다 작으면 0을 return

출력 결과


비슷한 방식으로 NAND, OR 게이트를 구현한 코드는 다음과 같다.

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

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
print(NAND(0, 0))
print(NAND(1, 0))
print(NAND(0, 1))
print(NAND(1, 1), end='\n\n')

print(OR(0, 0))
print(OR(1, 0))
print(OR(0, 1))
print(OR(1, 1))

출력 결과

위 코드의 w,bw, b 값 말고도 다양한 조합으로 AND, OR, NAND 게이트를 구현할 수 있다. 하지만 위와 같은 단층 퍼셉트론으론 구현할 수 없는 게이트가 있다.


퍼셉트론의 한계

위에서 표현한 AND, OR, NAND 게이트는 선형적으로 결과를 나누는 것이 가능하다. 예를 들어 (b,w1,w2)=(0.5,1.0,1.0)(b, w1, w2) = (-0.5, 1.0, 1.0) 으로 OR 게이트를 만족시키는 퍼셉트론을 그림으로 그려보면 다음과 같다.

y={0(w1x1+w2x20.50)1(w1x1+w2x20.5>0)y = \begin{cases} {0 (w_1x_1 + w_2x_2 - 0.5 \le 0)} \\ {1 (w_1x_1 + w_2x_2 - 0.5 > 0)} \end{cases}

위 그림에서 보면 직선을 기준으로 아래 구역은 0이 출력 되고, 위 구역은 1이 출력된다. 하지만, XOR 게이트는 위와 같이 0, 1이 출력되는 구간을 선형적으로 나눌 수 없다.

XOR 게이트

배타적 논리합으로 x1,x2x1,x2 중 한 쪽이 1일 때만 1을 출력한다. 두 입력 값 중 하나만 1일 때 1을 출력한다고 생각하면 된다.

XOR 게이트의 진리표

x1x1x2x2yy
000
101
011
110

위와 같은 XOR 게이트의 입력 시 출력 결과를 살펴보자.

○는 0이 출력, △는 1이 출력된다. 도무지 직선 하나로 두 구역을 나눌 방법은 생각할 수 없다. 하지만, 다층 퍼셉트론을 이용하여 비선형적으로 접근한다면 가능하다.


다층 퍼셉트론

위에서 살핀 퍼셉트론을 여러 층 쌓아 더 다양한 회로를 만들 수 있다.


기존 게이트 조합하여 XOR 게이트 구현

다음 그림과 같이 x1,x2x1, x2를 NAND, OR 게이트에 입력하여 나온 출력들을 AND 게이트에 입력하여 XOR 게이트를 구현할 수 있다. 이를 진리표로 다시 구성하면 다음과 같다.

XOR 게이트의 진리표

x1x1x2x2s1s1s2s2yy
00100
10111
01111
11010

s1,s2s1, s2는 각각 NAND의 출력, OR의 출력 결과이다. 2층 퍼셉트론으로 표현하면 아래와 같다.


XOR 게이트 구현 코드

# 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))
print(XOR(1, 0))
print(XOR(0, 1))
print(XOR(1, 1))

출력 결과

profile
큰 사람이 되겠어요

0개의 댓글