본문 바로가기
DeepLearning Framework & Coding/Tensorflow 1.X

[코드로 이해하는 딥러닝 8] - Logistic Regression(sigmoid)

by 노마드공학자 2020. 12. 21.

[코드로 이해하는 딥러닝 0] - 글연재에 앞서 https://limitsinx.tistory.com/27

[코드로 이해하는 딥러닝 1] - Tensorflow 시작 https://limitsinx.tistory.com/28 

[코드로 이해하는 딥러닝 2] - Tensorflow 변수선언 https://limitsinx.tistory.com/29

[코드로 이해하는 딥러닝 3] - Tensorflow placeholder변수 https://limitsinx.tistory.com/30

[코드로 이해하는 딥러닝 4] - 선형회귀(Linear Regression) https://limitsinx.tistory.com/31

[코드로 이해하는 딥러닝 5] - 다중선형회귀(Multiple Linear Regression) https://limitsinx.tistory.com/32

[코드로 이해하는 딥러닝 6] - 회귀(Regression)에 대한 다른 접근 https://limitsinx.tistory.com/33

[코드로 이해하는 딥러닝 7] - .txt(.csv)파일 불러오기 https://limitsinx.tistory.com/34

 

※이 전글에서 정리한 코드/문법은 재설명하지 않으므로, 참고부탁드립니다

 

Sigmoid

이제까지는 y=Wx + b 형식으로, Linear Regression을 해보았습니다.

여기서 "Linear"란 선형이란 뜻이죠, Homogenity와 additivity를 둘다 만족한다는게 수학적 정의인데요

 

세상에는 선형적인게 거의 없다고 보시면됩니다.

대부분 Non-linear죠

 

내가 학습시켜야 하는 데이터가 y=ax+b형태로 쫙! 나와 버리면 얼마나 좋겠나만은.. 그런경우는 0이라고 보시면 됩니다.

따라서 비선형(Non-linear) 학습을 하는 방법에 대해서도 숙지를 해야하는데요

 

그 시작이 보통 Logistic Regression (= sigmoid) 입니다.

 

출처 : Wikimedia, Rosenblett image

앞으로 ReLU, Sigmoid, Tanh 같은 여러가지의 비선형함수에 대해 정리를 해나갈건데요

비선형성을 주기위해 사용하는 목적도 있지만, Normalizing을 위해서도 사용합니다.

 

예를들어, y=x1 + 10000x2 + 1000000000000000x3 + b 라는 Hypothesis가 나왔다고 가정해보시죠

 

x1,x2,x3가 가질 수 있는 범위는 엄청나게 차이가 많이나게 될것입니다.

x2는 1만큼만 변해도 10000만큼 y가 변하기때문에 엄청나게 작은 값으로 나올것이고, x1은 상대적으로 큰값이 나오겠죠

 

출처 : sunburg.net

Sigmoid function은 output이 0~1 입니다. 

즉, 어떠한 값을 넣어도 0~1사이로 normalizing 해준다는것이죠. 이를 통해 상대적으로 weighting이 작은 값들이 주목받는(?) 이런 문제점을 해결할 수 있습니다.

 

요약하자면,

 

Sigmoid를 사용하는 이유는, 여러 데이터들의 Normalizing과 Non-linearity를 반영하기 위해서

 

입니다.

 

이 sigmoid 함수를 f(x)라고 해보죠

그럼 이제까지 저희가 y=wx+b를 얻어내는것은 모두~~동일하게 적용되고 다음 1개의 스텝만 추가되는것입니다.

y_sigmoid = f(wx+b).

 

즉, y값 자체를 sigmoid함수의 input값으로 넣어버리는 것이죠

 

sigmoid = 1/(1+exp(-x)) 

0 <= y_sigmoid = 1/(1+exp(-wx-b)) <=1

 

[코드 전문]

보통, Sigmoid function은 BinaryClassification을 위해 많이 사용되는데요

Binary Classification이란 최종결과가 True(1)니 False(0)니? 를 찾는 방법입니다.

 

 

binary classification

예를들면, 이 환자의 이런이런 과거의 증상 데이터들을 학습해봤을때 환자는 현재 암이니? 아니니? 

이런류의 문제에 사용됩니다.

 

Sigmoid를 통과한 값은 위에서 설명했다 시피 0~1로 나오게 되므로, 최종적으로 나온 값이

0.5보다 크면 1, 작으면 0으로 나누겠다~라고하면 상당히 타당하지 않을까요?? 딱 절반 기준이니까요

 

따라서 위의 코드 전문을 해석해보자면

 

y=wx+b를 구하고 sigmoid를 통과시킨 값 > 0.5 = True(1)!

y=wx+b를 구하고 sigmoid를 통과시킨 값 < 0.5 = False(0)!

 

이렇게 학습을해서, 나중에 내가 어떤어떤 데이터들을 넣어줄때 이게 True니? False니?를 판단하고자 하는것입니다.

 

[코드 분석-1]

전체 코드중, 이부분을 제외하고는 모두 이전글에서 정리를 했었던 내용입니다.

 

① hypothesis = tf.sigmoid(tf.matmul(X,W)+b)

: hypothesis = f(wx+b). 즉, y=wx+b를 sigmoid에 넣어주겠다 라는 의미입니다.

 

② cost = -tf.~~~

: 이부분은, Cross Entropy라는 information Theory에 나오는 수식과 Heuristic한 방법이 접목되어 유도된 것으로

기존에는 그냥 (Hypothesis-y)^2으로 정리를 해두었지만, sigmoid함수를 쓰면서 바뀌게 된 부분입니다.

 

이부분은 sigmoid함수를 쓰면 cost function은 이렇구나~~라고 외워 주시면 됩니다.

유도과정을 굳이 아실 필요는 없습니다.

 

③ predicted = tf.cast(hypothesis>0.5, dtype-tf.float32)

: y=wx+b를 sigmoid에 넣고 최종으로 나온 값이 0.5보다 크면 1로, 작으면 0으로 Mapping(매핑)하는 코드입니다.

 

④ accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted,Y),dtype=tf.float32))

: 정확도를 비교하는것입니다.

x_train을 통해 학습 시켜서 얻어진 0과 1값(predicted)이, 실제 y_train(Y)과 동일한지를 비교하는 코드입니다.

 

 

[코드 분석-2]

그다음 하기에, print해서 표출하는 방식으로는 위와 같이 코드를 짜주시면 됩니다.

 

[결과값(5000번 학습)]

 

5000번 학습하여 Weighting과 bias를 얻어보았습니다.

 

학습한 데이터를 가지고 실제값과 비교를 해보니 Accuracy = 1 (100%)로 나오네요 :)

 

 

Summary

 

Activation Function(sigmoid)를 사용하기 전에는 어떻게보면 수치해석적인 부분이였습니다.

 

수치해석을 여러번 반복한다는 뜻으로, 딱히 머신러닝이라고 하기는 어려웠었죠

 

그래서 제가 회귀(Regression) 부분을 정리할때는 항상, 아직은 머신러닝과 수치해석의 중간정도다... 라고 말씀드렸는데요

 

Activation function을 도입하는 이 글부터 본격적으로 머신러닝을 시작한다고 보시면 됩니다.

 

▶ Keyword : binary classification, sigmoid, activation function, logistic regression

 

[코드 공유]

import tensorflow.compat.v1 as tf

tf.disable_v2_behavior()

import numpy as np

 

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

y_data = [[1], [1], [1], [0], [0], [0]]

 

#placeholder을 만들때는 shape에 주의

X=tf.placeholder(tf.float32,shape=[None,2])

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를 sigmoid에 통과 : 0~1의 값으로 나오게 될것임.

hypothesis = tf.sigmoid(tf.matmul(X,W) + b)

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

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

 

#sigmoid를 통과한 값이 0.5보다 크면 1 아니면 0 으로 기준 설정(Cast)

predicted = tf.cast(hypothesis>0.5dtype = tf.float32) #True = 1, False = 0

accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted,Y),dtype=tf.float32))

 

sess=tf.Session()

sess.run(tf.global_variables_initializer()) #Variable 초기화

 

for step in range(5001):

    cost_val,_=sess.run([cost,train],feed_dict={X:x_data,Y:y_data})

    if step%1000 == 0:

        print("%05d" % step, cost_val)

 

h, c, a ,w, b, cost= sess.run([hypothesis, predicted, accuracy, W, b, cost], 

feed_dict = {X:x_data, Y:y_data})

 

print("\n [5001번 학습결과]")

#print(h)

print("1. 시그모이드 적용 : ",h.T)

print("2. + 활성함수 적용 : ", [int(x) for x in c])

print("3. 기존 정답과 비교 : "sum(y_data,[]))

print("정확도(Accuracy) : ",a)

print("Weighting : ", w )

print("bias :", b)

print("cost : ", cost)

 

댓글