[Multi-Variable Linear Regression]
Linear Regression 중 변수가 여러개인 경우가 많습니다. (사실 실생활에서는 이게 대부분입니다.)
변수라 함은 Hypothesis에서 x가 여러개라는 뜻입니다.
x가 여러개면, Hypothesis는 어떤 모습일까요?
3개의 x에 따라서 3개의 W(weight)와 3개의 Hypothesis가 나왔네요. (bias는 constant이므로 제외하고 말하겠습니다.)
각각 독립적인 변수들이므로 모든 항의 합으로 식을 통일시킬 수 있겠군요.
이과생들 중에서 조금만 공부를 하신 분이라면(물론 이걸 아는 문과 능력자 분들도 많죠) 이 식 표현을 어디서 많이 보셨을 겁니다.
Dot Product. 내적이죠.
여기서 우리는 행렬이 얼마나 강력한 힘을 가지고 있는지 알게 됩니다. (학창시절에는 왜 배우는지 알고 싶지 않았던..)
위의 식을 행렬의 내적으로 표현해보겠습니다.
(위의 식들에서 첨자를 윗첨자를 줬네요... 편의상 아래첨자로 바꾸겠습니다. 혼동없으시길..)
x와 w의 자리가 바꼈는데요. 결과는 어차피 같고 그 이유는 나중에 알게 됩니다. (하지만 행렬에서 순서는 중요하죠. 이유를 미리 말씀드리자면 직.관.성.을 위함입니다)
자, 이제 Hypothesis는 행렬 X와 W의 내적으로 표현됩니다.
이제 이러한 데이터를 많이 가져와서 학습을 시키게 되는데요.
그럼 x의 값이 수없이 많아지겠죠. 이를 인스턴스가 많아진다고 합니다. (x = 인스턴스, 사례정도라고 해석하시면 될 것 같습니다.)
x가 많아질 때, 다시 수식을 표현해보겠습니다. 고등학교 때도 안하던 내적 풀이 수식 노가다...출발..!
네 줄 적는 것도 힘드네요! 어쨋든 4개의 인스턴스가 있을 때 y도 4개가 나오게 됩니다. (당연하죠)
여기서 W와 X의 자리가 바뀐 이유를 알 수 있습니다. 인스턴스별로 세로 방향으로 적어나가는게 더 직관적이죠.
(사실 진짜 이유는 잘 모르겠습니다. 제 생각일 뿐...그냥 원래대로 w를 앞에 배치하고 x를 뒤에 적어가면 굉장히 불쾌하다는 생각이 듭니다. 코드로 작성하면 얼마나 더 심할까요? 정확히 아시는 분은 이 무지한 민생을 댓글로 혼내주세요..)
x는 4x3 행렬, y는 4x1 행렬 입니다. 그럼 우리는 weight가 어떤 행렬인지 알 수 있겠죠? 네, 3x1 행렬이어야겠죠.
이렇게 실제로 hypothesis는 matrix를 이용해서 구하면 되겠습니다.
[문제]
인스턴스가 많은 데이터인 경우 .csv 파일(,로 값이 구분된 데이터)로 읽어와서 학습하게 됩니다.
[그림1] 첫번째 Column이 x1, 두번째 Column이 x2, 세번째 Column이 x3, 네번째 Column이 y
다음과 같은 데이터가 있습니다.
우리가 파이썬을 사용하는 여러가지 이유 중 하나인 numpy를 사용해서 데이터를 예쁘게 정리할 수 있죠.
슬라이싱과 인덱스 기능으로 칼자루를 들고 List를 요리조리 자를 수 있습니다.
[그림2] [num : num_2, num_3 : num_4] 와 같은 형태로 slicing 할 수 있다. num~num_2까지의 행을 num_3~num_4까지의 열로 자름.
[그림2]를 이용하면 1,2,3열을 x_data에 넣고 4열을 y_data에 쉽게 넣을 수 있습니다.
import tensorflow as tf
import numpy as np
## delimiter = '' 안의 문자를 빼고 불러옴
data = np.loadtxt('data-01-test-score.csv', delimiter = ',', dtype = np.float32)
x_data = data[:,:-1]
y_data = data[:,[-1]]
print(x_data)
print(y_data)
앞선 설명과 같이 X행렬과 Y행렬의 Shape을 알고 있으니 W의 shape을 추측할 수 있겠네요.
하나의 인스턴스 당 X = 1 x 3 행렬, Y = 1 x 1 행렬이므로 W는 3 x 1 행렬입니다.
import tensorflow as tf
import numpy as np
## delimiter = '' 안의 문자를 빼고 불러옴
data = np.loadtxt('data-01-test-score.csv', delimiter = ',', dtype = np.float32)
x_data = data[:,:-1]
y_data = data[:,[-1]]
X = tf.placeholder(tf.float32, shape=[None, 3]) ## 행은 미지정, 열은 3개의 Shape을 가지고 있다.
Y = tf.placeholder(tf.float32, shape=[None, 1])
W = tf.Variable(tf.random_normal([3,1]), name = 'weight')
b = tf.Variable(tf.random_normal([1]), name = 'bias')
hypothesis = tf.matmul(X, W) + b ## matmul = 행렬 내적
## cost function
cost = tf.reduce_mean(tf.square(hypothesis - Y))
## minimize cost
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 = sess.run(cost, feed_dict = { X:x_data, Y:y_data }) ## cost_val = x,y 피드값에 따른 계산된 cost값
hy_val = sess.run(hypothesis, feed_dict = { X:x_data, Y:y_data }) ## cost_hy = x,y 피드값에 따른 계산된 hypothesis값
sess.run(train, feed_dict = { X:x_data, Y:y_data } ) ## training
## 간략히 이렇게 쓸 수 있다.
#cost_val, hy_val, _ = sess.run([cost, hypothesis, train], feed_dict = {X:x_data, Y:y_data})
if step%10 == 0:
print(cost_val)
## 예측하기
print("ASK", sess.run(hypothesis, feed_dict = {X:[[100,70,101], [90,100,50], [111,40,60]]}))
데이터를 통해 훈련시키고 최종적으로 질문을 던져 값을 예측할 수 있습니다.
또한 Tensorflow는 Queue Runner를 지원해서 txt 파일이 많을 때 Queue 자료구조 처럼 데이터를 한 곳에 차곡차곡 쌓아서 학습시킬 수도 있습니다. (물론 Shuffle Option을 통해 섞어서 쌓을 수도 있습니다.)
Queue 자료구조에 관한 개념은 밑의 글에서 확인하세요.
http://twoearth.tistory.com/3?category=809135
# Lab 4 Multi-variable linear regression
import tensorflow as tf
## 데이터 파일 리스트업
filename_queue = tf.train.string_input_producer(
['data-01-test-score.csv','...'. '...'], shuffle=False, name='filename_queue')
## 파일의 데이터를 읽어온다
reader = tf.TextLineReader()
key, value = reader.read(filename_queue) ## key, value를 따로 읽어온다.
## 디코딩(Tensorflow에 사용하기 위해 변환) 하는 과정에서 value 형태를 정해줄 수 있다. (예시에서는 float형)
record_defaults = [[0.], [0.], [0.], [0.]]
xy = tf.decode_csv(value, record_defaults=record_defaults)
## batch = 데이터를 읽어 올 수 있는 장치
train_x_batch, train_y_batch = \
tf.train.batch([xy[0:-1], xy[-1:]], batch_size=10) ## batch_size = 한번에 몇개의 데이터를 가져오는 지
## 나머지는 똑같이
X = tf.placeholder(tf.float32, shape=[None, 3])
Y = tf.placeholder(tf.float32, shape=[None, 1])
W = tf.Variable(tf.random_normal([3, 1]), name='weight')
b = 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())
## queue runner를 쓰기 위한 장치(스위치라고 생각)
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
for step in range(2001):
x_batch, y_batch = sess.run([train_x_batch, train_y_batch])
cost_val, hy_val, _ = sess.run(
[cost, hypothesis, train], feed_dict={X: x_batch, Y: y_batch})
if step % 10 == 0:
print(cost_val)
## queue runner를 쓰기 위한 장치(스위치라고 생각)
coord.request_stop()
coord.join(threads)
데이터 파일이 많을 때, Queue Runner을 이용해 Batch로 큼직큼직하게 훈련시키는 과정이라고 생각하면 좋을 것 같습니다.