[핸즈온 머신러닝 ch9]9강텐서플로우 사용해보기 1편

2018. 9. 2. 04:12Python-이론/python-인공지능2

ch9 텐서플로우 사용해보기 1편



텐서플로우란? 

구글에서 인공지능을 더 편하게 사용하기위해서 강력한 오픈소스 소프트웨어 라이브러리로 특히 머신러닝에 맞춰 세밀하게 튜닝되어 있습니다.

텐서플로우에 기본원리 

먼저 파이썬으로 수행할 계산 그래프를 정의한 다음 텐서플로가 최적화된 C++ 코드를 사용해 이 그래프를 효율적으로 실행시킵니다.  

간단한 계산 그래프의 예시




그리고 좋은 점이 계산 그래프를 여러 부분으로 나누어 여러 CPU나 GPU에서 병렬로 실행할 수 있습니다. 또한 분산 컴퓨팅도 지원하므로 수백 대의 서버에 계산을 나누어 납득할만한 시간 안에 대규모 데이터셋으로 거대한 신경망을 훈련시킬 수 있습니다. 그리고 수백만 개의 특성들을 가진 수십억 개의 샘플로 구성된 데이터셋에서 수백만 개의 파라미터를 가진 네트워크를 훈련시킬 수 있습니다. 


9.1 첫 번째 계산 그래프를 만들어 세션에서 실행하기 


import tensorflow as tf

a = tf.Variable(initial_value=3, name='a')
b = tf.Variable(initial_value=4, name='b')

c = a+b

대부분 이러한 형태로 코드를 만듭니다. 하지만 꼭 알아야 하는 것이 이렇게 만들었다고 실행되는 것이 아닙니다. 단순한 계산 그래프를 만든 것입니다. 변수도 초기화 되지 않고 + 연산도 되지 않습니다. 


이 계산 그래프를 실행시키기 위해선 세션을 시작해서 변수를 초기화하고 c를 평가해주면 됩니다. 


세션은 cpu나 Gpu 같은 장치에 올리고 실행하는 것을 도와주며 모든 변수 값을 가지고 있습니다. 


다음에는 세션을 만들어서 실행시켜 보겠습니다.  


방법 1.

session = tf.Session()
session.run(a.initializer)
session.run(b.initializer)
result = session.run(c)
print(result) session.close()


방법 2. 

with tf.Session() as sess:
sess.run(a.initializer)
sess.run(b.initializer)
sess.run(c)


그치만 매번 sess.run을 사용하기에는 귀찮습니다. 그래서 우리는 아래와 같은 방식을 사용해도 된다. 

with tf.Session() as sess:
a.initializer.run()
b.initializer.run()
result = c.eval()


그리고 변수 초기화가 매번 귀찮다면 

init = tf.global_variables_initializer()

with tf.Session() as sess:
init.run()
result = c.eval()


그리고 파이썬 셀이나 주피터에선 InteractiveSession을 사용해주면 더 편리합니다. 


sess = tf.InteractiveSession()
init.run()
result = c.eval()
sess.close()


9.1에서 텐서플로우를 살펴본 결과 첫부분은 계산 그래프를 만들고 두번째로는 이그래프를 계산합니다. 


9.3 계산 그래프 관리 


노드를 만들면 자동으로 기본 계산 그래프에 추가됩니다. 


x1 = tf.Variable(1)
print(x1.graph is tf.get_default_graph()) #True


대부분의 경우 이것으로 충분하지만, 가끔은 독립적인 계산 그래프를 여러 개 만들어야 할 때가 있습니다. 

이렇게 하려면 다음과 같이 새로운 Graph 객체를 만들어 with 블록 안에서 임시로 이를 기본계산 그래프로 사용할 수 있습니다. 


graph = tf.Graph()
with graph.as_default():
x2 = tf.Variable(2)

print(x2.graph is graph)
print(x2.graph is tf.get_default_graph())


9.4 노드 값의 생애주기 


한 노드를 평가할 때 텐서플로는 이 노드가 의존하고 있는 다른 노드들을 자동으로 찾아 먼저 평가합니다. 


import tensorflow as tf

w = tf.constant(3)
x = w + 2
y = x + 5
z = x * 3

with tf.Session() as sess:
print(y.eval())
print(z.eval())

이 코드는 매우 간단한 그래프를 정의하고 있습니다. 그리고 간단히 계산 그래프를 실행시킵니다. 


그러면 텐서플로우는 자동으로 y가 x에 의존하고 있고 x가 w에 의존하고 있다는 것을 감지합니다. 그래서 위와 같은 코드의 경우에는 w를 먼저 평가하고 다음에 x를 평가해서 y값을 반환합니다. 다음에 z를 평가하는데 다시 w와 x를 재평가해야한다. 

이점을 봤을 때 텐서플로우는 이전에 평가했는 것을 다시 평가한다는 것을 인식하자! 상수는 그렇지만 변수의 경우에는 계속해서 유지가 된다. 


그래서 효율적으로 실행하려면 한번의  그래프 실행에 보두 실행되어야 한다. 따라서 아래와 같은 방법을 사용하자!!

with tf.Session() as sess:
y_val, z_val = sess.run([y, z])
print(y_val)
print(z_val)


tip ~~ 주피터와 같은 경우에 같은 그래프가 반복해서 생길때가 있다. 이럴 경우에는 tf.reset_default_graph()로 기본 그래프를 초기화해주는 것입니다. 


9.5 텐서플로를 이용한 선형 회귀 


 텐서플로 연산은 여러 개의 입력을 받아 출력을 만들 수 있습니다. 예를 들어 덧셈과 곱셈 연산은 두 개의 입력을 받아 하나의 출력을 만듭니다. 


입력과 출력은 텐서라는 다차원 배열입니다. numpy배열과 비슷하게 텐서는 데이터 타입과 크기를 가집니다. 사실 파이썬 API에서 텐서는 넘파이 ndarray로 나타납니다. 보통은 실수로 채워 지지만 문자열을 저장할 수 있습니다. 


지금부터 캘리포니아 주택 가격 데이터셋에 선형회귀를 수행하기 위한 2d배열을 다룰 것 입니다. 


1. 먼저 데이터셋을 추출합니다.


2. 모든 훈련 샘플에 편향에 대한 입력 특성을 추가합니다. 


3. 두개의 텐서플로 상수 노드 X와 Y를 만들고 데이터와 타깃을 담습니다. 


4. theta를 정의합니다.(정규방정식)


사용할 함수 


transpose() 행렬을 전치시킵니다. 

matmul() 행렬들을 곱해서 결과를 반환합니다. 

matrix_inverse() 역행렬을 계산합니다.   


import numpy as np
import tensorflow as tf
from sklearn.datasets import fetch_california_housing

housing = fetch_california_housing()
m, n = housing.data.shape # 데이터 개수, 특성 수
housing_data_plus_bias = np.c_[np.ones((m, 1)), housing.data]

X = tf.constant(housing_data_plus_bias, dtype=tf.float32, name='X')
y = tf.constant(housing_data_plus_bias, dtype=tf.float32, name='y')
XT = tf.transpose(X)

theta = tf.matmul(tf.matmul(tf.matrix_inverse(tf.matmul(XT, X)), XT), y)

with tf.Session() as sess:
theta_value = theta.eval()