4 minute read

1. multi-variable linear regression (Multiple Linear Regression)

1.1 행렬을 사용안한 Multiple Linear Regression

변수의 개수가 늘어날 수록 예측의 정확도가 올라가는데 이것을 prediction power가 세진다고 말합니다.

import numpy as np
import tensorflow as tf
print("TensorFlow Version: %s" % tf.__version__)
# Data
# x1 = [73., 93., 89., 96., 73.]
# x2 = [80., 88., 91., 98., 66.]
# x3 = [75., 93., 90., 100., 70.]
# y = [152., 185., 180., 196., 142.]
x1 = [80., 65., 35., 78., 95.]
x2 = [75., 55., 55., 85., 90.]
x3 = [90., 60., 45., 80., 94.]
y  = [85., 70., 60., 78., 98.]

# Weights
tf.random.set_seed(2020)
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))
# print("w1: %f, w2: %f, w3: %f" %(w1, w2, w3))
# print("bias: %f" %b)
# print(hypothesis) # hypothesis값은 shape=(5, )인 텐서가 나온다.
# print(cost)

# Learning Rate
learning_rate = 0.0000001

# Training 
# w 3개의 값과 bias를 구하는 학습
for i in range(2000 + 1) :
    with tf.GradientTape() as tape:
        hypothesis = x1 * w1 + x2 * w2 + x3 * w3 + b
        cost = tf.reduce_mean(tf.square(hypothesis - y))
        w1_grad, w2_grad, w3_grad, b_grad = tape.gradient(cost, [w1, w2, w3, b]) # graident 메소드의 첫 번째 매개변수는 loss값, 두 번째에는 학습시키려는 variable tensor가 들어간다.
    
    w1.assign_sub(learning_rate * w1_grad)
    w2.assign_sub(learning_rate * w2_grad)
    w3.assign_sub(learning_rate * w3_grad)
    b.assign_sub(learning_rate * b_grad)

    if i % 200 == 0:
         print("#%s \t cost: %s" % (i, cost.numpy()))
#0 	 cost: 19095.684
#200 	 cost: 5163.9473
#400 	 cost: 1452.9823
#600 	 cost: 464.43408
#800 	 cost: 201.04555
#1000 	 cost: 130.81319
#1200 	 cost: 112.03182
#1400 	 cost: 106.95497
#1600 	 cost: 105.52873
#1800 	 cost: 105.07515
#2000 	 cost: 104.88092

1.2 행렬을 사용한 Multiple Linear Regression

데이터 슬라이싱을 통해 X, Y 변수에 값 할당

#data
data = np.array([
    [80., 75., 90., 85.],
    [65., 55., 60., 70.],
    [35., 55., 45., 60.],
    [78., 85., 80., 78.],
    [95., 90., 94., 98.]
], dtype = np.float32)

# Slice Data
X = data[:, :-1]
Y = data[:, [-1]]
X
# X변수에 대한 출력
array([[80., 75., 90.],
       [65., 55., 60.],
       [35., 55., 45.],
       [78., 85., 80.],
       [95., 90., 94.]], dtype=float32)
Y
# Y변수에 대한 출력
array([[85.],
       [70.],
       [60.],
       [78.],
       [98.]], dtype=float32)

행렬을 사용한 학습

# Weights
tf.random.set_seed(2020)
W = tf.Variable(tf.random.normal([3, 1], mean = 0.0))
b = tf.Variable(tf.random.normal([1], mean = 0.0))

# learning_rate = 0.0000001
learning_rate = 1e-5

# Hypothesis and Prediction Function
def predict(X):
    return tf.matmul(X, W) + b

# Training
for i in range(2000+1) :
    with tf.GradientTape() as tape:
        cost = tf.reduce_mean(tf.square(predict(X) - Y))
        W_grad, b_grad = tape.gradient(cost, [W, b])
    
    W.assign_sub(learning_rate * W_grad)
    b.assign_sub(learning_rate * b_grad)
    
    if i % 200 == 0:
        print("#%s \t cost: %s" % (i, cost.numpy()))
#0 	 cost: 7769.522
#200 	 cost: 57.931904
#400 	 cost: 56.41485
#600 	 cost: 55.062645
#800 	 cost: 53.856743
#1000 	 cost: 52.780952
#1200 	 cost: 51.82087
#1400 	 cost: 50.963943
#1600 	 cost: 50.198845
#1800 	 cost: 49.515617
#2000 	 cost: 48.905342

Lab4-2 TensorFlow로 파일에서 데이터 읽어오기

저는 실습환경이 코랩이라서, 코드를 조금 변경해서 사용했습니다.

import tensorflow as tf
import numpy as np
from google.colab import files

uploaded = files.upload()

print(uploaded) # 출력할 떄 b가 같이 나오는데, 이 때문에 byte?에러가 발생한다

# 삽질의 흔적
#print(uploaded['data-01-test-score.CSV'].decode('utf-8'))

#이 방법의 단점은 전체 데이터가 같은 타입이어야 한다.
# xy = np.loadtxt(uploaded['data-01-test-score.CSV'], delimiter = ',', dtype = np.float32) 
# xy = np.loadtxt(uploaded['data-01-test-score.CSV'].decode('utf-8'), delimiter = ',', dtype = np.float32)


xy_before = uploaded['data-01-test-score.CSV'] # 각 attribute의 종류 => EXAM1 EXAM2 EXAM3 FINAL 
xy_str = uploaded['data-01-test-score.CSV'].decode('utf-8')

# 리스트 초기화
data_list = [[]]
data_list.pop();

# 리스트에 값 넣기
delimiter = ','
carriage_return = '\r'
linefeed = '\n'

index_str = str() # 원소 하나를 가지고 있는 문자열
row_list = list() # 한 행을 가지고 있는 리스트

for i in xy_str:
    if (i == delimiter):
        floatIndexValue = float(index_str)
        row_list.append(floatIndexValue)
        index_str = ""
        continue

    if (i == carriage_return):
        continue

    if (i == linefeed):
        row_list.append(float(index_str))
        index_str = "" 

        data_list.append(row_list[:]) # 파이썬 append 연산은 얕은 복사이다. [:]을 붙여주면 깊은 복사를 할 수 있다.
        row_list.clear()
        continue
    
    index_str += i

# 2차원 리스트를 np.array로 변환하기
xy = np.array(data_list)

x_data = xy[:, 0:-1]
y_data = xy[:, [-1]]

print(x_data, "\nx_data shape:", x_data.shape)
print(y_data, "\ny_data shape:", y_data.shape)


# -Multi-variable linear regression-
tf.model = tf.keras.Sequential()
# activation function doesn't have to be added as a separate layer. Add it as an argument of Dense() layer
tf.model.add(tf.keras.layers.Dense(units=1, input_dim=3, activation='linear'))
# tf.model.add(tf.keras.layers.Activation('linear'))

tf.model.summary()

tf.model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(lr=1e-5))
history = tf.model.fit(x_data, y_data, epochs=2000)

# Ask my score
print("Your score will be ", tf.model.predict([[100, 70, 101]]))
print("Other scores will be ", tf.model.predict([[60, 70, 110], [90, 100, 80]]))

Queue Runners

넘파이를 가지고 간단히 해볼 수 있습니다.

파일이 굉장히 크다면 메모리에 한 번에 올리기도 힘든 경우가 있을 수도 있습니다. 이런 경우에서 넘파이를 사용해서 올리면 메모리가 부족하다고 뜰 수도 있습니다. 그래서 이런 경우에 대비해서 텐서플로우에서는 Queue Runners라는 시스템을 만들어 두었습니다.

image

  • 기본적으로 우리가 하나의 파일이 아니라 여러 개의 파일에서 데이터를 읽어오는 상황이 있을 것입니다.
  • 그러면 이 여러개의 파일을 Filename Queue에다가 쌓게 됩니다.
  • 그런 다음에 이걸 Reader로 연결해서 데이터를 읽은 다음에 읽은 데이터 양식에 맞게 decoder를 해야 합니다. (콤마를 분리한다던지)
  • 그리고 또 여기서 읽어온 값을 Example Queue에다가 쌓습니다.
  • 우리가 학습을 시킬 때 한 번에 전체 파일이 다 필요한 것은 아니니까, 어떤 batch만큼 읽어와서 학습을 시키고 이 큐에서 조금씩 꺼내쓰면 되는 것입니다.
  • 그리고 이 전체적인 과정은 텐서플로우가 책임지고 메모리에도 한 번에 전체 데이터를 올리지 않으니까 굉장히 큰 데이터를 쓸 때 유용할 수 있습니다.

꽤나 복잡해보이지만 간단할 수 있습니다. 한 번 살펴봅시다.

image

  1. 우리가 가지고 있는 파일이름의 리스트를 만듭니다. shuffle옵션을 추가할 수도 있습니다.
  2. 파일을 읽어올 Reader를 정의해줍니다.
  3. reader에서 읽어온 value를 어떻게 파싱할 것인지를 정하는 것이 tf.decode_csv()함수입니다. record_defaults라고 해서 각각의 필드에 해당되는 값이 어떤 데이터타입인지 정해줄 수 있습니다. 우리 예제에서는 다 float니까 recoder_defaults에 float값으로 지정해주었습니다.

tf.train.batch

batch는 펌프 같은 것입니다. (데이터를 빨아 들여옴.)

image

tensorflow의 batch를 통해 읽어오게 된다. 1번쨰 매개변수는 x_data를 의미하고, 2번째 매개변수는 y_data를 의미한다. 그것을 train_x_batch, train_y_batch로 받는다. batch_size = 10은 한 번에 10개씩 데이터를 가져오라는 소리이다.

(더 자세한 코드는 어차피 TF1.0이라 필요없어서 필기하지 않았습니다. 개념만 필기했음.)

shuffle_batch

batch의 순서를 바꾸고 싶으면 shuffle_batch를 사용하는 방법이 있다.


참고자료

Multiple Linear Regression
ML lab 04-1 ML lab 04-2