AI/모두의 딥러닝

[Deep Learning : 딥러닝] 로지스틱 회귀(Logistic Regression)

LiDARian 2021. 5. 16. 17:29
반응형

로지스틱 회귀를 써야만 하는 때

0/1,예/아니오 등 두개의 답 중 하나만 내놔야하는 경우에 로지스틱회귀(Logistic Regression)을 사용할 수 있다.

로지스틱 회귀에서 사용하는 함수를 활성화함수(activation function)이라고 하는데, 이 활성화 함수에는 시그모이드(Sigmoid), 렐루(ReLu) 등의 함수가 대표적이다.


그 중에서 시그모이드 함수는 $y = {1 \over 1+e^{-(ax+b)}}$이고, 로지스틱 회귀 문제는 이 함수에서의 $a, b$값을 구하는 것이다. 여기서 $a$는 함수의 경사도, $b$는 함수의 좌우 이동 정도를 나타내게 된다.

이번 포스팅의 주인공 시그모이드 함수

위의 sigmoid function은 0보다 큰 지점에서 1에 가까워져야하고, 0보다 작은 지점에서 0에 가까워져야한다.


여기서 $a$값이 커지는 경우는 오차가 무한으로 커지지는 않겠지만, $a$값이 0으로 작아지면 오차가 무한히 커질 것이다. 0.5에 걸친 직선형태가 될테니깐...

다만 $b$값은 커지던 작아지던 일정 범위에서 벗어나면 오차가 무한히 증가할 것이다.


$a, b$에 대한 각각의 오차 정도는 이렇게 될 것이다. x는 지정한 $a,b$의 값, y축은 오차의 크기

시그모이드 함수의 $a,b$는 경사하강법을 통해서 구한다.


왜 제곱평균으로 구하지 않는 지는 잘 모르겠다. 아마 경사하강법을 도입할 때 시그모이드 함수의 a값이 커질때 오차가 작아지니까, 계속해서 a가 커지는 방향으로만 가는 것을 우려해서 이렇게 오차함수를 새로 정의하는 것 같다. 딥러닝에 관한 수학적 공부를 더 해야 파악할 수 있을 듯?




로그함수를 이용해서 시그모이드 함수의 오차를 다음과 같이 쓴다.

h는 시그모이드 함수값이다. 그리고 logh는 오차값이다. y_data는 실제값(0 or 1)이다.

$-{y_{data}log(h) + (1-y_{data}log(1-h))}$


책에선 하지 않지만 난 이 오차함수의 편미분 결과를 도출해낼 것이다.만약 당신이 문과생이라면 그저 묵념...


우선 시그모이드 함수의 미분은
$sig'(x) = ({1 \over 1+e^{(-x)}})' = sig(a)(1-sig(a))$

이므로, chain rule에 의해 시그모이드 함수에 대한(오차함수가 아니다) $a, b$의 편미분은

$sig(ax+b)(1-sig(ax+b))x$

$sig(ax+b)(1-sig(ax+b))$


이렇게 되고, 이것을 기반으로

$-{y_{data}log(h) + (1-y_{data}log(1-h))} = -{y_{data}log(sig(ax+b)) + (1-y_{data}log(1-sig(ax+b)))}$

을 편미분하면...

아 하기 싫다




$y{sig'(ax+b) \over sig(ax+b)} - (1-y){sig'(ax+b) \over 1-sig(ax+b)}$이렇게 되고,

시그모이드 함수의 $a, b$의 편미분 결과를 대입하면 각각 이렇게 나올 것이다.

$x(sig(ax+b) - y)$

$(sig(ax+b) - y)$



내가 해봤다. 날 믿어라.


사용되는 라이브러리 함수들

matplotlib.pyplot.xlim(_args, *_kwargs)

는 주로 이렇게 사용한다.

left, right = xlim() # return the current xlim
xlim((left, right)) # set the xlim to left, right
xlim(left, right) # set the xlim to left, right

ylim도 똑같이 사용한다.


이건 함수가 아니라 Euler’s constant다

numpy.e


numpy.arange([start, ]stop, [step, ]dtype=None, *, like=None)

구간을 일정한 간격으로 나눠준 list를 반환한다.


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

#공부시간 X와 성적 Y의 리스트를 만듭니다.
data = [[2, 0], [4, 0], [6, 0], [8, 1], [10, 1], [12, 1], [14, 1]]

x_data = [i[0] for i in data]
y_data = [i[1] for i in data]

#그래프로 나타내 봅니다.
plt.scatter(x_data, y_data)
plt.xlim(0, 15)
plt.ylim(-.1, 1.1)

# 기울기 a와 절편 b의 값을 초기화 합니다.
a = 0
b = 0

#학습률을 정합니다.
lr = 0.05 

#시그모이드 함수를 정의합니다.
def sigmoid(x):
    return 1 / (1 + np.e ** (-x))

#경사 하강법을 실행합니다.
for i in range(2001):
    for x_data, y_data in data:
        a_diff = x_data*(sigmoid(a*x_data + b) - y_data) 
        b_diff = sigmoid(a*x_data + b) - y_data
        a = a - lr * a_diff
        b = b - lr * b_diff
        if i % 1000 == 0:    # 1000번 반복될 때마다 각 x_data값에 대한 현재의 a값, b값을 출력합니다.
            print("epoch=%.f, 기울기=%.04f, 절편=%.04f" % (i, a, b))

# 앞서 구한 기울기와 절편을 이용해 그래프를 그려 봅니다.
plt.scatter(x_data, y_data)
plt.xlim(0, 15)
plt.ylim(-.1, 1.1)
x_range = (np.arange(0, 15, 0.1)) #그래프로 나타낼 x값의 범위를 정합니다.
plt.plot(np.arange(0, 15, 0.1), np.array([sigmoid(a*x + b) for x in x_range]))
plt.show()


세개 이상의 입력값은 소프트맥스 함수를 사용해야한다 카더라


다음시간은 퍼셉트론이다.


좀 더 수치해석적인 방법으로 경사하강법을 실시할 수 있으면 좋지 않을까....란 생각이 든다.

참고

*_args, **_kwargs에 대하여

반응형