티스토리 뷰

오늘 공부 해 볼 내용은, 앞서 배운 선형회귀의 연장선상에 있는? 내용입니다. 

차이점이라고 하면, 앞서 배운 선형회귀는 변수 x가 한 개였다면, 지금은 여러개의 변수를 갖는 선형회귀 입니다.

Hypothesis로 보자면, H(x) = wx + b 에서 H(x) = w1x1 + w2x2 + w33.. + b가 되는 것이죠.

방법은 간단합니다. 데이터가 늘어난 만큼 weight과 x의 갯수를 늘려주면 되니까요. 

한번 코드로 살펴 볼까요? (참고로 지금 살펴 볼 코드는 나쁜 방법입니다.)

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

# 나쁜 방법
x1_data = [73., 93., 89., 96., 73.]
x2_data = [80., 88., 91., 98., 66.]
x3_data = [152., 185., 180., 196., 142.]
y_data = [152.,185.,180.,196.,142.]

x1 = tf.placeholder(tf.float32)
x2 = tf.placeholder(tf.float32)
x3 = tf.placeholder(tf.float32)
y = 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')
b = tf.Variable(tf.random_normal([1]), name = 'bias')
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, "\n prediction: \n", hy_val)

위와 같이 작성해도 잘 동작하지만, 지금이야 데이터가 많지 않아서 그렇지, 만약 데이터가 많아진다고 하면, 데이터와 가설등을 표현하는 코드의 길이가 엄청 커지게 됩니다. 그래서! 여기서 행렬곱을 사용하게 됩니다. 

한번 다음 코드를 보면 왜 행렬을 사용하는지 알게 되실겁니다! ㅎㅎ

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

# 좋은 방법 (매트릭스 사용 -> 적절한 사용)

x_data = [[73., 80., 75.], [93.,88., 93.], [89., 91., 90.], [96., 98., 100.], [73., 66., 70.]]
y_data = [[152.], [185.], [180.], [196.], [142.]]

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())

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, "\n prediction: \n", hy_val)
      

 

 

행렬 곱은 위와 같이 나타 낼 수 있습니다. 따라서 x,y,w,b 등을 행렬로 표현해줘야 하기 때문에 각각의 x_data와 y_data를 행렬로 표현한 것을 볼 수 있습니다.  placeholder도 행렬 데이터를 받을 것이기 떄문에 shape을 행렬로 만들어 줬는데요, 여기서 None으로 지정할 시 몇 행이던 상관없이 받을 수 있습니다.  또 Hypothesis를 보면

H = wx가 아닌 xw로 행렬곱을 하는 것 을 볼 수 있는데, 이는 행렬곱의 경우 곱할때 각각의 열과 행이 일치해야 곱이 가능하기 때문입니다. x는 1행 3열이고 w는 3행 1열이기때문에 wx xw 둘다 곱이 가능 하지만, xw로 행렬곱을 해야 x1w1 + x2w2 +x3w3... 가 나오게 됩니다. matmul은 매트릭스 곱을 해주는 함수입니다. 

행렬을 사용 했을때와 사용하지 않았을때의 차이점이 눈으로 확인이 되시나요? 행렬을 사용하면 많은 이점이 있는것 같습니다. 저도 아직 깊게 공부하지 않아서 잘 모르지만, 왜 머신러닝, 딥러닝을 공부할때 선형대수를 공부해야한다고 하는지? 알 것 같습니다. (물론 지금 사용한건 엄청 간단한 행렬곱이지만요 ㅋㅋ..) 

아래는 데이터를 다루기 위한 파이썬과 넘파이의 간단한 함수들 입니다. csv 형식의 텍스트파일 데이터를 로드한다고 했을 때, 아래와 같은 함수들을 사용하여 분리시켜 주면 좋겠죠?? 

# slicing & numpy
# 배열, 행렬 데이터를 다루기 위한 파이썬 슬라이싱과, 넘파이의 간단한 기능들
import numpy as np

nums = [0,1,2,3,4,5,6,7,8,9]
print(nums) # [0,1,2,3,4,5,6,7,8,9]

print(nums[2:4]) # [2,3]
print(nums[:2]) # [0,1]
print(nums[:-1]) # [0,1,2,3,4,5,6,7,8] -1은 맨 마지막 인덱스를 가리킴

# numpy
a = np.array([[1,2,3],[4,5,6],[7,8,9]])

a[:,1] # 모든 행 & 1열  array([2,5,8])
a[-1] # array([7,8,9])
a[0:2,: ] # array([[1, 2, 3],
          #       [4, 5, 6]])

a[0:3,1:3] # array([[2, 3],
               #    [5, 6],
               #    [8, 9]])

 

댓글
링크
최근에 올라온 글
최근에 달린 댓글