티스토리 뷰

Data Science/Machine Learning

Logistic Regression

Hula_Hula 2018. 11. 9. 23:25

[Logistic Regression]


Logistic Regression은 0과 1, 두개의 결과값이 나오는 데이터를 학습하기 위한 방법론입니다.

Binary Classification이죠.


그래서 Logistic Classification 보다는 Logistic Regression이 조금 더 정확한 말입니다. 하지만 이 회귀의 결과는 (나중에 알게되겠지만) 특정 기준으로 "분류"되고, "Logistic" Classification는 Logistic, 즉 Sigmoid 함수(무한대의 입력을 0~1의 사이값으로 출력)에 착안한 방법론이기 때문에 Classification에 가깝습니다.


먼저 Sigmoid 함수를 도입하게된 과정을 알아보죠.

간단합니다.


우리는 이진분류에 많은 이점을 알고있죠. 스팸/햄 메일(G메일..), 좋아하는게시물/좋아하지 않는 게시물(페이스북 뉴스피드..) 등등 이진분류는 두가지로 간단히 나뉘지만 강력한 힘을 가지고 있습니다.

이진분류이기 때문에 indexing도 편하겠군요. 1과 0.

그럼 나이에 따라서 건망증을 앓고있는 사람(1)과 앓지 않는 사람(0)의 데이터를 얻어 그래프를 그려보겠습니다.


[그림1] 51세부터 건망증 환자가 생기는 근거 없는 데이터이다.


그렇죠. 그냥 제 생각대로 그려본 데이터입니다. 어디가서 건망증이 생기는 평균 나이가 51세라고 하시면 안됩니다.

자, 이 데이터는 아주 예쁘게 두 부류로 나뉘어져 있는데요. 이걸 Linear Regresstion 처럼 그려도 무방할 것 같습니다.


[그림2] 이렇게 깔끔하게 나이에 맞춰 건망증에 걸린다면 세상이 우울해질 것 같다.


Linear Regression 처럼 Cost값을 구해 나가면 이런 1차 함수의 직선 그래프를 그릴 수 있을 것 같습니다.

병의 여부가 대략 0.4 아래인 사람들(51세 이하)은 모두 0으로 처리되고 병이 걸리지 않았다라고 가정하죠.

이런 Linear한 선을 그었을 때, 0.4보다 작은 사람은 건망증에 걸리지 않은 사람들이고 이렇게 학습된 데이터로 예측을 할 수 있겠죠.


하지만, 갑자기 200살의 할머니가 나타났습니다. 그럼 선이 어떻게 변할까요?

[그림3] 더 누워있는 선으로 바뀔 것이다.


0.4를 기준으로 0.4 아래인 사람들은 모두 건망증이 걸리지 않았다고 진단했는데, 200살 할머니가 나타나면서 두명이 건망증에 걸리지 않게 되었습니다. 

결론은 이런 분류 작업을 Linear Regression을 통해 예측하면 오류가 생긴다는 겁니다.


그래서 Sigmoid 함수가 등장합니다.


logistic regression에 대한 이미지 검색결과

[그림4] S자 모양으로 생겨서 Sigmoid 함수(그래프) 혹은 Logistic 함수라고 부른다.


이 Sigmoid 그래프는 0보다 작거나 1보다 큰 숫자를 갖지 않습니다.

데이터의 범위가 늘어나도 z값이 움직이지 않습니다.

z값에 따라 0~1의 값이 결정되므로 Hypothesis는 이렇게 바뀔 수 있습니다.



는 X와 곱이 되지 않는 행렬의 형태일 때, transpose 해서 계산하라는 의미입니다.



(이 함수가 그냥 생겨난 것은 아닙니다. (Odds = 성공할 확률 / 실패할 확률) 의 개념에서 나왔습니다. 실패할 확률 = (1 - 성공할 확률)이므로 분모에 들어갔습니다. http://mazdah.tistory.com/769 참고)


그럼 Cost Function은 그대로 사용하면 될까요?

Linear Regression에서 사용하던 Cost Function은 "제곱"의 평균입니다. 1차식의 제곱은 매끈한 선으로 나오지만 지수함수의 차이를 제곱하면 울퉁불퉁한 선이 나오게 됩니다. 그럼 최소값(기울기가 0)을 구하기 힘들겠죠.


그래서 Cost Function도 다시 설정합니다.





logistic regression cost function에 대한 이미지 검색결과

[그림5] g(x)는 Sigmoid function으로 Hypothesis이다. 이 그림에서 g(x) = H(x)라고 생각하자!



Cost Function의 의미를 다시 생각해보죠.

Hypothesis로 예측한 값과 실제 값(y)의 차이를 나타내기 위한 함수죠. 이 두 값이 같다면 Cost 값은 0이 나와야 합니다. y의 범위는 0~1, hypothesis의 범위도 0~1입니다.


y = 0 일 때, cost function은 [그림5]의 (b)입니다. H(x)가 0이면 y값과 같기 때문에 cost가 줄어듭니다. 반면 hypothesis가 1로 이동하면 cost값이 무한대로 높아집니다.

이는 y가 1일 때도 동일한 원리입니다.


이 두 식을 선형결합 해보겠습니다.



이렇게 식을 표현하면 y=0 일 때, 오른쪽 항만 남고 y=1일 때는 왼쪽 항만 남게 됩니다.

모든 x와 y에 대한 평균값을 구해야하므로



로 정리됩니다.


그 이후는 learning rate와 함께 미분해주는 원리는 Linear Regression과 같습니다.




[문제]


가장 기본적인 문제로 Logistic Regression의 Hypothesis와 Cost Function을 사용해보도록 하겠습니다.


1, 2, 0

2, 3, 0

3, 1, 0

4, 3, 1

5, 3, 1

6, 2, 1

이라는 테이블 데이터가 있습니다. 세번째 열이 y에 해당하고 첫번째와 두번째 열의 데이터가 2차원 x데이터가 됩니다.


import tensorflow as tf
import numpy as np

x_data = [[1,2],[2,3],[3,1],[4,3],[5,3],[6,2]]
y_data = [[0],[0],[0],[1],[1],[1]]

X = tf.placeholder(tf.float32, shape=[None, 2]) ## 행은 n개, 열은 2개의 Shape을 가지고 있다.
Y = tf.placeholder(tf.float32, shape=[None, 1])

W = tf.Variable(tf.random_normal([2,1]), name = 'weight')
b = tf.Variable(tf.random_normal([1]), name = 'bias')

hypothesis = tf.sigmoid(tf.matmul(X, W) + b) ## matmul = 행렬 내적, sigmoid = 시그모이드 함수 호출


개념이해는 힘들지 몰라도 Tensorflow는 사용하기에 굉장히 편리합니다.

tf.sigmoid와 tf.matmul이면 그 복잡한 hypothesis를 순식간에 만들어주죠.


이제 cost function을 표현해보겠습니다.


## cost function
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1-Y) * tf.log(1- hypothesis))

## minimize cost
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)

## True(1), False(0) 설정
predicted = tf.cast(hypothesis > 0.5, dtype = tf.float32) ## 0.5이상일 때 True(1), else False(0)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted,Y), dtype = tf.float32))
## hypothesis와 Y가 같을 때를 뽑아서 평균을 내면 정확도를 확인할 수 있다.

## 초기화
sess = tf.Session()
sess.run(tf.global_variables_initializer())



for step in range(10001):
cost_val, _ = sess.run([cost, train], feed_dict = {X:x_data, Y:y_data})
if step % 200 == 0:
print(step, cost_val)


h, c , a = sess.run([hypothesis, Y, accuracy], feed_dict = {X:x_data, Y:y_data})
print("hypothesis:",h,"Y:", c,"accuracy:", a)


(참고) tf.cast()는 조건에 맞게 데이터 형태를 뽑아오는 함수이다. tf.cast(x, tf.int32)는 x에서 소수점을 버리고 가져오는 함수이고 tf.cast(x>5, tf.float32)는 x>5의 조건에 맞는 x만 float형태로 가져오는 것이다.


[전체코드]


import tensorflow as tf
import numpy as np

x_data = [[1,2],[2,3],[3,1],[4,3],[5,3],[6,2]]
y_data = [[0],[0],[0],[1],[1],[1]]

X = tf.placeholder(tf.float32, shape=[None, 2]) ## 행은 n개, 열은 2개의 Shape을 가지고 있다.
Y = tf.placeholder(tf.float32, shape=[None, 1])

W = tf.Variable(tf.random_normal([2,1]), name = 'weight')
b = tf.Variable(tf.random_normal([1]), name = 'bias')

hypothesis = tf.sigmoid(tf.matmul(X, W) + b) ## matmul = 행렬 내적, sigmoid = 시그모이드 함수 호출

## cost function
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1-Y) * tf.log(1- hypothesis))

## minimize cost
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)

## True(1), False(0) 설정
predicted = tf.cast(hypothesis > 0.5, dtype = tf.float32) ## 0.5이상일 때 True(1), else False(0)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted,Y), dtype = tf.float32))
## hypothesis와 Y가 같을 때를 뽑아서 평균을 내면 정확도를 확인할 수 있다.

## 초기화
sess = tf.Session()
sess.run(tf.global_variables_initializer())



for step in range(10001):
cost_val, _ = sess.run([cost, train], feed_dict = {X:x_data, Y:y_data})
if step % 200 == 0:
print(step, cost_val)


h, c , a = sess.run([hypothesis, Y, accuracy], feed_dict = {X:x_data, Y:y_data})
print("hypothesis:",h,"Y:", c,"accuracy:", a)




'Data Science > Machine Learning' 카테고리의 다른 글

Softmax Regression  (0) 2018.11.14
Logistic Regression으로 당뇨병환자 예측  (0) 2018.11.14
Multi-Variable Linear Regression  (0) 2018.11.07
Linear Regression  (0) 2018.11.03
Machine Learning 이란  (0) 2018.11.01
댓글
최근에 올라온 글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
공지사항
최근에 달린 댓글