티스토리 뷰

본 포스팅은 한빛미디어에서 나온 "텐서플로 첫걸음"(조르디 토레스 지음/박해선 옮김) 책의 내용을 윈도우즈 환경에서 공부하면서 실습하고 알게된 내용으로 소스코드나 테스트 코드가 책에 나온 내용과 동일하거나 혹은 비슷할 수 있음을 먼저 공지합니다.

책의 내용 전체를 다루는 것이 아니라 필요한 내용만을 발췌하여 포스팅하므로 보다 깊은 내용을 공부하는 것을 필요로 하는 사람은 아래의 링크에서 책을 구매하는 것을 추천합니다. 본 포스팅은 협찬을 받지 않았습니다.

(http://www.hanbit.co.kr/store/books/look.php?p_code=B3286570432)



지난 시간엔 텐서플로를 설치해 보고 어떻게 실행되나 확인해보는 시간을 가졌더랬다.

오늘은 책의 다음 내용인 "선형회귀분석"을 읽어보았다......


라고 생각했는데 글은 한글인데 왜 나는 이해를 할 수 없는가에 대한 철학적인 질문이 이어졌다...


어흑에 대한 이미지 검색결과


이전에 딥러닝이라는 것이 "시작하기" 파트에서 이야기 했듯 통계학에 근거해서 만들어졌기 때문에 기본적인 통계수학을 이해하고 있어야 접근이 용이하다는 점을 알게되었다. 젠장. 어쩔 수 없다. 수학의 정석을 다시 펴도록 합니다.


수학의 정석에 대한 이미지 검색결과


뭐 수학은 수학이고 코딩은 해야하는 것이니 일단 시작해봅시다.

일단 선형회귀분석을 하려고 한다는 말부터 좀 이해하도록하자.


응답없음에 대한 이미지 검색결과



선형회귀분석에 대해서 글을 쓰려고 하자마자 말문이 막혀버렸다. 와 진짜 글은 한글인데 무슨 말인지 모르겠다. 정말. 그래서 물어봤다. 구글한테.


구글링을 몇시간하면서 스스로 깨달은 바에 의하면 선형회귀분석을 알기 이전에 회귀분석(回歸分析, Regression Analysis)를 먼저 이해할 필요가 있다고 생각했다.


회귀분석이란 관찰된 연속형 변수들에 대해 두 변수 사이의 모형을 구한 뒤 적합도를 측정해내는 분석 방법이라고 위키피디아에서 알려줬다.이 말을 다시 사람이 쓰는 말로 번역해보면 어떤 값 두개가 있고 그 사이의 아주 적절하게 합의 될만한 값(중간 값)을 찾아내는 분석방법인데 이때 값을 구하는 방정식이 선형이면 선형회귀분석, 방정식의 변수가 여러개라면 다중회귀분석이라고 한다.


위키피디아 "회귀분석" 파트에서 퍼옴


위의 이미지 처럼 X를 독립변수, Y를 종속 변수라고 했을 때 임의의 데이터들을 비교해 해당 데이터의 합의점을 이루는 가장 적절한 값을 선으로 표현할 수 있는데 이런 값을 구하는 방정식이 두개의 변수와 덧셈으로 이뤄졌다면 선형회귀분석이라고 한다. 

(나는 선(Line)이라서 선형인줄 알았더니 카페사장 이규민군이 덧셈이 리니어(Linear)하게 이어지는 모양을 선형이라고 한다고 알려줬다.)

이런 방식의 분석방법은 시간에 따라 변화하는 데이터나 어떤 영향, 가설적 실험, 인과관계의 모델링에서 통계적 예측을 할 때 이용될 수 있다고 위키가 알려줌. 역시 위키임.


아주 이해 못할 수준은 아닌듯 하다. 오늘은 이 선형회귀분석을 텐서플로로 어떻게 구현하는지 한번 알아보도록 하자.


아, 일단 위의 이미지 처럼 차트를 눈으로 보고 배울 필요가 있으니 matplotlib이라는 라이브러리를 pip으로 인스톨하도록 하자.



이때 중요한건 지난번 텐서플로 셋팅할때 사용한 가상환경에서 설치하는걸 잊지 않는거다.

위 처럼.


그러면 필요한 여러가지 라이브러리를 자동으로 설치해줄거다.

이제 선형회귀분석을 위한 표준 데이터 모델을 만드는 코드를 만들어보자.

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

num_point = 1000
vector_set = []

for i in range(num_point) :
	x1 = np.random.normal(0.0, 0.55)
	y1 = x1 * 0.1 + 0.3 + np.random.normal( 0.0, 0.03 )
	vectors_set.append([x1,y1])

x_data = [v[0] for v in vectors_set]
y_data = [v[1] for v in vectors_set]

plt.plot(x_data, y_data, 'ro')
plt.show()


위의 코드를 작성하고 실행하면 창이 하나 등장할텐데 대충 이런 모양이다.



이런 창이 떴다면 코딩은 적절하게 잘 된것이라고 생각하면 된다.


책에는 xrange를 통해 1,000번 반복하면서 랜덤 데이터 셋을 만들라고 되어있지만 파이썬 3 이후부터는 xrange는 없어지고 range만 사용한다고 해서 그 부분을 수정한 것 외에는 코드는 책과 동일하다. 


이 코드를 살펴보면 난수발생하는 코드를 numpy 라이브러리의 random.normal 을 이용했다는 것을 알 수 있다. 여기서 첫번째 파라미터는 난수의 분포평균값을 의미하고 두번째 파라미터는 표준편차값을 의미한다. 예를 들어 표준편차가 1인 경우 -4 부터 4 정도의 값을 랜덤으로 뱉어낸다고 보면 되겠다.


두번째로 이 코드의 가장 중요한 부분인데 이 코드의 종속변수 y축을 이루는 y_data 값을 이루는 공식이다. 난수로 발생으로 생성된 x1 값을 기준으로 (x1 * 0.1) + 0.3을 통해 만들어 내며 난수를 더해서 동일한 값이 들어가지 않게 했다는 점이다. 난수가 중요한건 아니고 해당 값을 이루는 공식을 살펴보면 y = ( W * x ) + b 라는 선형 방정식이라는 알 수 있고 이런 분포에서 W와 b 값을 구한다면 우리는 W = 0.1, b = 0.3 이라는 점을 알 수 있지만 컴퓨터는 그 사실을 모르고 있으니 이걸 텐서플로를 통해 학습시키는 코드를 작성해 볼거다.

(와.. 이 한 문장을 작성하기 위해 3시간을 투자했다니... 역시 사람은 시간과 노력만 들인다면 못할게 없는거 같다)


import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

num_point = 1000
vector_set = []

for i in range(num_point) :
	x1 = np.random.normal(0.0, 0.55)
	y1 = x1 * 0.1 + 0.3 + np.random.normal( 0.0, 0.03 )
	vector_set.append([x1,y1])

x_data = [v[0] for v in vector_set]
y_data = [v[1] for v in vector_set]

W = tf.Variable( tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable( tf.zeros([1]))
y = W * x_data + b

loss = tf.reduce_mean( tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

init = tf.global_variables_initializer()

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

for step in range(16):
	sess.run(train)
	print("step : ", step)
	print(sess.run(W), sess.run(b))
	print(sess.run(loss))
	print("--------------------------------")

	plt.plot(x_data, y_data, 'ro')
	plt.plot(x_data, sess.run(W) * x_data + sess.run(b))
	plt.xlabel('x')
	plt.ylabel('y')
	plt.xlim(-2, 2)
	plt.ylim(0.1, 0.6)
	plt.show()


위와같이 코드를 추가하고 실행시켜보면 아래의 이미지들이 등장하게 된다.

(창을 계속 닫아줘야 다음 loop를 돌리면서 다음 값을 확인해 볼 수 있다.)


0123456789101112131415


그리고 각각의 이미지에 대한 로그 정보는 아래와 같다.


step :  0
[-0.59586936] [0.2989126]
0.15470317
--------------------------------
step :  1
[-0.37520257] [0.29901376]
0.072729036
--------------------------------
step :  2
[-0.22438559] [0.29908293]
0.034437455
--------------------------------
step :  3
[-0.12130819] [0.2991302]
0.01655076
--------------------------------
step :  4
[-0.05085891] [0.2991625]
0.008195574
--------------------------------
step :  5
[-0.00270961] [0.2991846]
0.004292715
--------------------------------
step :  6
[0.03019852] [0.29919967]
0.0024696216
--------------------------------
step :  7
[0.05268991] [0.29921]
0.0016180215
--------------------------------
step :  8
[0.06806187] [0.29921705]
0.0012202244
--------------------------------
step :  9
[0.078568] [0.29922187]
0.0010344065
--------------------------------
step :  10
[0.08574852] [0.29922515]
0.0009476074
--------------------------------
step :  11
[0.09065612] [0.29922742]
0.000907062
--------------------------------
step :  12
[0.09401026] [0.29922894]
0.0008881227
--------------------------------
step :  13
[0.09630269] [0.29923]
0.0008792758
--------------------------------
step :  14
[0.09786947] [0.29923072]
0.000875143
--------------------------------
step :  15
[0.09894031] [0.2992312]
0.0008732126
--------------------------------


일단 코드를 작성하는 것으로 숨을 고르자.

오늘 너무 많은 공부를 했다. 수학 이야기를 하느라 너무 힘든건 둘째치고 너무 오래걸렸다.

다음 포스팅에선 위의 코드를 분석하고 이론적인 배경을 좀 공부해보도록하자.


오늘은 여기까지.

수고했다.



도움을 준 사이트


도움을 준 사람

  • 성수동 카페사장 이규민 군 (sld9849@gmail.com)


댓글
댓글쓰기 폼