machineLearning

선형 회귀 분석(Linear Regression)

탄생 2018. 4. 17. 12:40

선형회귀란 주어진 x와 y값을 가지고 서로간의 관계를 파악하는 것입니다.

이 관계를 알고 나면 새로운 x값이 주어졌을때 y값을 쉽게 알 수 있습니다.


예를 들어 보면 쉽게 이해가 될 것입니다.

택시요금은 거리대비 요금이 측정이 됩니다.

아래와 같이 거리이동시 발생한 택시 요금이 있다고

가정하면 13km를 가는데에는 얼마정도의 택시요금이 발생할까요??

 거리(x)

요금(y) 

 10

10000 

 10

10500 

 11

10000 

 11

11000 

 12

12000 

 12

11500 


위의 데이터를 가지고 자체적으로 계산해 본다면 12,000 ~ 13,000원 정도가 나오겠구나

예측할 수 있습니다.

데이터가 많으면 많을수록 오차범위는 줄어 더 정확한 값을 얻을 수 있을것입니다.


이제 머신런닝을 이용하여 값을 예측해 보겠습니다.

import tensorflow as tf
x_data = [10,10,11,11,12,12]                                        // x_data는 거리값
y_data = [10000,10500,10000,11000,12000,11500]                      // y_data는 택시 요금
 
= tf.Variable(tf.random_uniform([1], -1.01.0))                  // W값은 -1 ~ 1까지 랜덤한 수
= tf.Variable(tf.random_uniform([1], -1.01.0))                  // b값은 -1 ~ 1까지 랜덤한 수
 
= tf.placeholder(tf.float32, name ="X")                           // X값은 placeholder(데이터를 차후에 대입(feeding)에서 사용)
= tf.placeholder(tf.float32, name ="Y")                           // Y값은 placeholder(데이터를 차후에 대입(feeding)에서 사용)
 
hypothesis = W * X + b                                              // 가설은 W * X + b (x , y값을 가지고 최적의 W와 b값을 구한다)
 
cost = tf.reduce_mean(tf.square(hypothesis - Y))                    // cost = (가설값 - Y(실제값))²/ 계산되는예측값횟수
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 0.001)    // W 와 b를 구하는 최적화 함수(경사하강법)
train_op = optimizer.minimize(cost)                                 // 최적화 함수를 cost를 이용해 계산
 
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())                     // Variable을 초기해 해준다
    
    for step in range(100):                                         // 100번 반복을 한다
        _, cost_val = sess.run([train_op, cost], feed_dict={X:x_data, Y:y_data})    // train_op를 계산하여 최적의 W와 b값을 구한다.
        print(step, cost_val, sess.run(W), sess.run(b))
        
    print("\n=== Test ===")
    print("X: 5, Y:", sess.run(hypothesis, feed_dict={X:5}))        // 5km 이동시 택시요금은?
    print("X: 13, Y:", sess.run(hypothesis, feed_dict={X:13}))      // 13km 이동시 택시요금은?



실행결과

0 117681640.0 [240.00157] [22.475605]
 1 67116590.0 [420.44006] [38.817287]
 2 38317856.0 [556.61237] [51.15664]
 3 21915874.0 [659.3779] [60.47552]
 4 12574323.0 [736.9322] [67.51492]
 5 7253952.0 [795.46] [72.83405]
 6 4223798.0 [839.6291] [76.854935]
 7 2498010.5 [872.96185] [79.89605]
 8 1515106.6 [898.11676] [82.19776]
 9 955304.56 [917.1] [83.94146]
 10 636477.94 [931.4256] [85.264046]
 11 454892.84 [942.2362] [86.26882]
 12 351472.66 [950.39417] [87.03375]
 13 292570.03 [956.5502] [87.617676]
 14 259023.27 [961.1954] [88.065]
 15 239915.98 [964.7004] [88.40924]
 16 229033.92 [967.345] [88.67568]
 17 222835.81 [969.34015] [88.88341]
 18 219305.11 [970.8453] [89.04682]
 19 217294.0 [971.9805] [89.176796]
 20 216148.44 [972.83673] [89.28154]
 21 215495.69 [973.4823] [89.36723]
 22 215123.48 [973.9689] [89.43855]
 23 214911.23 [974.33545] [89.49903]
 24 214789.92 [974.6115] [89.55132]
 25 214720.58 [974.8192] [89.597435]
 26 214680.83 [974.9754] [89.638885]
 27 214657.92 [975.09265] [89.67682]
 28 214644.44 [975.18054] [89.7121]
 29 214636.45 [975.2463] [89.74537]
 30 214631.56 [975.2953] [89.77713]
 31 214628.42 [975.33167] [89.80775]
 32 214626.56 [975.3585] [89.8375]
 33 214624.95 [975.3782] [89.86661]
 34 214624.0 [975.39246] [89.895226]
 35 214622.8 [975.4026] [89.92347]
 36 214622.08 [975.4096] [89.95143]
 37 214621.25 [975.41437] [89.97919]
 38 214620.25 [975.4173] [90.00678]
 39 214619.48 [975.41895] [90.034256]
 40 214618.8 [975.41956] [90.06164]
 41 214618.14 [975.41943] [90.08895]
 42 214617.2 [975.41876] [90.11621]
 43 214616.61 [975.41766] [90.14343]
 44 214615.88 [975.4162] [90.17062]
 45 214615.0 [975.4145] [90.19779]
 46 214614.45 [975.4126] [90.224945]
 47 214613.7 [975.4106] [90.25208]
 48 214613.0 [975.40845] [90.27921]
 49 214612.3 [975.40625] [90.306335]
 50 214611.36 [975.404] [90.33345]
 51 214610.69 [975.4017] [90.360565]
 52 214609.86 [975.39935] [90.38767]
 53 214609.17 [975.397] [90.41478]
 54 214608.5 [975.3946] [90.44188]
 55 214607.64 [975.3922] [90.46898]
 56 214607.05 [975.3898] [90.49608]
 57 214606.19 [975.3873] [90.52318]
 58 214605.55 [975.3849] [90.55028]
 59 214604.73 [975.38245] [90.57738]
 60 214604.08 [975.38] [90.60448]
 61 214603.23 [975.37756] [90.63158]
 62 214602.56 [975.3751] [90.658676]
 63 214601.77 [975.3727] [90.685776]
 64 214601.11 [975.37024] [90.712875]
 65 214600.27 [975.3678] [90.73997]
 66 214599.62 [975.36536] [90.76706]
 67 214598.8 [975.3629] [90.79415]
 68 214598.17 [975.3605] [90.82124]
 69 214597.31 [975.35803] [90.848335]
 70 214596.67 [975.3556] [90.87543]
 71 214595.83 [975.35315] [90.90252]
 72 214595.19 [975.3507] [90.92961]
 73 214594.33 [975.34827] [90.9567]
 74 214593.69 [975.3458] [90.983795]
 75 214592.88 [975.3434] [91.01089]
 76 214592.23 [975.34094] [91.03798]
 77 214591.38 [975.3385] [91.06507]
 78 214590.75 [975.336] [91.09216]
 79 214589.89 [975.33356] [91.119255]
 80 214589.05 [975.3311] [91.14635]
 81 214588.39 [975.3287] [91.17344]
 82 214587.55 [975.32623] [91.20052]
 83 214586.92 [975.3238] [91.227615]
 84 214586.06 [975.32135] [91.2547]
 85 214585.42 [975.31885] [91.281784]
 86 214584.81 [975.3164] [91.30887]
 87 214584.0 [975.31396] [91.33596]
 88 214583.14 [975.3115] [91.363045]
 89 214582.48 [975.3091] [91.39013]
 90 214581.88 [975.30664] [91.41721]
 91 214581.02 [975.3042] [91.4443]
 92 214580.19 [975.30176] [91.47138]
 93 214579.55 [975.2993] [91.49847]
 94 214578.92 [975.2969] [91.52555]
 95 214578.08 [975.29443] [91.552635]
 96 214577.23 [975.292] [91.57972]
 97 214576.58 [975.2895] [91.606804]
 98 214575.98 [975.28705] [91.63389]
 99 214575.14 [975.2846] [91.66097]
 
 === Test ===
 X: 5, Y: [4968.084]
 X: 13, Y: [12770.361]

실행결과는 오차범위가 있을 수 있다

5Km 이동시에는 약 4968원, 13km 이동시에는 12,770원이 나오겠구나 예측값이 나왔습니다.

 


이제 선형회귀가 무엇이고 예측하는 방법을 알았다면 어떻게 저렇게 예측했는지 이해 할 필요가 있습니다.

1. 먼저 가설식을 세운다.

hypothesis = W * X + b

X(거리)가 커지면 y(택시비)는 늘어갈 것이며 w(기울기)와 b(편차, y절편)를 찾아 최적의 y값을 찾는다

그래프로 그리면 아래와 같다 

 

2. 비용

cost = tf.reduce_mean(tf.square(hypothesis - Y))

비용은 실제 y값과 가설식으로 세운 직선과의 거리이다 

모든 y값과 가설식과의 거리를 모두 더해 평균을 낸 값이 cost이다

가설값 - 실제값을 한후 square(제곱)을 한 이유는 거리가 음수로 나올수도 있기 때문이다

절대값을 사용해도 되지만 제곱을 이용하면 거리의 차가 커지기 때문에 더 명확한 데이터를 얻을 수 있다

즉 실제값과 가설식으로 세운 직선의 거리가 가장 짧은 W와 b값을 구하는 것이 선형회귀의 목표이다

 


 

3. 옵티마이저

optimizer = tf.train.GradientDescentOptimizer(learning_rate = 0.001)
 
train_op = optimizer.minimize(cost)


  

그렇다면 W와 b값을 얻기 위해 모든 경우의 수를 대입하여 비용이 가정 적은 직선을 그릴때까지

반복하며 데이터를 찾아야 할까? 그렇게 되면 굉장히 많은 계산이 필요하며 시간도 오래 걸린다

따라저 옵티마이저를 통해 그 횟수를 절약 할 수 있다.

 

옵티마이저 함수의 알고리즘을 이해할 필요는 없다

비용을 얻는데에는 많은 옵티마이저 함수가 존재한다 선형회귀에서는 경사하강법을 이용하여 최적의 비용 함수를 얻을 수 있다고 이해하고 사용하면 된다.

좀 더 자세히 이해 하고 싶다면 아래 동영상을 참고하시면 됩니다.

https://www.youtube.com/watch?v=Y0EF9VqRuEA&list=PLlMkM4tgfjnLSOjrEJN31gZATbcj_MpUm&index=7

 

4. 학습

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())                     // Variable을 초기해 해준다
 
    for step in range(100):                                         // 100번 반복을 한다
        _, cost_val = sess.run([train_op, cost], feed_dict={X:x_data, Y:y_data})    // train_op를 계산하여 최적의 W와 b값을 구한다.
        print(step, cost_val, sess.run(W), sess.run(b))
 
    print("\n=== Test ===")
    print("X: 5, Y:", sess.run(hypothesis, feed_dict={X:5}))        // 5km 이동시 택시요금은?
    print("X: 13, Y:", sess.run(hypothesis, feed_dict={X:13}))      // 13km 이동시 택시요금은?


텐서플로우를 이용하여 train_op와 cost를 반복하며 최적의 값을 얻습니다

그렇게 얻은 W와 b값을 이용하여 X값을 입력하면 Y값이 출력하게 됩니다.



이미지 참고

http://kkokkilkon.tistory.com/77

http://bcho.tistory.com/1139