본문 바로가기

Theory/DeepLearning

[Tensor Flow] 텐서플로우로 풀어보는 다변수 입력에 대한 선형회귀 예제 - 나이, 체중에 대한 혈액지방함량 문제-

요즘 텐서플로우 글을 띄엄띄엄 올리네요^^. 처음에는 단순히 AND 연산을 예제로 텐서플로우의 흐름[바로가기]을 한 번 보고, 그 후 특정 변수의 내용을 history에 남겨 그래프로 확인하는 것[바로가기]도 한 번 실습해 보았지요. 뭐 이 모든 것이 따라하기지만 말이죠.. 이번에는 선형회귀 문제를 예제로 한 번 다뤄볼까 합니다. 예제는 엣지있게 설명한 텐서플로우라는 책에서 다룬 예제인데 이를 이전 글들과 프로그램 형식이 비슷하도록 다시 바꾸고, 또 책의 내용이 텐서플로우 이전 버전에서 작성되어 그것을 지금 버전(tensor flow 1.3, 1.4)에 맞춰 주었습니다. 뭐 그러거나 말거나,

언제나 Python을 공부하다 보면 참 고마운 분들이 많습니다. 너무 많은 분들이 좋은 내용을 공유하고 계시죠. 이번 글도 김성훈 교수님의 유명한 딥러닝과 텐서플로우 공개 강좌[바로가기], 그 외에 엣지있게 설명한 텐서플로우[바로가기], 딥러닝 첫걸음[바로가기], 처음 배우는 머신러닝[바로가기]을 정말 단순히 따라가는 수준입니다.

먼저 다룰려는 데이터는

x09.txt

입니다. 그 내용은

Linear Regression 문제에 대해 1978년에 최초 발간된 책에서 다루고 있었던 예제인가 봅니다. 헉...

이무튼 그 내용에는 몸무게, 나이, 그리고 혈중 지방 함량이 데이터 입니다.

import tensorflow as tf
import numpy as np
from tqdm import tqdm_notebook
import matplotlib.pyplot as plt
%matplotlib inline

tf.set_random_seed(777)  # for reproducibility
print(tf.__version__)

raw_data = np.genfromtxt('x09.txt', skip_header=36)
raw_data

먼저 필요한 모듈을 import하고, 데이터도 numpy를 이용해서 그냥 읽어버리겠습니다.~~ 뭔지 궁금하니 슬쩍 한 번 그려보죠~

from mpl_toolkits.mplot3d import Axes3D

xs = np.array(raw_data[:,2], dtype=np.float32)
ys = np.array(raw_data[:,3], dtype=np.float32)
zs = np.array(raw_data[:,4], dtype=np.float32)

fig = plt.figure(figsize=(12,12))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs, ys, zs)
ax.set_xlabel('Weight')
ax.set_ylabel('Age')
ax.set_zlabel('Blood fat')
ax.view_init(15, 15)

plt.show()

흠.. 뭐 데이터 자체가 몇 개 없으니.. 여하튼 상상력을 동원해보면 어쩌면 럭비공처럼 생겼을 수도 있겠습니다.

여하튼 오늘 우리가 거창하게 텐서플로우를 사용하면서 알아내고 싶은건 저 데이터를 하나의 직선으로 표현하려는 겁니다.^^ 일단 읽은 데이터를

x_data = np.array(raw_data[:,2:4], dtype=np.float32)
y_data = np.array(raw_data[:,4], dtype=np.float32)

y_data = y_data.reshape((25,1))

X = tf.placeholder(tf.float32, shape=[None, 2], name='x-input')
Y = tf.placeholder(tf.float32, shape=[None, 1], name='y-input')

이렇게 사용할 수 있게 살짝 변환하고 placeholder로 X, Y도 선언해 둡니다. 이제 중요한,

W = tf.Variable(tf.random_normal([2, 1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')
    
hypothesis = tf.matmul(X, W) + b

가설을 저렇게 정의합니다. 뭐 당연해 보이죠^^ 선형회귀 문제라서 지난번 AND 예제와 달리 sigmoid를 activation function으로 사용하지 않았습니다. 그리고

# Simplified cost/loss function
cost = tf.reduce_mean(tf.square(hypothesis - Y))

# Minimize
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.0001)
train = optimizer.minimize(cost)

cost도 AND에서는 cross-entropy를 사용했지만, 이번에는 그냥 단순하게 오차에 대한 Mean-Square만 사용했습니다. 그리고 optimizer로는 Gradient Descent를 사용했구용~~~

# Launch the graph in a session.
sess = tf.Session()
# Initializes global variables in the graph.
sess.run(tf.global_variables_initializer())

cost_history = []

for step in range(2001):
    cost_val, hy_val, _ = sess.run([cost, hypothesis, train], feed_dict={X: x_data, Y: y_data})
    if step % 10 == 0:
        print(step, "Cost: ", cost_val)
        cost_history.append(sess.run(cost, feed_dict={X: x_data, Y: y_data}))

드디어~ Session을 시작하고 학습을 시작했습니다.~~~

# Show the cost function
plt.figure(figsize=[12,6])
plt.plot(cost_history)
plt.grid()
plt.show()

cost가 어떻게 변해가는지 볼까요~~^^

넵... RMS도 아니고, 그냥 MS만 잡은데다, 데이터도 그 양이 적고 분산값이 만만치 않아서 수렴값이 좀 커보이긴 하지만, 뭐 하여간 수렴했네요^^

이렇게 질문을 이제 던져볼 수 있습니다. 100kg 몸무게에 나이 40이면?? 했더니 353.86이라는 수치가 나오네요... 흠 있는 데이터를 사용해서 혈액 지방 함량이라는 수치가 의미하는 바를 알 수는 없지만 말이죠. 그래서 이렇게 마치면 심심(^^)하니...

x = np.linspace(20, 100, 50).reshape(50,1)
y = np.linspace(10, 70, 50).reshape(50,1)

X = np.concatenate((x,y), axis=1)
Z = np.matmul(X, W_) + b_

fig = plt.figure(figsize=(12,12))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, Z)
ax.scatter(xs, ys, zs)
ax.set_xlabel('Weight')
ax.set_ylabel('Age')
ax.set_zlabel('Blood fat')
ax.view_init(15, 15)

plt.show()

그려보았습니다.^^

아하~~ 원 데이터들을 직선으로 잘 표현한 듯 보이네요^^

반응형