빅데이타 & 머신러닝/머신러닝

텐서플로우 하이레벨 API

Terry Cho 2017. 9. 6. 14:57

텐서플로우 하이레벨 API에 대한 이해


머신러닝을 공부하고 구현하다 보니, 모델 개발은 새로운 모델이나 알고리즘을 개발하는 일 보다는, 기존의 알고리즘을 습득해서 내 데이타 모델에 맞도록 포팅하고, 학습 시키는 것이 주된 일이 되고, 오히려, 모델 보다는 데이타에 대한 이해와 전처리에 많은 시간이 소요되었다.


특히 여러번 실험을 하면서 패러미터를 조정하고 피쳐등을 조정하기 위해서는 많은 실험을 할 수 있어야 하는데, 이러기 위해서는 실험(학습)시간이 짧아야 한다. 이를 위해서는 모델 개발 보다 분산 러닝을 하기 위한 코드 변경 작업등이 많이 소요된다.


결론을 요약하자면, 실제로 알고리즘을 개발하는 데이타 과학자가 아니라, 머신러닝을 활용만 하는 프랙티셔너 입장이라면, 모델을 개발하는 것 보다는 있는 모델을 선택해서 쉽게 사용할 수 있는 방법을 찾으면 된다.

하이레벨 API

이런 관점에서 시작한 것이 머신러닝 하이레벨 API 이다. 복잡한 수식이 없이 마치 함수처럼 모델을 선택해서 사용하는 방법인데, 쉽게 이야기 하면, Hash table 알고리즘을 100% 이해하지 않더라도, hashtable 라이브러리를 가져다가 사용하면 되는것과 같은 원리이다.


머신러닝에서도 이미 이러한 하이레벨 API가 많이 제공되고 있는데, 파이썬 싸이킥 런(http://scikit-learn.org/) 이나 SparkML 등이 해당한다.

텐서플로우에도 같은 방식으로 하이레벨 API를 제공하는데, 텐서플로우 공식 SDK와 써드파티 오픈소스 라이브러리들이 있다.

그중에서 tf.contrib가 공식 텐서플로우의 하이레벨 API이며, 딥러닝 모델을 간단하게 만들 수 있는 Keras역시 얼마전에 텐서플로우 공식 하이레벨 API로 로 편입되었다.




텐서플로우에서는 Linear regression, SVM등 많이 쓰이는 일반적인 머신러닝 모델에서 부터 Deep Wide Network와 같은 딥 러닝 모델들을 Estimator 라는 형태로 제공하고 있다.

하이레벨 API를 쓰면 장점

그러면 이러한 하이레벨 API를 쓰면 장점이 무엇일까?

모델 개발이 쉽다

모델 개발이 매우 쉽다. 복잡한 모델을 손쉽게 개발할 수 있을뿐더러, 일부 모델들은 Out of box 형태로, 바로 라이브러리 식으로 불러서 사용만 하면 되기 때문에 모델 개발 시간이 줄어들고, 모델에 대한 기본적인 이해만 있더라도 쉽게 개발이 가능하다.

스케일링이 용이하다

큰 모델을 많은 데이타로 학습하기 위해서는 여러 머신에서 학습을 하는 분산 학습이 필요한데, 로우레벨 API를 이용할 경우 분산 학습을 개발하기가 쉽지 않다.  하이레벨 API를 이용할 경우 코드 변경 없이 싱글 머신에서 부터 GPU 그리고 분산 학습까지 손쉽게 지원이 되기 때문에, 실험 (학습/테스트) 시간을 많이 절약할 수 있다.


배포가 용이하다

모델을 학습 시킨 후 예측을 위해서 배포를 할 경우, 보통 모델을 *.pb 파일 형태로 Export 해야 하는데, 이 경우 학습에 사용된 그래프 말고 예측을 위한 그래프를 새로 그려야 하는 등 추가적인 작업이 필요하고 쉽지 않은데 반해 하이레벨 API의 경우, 코드 몇줄만으로도 손쉽게 예측 서비스를 위한 그래프를 Export할 수 있다.


텐서플로우 하이레벨 API

tf.layers

텐서플로우는 특히 딥러닝 (뉴럴네트워크)에 강점을 가지고 있는데, 딥네트워크의 각 계층을 설계 하기 위해서는 컨볼루셔널 필터, 풀링, 스트라이드,드롭 아웃 등 다양한 기법을 사용하게 된다. 이러한 것들을 복잡하게 구현하지 않고, 딥 네트워크를 손쉽게 만들 수 있게 각 레이어에 대한 구현을 함수식으로 제공한다.


다음 그림은 tf.layer로 컨볼루셔널 네트워크 (CNN)을 구현한 예제로 컨볼루셔널 레이어와, 맥스풀링, 드롭아웃, ReLu 엑티베이션 함수등을 사용하였다. 각 레이어는 tf.layers 라이브러리 하나씩으로 간단하게 구현되었다.


Estimator

일반적으로 머신러닝 개발은 다음과 같은 구조를 갖는다


개발한 모델에 Input,Labels 데이타를 넣은 후, 학습(Training), 테스트(Evaluation), 예측(Prediction)을 한후, 학습이 완료된 모델을 저장(Export)하여 배포한다.  거의 모든 모델 개발이 위의 구조를 반복하기 때문에, 이러한 구조를 추상화 해놓은 것이 Estimator 이다.


이 추상화를 통해서 Estimator에 데이타를 넣게 되면, Estimator는 Training, Evaluation, Prediction, Export를 위한 인터페이스를 제공한다. 텐서플로우 그래프 구축이나 세션 관리등은 모두 Estimator 안으로 추상화 한다.


Estimator는 직접 개발자가 모델을 직접 구현하여 Estimator를 개발할 수 도 있고 (Custom Estimator) 또는 이미 텐서플로우 tf.contrib.learn에 에 미리 모델들이 구현되어 있다. 딥네트워크 기반의 Classifier나 Regressor (DNNClassifieir, DNNRegressor), SVM, RNN, KMeans 등이 있기 때문에 간단하게 불러다 사용하기만 하면 된다.

Estimator 예제

Estimator 예제로 간단한 LinearRegression Estimator를 사용하는 예제를 보자

학습용 데이타

먼저 학습용 데이타와 라벨을 생성하였다.

import numpy as np

num_points = 300

vectors_set = []

for i in xrange(num_points):

 x = np.random.normal(5,5)+15

 y =  x*2+ (np.random.normal(0,3))*2

 vectors_set.append([x,y])

 

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

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


import matplotlib.pyplot as plt

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

plt.ylim([0,100])

plt.xlim([5,35])

plt.xlabel('x')

plt.ylabel('y')

plt.legend()

plt.show()


데이타 분포는 아래와 같다.


모델 코드

데이타 리더

Estimator 를 사용하려면 데이타를 읽어서 Estimator 에 넣어주는 입력 함수를 구현해줘야 한다. 아래는  numpy 배열에서 데이타를 읽어서 리턴해주는 입력 함수이다.


input_fn_train = tf.estimator.inputs.numpy_input_fn(

   x = {"x":np.array(x_data[:200],dtype=np.float32)},

   y = np.array(y_data[:200],dtype=np.float32),

   num_epochs=100000,

   batch_size=50,

   shuffle=True

)


x_data 배열에서 0~200까지의 데이타를 학습용 데이타로 사용하였고, y_data 0~200을 라벨로 사용하였다. 한번에 50 개씩 리턴하도록 배치를 설정하였고, 100K epoch를 지원하고 데이타를 랜덤하게 리턴하도록 셔플 처리를 하였다.


input_fn_eval = tf.estimator.inputs.numpy_input_fn(

   x = {"x":np.array(x_data[200:300],dtype=np.float32)},

   y = np.array(y_data[200:300],dtype=np.float32),

   num_epochs=100000,

   batch_size=50,

   shuffle=True

)


input_fn_predict = tf.estimator.inputs.numpy_input_fn(

   x = {"x":np.array([15,20,25,30],dtype=np.float32)},

   num_epochs=1,

   shuffle=False

)


같은 방법으로 테스트용 데이타와 예측에 사용할 데이타 입력 함수를 같이 정의하였다.

모델 정의

column_x = tf.feature_column.numeric_column("x",dtype=tf.float32)

columns = [column_x]

읽어온 데이타에서, 어떤 컬럼을 학습에 사용할지, 그리고 그 컬럼의 데이타 타입 (연속형인지 분류형인지)를 정한다.  tf.feature_column.numeric_column("x",dtype=tf.float32) 는 컬럼 명 x를 학습 데이타로 사용하고 x는 연속형 변수로 지정하였다.

다음 columns에 피쳐로 사용할 컬럼 목록을 정한다.


LinearRegression Estimator를 정의하고, 여기에, column을 정해준다.  Optimizer나 Learning Rate등은 지정이 가능하다.

estimator = tf.contrib.learn.LinearRegressor(feature_columns=columns,optimizer="Adam")

학습과 예측

학습은 .fit 이라는 메서드를 사용하면 되고, 입력 함수와 학습 스텝을 정해주면 된다.

estimator.fit(input_fn = input_fn_train,steps=5000)

estimator.evaluate(input_fn = input_fn_eval,steps=10)

result = list(estimator.predict(input_fn = input_fn_predict))


마지막으로 예측은 predict 를 이용하면 된다.

x=15,20,25,30에 대해서 예측 결과는 다음과 같다.

[31.193062, 41.855644, 52.51823, 63.180817]



그래프와 비교해보면 유사 값이 나오는 것을 확인할 수 있다.



전체 코드 
https://github.com/bwcho75/tensorflowML/blob/master/HighLevel%20API%201.%20Linear%20Regression%20Estimator.ipynb






그리드형