ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • AI Logistic regression : 분류(Classification)
    인공지능 2020. 5. 24. 19:46
    728x90

    Logistic regression 은 데이터를 보고 동물인지 식물인지 판별하거나 스팸 메일인지 아닌지 판별하는 등의 분류 문제를 해결하는 방법 중 하나입니다.

     

    Classification 문제는 결과 값이 0 또는 1로 나오는 것이 그 특징입니다.

     

    시그모이드(Sigmoid) 함수

     

    x 축 input 이 어떤 값이 들어오더라도 0 또는 1 사이의 값으로 변환해주는 함수 입니다.

    Linear regression 으로 구해진 z = Wx + b,  z 를 시그모이드 함수에 넣으면 0과 1사이의 값이 나올 것이고, 0.5 보다 크면 1, 작거나 같으면 0으로 분류할 수 있습니다.

     

    시그모이드 함수는 0과 1 사이의 값만을 나타내기 때문에 결과가 나타날 확률이라는 의미를 지니기도 합니다.

     

    Cross entropy

    기존의 Linear regression 이후 signmoid 함수를 거치기 때문에 최종 결과물이 0 또는 1로 나와서 기존의 Loss function 은 사용할 수가 없습니다. 따라서 Logistic regression 을 위한 Loss function 을 새로 정의해야하고, 대표적인 함수로 Cross entropy 가 있습니다.

     

    실제 정답 t 는 0 또는 1 임에 주목해야합니다.

    t 가 만약 1이라면 우항의 (1 - ti) 가 0이 되므로 좌항의 값만 남게되고

    t 가 만약 0이라면 좌항의 ti 가 0이 되므로 우항의 값만 남게 됩니다.

     

    유도과정

    활성 함수(Activation function)

    Linear regression 작업 후 Sigmoid 같이 데이터를 Classification 에 맞게 변형해주는 함수를 활성함수라고 하며

    Sigmoid 뿐만 아니라 ReLU, tanh 같은 함수 들이 있습니다.

     

     

    예제

    공부시간 합격여부
    2 0
    4 0
    6 0
    8 0
    10 0
    12 0
    14 1
    16 1
    18 1
    20 1

    위 데이터에서 입력으로 공부시간이 주어졌을 때 합격할 수 있을지 없을지에 대한 예측 모델을 만들어보겠습니다.

     

    학습 데이터 준비

    # 학습 데이터 준비
    x_data = np.array([i for i in range(2, 21, 2)]).reshape([10, 1])
    y_data = np.array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1]).reshape([10, 1])

    임의의 W, b 준비

    # 임의의 W, b 값 초기화
    W = np.random.rand(1, 1)
    b = np.random.rand(1)

    Loss function 준비

    def sigmoid(x):
        return 1 / (1 + np.exp(-x))
    
    
    def loss_func(x, t):
        delta = 1e-7
        z = np.dot(x, W) + b
        y = sigmoid(z)
    
        # -log(t * y + (t - 1) * (y - 1))
        # 크로스 엔트로피
        return -np.sum(np.log(t * (y + delta) + (t - 1) * (y - 1 + delta)))

    크로스 엔트로피에 y + delta, y - 1 + delta 가 있는걸 볼 수 있습니다.

    간혹 y가 0이거나 -1 인 경우 delta 를 더해주지 않으면 log 함수에 의해 무한대값이 튀어나옵니다.

    loss 가 무한대로 나와버리면 learning_rate 로 아무리 보정해도 감당할 수 없기 때문에 무한대 값이 나오지 않도록 보정하는 역할을 합니다.

     

    수치미분

    def numerical_derivative(f, input_data):
        delta_x = 1e-4
        iter = np.nditer(input_data, flags=['multi_index'])
        ret = np.zeros_like(input_data)
    
        while not iter.finished:
            idx = iter.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) / (delta_x * 2)
            input_data[idx] = tmp
            iter.iternext()
    
        return ret

    학습 및 결과

    def predict(x):
        y = sigmoid(np.dot(x, W) + b)
        if y < 0.5:
            return 0
        return 1
    
    
    error_val = loss_func
    f = lambda x: loss_func(x_data, y_data)
    learning_rate = 1e-2
    
    for step in range(8001):
        W -= learning_rate * numerical_derivative(f, W)
        b -= learning_rate * numerical_derivative(f, b)
    
        if step % 400 == 0:
            print('step = ', step, 'error = ', error_val(x_data, y_data), 'W = ', W, 'b = ', b)
    
    print(predict(3))

     

    3 시간 시험공부를 하면 합격할 수 없다는 예측 결과를 받게 되었습니다.

     

    전체코드

    import numpy as np
    
    # 학습 데이터 준비
    x_data = np.array([i for i in range(2, 21, 2)]).reshape([10, 1])
    y_data = np.array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1]).reshape([10, 1])
    
    # 임의의 W, b 값 초기화
    W = np.random.rand(1, 1)
    b = np.random.rand(1)
    
    
    def sigmoid(x):
        return 1 / (1 + np.exp(-x))
    
    
    def loss_func(x, t):
        delta = 1e-7
        z = np.dot(x, W) + b
        y = sigmoid(z)
    
        # 크로스 엔트로피
        # -log(t * y + (t - 1) * (y - 1))
        return -np.sum(np.log(t * (y + delta) + (t - 1) * (y - 1 + delta)))
    
    
    def numerical_derivative(f, input_data):
        delta_x = 1e-4
        iter = np.nditer(input_data, flags=['multi_index'])
        ret = np.zeros_like(input_data)
    
        while not iter.finished:
            idx = iter.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) / (delta_x * 2)
            input_data[idx] = tmp
            iter.iternext()
    
        return ret
    
    
    def predict(x):
        y = sigmoid(np.dot(x, W) + b)
        if y < 0.5:
            return 0
        return 1
    
    
    error_val = loss_func
    f = lambda x: loss_func(x_data, y_data)
    learning_rate = 1e-2
    
    for step in range(8001):
        W -= learning_rate * numerical_derivative(f, W)
        b -= learning_rate * numerical_derivative(f, b)
    
        if step % 400 == 0:
            print('step = ', step, 'error = ', error_val(x_data, y_data), 'W = ', W, 'b = ', b)
    
    print(predict(3))
    

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

    AI Multi layer (XOR 문제)  (0) 2020.05.29
    AI Logistic regression 예제  (0) 2020.05.26
    AI Linear regression 예제  (0) 2020.05.24
    AI Linear regression 파이썬 구현  (0) 2020.05.24
    AI Gradient descent 알고리즘  (0) 2020.05.24

    댓글

Designed by Tistory.