Home python으로 하는 머신러닝 로지스틱 회귀분석
Post
Cancel

python으로 하는 머신러닝 로지스틱 회귀분석


Logistic Regression

이번 포스팅에선 로지스틱 회귀분석을 python으로, tensorflow로, 그리고 sklearn으로 직접 구현해보자.

공부시간과 시험 합격에 대한 데이터를 간단하게 직접 만들어서 사용하자.

1. python으로 하는 logistic regression

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
# 환경설정
import numpy as np

# 수치미분 
def numerical_derivative(f, x):

    delta_x = 1e-4   
    derivative_x = np.zeros_like(x)  
    
    it = np.nditer(x, flags=['multi_index'])
    
    while not it.finished:
        idx = it.multi_index
        tmp = x[idx]   
        
        x[idx] = tmp + delta_x 
        fx_plus_delta_x = f(x) 
        
        x[idx] = tmp - delta_x 
        fx_minus_delta_x = f(x)
        
        derivative_x[idx] = (fx_plus_delta_x - fx_minus_delta_x) / (2 * delta_x)
        
        x[idx] = tmp         
        it.iternext() 
        
    return derivative_x
1
2
3
4
5
# training data set 준비
# 그냥 내 마음대로 데이터 값을 주었다.

x_data = np.arange(2, 21, 2).reshape(-1, 1) # 공부 시간
t_data = np.array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1]).reshape(-1, 1)  # 0은 불합격, 1은 합격

위 데이터에 따르면 공부시간이 12시간일 때는 시험에 불합격하지만, 14시간이라면 합격을 한다. 그렇다면 실측 데이터가 없는 13시간일 땐 어떻게 되는걸까? 그걸 알아보자!

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
32
33
34
35
# Weight and bias 설정
W = np.random.rand(1, 1)  # 1x1 2차원 행렬로 설정
b = np.random.rand(1) 

#### 각종 함수 정의
# 예측함수 정의
def logistic_predict(x):
    
    z = np.dot(x, W) + b  # linear
    y = 1 / (1 + np.exp(-1 * z))  # sigmoid 함수
    
    result = 0
    if z >= 0.5:
        result = 1
    else:
        result = 0

    return result, y        # 0과 1 결과값 뿐만 아니고 확률 y 까지 같이 리턴한다.

# loss 함수 정의
def loss_func(input_value):

    input_w = input_value[0].reshape(-1, 1)
    input_b = input_value[1]
    
    z = np.dot(x_data, input_w) + input_b
    y = 1 / (1 + np.exp(-1 * z))
    
    delta = 1e-7   # 혹여나 y의 값이 1이 되는것을 방지하기 위해서
    
    return -np.sum( (t_data * np.log(y + delta)) + ((1 - t_data) * np.log(1 - y + delta)) )
    # return 값은 cross entropy 
    
# learning rate 정의
learning_rate = 1e-4

이제 설정은 다 끝났다! 반복학습 고고!

1
2
3
4
5
6
7
8
9
10
for step in range(300000):
    input_param = np.concatenate(W.ravel(), b.ravel(), axis=0)  # [w의 값, b의 값]
    result_derivative = learning_rate * numerical_derivative(loss_func, input_param)
    
    # update W and b
    W = W - result_derivative[0].reshape(-1, 1)
    b = b - result_derivative[1]
    
    if step % 30000 == 0:
        print("loss: {}".format(loss_func(input_param)))
1
2
3
4
5
6
7
8
9
10
11
결괏값:
loss값은 37.363400822887364
loss값은 2.8965998492103546
loss값은 2.1229618648269253
loss값은 1.7758889573534715
loss값은 1.5682037282670798
loss값은 1.4256076774651414
loss값은 1.319509267965889
loss값은 1.236302240833145
loss값은 1.1685835845187729
loss값은 1.1119343375856396

썩 낮은 loss 값은 아니다. 0에 그리 가깝지 않기 때문이다. 이런 결과가 도출된 까닭은 데이터 양이 매우 적기 때문일 확률이 크다.

아무튼 지금은 넘어가도록 하자.

이제 예측을 해보자.

1
2
3
4
5
6
7
8
result = logistic_predict([[13]])
print(result)
"""
출력물:
(1, array([[0.54444063]]))

1은 시험에 합격을 예측했다는 것이다. 뒤에 온 실수 0.54444 는 시험에 합격할 확률을 나타낸다.
"""

2. SciKit Learn으로 구현

지난번 포스팅을 보았다면 짐작하겠지만, sklearn으로 구현하는건 엄청 간단하고 편리하고 빠르다!

1
2
3
4
5
6
7
8
9
10
11
from sklearn import linear_model

model = linear_model.LogisticRegression()   # 로지스틱 회귀분석 모형 객체를 하나 만들어준다.

model.fit(x_data, t_data.ravel())   # sklearn에서 로지스틱을 할 땐 t_data를 1차원으로 풀어쓰자
result = model.predict([[13]])

print(result)

result_proba = model.predict_proba([[13]])
print(result_proba)
1
2
3
4
5
result 결과값:   0      sklearn은 불합격하리라 예측했다.
result_proba 결과값: [[0.50009391 0.49990609]]
  
  0 확률이  50.009 퍼센트
  1 확률이  49.991 퍼센트이다.

도깨비 방망이로 뚝딱! 한 것처럼 엄청 빠르고 간결하게 결과가 나왔다.

텐서플로우는 어떨까?


3. tensorflow로 구현

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
32
import numpy as np
import tensorflow as tf

# 데이터를 입력받기 위한 노드를 만들고 시작.
X = tf.placeholder(shape=[None, 1], dtype=tf.flaot(32))
T = tf.placeholder(shape=[None, 1], dtype=tf.float(32))

# Weight and bias 설정
W = tf.Variable(tf.random.normal([1,1]), name='weight')  # 초기값을 랜덤하게 하나 받음
b = tf.Variable(tf.random.normal([1]), name='bias')  # 초기값을 랜덤하게 하나 받음

# hypothesis 설정
logit = tf.matmul(X, W) + b  
H = tf.sigmoid(logit)  # tf는 sigmoid 함수를 직접 제공한다. 따라서 따로 수식을 잡아주지 않아도 된다.

# loss function
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logit, labels=T))
# 마찬가지로 loss 함수에 대해서도 따로 cross entropy를 주는 메서드가 있다.

# train node 설정
train = tf.train.GradientDescentOptimizer(learning_rate=1e-4).minimize(loss)
   # w와 b를 최적화할건데, gradient descent를 이용해서 loss 값을 최소화할거다.
# graph를 실행시켜줄 session이 필요.
sess = tf.Session()
sess.run(tf.global_variables_initializer())   # 그래프 실행전 반드시 해야하는 초기화

# 반복학습 고고
for step in range(300000):
    tmp, loss_val = sess.run([train, loss], feed_dict={X: x_data, T: t_data})
    
    if step % 30000 == 0:
        print("loss: {}".format(loss_val))
1
2
3
4
5
6
7
8
9
10
11
결과값:
loss: 5.002998352050781
loss: 0.46201056241989136
loss: 0.4189934730529785
loss: 0.3852218985557556
loss: 0.3580852746963501
loss: 0.3357999920845032
loss: 0.3171757757663727
loss: 0.3013768792152405
loss: 0.2877642512321472
loss: 0.275882750749588

이렇게 쭉쭉 떨어지는 loss값을 볼수 있으리라. 다시한 번 말하지만, loss값이 결코 낮은게 아니다. 더 0에 가까워야한다.

높게 나온 이유는 뭐라고? 데이터 값이 터무니없이 적기 때문일것이다.

자 그럼 마지막으로 예측을 해보자

1
2
3
result = sess.run(H, feed_dict={X: 13})

print(result)
1
2
결과값:
[[0.57707125]]   ==> 합격!!!

이렇게 결과값이 도출되었다.

오늘 다룬 주제같은 경우에는 따로 데이터 값이 많지 않았기때문에 loss 값도 높게 나왔고, sklearn, python, 그리고 tensorflow간의 예측값이 크게 달랐다.

양질의 데이터를 갖고 있다면 분명 일치하는 결과가 나왔으리라 생각한다.

아무튼 오늘은 여기까지..

👋

This post is licensed under CC BY 4.0 by the author.

python으로 하는 머신러닝 로지스틱 회귀분석 개념

머신러닝 로지스틱 회귀분석 분류 성능 평가 지표 (metric)

Comments powered by Disqus.