본문 바로가기

인공지능

[인공지능] 로지스틱 회귀(logistic regression)과 1-layer perceptron의 차이는 무엇일까?

thebook.io/080228/part03/ch06-01/

여기에 있는 글을 정리한것.

 

모두의 딥러닝 개정2판: 6장 퍼셉트론 - 1

 

thebook.io

로지스틱 회귀는 참 거짓 판단장치이다. 

 

점수가 아니라 함격과 불합격만 발표되는 시험이 있다고 하자.  공부한 시간에 따른 합격여부는 표 5-1과 같다. 

앞장에서 배운 대로 선을 그어 이 점의 특성을 잘 나타내는 일차 방정식을 만들 수 있을까요? 이 점들은 1과 0 사이의 값이 없으므로 직선으로 그리기가 어렵습니다. 점들의 특성을 정확하게 담아내려면 직선이 아니라 다음과 같이 S자 형태여야 합니다.

 

그림 5-2

각 점의 특성을 담은 선을 그었을 때

로지스틱 회귀는 선형 회귀와 마찬가지로 적절한 선을 그려가는 과정입니다. 다만 직선이 아니라, 참(1)과 거짓(0) 사이를 구분하는 S자 형태의 선을 그어 주는 작업입니다.

 

 

2 시그모이드 함수

 

그런데 이러한 S자 형태로 그래프가 그려지는 함수가 있습니다. 바로 우리가 ‘2장 딥러닝을 위한 기초 수학’에서 배운 시그모이드 함수(sigmoid function)입니다. 시그모이드 함수를 이용해 로지스틱 회귀를 풀어나가는 공식은 다음과 같습니다.

 

 

이 식을 통해 우리가 알 수 있는 것은 우리가 구해야 하는 값이 여기서도 결국 ax + b라는 것입니다. 선형 회귀 때와 마찬가지지요. 그러면 여기에서의 ab는 무슨 의미를 가지고 있을까요?

먼저 a는 그래프의 경사도를 결정합니다. 그림 5-3과 같이 a 값이 커지면 경사가 커지고 a 값이 작아지면 경사가 작아집니다.

 

그림 5-3

a 값이 클 때와 작을 때의 그래프 변화

 

b는 그래프의 좌우 이동을 의미합니다. 그림 5-4와 같이 b 값이 크고 작아짐에 따라 그래프가 이동합니다.

 

그림 5-4

b 값이 클 때와 작을 때의 그래프 변화

 

따라서 ab의 값에 따라 오차가 변합니다. a 값에 따라 변화하는 오차를 그래프로 나타내면 다음과 같습니다.

 

그림 5-5

a와 오차와의 관계: a가 작아질수록 오차는 무한대로 커지지만, a가 커진다고 해서 오차가 없어지지는 않는다.

 

a 값이 작아지면 오차는 무한대로 커집니다. 그런데 a 값이 커진다고 해서 오차가 무한대로 커지지는 않습니다.

한편, b 값에 따른 오차의 그래프는 그림 5-6과 같습니다.

 

그림 5-6

b와 오차와의 관계: b 값이 너무 작아지거나 커지면 오차도 이에 따라 커진다.

 

b 값이 너무 크거나 작을 경우 오차는 위와 같이 이차 함수 그래프와 유사한 형태로 나타납니다.

 

3 오차 공식

 

이제 우리에게 주어진 과제는 또다시 ab의 값을 구하는 것임을 알았습니다. 시그모이드 함수에서 ab의 값을 어떻게 구해야 할까요? 답은 역시 경사 하강법입니다.

그런데 경사 하강법은 먼저 오차를 구한 다음 오차가 작은 쪽으로 이동시키는 방법이라고 했습니다. 그렇다면 이번에도 예측 값과 실제 값의 차이, 즉 오차를 구하는 공식이 필요합니다. 오차 공식을 도출하기 위해 시그모이드 함수 그래프의 특징을 다시 한번 살펴보겠습니다.

 

그림 5-7

시그모이드 함수 그래프

 

시그모이드 함수의 특징은 y 값이 0과 1 사이라는 것입니다. 따라서 실제 값이 1일 때 예측 값이 0에 가까워지면 오차가 커집니다. 반대로, 실제 값이 0일 때 예측 값이 1에 가까워지는 경우에도 오차는 커집니다. 이를 공식으로 만들 수 있게 해 주는 함수가 바로 로그 함수입니다.

 

4 로그 함수

2장 딥러닝을 위한 기초 수학편, 로그 함수에서 배운 그래프를 다시 가져오겠습니다.

 

그림 5-8

실제 값이 1일 때(파란색)와 0일 때(빨간색) 로그 함수 그래프

 

파란색 선은 실제 값이 1일 때 사용할 수 있는 그래프입니다. 예측 값이 1일 때 오차가 0이고, 반대로 예측 값이 0에 가까울수록 오차는 커집니다.

빨간색 선은 반대로 실제 값이 0일 때 사용할 수 있는 함수입니다. 예측 값이 0일 때 오차가 없고, 1에 가까워질수록 오차가 매우 커집니다.

앞의 파란색과 빨간색 그래프의 식은 각각 -logh -log(1 - h)입니다. 실제 값이 1일 때는 -logh 그래프를 쓰고, 0일 때는 -log(1 - h) 그래프를 써야 합니다. 이는 다음과 같은 방법으로 해결할 수 있습니다.

 

 

실제 값을 y_data라 할 때, 이 값이 1이면 b 부분이 없어집니다. 반대로 0이면 a 부분이 없어집니다. 따라서 실제 값에 따라 빨간색 그래프와 파란색 그래프를 각각 사용할 수 있게 됩니다.

 

5 코딩으로 확인하는 로지스틱 회귀

 

지금까지 배운 것을 정리하면, 로지스틱 회귀를 위해서는 시그모이드 함수를 사용한다는 것, 그리고 0부터 1사이의 값을 가지는 특성 때문에 로그 함수를 함께 써야 한다는 것입니다. 이제 경사 하강법을 이용해 ab의 최적 값을 찾는 과정을 해 볼 차례입니다. 앞서 선형 회귀에서 배운 것과 방법은 동일합니다. 먼저 공부 시간과 합격 여부 리스트를 다음과 같이 만들어 줍니다.

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] # 합격 여부

이를 그래프로 나타내면 다음과 같습니다.

 

import matplotlib.pyplot as plt

plt.scatter(x_data, y_data)
plt.xlim(0, 15)
plt.ylim(-.1, 1.1)

그림 5-9

공부 시간에 따른 합격 여부를 그래프로 나타낸 모습

 

기울기와 a와 절편 b의 값을 초기화하고 학습률을 정합니다. 학습률은 임의로 0.05로 정하겠습니다.

a = 0
b = 0
lr = 0.05 # 학습률

이제 시그모이드 함수를 정의합니다.

def sigmoid(x):                   # sigmoid라는 이름의 함수 정의
    return 1 / (1 + np.e ** (-x)) # 시그모이드 식의 형태 그대로 파이썬으로 옮김

이제 경사 하강법을 시행할 순서입니다. ab로 편미분한 값(a_diff, b_diff)에 학습률(lr)을 곱하여 각각 업데이트 하는 방법은 앞서 배운 선형 회귀와 같습니다. 다만 오차를 구하는 함수가 다르므로 a_diffb_diff를 결정하는 식에 변화가 생깁니다. 로지스틱 회귀의 오차 함수는 조금 전에 배운 것을 이용해 다음과 같은 식으로 표시할 수 있습니다.(정확히 말하면 cost function의 합 J)

 

cost function이 왜 위와 같이 나오는지 이해가  안갈 경우 참고.
https://daeson.tistory.com/180

이 식을 ab로 편미분 하는 과정은 꽤 복잡한 수학의 영역이므로 여기에 옮기지는 않겠습니다. 이 식을 편미분한 후 파이썬 코드로 옮겨 놓은 결과가 다음과 같다는 것은 기억하기 바랍니다.

for i in range(2001):
    for x_data, y_data in data:
        # a에 관한 편미분. 앞서 정의한 sigmoid 함수 사용
        a_diff = x_data*(sigmoid(a*x_data + b) - y_data)
        # b에 관한 편미분
        b_diff = sigmoid(a*x_data + b) - y_data
        # a를 업데이트 하기 위해 a - diff에 학습률 lr을 곱한 값을 a에서 뺌
        a = a - lr * a_diff
        # b를 업데이트 하기 위해 b - diff에 학습률 lr을 곱한 값을 b에서 뺌
        b = b - lr * b_diff

이제 모든 코드를 함께 모아보고 실행해 보겠습니다.

 

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))

# 경사 하강법 실행
# 1,000번 반복될 때마다 각 x_data 값에 대한 현재의 a 값, b 값 출력
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:
            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()

6 로지스틱 회귀에서 퍼셉트론으로

 

지금까지 배운 내용을 정리해 보겠습니다. 입력 값을 통해 출력 값을 구하는 함수 y는 다음과 같이 표현할 수 있습니다.

 

 

우리가 가진 값은 x1과 x2입니다. 이를 입력 값이라고 합니다. 그리고 계산으로 얻는 값 y를 출력 값이라고 합니다. 즉, 출력 값을 구하려면 a1 값, a2 값 그리고 b 값이 필요합니다.

이를 그림으로 나타내면 그림 5-11과 같습니다.

 

그림 5-11

로지스틱 회귀를 퍼셉트론 방식으로 표현한 예

 

x1과 x2가 입력되고, 각각 가중치 a1, a2를 만납니다. 여기에 b 값을 더한 후 시그모이드 함수를 거쳐 1 또는 0의 출력 값 y를 출력합니다. 우리가 지금까지 배운 내용을 그림 5-11은 한눈에 설명하고 있습니다.

 

그런데 이 그림을 아주 오래전에 그려서 발표한 사람이 있었습니다. 1957년, 코넬 항공 연구소의 프랑크 로젠블라트라는 사람은 이 개념을 고안해 발표하고 여기에 퍼셉트론(perceptron)이라는 이름을 붙였습니다.

 

이 퍼셉트론은 그 후 여러 학자들의 노력을 통해 인공 신경망, 오차 역전파 등의 발전을 거쳐 지금의 딥러닝으로 이어지게 됩니다. 다음 장에서는 퍼셉트론이 어떻게 딥러닝의 골격인 신경망을 구성하는지 설명하겠습니다.

 

 

1 가중치, 가중합, 바이어스, 활성화 함수

로지스틱 회귀가 곧 퍼셉트론의 개념이라고 이야기했던 것 기억하나요? 퍼셉트론은 이미 여러분이 배운 것과 다르지 않습니다. 다만 용어를 좀 정리하겠습니다. 중학교 수학 수준에 맞춰 설명했던 기울기 ay 절편 b와 같은 용어를 퍼셉트론의 개념에 맞춰 좀 더 ‘딥러닝답게’ 표현해 보면 다음과 같습니다.

 

y = ax + b (a는 기울기, by 절편)

y = wx + b (w가중치, b바이어스)

 

먼저 기울기 a는 퍼셉트론에서는 가중치를 의미하는 w(weight)로 표기됩니다. y 절편 b는 뭐라고 표기할까요? 똑같이 b라고 씁니다. 하지만 y = ax + bb가 아니라 ‘편향, 선입견’이라는 뜻인 바이어스(bias)에서 따온 b입니다. 그림 6-1을 보면 기울기가 가중치 w로, y 절편은 바이어스의 b로 표기된 것을 알 수 있습니다.

 

그리고 이 그림에 가중합(weighted sum)이라는 용어가 처음 등장했습니다. 입력 값(x)과 가중치(w)의 곱을 모두 더한 다음 거기에 바이어스(b)를 더한 값을 가중합이라고 합니다. 가중합의 결과를 놓고 1 또는 0을 출력해서 다음으로 보냅니다. 여기서 0과 1을 판단하는 함수가 있는데, 이를 활성화 함수(activation function)라고 합니다. 앞서 배웠던 시그모이드 함수가 바로 대표적인 활성화 함수입니다.

 

결론 로지스틱 회귀가 곧 퍼셉트론의 개념이다. (명확히 말하면 같은건 아니다.)

1-layer perceptron으로 로지스틱 회귀를 표현할 수 있다. 

1-layer perceptron의 activation function이 sigmoid(logistic) function 이면 이는 로지스틱 회귀이다. 라고 말할 수 있을듯.