gunnew의 잡설

3. Multi-variable linear regression 본문

TensorFlow

3. Multi-variable linear regression

higunnew 2019. 11. 10. 21:56
반응형

  저번에는 하나의 변수와 결괏값의 관계를 예측하는 것을 배웠다. 가장 기초적인 선형 회귀였다. 그러면 이번엔 변수가 여러 개일 때를 생각해보자.

 


(1) 가설 설정

 

 변수가 하나일 때, 우리는 가설 설정을 Y = W * X + b로 하였다. 그러면 변수가 여러 개일 때는? 변수가 3개라고 하자. 그러면 Y = w1 * x1 + w2 * x2 + w3 * x3 + b로 설정할 수 있을 것이다. 그런데 w1 * x1 + w2 * x2 + w3 * x3. 이 형태 어디서 많이 본 적 있던 것 같은데... 아! 바로 벡터의 내적이다.

 

 벡터의 내적을 처음 들어본다면 뒤로 가기를 누르자. 벡터의 내적은 아주 쉬운 개념이므로 구글링을 해 보면 정말 금방 이해할 수 있다. 그렇다면 w = [w1, w2, w3]로 두고 x = [x1, x2, x3]로 둔다면 x * wT가 될 것이다. 아니 그럼 T는 또 뭔가? Transpose를 모른다면 다시 뒤로 가기를 누르자. T는 행과 열을 서로 바꾼다는 뜻이다. 여기에서 wT는 w가 세로로 세워져 있는 상태가 된다는 것을 뜻한다. 

 

 자, 그럼 정리해보자. 우리의 가설 H(x) = x * wT + b로 정리할 수 있을 것이다. 그럼 x 벡터가 여러 개일 때는 어떻게 생각하면 될까? x 벡터 5개일 때를 생각해보자. 그러면 다음과 같은 행렬의 형태로 나타낼 수 있을 것이다.

이 경우에 notation을 소문자에서 대문자로 바꿔서 행렬로 나타내보자면 

H(X) = XW + b로 나타내어질 것이다.

 


(2) 바로 텐서플로우로 구현하기

 

 백날 이론으로 떠들어봤자 한 번 해보느니만 못하다. 바로 파이썬을 켜보자.

자, 이제 다음과 같은 데이터를 다중 선형 회귀 분석을 해볼 것이다.

x1

x2

x3

Y

73

80

75

162

93

88

93

185

89

91

90

180

96

98

100

196

73

66

70

142

가설을 세우자.

 

H(x1, x2, x3) = x1*w1 + x2*w2 + x3*w3 + b

 

자 그럼 지난 번의 x_data 대신에 x1_data, x2_data, x3_data에 각각 정보를 담고 y_data에도 담는다. 그리고 w1, w2, w3 모두 Variable로 선언할 수 있을 것이다. 


아 참, 지난 번에 설명하지 않았던 것이 placeholder라는 개념이다. 이것은 어떤 자료형이 들어갈지만 선언해놓고 값은 이후에 채우게 하는 것이다. 즉, 그릇만 만들어 놓겠다는 것이다. 여기서 분석할 데이터 x1, x2, x3, Y를 앞에서 미리 만들어 놓고 나중에 트레이닝을 할 때 넣어주는 형태로 만들었기 때문에 placeholder를 사용한 것이다. 따라서 placeholder를 사용할 때는 추후 트레이닝을 할 때 feed_dict라는 dictionary 자료형을 통해 값을 넣어주어야 한다.


 

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
36
37
# multi variable linear regression
 
import tensorflow as tf
 
x1_data = [73.93.89.96.73.]
x2_data = [80.88.91.98.66.]
x3_data = [75.93.90.100.70.]
 
y_data = [152.185.180.196.142.]
 
x1 = tf.placeholder(tf.float32)
x2 = tf.placeholder(tf.float32)
x3 = tf.placeholder(tf.float32)
 
= tf.placeholder(tf.float32)
 
w1 = tf.Variable(tf.random_normal([1]), name = "weight1")
w2 = tf.Variable(tf.random_normal([1]), name = "weight2")
w3 = tf.Variable(tf.random_normal([1]), name = "weight3")
 
hypothesis = x1*w1 + x2*w2 + x3*w3 + b
 
cost = tf.reduce_mean(tf.square(hypothesis- Y))
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 1e-5)
 
train = optimizer.minimize(cost)
 
sess = tf.Session()
 
sess.run(tf.global_variables_initializer())
for step in range(2001):
    cost_val, hy_val, _ = sess.run([cost, hypothesis, train], feed_dict= 
    {x1 : x1_data, x2 : x2_data, x3: x3_data, Y: y_data})
    if step % 10== 0:
        print(step, "cost: ", cost_val, "\nPrediction : \n", hy_val)

 

 

1600 cost:  1.3447645 
Prediction : 
 [153.1095  183.73505 181.43095 194.70752 142.41785]
1700 cost:  1.326948 
Prediction : 
 [153.08806 183.74927 181.42381 194.70691 142.43268]
1800 cost:  1.3098308 
Prediction : 
 [153.06715 183.76315 181.4168  194.7064  142.44705]
1900 cost:  1.2934353 
Prediction : 
 [153.04675 183.77667 181.40997 194.706   142.46095]
2000 cost:  1.2776887 
Prediction : 
 [153.02686 183.78986 181.4033  194.7057  142.47444]

 

 위와 같은 결과가 나올 것이다. 점차 cost가 줄어들며, hypothesis의 값이 y_data와 거의 근사해 감을 확인할 수 있다.

 


 (3) placeholder를 통한 행렬 표현

 

  하지만 위 코드는 너무 지저분하다. x1_data : ~, x2_data : ~, x3_data : ~, w1 : ~ , w2 : ~

x가 142,562개라면 어떻게 할까. 생각만 해도 너무 끔찍한 코드가 될 것이다. 이 반복적인 작업을 대체할 수 있는 방법이 placeholder의 shape인자를 활용하는 것이다. 즉, 행렬로 데이터를 처리한다는 것이다. 사용법은 아주 간단하다. 우리가 분석하고자 하는 변수의 개수를 열의 개수로 둔다. 그리고 행의 개수는 input data의 개수이다. 위에서는 5개가 주어졌지만 100개가 주어진다면 그때마다 100으로 고치고 실행할 수는 없는 노릇이다. 이렇듯, 미정 개수를 나타내는 python의 심벌은 None이다. 바로 파이썬 코드로 살펴보자.

 

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
# multi variable linear regression
 
import tensorflow as tf
x_data = [[73.80.75.], [93.88.93.], [89.91.90.], [96.98.100.], [73.66.70.]]
y_data = [[152.], [185.], [180.], [196.], [142.]]
 
= tf.placeholder(tf.float32, shape = [None, 3])
= tf.placeholder(tf.float32, shape = [None, 1])
 
= tf.Variable(tf.random_normal([31]), name = "weight")
= tf.Variable(tf.random_normal([1]), name = "bias")
hypothesis = tf.matmul(X, W) + b
 
cost = tf.reduce_mean(tf.square(hypothesis - Y))
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 1e-5)
 
train = optimizer.minimize(cost)
 
sess = tf.Session()
 
sess.run(tf.global_variables_initializer())
for step in range(2001):
    cost_val, hy_val, _ = sess.run([cost, hypothesis, train], feed_dict = {X : x_data,
                                                                          Y : y_data})
    if step % 1000== 0:
        print(step, "cost: ", cost_val, "\nPrediction : \n", hy_val)
 
cs

 

 이전 코드와 다른 점은 X와 Y를 입력받을 데이터 집합의 개수에 따라 맞추기 위해 [None, 3], [None, 1]로 설정하였다는 점과 W를 행렬의 곱셈을 위해 X의 열의 개수와 W의 행의 개수를 맞추어 설정하여, W를 column vector로 썼다는 점이다. hypothesis = tf.matmul(X, W) + b에서 matmul은 두 행렬의 곱셈 연산을 도와주는 메소드이고, 행렬의 모든 원소에 b를 더해준다는 뜻이다. 이 코드의 실행 결과는 다음과 같다.

 

0 cost:  28822.744 
Prediction : 
 [[-5.355444  ]
 [ 7.73403   ]
 [ 0.08409286]
 [ 2.2326295 ]
 [ 7.7828655 ]]
1000 cost:  9.391671 
Prediction : 
 [[146.55464]
 [187.84892]
 [178.8429 ]
 [196.70135]
 [144.7128 ]]
2000 cost:  5.8673368 
Prediction : 
 [[147.55893]
 [187.16501]
 [179.1564 ]
 [196.88307]
 [143.85333]]

 cost도 계속해서 줄어들며, prediction도 주어진 y_data와의 차이가 줄어들고 있음을 확인할 수 있다.

 


(4) 결론

 

 variable이 여러 개일 때의 선형 회귀에 대해 알아보았다. 어려운 것은 없었다. placeholder의 적절한 활용과 행렬의 곱셈을 위해 행의 개수와 열의 개수를 잘 맞추는 테크닉을 필요로 했다. 또한, 데이터를 미리 주는 것이 아니라 트레이닝을 할 때에 dictionary 형태로 데이터를 제공하는 dictionary형 인자 feed_dict에 주목할 필요가 있겠다.

 

 세 줄 요약 :

  1. placeholder로 shape를 설정할 때, input 데이터가 몇 set일지 모르므로 행을 None으로 설정하자.

  2. 행렬의 곱셈시 앞에 곱하는 행렬의 열의 개수와 뒤에 곱하는 행렬의 행의 개수는 같아야 함을 인지하자.

  3. feed_dict를 이용하여 트레이닝할 때 data를 제공하는 테크닉을 이용하자.

 

반응형

'TensorFlow' 카테고리의 다른 글

2. Linear Regression Using Tensor Flow  (0) 2019.11.10
1. Why Tensor Flow?  (2) 2019.11.10
Comments