ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 딥러닝 기초 (XOR 문제 해결)
    인공지능 2020. 6. 1. 14:23
    728x90

    2020/05/29 - [AI] - AI Multi layer (XOR 문제)

     

    AI Multi layer (XOR 문제)

    지금까지 공부했던 Logistic regression 으로는 XOR 문제를 풀 수 없는데 오늘은 그것에 대해 알아볼게요 기본 구현 Sigmoid(), numerical_derivation() 함수 준비 # 시그모이드 함수 # 입력 x에 대해서 결과가 1..

    bubble-dev.tistory.com

     

    이 전에 XOR 문제를 해결하기 위해 AND, OR, NAND 게이트를 결합시킨 방법인 Multi layer로 해결하는 방법에 대해 알아봤었습니다.

    요즘 핫한 딥러닝이란게 이런 Multi layer 방법을 발전시킨 방법인데요.

     

    Multi layer 방식에서 얻을 수 있는 중요한 인사이트 중 하나가 특정 모델의 출력이 다른 모델의 입력이 된다. 였습니다.

     

    사람의 신경(뉴런)도 동일한 동작 방식을 가집니다.

    다만 정해진 임계값을 넘어선 입력값이 들어와야 반응한다는 것이 차이점입니다.

     

    예를 들면 슬픈 영화를 봤을 때 5만큼 슬플 때는 눈물 뉴런이 반응하지 않다가 10만큼 슬플 때 눈물 뉴런이 반응한다던가 하는 것이지요

    물론 5이냐 10이냐는 사람마다 다르고, 이 값이 작은 사람은 조금만 슬퍼도 우는 사람, 큰 사람은 많이 슬퍼야 우는 사람이 되겠습니다.

     

    신경망

     

     

    다변수(Multiple variable) Logistic Regression

    신경망 기법을 사용하려면 Multi variable Logistic Regression 을 구현한 뒤 각각의 모델을 결합하는 방식을 사용해야합니다.

    인공 신경망

    입력과 출력이 있을 때 이 전까지는 입력과 출력을 직접 잇는 z = Wx + b 를 구하고 여기에 sigmoid(z) 를 취했습니다.

    하지만 신경망 기법은 입력과 출력을 직접 잇는 것이 아닌 한 개 이상의 층을 두어 간접적으로 잇는 방식을 사용합니다.

     

    입력층

    입력에서 값을 받아들이는 최초의 층을 말합니다.

    은닉층

    입력층과 출력층 사이의 모든 층을 은닉층이라 부릅니다.

    출력층

    Feed Forward

    이전 층의 출력이 다음 층의 입력이 되는 방식을 일컫는 말입니다.

    딥러닝

    은닉층의 깊이를 깊게 만들어서 많은 층을 거치며 학습한다하여 딥러닝 이라는 이름이 붙게 되었습니다.

     

    Feed forward 표기법(Notation)

    Feed forward notation

    그림 상에서 가중치는 선으로 표시된 것으로, 계층간 가중치를 표현할 때 화살표가 m에서 출발하여 l 로 도착하는 것이 아닌, l에서 출발하여 m으로 도착하는 가중치라는 것. 생각되는것과는 달리 거꾸로 표현된다는 것만 기억하시면 됩니다.

     

    딥러닝

    입력층의 출력

    입력을 그대로 행렬 형태로 내보낸 것입니다.

    은닉층 Linear Regression 값

    은닉층의 Linear Regression 의 입력으로는 이전 층의 출력이 들어옵니다.

    그렇게 들어온 입력 x에 대해서 z = Wx + b 의 수식을 가진 Linear Regression 을 찾습니다.

     

    위 그림의 경우 각 층마다 2개의 노드를 갖고 있으므로 각 층마다 2개의 출력을 내며, 이는 곧 각 층의 입력값 또한 2개라는 것을 의미합니다.

    따라서 z = W1x1 + W2x2 + b 가 될 것입니다.

     

    이를 행렬식으로 표현하는 것은 머신러닝에서 자주 사용되는 표현입니다.

    은닉층 출력

    은닉층의 출력을 위해 Linear Regression 값 z를 구하고, 그 값에 Activation function(z) 를 취한 값이 은닉층의 출력이 됩니다.

    즉 각 층의 각 노드마다 정해진 임계값이 있으며 해당 임계값을 넘게되면 1 아니면 0이 될 것입니다.

    출력층 출력

    출력층은 Logistic regression 특징 상 0 또는 1이므로 하나의 출력을 내야하므로 한 개의 노드를 갖게 됩니다.

    은닉층과 동일한 과정을 거쳐 출력하게됩니다.

     

    XOR 문제

    은닉층을 한 층만 두었고, 그 노드를 6개 두었습니다.

    이 층의 두께와 노드의 갯수는 구현하는 사람 마음이지만 너무 많이 두게 되면 학습이 오래걸린다는 단점이 있습니다.

     

    저의 경우에는 은닉층을 하나의 층으로만 두었고, 6개의 노드로 학습을 진행했습니다.

    코드

    import numpy as np
    
    
    # 시그모이드 구하는 함수
    def sigmoid(x):
        return 1 / (1 + np.exp(-x))
    
    
    # 수치 미분 함수
    def numerical_derivative(f, input_data):
        delta_x = 1e-4
    
        ret = np.zeros_like(input_data)
        it = np.nditer(input_data, flags=['multi_index'])
    
        while not it.finished:
            idx = it.multi_index
    
            tmp = input_data[idx]
            input_data[idx] = float(tmp) + delta_x
            fx1 = f(input_data)
    
            input_data[idx] = float(tmp) - delta_x
            fx2 = f(input_data)
    
            ret[idx] = (fx1 - fx2) / (2 * delta_x)
            input_data[idx] = tmp
            it.iternext()
    
        return ret
    
    
    class LogicGate:
    
        def __init__(self, gate_name, x_data, t_data):
            self.name = gate_name
    
            # 입력 데이터
            self.__x_data = x_data
            self.__t_data = t_data
    
            # 임의의 W2, b2, W3, b3 준비
            self.__W2 = np.random.rand(2, 6)
            self.__b2 = np.random.rand(6)
    
            self.__W3 = np.random.rand(6, 1)
            self.__b3 = np.random.rand(1)
    
            self.__learning_rate = 1e-1
            self.loss_func = self.__feed_forward
    
        # feed_forward 함수로, 에러를 찾아줌
        def __feed_forward(self):
            delta = 1e-7
    
            # 입력층 -> 은닉층
            z2 = np.dot(self.__x_data, self.__W2) + self.__b2
            a2 = sigmoid(z2)
    
            # 은닉층 -> 출력층
            z3 = np.dot(a2, self.__W3) + self.__b3
            y = sigmoid(z3)
    
            # 크로스 엔트로피로 에러를 측정
            return -np.sum(self.__t_data * np.log(y + delta) + (1 - self.__t_data) * np.log(1 - y + delta))
    
        def train(self):
            f = lambda x: self.__feed_forward()
    
            print("Initial W2 = ", self.__W2, "b2 = ", self.__b2, "W3 = ", self.__W3, "b3 = ", self.__b3, "error_val = ", self.loss_func())
    
            for step in range(8001):
                self.__W2 -= self.__learning_rate * numerical_derivative(f, self.__W2)
                self.__b2 -= self.__learning_rate * numerical_derivative(f, self.__b2)
                self.__W3 -= self.__learning_rate * numerical_derivative(f, self.__W3)
                self.__b3 -= self.__learning_rate * numerical_derivative(f, self.__b3)
    
                if step % 400 == 0:
                    print("step = ", step, "W2 = ", self.__W2, "b2 = ", self.__b2, "W3 = ", self.__W3, "b3 = ", self.__b3, "error_val = ", self.loss_func())
    
        def predict(self, x_data):
            z2 = np.dot(x_data, self.__W2) + self.__b2
            a2 = sigmoid(z2)
    
            z3 = np.dot(a2, self.__W3) + self.__b3
            pro = sigmoid(z3)
    
            if pro < 0.5:
                return 0, pro
            return 1, pro
    
    
    # XOR 데이터
    x_data = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]).reshape([4, 2])
    y_data = np.array([0, 1, 1, 0]).reshape([4, 1])
    
    # 학습
    XOR_Gate = LogicGate("XOR_Gate", x_data, y_data)
    XOR_Gate.train()
    
    # 출력
    print(XOR_Gate.predict([0, 0]))
    print(XOR_Gate.predict([1, 0]))
    print(XOR_Gate.predict([0, 1]))
    print(XOR_Gate.predict([1, 1]))
    

    '인공지능' 카테고리의 다른 글

    AI Back propagation(오차역전파)  (1) 2020.06.06
    딥러닝 MNIST 필기체 인식  (0) 2020.06.03
    AI Multi layer (XOR 문제)  (0) 2020.05.29
    AI Logistic regression 예제  (0) 2020.05.26
    AI Logistic regression : 분류(Classification)  (0) 2020.05.24

    댓글

Designed by Tistory.