본문 바로가기

파이썬/머신러닝

[#E4] 다중 변수를 사용하는 Multi Variables Linear Regression

[#E2 : 머신러닝의 첫 단계 Linear Regression이란?][#E3 : Linear Regression 데이터를 유동적으로 지정하는 방법]에서는 1차원 데이터를 가지고 LinearRegression을 진행했습니다.



1
2
x_data = [1, 2, 3, 4, 5]
y_data = [1, 2, 3, 4, 5]
cs


(2) 2차원 데이터


1
2
x_data = [[1, 2, 3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]]
y_data = [[10],[20],[30],[40],[50]]
cs


데이터가 몇 차원인지 파악하기 위해서는 위의 색칠된 부분처럼 대괄호의 개수로 파악할 수 있습니다. 즉 슬래시가 1개면 1차원, 2개면 2차원, 3개면 3차원입니다.


중요한 것은 1차원 데이터에서 변수 w 값( Hypothesis = w*x + b 에서의 w )은 1개를 갖는데 비해, 다차원 데이터에서는 각각의 데이터 셋이 모두 각자의 W, 즉 Hypothesis를 갖습니다.


즉, 제공된 2차원 데이터에서 보면



Hypothesis1 = w1*[1,2,3] + b ,


Hypothesis2 = w2*[4,5,6] + b ,


...


이런 공정으로 결국 x_data에는 5개의 W가 존재하게 됩니다. ( =5개의 Hypothesis를 갖는다 )


이렇게 존재하는 5개의 Hypothesis를 편리하게 종합하면 결국 매트릭스(행렬)곱 W * X = Y 로 표현될 수 있습니다. W는 각각 5개의 w를, X와 Y는 각각의 데이터 셋을 포함합니다.


이것은 다른 작업 없이 텐서플로우에서 제공하는 matmul 메소드로 구현할 수 있으며, 이것은 곧 우리가 원하는 최종 Hypothesis 함수가 됩니다.


즉, tf.matmul 함수는 기존의 * (곱하기)의 역할을 하는 셈입니다.



1
2
3
4
5
//LinearRegression
Hypothesis = W * x + b
 
//Multi Variable LinearRegression
Hypothesis = tf.matmul(X, W) + b
cs



이제 신경써야할 마지막 부분은 x_data와 y_data를 넣을 변수 X 와 Y, 그리고 W와 b를 정의하는 일입니다.


<OLD>


1
2
3
4
5
X(x_train) = tf.placeholder(tf.float32, shape=[None])
Y(y_train) = tf.placeholder(tf.float32, shape=[None])
 
= tf.Variable(tf.random_normal([1]), name="weight")
= tf.Variable(tf.random_normal([1]), name="bias")
cs


저번 포스트 [#E3 : LinearRegression 데이터를 유동적으로 지정하는 방법]에서 정의한 X, Y 변수에서는 1차원 데이터를 대입했으므로 shape=[None], 즉 데이터 구조 shape를 신경쓰지 않겠다 ( =알아서 인식하라는 뜻 ) 고 정의했습니다.



<NEW>


1
2
3
4
5
6
= tf.placeholder(tf.float32, shape=[None, 3])
= tf.placeholder(tf.float32, shape=[None, 1])
 
= tf.Variable(tf.random_normal([3,1]), name='weight')
= tf.Variable(tf.random_normal([1]), name='bias')
 
cs

 

shape=[None, 3]에서 None과 3은 각각 데이터 셋의 개수와, 셋에 포함된 데이터 개수를 의미합니다. 즉, shape는 데이터의 행렬 구조를 의미합니다.
 

1
2
x_data = [[123],[4,5,6],[7,8,9],[10,11,12],[13,14,15]]
y_data = [[10],[20],[30],[40],[50]]
cs

주어진 2차원 데이터 X에는 각각 5개의 데이터 셋이 있고, 그 안에는 3개의 데이터가 포함되어 있으므로 정확한 shape는 [5,3] 입니다. 마찬가지로 Y의 shape = [None, 1] = [5,1] 입니다.

 

데이터 셋의 개수는 우리가 굳이 지정할 필요 없이 None으로 설정하면 알아서 구조를 인식하게 됩니다.

 
이제 W의 shape를 정해주기만 하면 되는데, 이는 [3,1]로 지정할 수 있습니다. 이것은 X의 데이터셋에 포함된 데이터 개수 3 (행)과 Y데이터의 데이터셋에 포함된 데이터 개수 1 (열) 입니다.


이렇게 되는 이유는 매트릭스(행렬) 곱셈의 성질에 있습니다.


Hypothesis는 매트릭스의 곱이므로 행렬 곱셈 W * X = Y 이 성립하려면 행렬의 성질에 따라 (1) W의 행과 X의 열이 일치해야합니다. 그리고 (2) 곱셈 결과 Y는 행과 상관없이 열이 W의 열과 일치해야합니다.

 
쉽게 말해 주어진 2차원 데이터에서는 Hypothesis W * X = Y == [3, 1] * [?, 3] = [?, 1] 관계가 성립해야합니다.

 
따라서 W의 구조는 [X의 열, Y의 열]입니다. 그러므로 X의 열과 Y의 열은 각각의 데이터 셋이 포함한 데이터의 개수이므로 [3,1]이 됩니다. 

 

즉, 이것은 편리하게 3개의 x데이터 당 1개의 y데이터 출력을 낸다고 이해할 수 있습니다. 


b는 y데이터 출력 개수를 데이터 셋 개수로 갖습니다. 즉 b의 구조는 W의 열 1 ( =y데이터의 출력 )이므로 [1]입니다.



SOURCE CODE



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
import tensorflow as tf
 
x_data = [[123],[4,5,6],[7,8,9],[10,11,12],[13,14,15]]
y_data = [[10],[20],[30],[40],[50]]
 
= tf.placeholder(tf.float32, shape=[None, 3])
= tf.placeholder(tf.float32, shape=[None, 1])
 
= tf.Variable(tf.random_normal([3,1]), 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=0.01)
train = optimizer.minimize(cost)
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
 
for step in range(2001):
    cost_val, hy_val, w_val, _ = sess.run(
        [cost, hypothesis, W, train], feed_dict={X: x_data, Y: y_data})
    if step % 20 == 0:
        print(step, "Cost: ", cost_val, "\nPrediction:\n", hy_val, "\nWeight:\n", w_val)
 
cs



이외의 나머지 부분은 같습니다. 이것을 Tensorflow에서 실행시켜보면 결과는 다음과 같습니다.


0회차


1
2
3
4
5
6
7
8
0 
Cost:  727.99774 
Prediction:
 [[1.404572 ]
 [3.4425058]
 [5.4804397]
 [7.518374 ]
 [9.556308 ]] 
cs


...


2000회차


1
2
3
4
5
6
7
8
2000
Cost:  1.7787834 
Prediction:
 [[ 7.7103186]
 [18.5457   ]
 [29.38108  ]
 [40.21646  ]
 [51.05184  ]]
cs



Cost는 727 -> 1로 그 차이가 현저하게 줄어들었습니다. 

예측값 또한 [4,5,6] -> [3.44] 에 비해 [4,5,6] -> [18.54] 로 상당히 정확하게 예측했습니다.