3번째로 지금까지 했던 Linear Regression과 Logisitc Classification 중 Linear Regression의 확장판인 Multiple Linear Regression을 해보려고 합니다. 방식은 아주 간단합니다. 지금까지 했던 Linear Regression에서 변수를 x 하나에서 여러 개의 x로 확장하면 되는 겁니다.


실생활의 예를 들어서 실습해보면 좋을 거 같았는데, 생각보다 Multiple Linear Regression의 데이터셋을 구하기가 어려워서 그냥 제가 임의로 식을 하나 잡고 데이터셋을 랜덤으로 제작해서 만들어봤습니다. 아래는 변수가 2개인(x1, x2) 3D 함수입니다. 3D는 일반적으로 (x, y, z)로 표현하기 때문에 아래의 예시들도 다 그렇게 좌표를 뒀습니다.

이 식을 그려보면 다음과 같은 3D plane이 나오게 됩니다.

이것을 기반으로 np.random.normal(API 문서에는 정규 분포(가우시안 분포) 기반이라고 하더군요)을 통해 데이터셋 99개를 뽑아봤습니다. 그 데이터셋을 그려보면 다음과 같습니다.

아래는 위의 함수 하나 가지고 plane 그려내고 random으로 dataset을 뽑아내는 코드입니다.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

# z = 10x - 4y + 7

#draw 3D graph
fig = plt.figure()

x, y = np.meshgrid(np.arange(-10, 10), np.arange(-10, 10))

a1 = fig.add_subplot(111, projection="3d")
a1.plot_surface(x, y, 10 * x - 4 * y + 7, rstride=1, cstride=1, cmap=cm.Blues)

a1.set_xlabel("X")
a1.set_ylabel("Y")
a1.set_zlabel("Z")

plt.show()

# data maker
fig = plt.figure()

coordinates = []

for i in xrange(100):
    x = np.random.normal(0.0, 1.)
    y = np.random.normal(0.0, 1.0)
    z = 10 * x - 4 * y + 7 +  np.random.normal(0.0, 0.1)
    coordinates.append([x, y, z])

a2 = fig.add_subplot(111, projection="3d")
a2.scatter([v[0] for v in coordinates], [v[1] for v in coordinates], [v[2] for v in coordinates])

a2.set_xlabel("X")
a2.set_ylabel("Y")
a2.set_zlabel("Z")

plt.show()

np.savetxt("dataset.txt", coordinates, fmt="%f")

데이터를 뽑아냈으면 이제 학습해야 겠죠? 아래는 Multiple Linear Regression을 학습하는 코드입니다.

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

data = np.loadtxt("dataset.txt", unpack=True, dtype="float32")

x_data = np.transpose(data[0:-1])
y_data = np.transpose(data[-1])

y_data = np.reshape(y_data, [len(y_data), 1])

X = tf.placeholder("float", [None, 2])
Y = tf.placeholder("float", [None, 1])

w = tf.Variable(tf.random_uniform([2, 1], -2.0, 2.0))
b = tf.Variable(tf.random_uniform([1, 1], -2.0, 2.0))

y = tf.matmul(X, w) + b

loss = tf.reduce_mean(tf.square(y - Y))
optimizer = tf.train.GradientDescentOptimizer(0.1)
train = optimizer.minimize(loss)

init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)

for step in xrange(1001):
    sess.run(train, feed_dict={X: x_data, Y: y_data})
    if step % 100 == 0:
        print step, sess.run(w), sess.run(b)
        print "loss:", sess.run(loss, feed_dict={X: x_data, Y: y_data})

# Graph
fig = plt.figure()

x1, x2 = np.meshgrid(np.arange(-10, 10), np.arange(-10, 10))

x = np.transpose([x1.flatten(), x2.flatten()])

result = sess.run(y, feed_dict={X: x})

a1 = fig.add_subplot(111, projection="3d")
a1.scatter(data[0], data[1], data[2], c='r')
# 원함수 출력 원할 경우 
#a1.plot_surface(x1, x2, 10 * x1 - 4 * x2 + 7, linewidth=0, rstride=1, cstride=1, cmap=cm.Blues)
a1.plot_surface(x1, x2, np.reshape(result, x1.shape), linewidth=0, rstride=1, cstride=1, cmap=cm.Greens)

a1.set_xlabel("X1(X)")
a1.set_ylabel("X2(Y)")
a1.set_zlabel("Y(Z)")

plt.show()

이 코드를 돌리게 되면, 생각보다 수렴이 아주 빠른 건지 저 같은 경우 특정 데이터셋에 대해 100번만 학습해도 cost값이 0.0100895으로 내려가고, 이후에 전혀 내려가지 않더라고요. 그렇게해서 구해보니 w는 [[ 9.99918079] [-4.00411749]], b는 [[ 6.9931798]]가 나와서 최초 함수값과 거의 가까워졌습니다. 아래는 데이터셋과 TensorFlow로 학습된 함수를 그려본 것입니다. 거의 일치해서 데이터셋이 본 함수에 묻혔음을 알 수 있습니다.

조금 더 확실하게 확인하기 위해서 최초 함수와 학습된 함수를 그려봤습니다. 완전 덮은 것이 보입니다. 실제로 덮어졌기 때문에 pyplot창에서 이리저리 grid를 움직이다보면 앞면엔 학습된 함수인 초록색이, 뒷면엔 최초 함수인 파란색이 보입니다.

x가 더 필요하시다면 많이 늘리셔서 그대로 적용하시면 됩니다. 단, 차원이 올라가기 때문에 실제로는 x를 2개까지만 하는게 시각화하기에 적절합니다.


이렇게 Mutiple Linear Regression을 마무리해봤습니다. 다음 번에는 유명한 붓꽃(iris) 데이터셋을 통해 Softmax Classification을 해보겠습니다. 보통은 Multiple Logisitc Classification 대신 Softmax Classification(Multinomial Logistic Regression(Classification))이라고 하는 거 같더군요.

+ Recent posts

티스토리 툴바