SW 개발

[스터디] 머신러닝 입문 - 05 : matrix hypothesis

. . . 2018. 7. 6. 20:31
반응형

본자료는 머리털나고 처음으로 머신러닝을 공부하는 입장에서 정리한 머신러닝 스터디노트입니다.

  • 오픈소스 강의를 들으면서 정리 및 요약한 자료입니다.
  • 제가 이해한 내용을 중심으로 작성했기 때문에 개인적인 의견 및 오류가 있을수있습니다.
  • 원본 강의는 항상 링크를 올립니다. 본강의와 함께 스터디하시는걸 추천드립니다.

머신러닝_기본_스터디 리스트 :

개요

강의자료

Sung Kim 교수님 강의 Lec 04 시청 및 Lab 04-1, 04-2 실습

강의요약

이전 강의 요약

데이터의 차이 - n:1 / n:1

1개 데이터당 1개 결과

hypothesis - 1

3개데이터당 1개 결과

hypothesis - 2

즉 학습해야할 변수가 많아졌다 -> w1 / w2 / w3 / b

cost

cost 는 기존과 같다.hypothesis 만 변경되었다.

n개데이터당 1개 결과

더많은경우도 다음과 같이 가능하다.

n개일때 위와같이 계속길어지계 되면 수식이 복잡하다. 그래서 matrix 를 이용한다.

matrix (배열)

matrix 의 곱셈

matrix 를이용한 hypothesis

위와같이 표현가능하다.

위의 표현대로 매트릭스의 곱으로 표현한다면 다음과 같겠지…

근데 위의 수식은 단점이 있다.

  • 위의 예제의 경우 총 5개의 데이터가있으므로.. 매트릭스를 5번 써야한다. - 73 80 75 -> 이것의 매트릭스 계산식.. - 93 88 93 -> 이것의 매트릭스 계산식.. - ... - 주어진 인수(인스턴스) 의 갯수만큼 계산을 해야한다 -> 표현이 많아진다.

그래서 2차원배열을 쓰면 간단하게 표현식이 가능하다.

인스턴스를 한번에 배열에 넣고 한번에 표현가능하다.

  1. 즉 5×3 의 매트릭스의 경우 w는 3×1 이어야한다.
  2. 이때 나오는결과는 5×1 이다.

문제 1

  • ? x ? 의 답은 3 x 1 이다.
  • 결국은 hypothesis 를 구해야한다. - 입력 데이터와 결과는 안다. - 리니어 모델에서는 결과는 항상 1개다.
  • 즉, W의 값을 구해야한다. W는 3×1 이다.

문제 2

  • 리니어 일반적인 모델은 입력되는 데이터가 n 개 이다. -> 결과는 1개 - 얼마나 입력될지 모른다면.. None 혹은 -1 이라고 표현 한다.

n개 입력 / m개 결과

  • 입력할 데이터의 갯수는 정해져있지 않고… 3개의 항목이다. - n x 3
  • 출력은 2개이므로 - n x 2
  • 이때 ? 부분은.. - 3 x 2

이와같이 매트릭스를 이용하면, 입력과 출력의 갯수를 마음대로 유연하게 처리가 가능하다.

정리

굉장히 단순화한 모델은 다음과 같다.

하지만, 실제 처리해야할 때는 다음과같이 매트릭스로 바로 표현하여 처리할수있다.

실습 1 : matrix hypothesis

입력데이터

예제코드1

https://github.com/hunkim/DeepLearningZeroToAll/blob/master/lab-04-1-multi_variable_linear_regression.py

위의 예제를 hypothesis 를 세우면…

위의 코드를 텐서플로로 구현하면 다음과같이 표현할 수 있다.

# Lab 4 Multi-variable linear regression
import tensorflow as tf
tf.set_random_seed(777) # for reproducibility
x1_data = [73., 93., 89., 96., 73.]
x2_data = [80., 88., 91., 98., 66.]
x3_data = [75., 93., 90., 100., 70.]
y_data = [152., 185., 180., 196., 142.]
# placeholders for a tensor that will be always fed.
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
print(hypothesis)
x1 \* w1 + x2 \* w2 + x3 \* w3 + b : 일반적인 hypothesis

cost function… 은 다음과 같이 표현가능하다.

# Hypothesis
hypothesis = tf.matmul(X, W) + b

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

# Minimize
optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-5)
train = optimizer.minimize(cost)

# Launch the graph in a session.
sess = tf.Session()
# Initializes global variables in the graph.
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, "\nPrediction:\n", hy_val)

# Ask my score
print("Your score will be ", sess.run(
    hypothesis, feed_dict={X: [[100, 70, 101]]}))

print("Other scores will be ", sess.run(hypothesis,
    feed_dict={X: [[60, 70, 110], [90, 100, 80]]}))

실행결과..

0 Cost: 19614.8 Prediction: [ 21.69748688 39.10213089 31.82624626 35.14236832 32.55316544] 
10 Cost: 14.0682 Prediction: [ 145.56100464 187.94958496 178.50236511 194.86721802 146.08096313]
1990 Cost: 4.9197 Prediction: [ 148.15084839 186.88632202 179.6293335 195.81796265 144.46044922]
2000 Cost: 4.89449 Prediction: [ 148.15931702 186.8805542 179.63194275 195.81971741 144.45298767]

위의 예제에서의 문제는 굉장히 복잡하다는것이다.

x1_data = [73., 93., 89., 96., 73.]
x2_data = [80., 88., 91., 98., 66.]
x3_data = [75., 93., 90., 100., 70.]
y_data = [152., 185., 180., 196., 142.]
# placeholders for a tensor that will be always fed.
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')

만약 입력 데이터가 많아진다면 위의 코드는 계속 x4/x5/x6 … 엄청 많아지게된다.

즉 입력데이터가 많아질때마다 코딩량이 늘어난다는것이다.

예제코드2

https://github.com/hunkim/DeepLearningZeroToAll/blob/master/lab-04-2-multi_variable_matmul_linear_regression.py

위의 예제를 matrix 를 이용한 hypothesis 를 세우면…

위의 matrix hypothesis 를 그대로 표현하면 다음과 같다.

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

# placeholders for a tensor that will be always fed.
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
hypothesis = tf.matmul(X, W) + b

X = tf.placeholder(tf.float32, shape=[None, 3])

위의 부분에서 배열의 형태를 결정하는 부분은 shape=[None, 3] 이다.

  • None : 배열의 행의 갯수를 None 으로 정하면 무한대. 정해놓지 않았다는것이다. 즉 입력하는데로 바로 대응가능. 원하는대로 주면된다.
  • 3 : 인자수는 3개
    Y = tf.placeholder(tf.float32, shape=[None, 1])

결과는 무한대로 지워질것이다.

cost function… 은 다음과 같이 표현가능하다.

# Simplified cost/loss function  
cost = tf.reduce_mean(tf.square(hypothesis - Y))
# Minimize
optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-5)
train = optimizer.minimize(cost)
# Launch the graph in a session.
sess = tf.Session()
# Initializes global variables in the graph.
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, "\nPrediction:\n", hy_val)

결과.

linear 모델에서 matrix hypothesis 를 사용하게 되면 입력데이터, 결과데이터를 얼마만큼 주어지더라도 유연하게 대처가능하다는것이다.

실습 2 : Loading data File

https://github.com/hunkim/DeepLearningZeroToAll/blob/master/lab-04-3-file_input_linear_regression.py

기존의 코드를 보면… 입력데이터를 일일이 모두 코드에 작성해놔야했었다.

x_data = [[73., 80., 75.],
    [93., 88., 93.],
    [89., 91., 90.],
    [96., 98., 100.],
    [73., 66., 70.]]
y_data = [[152.],
    [185.],
    [180.],
    [196.],
    [142.]]
# placeholders for a tensor that will be always fed.
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
hypothesis = tf.matmul(X, W) + b

위의 코드를 보면 입력데이터가 많아지면, 실제로 그에 해당하는 코딩을 해줘야했다. 데이터를 일일이 입력해야하며, 매번 프로그램을 바꿔야하는 불편함.

Loading data form file 1

그래서 위의 입력 부분을 데이터파일에서 읽어오게 할 필요가 있다.

입력데이터 파일

코드구현

np 모듈을 이용한다.

xy = np.loadtxt('data-01-test-score.csv', delimiter=',', dtype=np.float32)
x_data = xy[:, 0:-1]
y_data = xy[:, [-1]]
# Make sure the shape and data are OK
print(x_data.shape, x_data, len(x_data))
print(y_data.shape, y_data)
# placeholders for a tensor that will be always fed.
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')

xy[:, 0:-1]
  • 파이썬에서 2차원 배열에서 데이터를 갖고오는 방법이다.
  • 배열에서 인덱싱을 하여 데이터를 원하는 열 or 행 전체를 잘라서 데이터를 획득가능하다.
  • 2차원 배열에서 마지막 열을 뺀 나머지 2차원배열을 갖고온다.
    xy[:, [-1]]
  • 2차원 배열에서 끝의 열을 가져온다.

나머지 구현…

# Hypothesis 
hypothesis = tf.matmul(X, W) + b 

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

# Minimize 
optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-5) 
train = optimizer.minimize(cost) 

# Launch the graph in a session. 
sess = tf.Session() 
# Initializes global variables in the graph. 
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, "\nPrediction:\n", hy_val) 

# Ask my score 
print("Your score will be ", sess.run( 
    hypothesis, feed_dict={X: [[100, 70, 101]]})) 

print("Other scores will be ", sess.run(hypothesis, 
    feed_dict={X: [[60, 70, 110], [90, 100, 80]]})) 

Loading data form file 2 - queue runner

https://github.com/hunkim/DeepLearningZeroToAll/blob/master/lab-04-4-tf_reader_linear_regression.py

위와같은 예제의 문제점은… 입력데이터(ex. csv) 값이 엄청나게 많아질경우… 그데이터를 모두 메모리에 올린다음에 실행해야하는데… 결국 파일 read 자체가 메모리에 임시로 올리는거니까… 이렇게 메모리에 모두 올리는 비효율적인것을 해결하기위해서 텐서플로에서는 queue runner 라는것을 제공한다.

  • queue runner 의 대략적인 구상도다
  • 파일의 리스트를준다. - ABC
  • 파일에서 랜덤으로 데이를 읽어서 file name queue로 저장한다.
  • 이때 queue 에서 dequeue 하여 Reader 로 옮기고
  • decoder 에서 다시 example queue 로 관리한다.
  • 메인 루틴은 example queue 에서 데이터 데이터를 꺼내서 학습시킨다.

위의 내용대로 구성해보면…

  1. file list 를 정의 한다.
  2. file 을 read 할 reader 를 정의한다.
    • ex) 바이너리로 읽을것인지?텍스트로 읽을것인지 등등
  3. 읽은 파일에서 어떻게 파싱할것인가를 결정
    • recode_defaults : 파일의 각각의 데이터 형식이 어떤형식일지를 결정
    • decode_csv() : 각 데이터를 읽어올때 csv 형식으로 읽어올것

결국 example queue 에서 데이터를 꺼내(batch)와서 학습시킨다.

# collect batches of csv in
train_x_batch, train_y_batch = \
    tf.train.batch([xy[0:-1], xy[-1:]], batch_size=10)
    tf.train.batch([xy[0:-1], xy[-1:]], batch_size=10)
  • batch_size = 10
    • 한번에 batch 할때 10개씩 가져올것

학습을 시킬때 batch 에서 매번 꺼내서 학습시키는 예제…

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(step, "Cost: ", cost_val, "\nPrediction:\n", hy_val)

참고) batch 하는 순서를 랜덤하게 갖고오는 여러 기법들이 있으니 추후 참고해볼것

반응형