πŸ’»/ML

[λͺ¨λ‘λ₯Ό μœ„ν•œ λ”₯λŸ¬λ‹] ν…μ„œν”Œλ‘œμš° 기초, μ„ ν˜•νšŒκ·€

ruhz 2020. 7. 26. 16:13
import tensorflow as tf

# 데이터에 λžœλ€ν•œ 값을 ν•˜λ‚˜ λ„£κ³ , 이름을 'weight', 'bias'둜 λΆ™μ—¬μ€€ Variable을 μƒμ„±ν•œλ‹€.
W = tf.Variable(tf.random_normal([1]), name = 'weight')
b = tf.Variable(tf.random_normal([1]), name = 'bias')

# λ“€μ–΄μ˜¬ λ°μ΄ν„°μ˜ νƒ€μž…μ€ float32, shape은 아직 μ •ν•΄μ§€μ§€ μ•Šμ€ placeholderλ₯Ό μƒμ„±ν•œλ‹€.
X = tf.placeholder(tf.float32, shape=[None])
Y = tf.placeholder(tf.float32, shape=[None])

ν…μ„œν”Œλ‘œμš°λŠ” 'ν…μ„œ(Tensor)'λ₯Ό μ΄μš©ν•΄μ„œ κ·Έλž˜ν”„λ₯Ό κ΅¬μ„±ν•˜κ³ , κ·Έλž˜ν”„μ— 데이터λ₯Ό λ„£μ–΄ '흐름(Flow)'을 λ§Œλ“œλŠ” 컨셉을 κ°€μ§€κ³  μžˆλ‹€. μ—¬κΈ°μ„œ ν…μ„œλŠ” ν…μ„œν”Œλ‘œμš°μ˜ κΈ°λ³Έ λ‹¨μœ„κ°€ λ˜λŠ” μ–΄λ–€ ꡬ쑰체(λ°°μ—΄)쯀으둜 μƒκ°ν•˜λ©΄ 쒋을 것 κ°™λ‹€. μœ„ μ½”λ“œλ₯Ό μ΄ν•΄ν•˜λ €λ©΄, ν…μ„œμ˜ μžλ£Œν˜•κ³Ό 속성에 λŒ€ν•΄ μ•Œμ•„μ•Όν•œλ‹€. W, bλŠ” ν•™μŠ΅μ‹œν‚¬ λ³€μˆ˜ λ‘κ°œλ₯Ό, X, YλŠ” ν•™μŠ΅μ— μ‚¬μš©ν•˜λŠ” 데이터λ₯Ό 넣을 placeholder λ‘κ°œλ₯Ό μƒμ„±ν–ˆλ‹€.

 

 

μžλ£Œν˜•

  • constant : μƒμˆ˜λ₯Ό μ˜λ―Έν•˜λŠ” ν…μ„œ
  • Variable : ν•™μŠ΅ 과정이 μ§„ν–‰λ˜λ©΄ Tensorflowκ°€ 값을 μˆ˜μ •ν•˜λ©°, μ°Ύκ³ μžν•˜λŠ” κ°’μœΌλ‘œ λ‚˜μ•„κ°€κ²Œ λ˜λŠ” ν•™μŠ΅λ³€μˆ˜μ΄λ‹€.
  • placeholder : μžλ£Œν˜• constantλŠ” μƒμˆ˜λ‘œ 값을 μˆ˜μ •ν•  수 μ—†μ§€λ§Œ, placeholderλŠ” λ‚˜μ€‘μ— 값을 μ„€μ •ν•  수 μžˆλ‹€.

 

 

속성

  • Rank : 차원을 μ˜λ―Έν•œλ‹€.
    (Rank=0인경우 슀칼라(κ°’), Rank=1인경우 벑터(1차원배열), Rank=2인경우 ν–‰λ ¬(2차원배열)이 λœλ‹€)
  • Shape : μ •ν•΄μ§„ Rank에 μ–΄λ– ν•œ ꡬ쑰의 데이터가 λ“€μ–΄κ°€λŠ”μ§€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 값이닀.
    (ShapeλŠ” Rank만큼 μ›μ†Œμ˜ 개수λ₯Ό κ°–κ²Œλœλ‹€. 예λ₯Ό λ“€μ–΄, Rank=2 -> Shape=(3, 5) : 3X5의 ν–‰λ ¬)
  • dtype : ν…μ„œκ°€ κ°€μ§ˆ 데이터 값이 μ–΄λ–€ νƒ€μž…μ„ κ°–λŠ”μ§€λ₯Ό μ˜λ―Έν•œλ‹€. 주둜 float32, int32λ₯Ό μ΄μš©ν•˜κ²Œ λœλ‹€.
  • name : ν…μ„œμ— 이름을 뢙여쀄 수 있고 ν•„μˆ˜λŠ” μ•„λ‹ˆλ‹€.

 

 

# 가정을 μ •μ˜ν•œλ‹€.
hypothesis = W * X + b

# λΉ„μš©μ„ μ •μ˜ν•œλ‹€.
cost = tf.reduce_mean(tf.square(hypothesis - Y))

ν˜„μž¬ μš°λ¦¬κ°€ λ³Ό μ˜ˆμ œλŠ” 인곡지λŠ₯ > λ¨Έμ‹ λŸ¬λ‹ > μ§€λ„ν•™μŠ΅(Supervised Learning)에 ν•΄λ‹Ήν•œλ‹€. λ³΅μŠ΅ν•˜μžλ©΄, μ§€λ„ν•™μŠ΅μ€ μž…λ ₯에 λŒ€ν•œ 결과값을 같이 μ£Όκ³  ν•™μŠ΅μ‹œμΌœ, λ‚˜μ€‘μ—λŠ” μž…λ ₯κ°’λ§Œ 받아도 κ²°κ³Όλ₯Ό μΆ”λ‘ ν•΄λ‚Ό 수 있게 ν•˜λŠ” 것이닀. μœ„μ—μ„œ μƒμ„±ν•œ placeholder X, Yμ—λŠ” 후에 μž…λ ₯κ°’, μž…λ ₯에 λŒ€ν•œ 좜λ ₯값이 각각 λ“€μ–΄κ°ˆ 것이닀.

 

 

κ°€μ •

가정은 'μž…λ ₯κ³Ό 좜λ ₯사이에 이런 관계가 μžˆμ„ 것이닀' ν•˜κ³  ν•¨μˆ˜μ‹μ„ μ„Έμ›Œλ³΄λŠ” 것이닀. λ§Œμ•½ 데이터가 μ„ ν˜•μ˜ 관계λ₯Ό κ°–λŠ”λ‹€κ³  ν•˜λ©΄ 가정을 H(X) = W*X + b 라고 μ„ΈμšΈ 수 μžˆλ‹€. μ•„κΉŒ μ •μ˜ν•œ W와 b에 μ΄ˆκΈ°κ°’μ€ 랜덀으둜 λ“€μ–΄κ°”λ‹€. μ•žμœΌλ‘œ ν•™μŠ΅μ„ λ°˜λ³΅ν•˜λ©° W, bλŠ” 'X, Y μ‚¬μ΄μ˜ 관계에 ν•΄λ‹Ήν•˜λŠ” κ°’'으둜 점점 κ°€κΉŒμ›Œμ§ˆ 것이닀.
( X=[1, 2, 3], Y=[3, 5, 7] 이 ν•™μŠ΅λ°μ΄ν„°λ‘œ μ£Όμ–΄μ‘Œλ‹€λ©΄ W=2, b=1에 점점 κ°€κΉŒμ›Œμ§„λ‹€)

 

 

λΉ„μš©ν•¨μˆ˜

κ·Έλ ‡λ‹€λ©΄ μ–΄λ–»κ²Œ W, bλ₯Ό νŒŒλž€μƒ‰ 정닡직선에 κ·Όμ‚¬μ‹œν‚¬ 수 μžˆμ„κΉŒ? μ„Έμš΄ κ°€μ •μ—μ„œμ˜ H(X)κ°’κ³Ό μ‹€μ œ ν•™μŠ΅λ°μ΄ν„° Yκ°’μ˜ 차이λ₯Ό μ΅œμ†Œν™”ν•˜λŠ” 것이닀. 이 λ•Œ, λΆ€ν˜Έμ™€ 관계없이 차이λ₯Ό 보고싢은 κ²ƒμ΄λ―€λ‘œ square() 을 μ΄μš©ν•΄ 값을 μ œκ³±ν•΄μ€€λ‹€. reduce_mean() 으둜 값을 λͺ¨λ‘ λ”ν•œ λ’€ λ°μ΄ν„°μ˜ 갯수만큼 λ‚˜λˆ μ£Όλ©΄ λΉ„μš©(cost)κ°€ μ •μ˜ λœλ‹€.

κ·Έλ ‡λ‹€λ©΄ μ•žμœΌλ‘œ 이 μ½”λ“œμ˜ λͺ©μ μ€ λΉ„μš©μ„ μ΅œμ†Œλ‘œ μ€„μ΄λŠ” 것이 λœλ‹€. λΉ„μš©μ΄ μ΅œμ†Œκ°€ λœλ‹€λŠ” 것은 κ°€μ •ν•œ 직선과 μ‹€μ œ 데이터 κ°’ κ°„μ˜ 차이가 μ΅œμ†Œν™” λœλ‹€λŠ” 말이 되기 λ•Œλ¬Έμ΄λ‹€.

 

 

 

# μ›λž˜λŠ” λ‹€μŒκ³Ό 같은 과정을 거쳐 cost의 μ΅œμ†Ÿκ°’μ„ μ°Ύμ•„κ°€μ•Ό ν•œλ‹€.
# μ„€λͺ…을 μœ„ν•΄ κ°„λ‹¨ν•œ 예 H(X) = W * X둜 κ°€μ •ν–ˆλ‹€.
'''
learning_rate = 0.1
gradient = tf.reduce_mean((W * X - Y) * X)
descent = W - learning_rate * gradient
update = W.assign(descent)
'''

# ν•˜μ§€λ§Œ ν…μ„œν”Œλ‘œμš°λŠ” 이 과정이 μΉœμ ˆν•˜κ²Œ κ΅¬ν˜„λ˜μ–΄ μžˆλ‹€.
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)

λ¨Όμ € μœ„ μ½”λ“œμ—μ„œ λ°‘μ—μ„œ λ‘λ²ˆμ§Έ 쀄을 보자.
GradientDescentOptimizer λŠ” 경사(Gradient)λ₯Ό ν•˜κ°•(Descent)ν•˜λ©° 졜적의 κ°’, 즉 μ—¬κΈ°μ„œλŠ” μ΅œμ†Ÿκ°’μ„ μ°Ύμ•„μ£ΌλŠ”(Optimizer) ν•¨μˆ˜λΌλŠ” 의미λ₯Ό κ°–κ³  μžˆλ‹€. 무슨 경사λ₯Ό μ™œ ν•˜κ°•ν•œλ‹€λŠ” 말일까, 또 λ§€κ°œλ³€μˆ˜λ‘œ μ£Όμ–΄μ§„ learning_rate λŠ” 무슨 말일까?

 

 

κ²½μ‚¬ν•˜κ°• μ•Œκ³ λ¦¬μ¦˜

λ¨Όμ € 무슨 경사λ₯Ό μ–΄λ–»κ²Œ ν•˜κ°•ν•˜λŠ”μ§€ μ•Œμ•„μ•Όν•œλ‹€. 예λ₯Ό λ“€μ–΄, H(X) = W*X 라고 κ°€μ •ν•˜μž. λΉ„μš©(cost)을 계산할 λ•Œ, X와 YλŠ” μ–΄μ°¨ν”Ό μ£Όμ–΄μ ΈμžˆλŠ” λ°μ΄ν„°μ΄λ―€λ‘œ, κ°€μ •(hypothesis)에 따라 값이 쒌우 λœλ‹€. 또 가정은 κ²°κ΅­ 기울기인 W에 μ˜ν•΄ μ§μ„ μ˜ λͺ¨μ–‘이 λ°”λ€Œκ²Œ λœλ‹€. λ”°λΌμ„œ costλŠ” W에 κ΄€ν•œ ν•¨μˆ˜ cost(W)라고 말할 수 μžˆλ‹€.

λ§Œμ•½ κ°€λ‘œμΆ•μ„ W둜, μ„Έλ‘œμΆ•μ„ cost라고 ν•œλ‹€λ©΄ κ·Έλž˜ν”„λŠ” λ‹€μŒκ³Ό 같이 κ·Έλ €μ§„λ‹€. μš°λ¦¬λŠ” 처음 Wλ₯Ό random_normal([1])둜 μ΄ˆκΈ°ν™”ν–ˆμ—ˆλ‹€. μ΄λ•Œ 3이 μ΄ˆκΈ°ν™”λλ‹€λ©΄, (3, cost(3)) λΆ€ν„° μ‹œμž‘ν•΄μ„œ μ ‘μ„ μ˜ 기울기(경사)λ₯Ό 타고 λ‚΄λ €κ°€λ©°(ν•˜κ°•) λΉ„μš©μ˜ μ΅œμ†Ÿκ°’μ„ 찾을 것이닀.

  1. W = W - learning_rate * gradient
    learning_rateλŠ” ν•˜κ°•κ°„κ²©μ„ μ‘°μ •ν•˜κΈ° μœ„ν•œ μ–‘μˆ˜μΈ μƒμˆ˜μ΄λ‹€. gradientλŠ” μ ‘μ„ μ˜ 기울기λ₯Ό μ˜λ―Έν•œλ‹€. μ–‘μˆ˜μ˜ κ³±μ΄λ―€λ‘œ, WλŠ” μ›λž˜μ˜ 값보닀 쀄어든 κ°’μœΌλ‘œ μ—…λ°μ΄νŠΈ 될 것이닀.
  2. 이λ₯Ό 계속 λ°˜λ³΅ν•˜λ©΄ 꼭짓점을 ν–₯ν•΄ ν•˜κ°•ν•˜κ²Œ λœλ‹€.
  3. 꼭짓점에 κ°€κΉŒμ›Œμ§ˆμˆ˜λ‘ μ ‘μ„ μ˜ κΈ°μšΈκΈ°κ°€ κ°μ†Œν•΄ λ³€ν™”λŸ‰μ΄ μž‘μ•„μ§„λ‹€.

ν•˜μ§€λ§Œ, 잠깐 μƒˆλ‘œμš΄ κ·Έλž˜ν”„λ₯Ό 보자. λ§Œμ•½ λΉ¨κ°„ 점뢀터 ν•˜κ°•μ„ μ‹œμž‘ν•œλ‹€λ©΄, μœ„μ˜ μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ 생각해 봀을 λ•Œ, λΉ„μš©μ˜ μ΅œμ†Ÿκ°’μ΄ μ•„λ‹˜μ—λ„ λΆˆκ΅¬ν•˜κ³  λ…Έλž€ 뢀뢄에 근사할 것이닀.

 

λ”°λΌμ„œ κ²½μ‚¬ν•˜κ°•λ²•μ€ convex functionμ΄λΌλŠ” νŠΉμ • 쑰건을 λ§Œμ‘±μ‹œν‚¬λ•Œλ§Œ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€. λ³Όλ‘ν•¨μˆ˜(convex function)​에 λŒ€ν•œ μ„€λͺ…이 잘 λ‚˜μ™€μžˆλŠ” λ™μ˜μƒμ΄λ‹€(링크)

 

μœ„μ˜ μ½”λ“œμ—μ„œ μ£Όμ„μ²˜λ¦¬ λ˜μ–΄μžˆλŠ” 뢀뢄은 κ²½μ‚¬ν•˜κ°•λ²•μ„ μ΄μš©ν•΄μ„œ cost의 μ΅œμ†Ÿκ°’μ„ κ΅¬ν•˜λŠ” κ·Έλž˜ν”„λ₯Ό 직접 λ§Œλ“  것이닀. ν•˜μ§€λ§Œ tensorflowμ—μ„œ μ œκ³΅ν•˜λŠ” ​GradientDescentOptimizer()β€‹ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ ν•™μŠ΅μœ¨κ³Ό, μ΅œμ†Œν™”ν•  λŒ€μƒμ„ μ§€μ •ν•˜λŠ” 것 만으둜 μ‰½κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€. μ•Œμ•„μ„œ 경사λ₯Ό κ³„μ‚°ν•˜κ³ , ν•˜κ°•μ„ ν•˜λ©°, κ·Έ 값을 W에 μ—…λ°μ΄νŠΈν•œλ‹€. 

 

 

 

# κ·Έλž˜ν”„λ₯Ό μ‹€ν–‰ν•  μ„Έμ…˜μ„ λ§Œλ“€μ–΄μ€€λ‹€.
sess = tf.Session()
sess.run(tf.global_variables_initializer())

# ν•™μŠ΅μ€ 2000번 μ§„ν–‰ν•œλ‹€.
for step in range(2001):
   cost_val, W_val, b_val, _ = sess.run([cost, W, b, train],
       feed_dict={X: [1, 2, 3, 4, 5], 
                  Y: [2.1, 3.1, 4.1, 5.1, 6.1]})
   # 20λ²ˆμ— ν•œ λ²ˆμ”© ν•™μŠ΅κ²°κ³Όλ₯Ό 좜λ ₯ν•΄μ€€λ‹€.
   if step % 20 == 0:
       print(step, cost_val, W_val, b_val)

ν…μ„œν”Œλ‘œμš°λŠ” ν…μ„œ(Tensor)둜된 κ·Έλž˜ν”„λ₯Ό λ§Œλ“€κ³  데이터λ₯Ό λ„£μ–΄ 흐름(Flow)을 λ§Œλ“œλŠ” 언어이닀.
μ„Έμ…˜μ„ λ§Œλ“€κ³  μ‹€ν–‰ν•˜κΈ° 전에, ν˜„μž¬ κ΅¬μ„±λ˜μ–΄ μžˆλŠ” κ·Έλž˜ν”„λ₯Ό 그렀보면 μ΄λŸ¬ν•˜λ‹€.

ν…μ„œλ³΄λ“œλ₯Ό μ΄μš©ν•΄ 좜λ ₯ν•œ κ·Έλž˜ν”„μ΄λ‹€. μ—°μ‚°λ…Έλ“œλ“€μ„ 거쳐 데이터가 흐λ₯΄κ²Œ 되고, GradientDescentOptimizerκ°€ W, b에 λΆ™μ–΄ ν•™μŠ΅ν•œ 정보λ₯Ό λ°”νƒ•μœΌλ‘œ μˆ˜μ •ν•  κ²ƒμž„μ„ 확인할 수 μžˆλ‹€. μœ„ μ½”λ“œμ—μ„œλŠ” sess.run( [ ..., train, ... ])을 μ‹€ν–‰ν•˜λ©΄ train = optimizer.minimize(cost)λΆ€ν„° μ‹œμž‘ν•˜μ—¬ κ·Έλž˜ν”„μ— 흐름이 생길 것이닀. 좜λ ₯된 κ²°κ³ΌλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

X ←[1, 2, 3, 4, 5 ]
Y ←[2.1, 3.1, 4.1, 5.1, 6.1] κ°€ μž…λ ₯λ˜μ—ˆμœΌλ―€λ‘œ,
μ–΄λ¦Όμž‘μ•„ λ³΄μ•˜μ„ λ•Œ, y = x + 1.1 의 직선, 즉 W = 1, b = 1.1이면 ν›Œλ₯­ν•˜κ²Œ ν•™μŠ΅μ„ ν–ˆλ‹€κ³  ν•  수 μžˆμ„ 것이닀. 2000번의 ν•™μŠ΅κ²°κ³Ό κ½€λ‚˜ ν›Œλ₯­ν•˜κ²Œ ν•™μŠ΅μ΄ λ˜μ—ˆλ‹€.

 

μ•žμ„  κ²Œμ‹œλ¬Όμ— λ§ν¬ν–ˆλ˜ 'λͺ¨λ‘λ₯Ό μœ„ν•œ λ”₯λŸ¬λ‹' κ°•μ˜λ₯Ό λ“£κ³  ν•„κΈ°ν•œ λ…ΈνŠΈμ—
μΆ”κ°€μ μœΌλ‘œ κ³΅λΆ€ν•œ 것을 더해 μž‘μ„±ν•œ κ²Œμ‹œκΈ€μž…λ‹ˆλ‹€.