본문 바로가기
Machine-Learning/Basic

[ML] 퍼셉트론과 인공신경망

by AteN 2021. 3. 4.

생물학적 뉴런과 퍼셉트론 

생물학적으로 신경 세포인 뉴런은 여러 개의 수상 돌기 (Denrites)로부터 서로 다른 세기의 전기적인 신호를 받고 이 신호 세기의 합이 정해진 임계값을 넘으면 시냅스(Synapse)를 통해 출력 신호를 보낸다. 이 출력은 또 다른 뉴런으로 연결되어 같은 과정을 반복하는 것이다. 

생물학적 뉴런

인간의 신경망은 수 많은 뉴런들이 연결되어 뇌로 정보를 전달하는 구조를 지닌다. 딥러닝은 인간의 신견망을 모사하여 만든 인공 신경망 (Artificial Neural Network)을 기반으로 학습하는 방법이다. 

인공 신경망은 노드와 가중치가 연결된 구조로써 노드 (Node)는 뉴런에 해당하고 가중치 (Weight)는 시냅스에 대응하는 개념이다. 이때 노드에 있는 값과 시냅스에서 나오는 가중치가 선형 결합 (Linear Combination)의 형태로 계산되어 다음 노드로 정보가 전달된다. 

인공 신견망은 3가지 종류의 층으로 나눌 수 있으며, 각 층마다 원형으로 표시된 노드로 구성되어 있다. 가장 첫 번째 입력층 (input layer)이라고 하며 처음 데이터가 들어오는 층을 의미한다. 

받은 데이터의 값은 가중치가 있는 선을 거쳐 일련의 계산을 통해 은닉층(Hidden Layer)으로 보내지고, 다시 다음 가중치와 계산된 값은 마지막 결과 산출에 해당하는 출력층 (Output Layer)으로 보내지게 된다. 

이때 입력측과 출력층 사이에 있는 은닉층이 많은 경우를 깊은 신견망이라고 말한다. 또한 입력층에서 부터 은닉층을 거쳐 출력층까지 계산 과정을 순전파(Forward Propagation)라고 하며 실질적인 예측 과정에 해당한다. 

 

퍼셉트론 (perceptron)

퍼셉트론은 프랑크 로젠블라트(Frank Rosenblatt)가 1957년에 고안한 알고리즘이다. 위에서 설명했듯이 인공신견망은 뉴런의 형태를 모사하여 만들었고, 퍼셉트론은 뉴런이 하나뿐이 가장 간단한 형태의 신경망이다.  다수의 신호를 입력으로 받아 활성화 함수와 함께 사용해 출력 값을 다음으로 넘기는 가장 작은 신경망 단위 신경망(딥러닝)의 기원이 되는 알고리즘이라고 할 수 있다. 

그럼 기본적으로 신호란 무엇일까? 

신호란 전류나 강물처럼 흐름이 있는 것이다. 이때 출력 값이 1은 신호가 흐른다는 의미이고 0은 신호가 흐르지 않는다는 의미이다. 

  • 입력값 (x)과 가중치(w)의 곲을 모두 더한 다음 거기에 바이어스(b)를 더한 값을 가중합(y)이라고 한다
    가중합의 결과를 놓고 1 또는 0을 출력해서 다음으로 보내며,  0과 1을 판단하는 함수가 있는데 이를 활성화 함수 (activation function)이라 한다

 

  • 단순한 논리 회로  
    게이트(gate, 회로) 정의
    AND 게이트 모두가 1일때만
    NAND 게이트 Not AND 의미
    OR 게이트 신호중에 하나 이상이 1이면
    XOR 게이트 둘 중 하나만 1일 때 1을 출력

퍼셉트론으로 구현하기 : AND, NAND, OR

  • OR 게이트
    import numpy as np
    
    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
    if __name__ == '__main__':
        for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
            y = OR(xs[0], xs[1])
            print(str(xs) + " -> " + str(y))
    # (0, 0) -> 0
    # (1, 0) -> 1
    # (0, 1) -> 1
    # (1, 1) -> 1​
  • NAND 게이트
    import numpy as np
    
    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
    if __name__ == '__main__':
        for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
            y = NAND(xs[0], xs[1])
            print(str(xs) + " -> " + str(y))
    # (0, 0) -> 1
    # (1, 0) -> 1
    # (0, 1) -> 1
    # (1, 1) -> 0​
  • 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
    if __name__ == '__main__':
        for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
            y = AND(xs[0], xs[1])
            print(str(xs) + " -> " + str(y))
    # (0, 0) -> 0
    # (1, 0) -> 0
    # (0, 1) -> 0
    # (1, 1) -> 1

다층 퍼셉트론


: 기존이 퍼셉트론으로는 XOR를 해결할 수 없어 다층 퍼셉트론으로 그 문제를 해결하였다. , 좌표 평면 자체에 변화를 주어, 두개의 퍼셉트론을 한번에 계산가능하게 만들었으며, 숨어있는 층, 즉 은닉층을 만들어서 그 문제를 해결하였다은닉층에 모이는 중간 정거장을 노드(node)라고 한다

- 위 두 식의 결과값이 출력츠응로 보내지며, 출력층에서는 시그모이드 함수를 통해 y값이 정해진다
이 값을 yout이라 할때 식으로 표현하면

- 각각의 가중치(w) 와 바이어스 (b)의 값을 2차원 배열로 늘어 놓을 수 있으며,
은닉층을 포함해 가중치 6개와 바이어스 3개가 필요하다

 

코딩으로 XOR 문제 해결

import numpy as np

# 가중치와 바이어스
w11 = np.array([-2, -2])
w12 = np.array([2, 2])
w2 = np.array([1, 1])
b1 = 3
b2 = -1
b3 = -1

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

# NAND 게이트
def NAND(x1,x2):
    return MLP(np.array([x1, x2]), w11, b1)

# OR 게이트
def OR(x1,x2):
    return MLP(np.array([x1, x2]), w12, b2)

# AND 게이트
def AND(x1,x2):
    return MLP(np.array([x1, x2]), w2, b3)

# XOR 게이트
def XOR(x1,x2):
    return AND(NAND(x1, x2),OR(x1,x2))
    # XOR를 만들어 주기 위해서는 위에서 정의한 AND, NAND, OR를 이용하여 
    # 숨어있는 두 개의 노드를 둔 다층의 퍼셉트론으로 XOR 문제를 해결한다  


# x1, x2 값을 번갈아 대입해 가며 최종값 출력
if __name__ == '__main__':
    for x in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = XOR(x[0], x[1])
        print("입력 값: " + str(x) + " 출력 값: " + str(y))

# 입력 값: (0, 0) 출력 값: 0
# 입력 값: (1, 0) 출력 값: 1
# 입력 값: (0, 1) 출력 값: 1
# 입력 값: (1, 1) 출력 값: 0

 

'Machine-Learning > Basic' 카테고리의 다른 글

[ML] 회귀 (Regression) 평가 지표  (0) 2021.09.05
[ML] 분류 (Classification)  (0) 2021.09.05
[ML] Logistic Regression  (0) 2021.03.17
[ML] 회귀(Regression)  (0) 2021.03.15
[ML] 인공지능(AI) 개요  (0) 2019.12.05

댓글