2017년 12월 27일 수요일

Deep Learning Inference & Serving Architecture 를 위한 실험 및 고찰 1 - GPU vs CPU

최근 Production을 위한 Deep Learning Serving 레이어의 아키텍처를 구성하기 위해 몇가지 실험을 했던 내용을 정리해 보았다. 몇번에 걸쳐 연재 될 수 있을 듯 한데...

우선 오늘의 주제는 Inference 에 있어서도 정말 GPU 가 CPU보다 유리한가? (결론이 유추 되는가???)


아키텍처를 구성함에 있어, 다양한 Use Case 가 있을 수는 있으나, 정답이 존재하지는 않는다고 생각한다. 다양한 비지니스로직, 데이타의 양이나 성격, 사용하는 기술들, 개발 언어, 목적하는 바, 동시접속자 수, On-premise , Cloud 여부 등에 따라 다양한 조합이 있을 수 있을 것이고, 각각이 장단점이 존재할 것이기 때문이다.

여러 참고 자료로 사전 조사를 해본것은 사실이지만, 우리의 Deep Learning 모델과 우리의 데이타, 우리의 로직으로 후보 아키텍처에서 직접 실험을 하고 아키텍처를 확정하고자 아래와 같은 실험을 진행하였다.

실험에 앞서, 주안점은 다음과 같다.

  1. 우리는 Keras , Tensorflow (일부 CNTK) 등의 Deep Learning Framework 로 만들어진 Deep Neural Network 모델을 이용, 대국민 서비스를 준비하고 있다.
  2. 다수의 동접이 있을 수 있고, 이벤트나 행사 여부, 광고 및 홍보 여부에 따라, 트래픽이 매우 가변적일 수 있고, 다수의 동접 및 다수의 inference 가 일어날 수 있다.
  3. 많은 동접의 경우에도 응답은 1초 이내를 목표로 한다.
  4. Deep Learning 모델은 RNN, LSTM 류와 간단한 류의 CNN 이 주를 이룬다.(우리의 모델은 vgg, inception 류의 heavy CNN  은 아니다.)
  5. 우리의 모델이 특이한 점은 주기적인 Fine Tuning 과 시시 각각의 RealTime on-line Training 이 운영중인 Model 에 시시각각 이루어진다는 점이다. 이는 Serving Layer 설계에 있어 중요 고려 사항 중 하나인데, Serving 되는 모델의 Size 를 줄이고 응답 속도를 빠르게 하기 위한 알려진 기법들을 적용하는데 방해가 되는 요소이기 때문이다. 
  6. Tensorflow 의 Serving 은 써본 사람들은 알겠지만, Web Service 로 만들어 배포하기에는 몇가지 제약이 느껴진다. 이 실험은 Tensorflow Serving 전용 엔진을 통한 실험은 아니며, 보다 High Level 로 접근하여 Inference Layer 를 직접 구현했을 때의 실험이다.
일반적으로 Inference 전용 Model Optimization 을 할 때는 주로 아래의 방법들이 사용된다.

  1. check point 등 training 에서만 사용되는 operation 을 없앤다.
  2. batch normalization ops 도 제거한다.
  3. 도달하지 않는 graph 영역 제거
  4. Check Numeric 제거
  5. 각종 variable 값 들은 constant 로 바꾸어, 크기를 줄이고 속도를 빠르게 하며, Thread Safe 하게 변경한다.
위 기법들은 Model 이 Freezing 된 경우에 한하여서이다. realtime training 과 inference 가 동시에 일어나는 경우는 
  1. training  model 과 inference  model 을 분리하고, 지연 동기화 시키거나
  2. 둘을 하나로 가져가되 constant 화 하고 freezing 하는 것을 포기해야 한다.
위 둘의 중간도 가능할 수는 있다. Node 가 복수개인 경우 Training  중인 Node 가 잠시 Serving Node 에서 빠져 있는 경우가 그 경우에 해당 할 것이다. 후에 우리는 Serving Layer 에 있어, Auto Scale Out 가능한 Docker PaaS나 Microservice Serverless PaaS 를 중요 고려 요소로 낙점하고 추가적인 실험을 하였는데, (아마 이 연재가 좀더 계속되어진다면, 다시 상세하게 다루어 보도록 하겠다. ) 이 시나리오 에서는 Training Layer 와 Serving Layer 를 각각의 장점을 극대화 시키고, Model 파일의 경우만 지연 공유시키는 또다른 시나리오가 나올 수 있다.


우선 오늘 다룰 내용은 위에서 언급된 다양한 방법론의 첫단추로서, 우리 모델이 과연 CPU 에서 더 잘 inference 되는 지, GPU 에서 더 잘 inference 되는지 의 여부에 대하여 실험 해본 결과이다. (ps. 실험에서 사용된 모델은 실험용으로 실제 모델이 다소 단순화된 General Model 임)
다수 동접 Inference 테스트 전 training 퍼포먼스 또한 실험한 결과를 함께 정리 하였다.

[1] 실험에 사용된 딥러닝 모델 및 모델 크기

- 일반적인 Language Model 용 LSTM 모델
- categorical_cross_entropy 사용
- Top 1 분류 모델
- Word Embedding Layer 차원 수 : 300차원
- Total Parameter 수 : 80,656,435 개

- [특이사항] Language Model 특성상 Total Parameter 에서 앞부분이 많은 부분 차지.
- [특이사항] LSTM 이 번역등의 문제가 아닌 Text Classification 문제에 적용된 경우 이므로, 층이 복잡하지는 않음. 층을 복잡하게 하여도 성능 향상 없었음. 그러나, 일반적인 word2vec + cnn 보다는 3% 정도 성능 향상된 모델임.


[2] 실험에 사용된 hyper parameter

- epochs=4 , batch_size=64 , optimizer=adam
- learning Rate=0.001, beta_1=0.9 , beta_2=0.999, epsilon=1e-8

- [특이사항] CPU Training 은 GPU 와 달리 batch size 를 4096등 훨씬 큰 수치를 주어도 memory resource 고갈 에러가 발생하지 않음, drop out 이나 batch bormalize 를 적절히 쓰는 경우 batch size 를 크게 주는 경우, 정확도는 비슷한데, 더 빨리 Training 이 될 수 있음.
- 즉, CPU vs GPU 트레이닝 퍼포먼스는 실무에서는 batch_size 를 달리 주어, CPU가 아래보다 더 빨리 응답하는 것도 가능하나, 동일 hyper parameter 값에 대한 성능 비교를 위해 아래에서는 동일 값으로 수행한 결과 이다.

[3] 실험에 동원된 HW 장비 Spec

- cpu : 12 vcore , 112gb Memory ( On Azure Cloud VM )
- gpu : K80 GPU * 2개 , 12 vcore , 112GB Memory ( On Azure Cloud Data Science GPU VM ) (단, 모델 inference 시에는 1개 GPU 만 사용하여 실험하였음)

[4] Training Data 크기

- training data row 수 : 1,649,415 건

[5] Training 속도 및 성능


  1. CPU Training Performance
    1. epoch1 : 23,790 초
    2. epoch2 : 24,071 초
    3. epoch3 : 24,026 초
    4. epoch4 : 24,100 초
  2. GPU Training Performance

    1. epoch1 : 8,612초
    2. epoch2 : 8,370초
    3. epoch3 : 8,377초
    4. epoch4 : 8,360초
[6] Single Inference 성능

      

예상과 달리 CPU가 Wall Time 이 더 빠르다. Wall Time 은 벽걸이 시계 시간을 의미한다. 즉 실제, 걸린 시간이다. CPU 의 경우 user time 은 150에 육박하는 경우가 있는데, 그래도 wall time 은 일정하게 30에서 40 사이의 값을 보여준다. 여기에서 다음과 같은 가정을 해볼 수 있다. CPU 는 멀티코어를 써서 더 빠른가??

[7] Multiple Sequential Inference 성능

이번에는 1개 Inference 가 아닌 1000번의 inference 를 sequencial  하게 (Not 병렬) 수행해보았다. 그리고, 위 (6)의 가정이 맞는지 cpu 및 gpu 의 usage 상황을 확인해 보았다.

사용된 코드도 아래에 참고로 넣어 보았다.

1000번을 연속하여 serial 하게 수행해보자 위와 같은 속도가 측정되었으며, 평균을 내 보면, CPU는 20ms , GPU는 60 ms 정도가 걸렸다.

특이한점은 , 처음 예상과 비슷하게, CPU는 멀티코어를 쓰고 있고,(코어 전체를 쓰진 않았음, 위 스크린샷 시점에는 420% 정도가 동작하고 있음.), GPU 는 GPU 1번 코어만을 50~70% 정도 사용하고 있으며, CPU 는 1개 CPU만 100% 사용하고 있다는 점 이었다.

여기에서 한가지 의문이 생겼다. 그렇다면 혹시 CPU가 병목인가?
그리고, 그렇다면, 혹시 위 코드에서 사용된 유일한 Pre Processing 인 Tokenizer 가 영향을 주고 있는 것인가?

그래서 위 실험에 사용된 코드에서 Tokenizer 전처리 Pre Processing 부를 1000번의 loop 바깥으로 빼보고 성능 향상 정도를 측정해 보았다.

[8] CPU  에서 Tokenizer 가 주는 영향


위 처럼 CPU 실험에서는 Pre-Processing 영역인 Tokenizer 가 주는 영향은 5% 정도에 지나지 않았다.

[9] GPU에서 Tokenizer 가 주는 영향


GPU에서도 마찬가지로 Pre-Processing 부분이 주는 영향은 2% 정도에 지나지 않았다. %는 줄었고, 절대치는 비슷하다. 즉, CPU에서이든 GPU에서이든 Pre-Processing 은 CPU 를 이용하기 때문에 절대치는 비슷한것이 이치에 맞다.

위 상황에서 CPU와 GPU  의 USAGE 도 확인해 보았다.



여전히 CPU 는 1Core 만 100% Full로 일하고 있고, GPU 는 50%에서 70%를 왔다갔다 하였다. 그러므로, CPU 는 전처리 때문이 아닐까 하는 가정은 False 라고 할 수 있을 것이다. 해당 가정에 대한 의문은 해소 되었다.

[10] 이제 실제 Inference 테스트를 위해 모델을 flask microservice 형태로 배포하였다. 


위 구동은 CPU 전용 머신과 GPU 전용 머신에서 각각 해 주었다.
실제 Production 에서는 성능 극대화를 위해 하나의 머신에 port 를 달리하여 여러 Process 를 띄우고 앞에 웹프록시 등을 두는 것이 일반적이지만, 이 실험은 상대적인 비교를 위함이 목적이므로, 그런 작업을 해주지는 않았다.

[11] 이제 실제 운영 Production 환경과 유사한 환경에서 동시접속수행 Test 를 해보겠다.

이곳에 따로 기재하진 않았으나, 앞선 시점에서의 비교는 Jupyter Notebook 에서 이루어졌다. 모두가 아는 바와 같이 Jupyter Notebook 위에서의 구동은 단일 Python 독립 프로세스보다 훨씬 느리다. 즉, 동일한 실험이 flask 위에서 구동된 경우 Jupyter 위에서 구동된 경우보다 훨씬 빠르다. 그리고, flask 는 경량의 비동기 웹 프레임워크 이기 때문에, 병렬 수행이 위의 경우보다 훨씬 빠르게 일어난다.

위에서는 Serial 하게 한번에 하나씩만 Job 을 수행하였다. 이번 flask 에서의 수행은 다수 User 에서의 Parallel 동접 수행이다. 때문에 Serial 하게 수행했을 때보다 더 많은 병렬 Job 이 수행되었고, 그 결과 Jupyter 에서의 serial 수행보다 성능이 훨씬 더 좋게 나오고 있다.

(1) CPU 에서의 최종 결과

[Run User]      [TPS]   [Time Per Request : millisec]   [Transfer rate: Kbytes/sec]     [Complete Request]      [Failed Request]
1       200.35  4.991   30.13   201     0
11      273.97  3.650   41.20   274     0
21      245.21  4.078   36.88   246     0
31      265.94  3.760   39.99   266     0
41      265.97  3.760   40.00   266     0
51      265.95  3.760   40.00   266     0
61      258.76  3.865   38.92   259     0
71      260.95  3.832   39.24   262     0
81      244.99  4.082   36.84   245     0
91      251.80  3.971   37.87   253     0

[Run User]      [TPS]   [Time Per Request : millisec]   [Transfer rate: Kbytes/sec]     [Complete Request]      [Failed Request]
300     274.39  3.644   41.27   275     0
310     233.33  4.286   35.09   234     0
320     173.71  5.757   26.12   174     0
330     133.75  7.476   20.12   134     0
340     142.73  7.006   21.46   143     0
350     130.86  7.642   19.68   131     0
360     128.93  7.756   19.39   129     0
370     280.45  3.566   42.18   281     0
380     267.97  3.732   40.30   268     0
390     278.43  3.592   41.87   279     0
400     200.84  4.979   30.20   201     0

Apach 오픈소스 부하테스트 도구를 이용하여 동시접속 수행 성능을 측정하였다.
하나의 단일 User 가 비동기로 여러개의 병렬 수행을 요청하며, 그러한 User 또한 1에서 최고 400까지 늘려가며 측정 하였다.

CPU는 TPS 가 270 정도씩 나와 주고 있다. 그 시점 flask  의 로그를 보면, 실제 초단위로 동일한 log 가 270여개 실제로 모두 200 응답으로 존재함을 확인 할 수 있다.




(2) GPU 에서의 최종 결과

[Run User]      [TPS]   [Time Per Request : millisec]   [Transfer rate: Kbytes/sec]     [Complete Request]      [Failed Request]
1       16.47   60.735  2.48    17      0
11      16.24   61.565  2.44    17      0
21      15.69   63.740  2.36    16      0
31      11.60   86.215  1.74    12      0
41      4.98    200.914         0.75    5       0
51                              0       0
61      17.80   56.186  2.68    18      0
71                              0       0
81      17.47   57.242  2.63    18      0
91                              0       0

[Run User]      [TPS]   [Time Per Request : millisec]   [Transfer rate: Kbytes/sec]     [Complete Request]      [Failed Request]
1       15.87   63.014  2.39    16      0
11      17.28   57.886  2.60    18      0
21      15.69   63.744  2.36    16      0
31      12.46   80.263  1.87    13      0
41      5.76    173.748         0.87    6       0
51                              0       0
61      17.33   57.706  2.61    18      0
71                              0       0
81      12.42   80.529  1.87    13      0
91                              0       0



GPU 는 TPS 가 16 정도밖에 되지 않는 저조한 결과를 보여 주었다.

[결론]

(ps. 동시수행 과정에서의 cpu , gpu 사용량은 serial 1000건 수행의 경우와 매우 유사했다.)

CPU 의 경우 특징은 느려질 지언정 400동접까지도 Fail Request 가 하나도 없었다는 점이다.
그리고 Serial 하게 1000개를 수행했을때, 개당 20 ms 이던것이 병렬로 수행했을때에는 약 5배정도 빠른 성능을 보여 주었다. 

하지만 GPU 의 경우는 동접자가 많아지면, Fail Request 가 매우 많아 졌고, TPS 자체도 CPU 에 비하여 매우 느렸다. Serial 수행에서 3배 느렸으나, 동접 수행은 거의 10배 이상 느렸다. CPU 코어가 여러개인것도 그렇지만, 메모리 등도 한몫을 했을 것으로 보여진다. GPU 의 경우는 serial 하게 측정했을때나 parallel 하게 측정했을때 모두 개당 응답 속도가 60ms  정도로 일정하다는 특징도 보여주었다. 즉, 동시 처리가 좀 매우 취약해 보인다. 동시 수행하는 속도 개선 효과가 거의 없었다.(CPU 와는 전혀 다른 양상이다.)

또한 GPU inference 의 경우 단일 CPU 가 GPU 한개와 함께 힘들게 일하고 있었던 양상 또한, 병렬 동시접속 능력을 떨어뜨리는 계기가 된듯 하다.
(이는 Tensorflow 에서의 실험 내용이다. CNTK  로도 동일한 모델을 수행할 수 있는데, 그 비교 결과는 다음 기회에 Posting 해보도록 하겠다.)

일단 CPU Inference 의 경우는, 메모리 사용량, CPU 사용량, 모두 저정도의 traffic 에 대하여는 안정적인 결과를 보여주는 것을 확인 할 수 있었다. GPU 의 경우는 Production 으로 대국민 서비스를 하기에 매우 위험한 수준이었다.

Developer 입장에서, 우리에게 CPU는 사실 GPU에 비하여 상대적으로 너무나 친숙하고 풍족한 리소스 이다. 게다가, 우리는 Docker , Microservice , Spark on Hadoop Yarn, Mesos  등 다양한 CPU + in-Memory 병렬 cluster 솔루션이 있다. 그리고 Public Cloud 에도 Auto Scale Out  이 가능한 Docker PaaS 나 Serverless MicroService PaaS 가 GPU 보다는 훨씬 저렴한 가격으로 구비되어 있다.

AI Serving Layer 는 이렇게 일단 우리의 시나리오와 우리의 모델에 있어서는 GPU 를 제끼고 고려할만 한 실험 결과가 나왔다. ( 물론 VGG, Inception 등 층이 깊은 Deep Learning 모델은 이것과 다른 양상이 나올 지도 모른다. TensorRT 등 Nvidia 는 Inference 전용 솔루션도 내놓은 것으로 알고 있다.) 

지금 담담하게 결론을 적고 있지만, 사실 실험결과가 이렇게 나왔을때 나는 흥분을 감추지 못했다. 하마터면 수억원짜리 GPU가 6~8개씩 꼳 힌 장비를 수대 구매하는 프로세스를 태울 뻔 했기도 했지만.... 무엇보다, 대용량 서비스와 다수 동접자를 위한 아키텍처에, 위 결론에서는 많은 솔루션과 오픈소스 그리고 public cloud 를 쓸 수 있는 풍부한 가능성이 생겼다는 점에서 안도의 한숨을 쉴 수 있었다.

PS. 위 실험 결과와 결론 유추 과정에서 제가 범한 논리적 오류가 있었다면 지적해주시기 바랍니다. 공유 이후 컴멘트는 곧 저에게는 배움이기도 하다는 자세로 공유를 실천 하고 있습니다.

2017년 9월 7일 목요일

BigData와 결합한, 분산 Deep Learning 그 의미와 접근 방법에 대하여

딥러닝의 대부이신 제프리 힌튼 교수님은, 머신러닝의 수십년간 암흑기가 극복될 수 있었던 계기로 3대 난재가 풀렸기 때문이라고 언급하신 바 있다. 바로 아래와 같다.
  1. 알고리즘적 혁신 ( Deep Neural Net 이 가능해진,  Relu, DropOut, 발견 등등..)
  2. 하드웨어 혁신 ( GPU 를 이용한 컴퓨팅 파워 Scale Up )
  3. 소프트웨어 혁신 ( BigData Cluster 를 이용한 분산 컴퓨팅 파워 Scale Out )
이 중 1은 우리가 너무나 많이 알고 있고, 곁에서 접하고 있고, 심지어 사랑하고 있는 분야이다.
2는 약간 비싸지만, 회사에서 안사주면, 자비를 털어서라도 집 Desktop에 2개 정도 꼳아주고, 그 날개 돋힌 파워를 충분히 느껴 볼 수 있는 분야이다.

하지만, 3은 좀 말이 다르다. 힌튼 교수님이 말씀 하셨지만,  Lab 에서든 기업에서든, 섣불리(아직까지는) 시도되지 못하는 경향이 있고, 관련된 자료도 많지 않다. 무엇보다도, Popular 한 오픈 Data 를 통해 논문에서 통용되는 수십만 혹은 수백만건의 데이타는 그다지 Big 하지 않기 때문에, 1+2 만 가지고도 꾸엮 꾸엮 실험하고 돌려보고, 논문을 완성해갈 수도 있는 수준일 수 있다. 때문에, 구글, MS 등 몇몇 회사등을 제외하고는 수십층 짜리 Very Very Deep 류의 모델을 밑바닥부터 적합한 Neural Networks 구조를 발견하고, 이를 초기값부터 시작하여 새롭게 학습시키는 등의 작업은 일반 소규모 Lab 등에서는 하기가 매우 힘들고, 그러다 보니, 그에 대한 학계의 연구가 보편화 되어 있지는 않는 듯 보인다. 

그래서인지 3의 접근은 일부 공룡 기업들에 의하여 자체 구축 혹은 오픈소스화 되어 일부 만이 오픈된 상태이다. 

기업의 Production Deep Learning 프로젝트의 경우, 우선 보유 Data 의 크기가 논문에서 사용되는 Data 의 크기보다 수십배 ~ 수백배인 경우가 많다.(아닌경우도 많지만...) 그리고, 복수의 모델을 함께 쓰거나 좀더 Fine Tuning 을 위해, Online Learning , Transfer Learning  보다는  초기부터의 Learning 을 시도하는 경우가 훨씬 많다.(특히, 한글 Deep Learning Text NLP 등은 기 학습되어 있는 Pre training Set 도 존재하지 않는다.)


오늘은 그런 부분 즉, Deep Learning 을 Big Data Scale Data 를 가지고 수십대 수백대의 GPU 클러스터를 가지고서 병렬 Training 을 하기 위한 BigData Platform + deep Learning Platform 구성에 대하여 이야기 해보고자 한다.

[1] GPU 만으로 하는 Deep Learning Approach의 한계

가장 Popular 한 Deep Learning  프레임워크 중 하나인 Tensorflow 는 사실, 이미 멀티 GPU 를 지원하고, 멀티 노드도 지원하며, 아직 미흡하지만, 자체 Serving Layer 도 가지고 있다. 하지만, Tensorflow 가 지원하는 수준의 분산 컴퓨팅, 분산 GPU 는 마치, 분산 데이타 컴퓨팅을 Map/Reduce 로 하는 경우와 유사하게 너무 Low Level 접근을 필요로 하는 경우가 많다. 하나의 Simple 한 Neural Network 모델이 Data Parallel 이 되거나 Compute Parallel 이 되는것 특히, 그것이 High Level 로 저절로 되는 것은 아직 그 어떤 Deep Learning 프레임워크도 완벽하게 지원하고 있지는 않는 영역이다.
Caffe나 Tensorflow , Torch, CNTK 등의 deep learning  프레임워크는 그 자체만으로 은총알은 아니다. High Level Scale Up 된 장비 한두대로 논문에서 다루는 크기의 데이타를 처리하는데에는 문제가 되지 않으나, 실무 데이타, 특히 클릭 스트림을 RNN이나 LSTM 분석하는 정도의 시나리오만 되도, 데이타의 크기나 GPU 머신의 Memory 문제로 금방 문제가 드러나기 십상이다.
다중 사용자에게 Deep Learning Serving(Service Request 대응) 을 하는 도중에, Model traing 갱신이 일어나고, 실시간 업데이트가 되면서, 무중지로 Model 배포되는 시나리오는 또 다른 고급 기술을 요구하기도 한다.
GPU 만으로 하는 Single Scale Up, Deep Learning Approach의 한계를 정리해 보자면 아래정도 일 것이다. 
  1. Hyper Parameter Tunning 노가다
  2. Training 속도 한계있음
  3. 멀티 GPU 코딩의 거시기함.
  4. GPU의 협소한 메모리로 인한 ResourceExhaustedError. 
  5. 강제된 작은 Batch Size
  6. RealTime Inference, 다수 동접자 Serving Layer, 모델의 무중지 Rolling Upgrade
  7. BigData Scale Data 들을 접근 하기 위한 Data Pipe lining  
  8. 모델 태우기 전, Python 레벨 데이타 전처리와 후처리의 한세월...

[2] Open Source 진영 BigData Scale Distributed Deep Learning Approach 
하지만, 오픈소스 진영에서는 그러한 것들을 주로 hadoop + Spark (PySpark) 를 통해 해결 시도 하고 있고, 어느정도 Production 레벨까지 활용 가능한 수준의 결과물들이 나오고 있다. 즉, 서두에서 언급했던 3(BigData 혁신)의 시도가 되고 있는 것이다.
BigDL, elaphas , caffeOnSpark  등 그런류의 몇가지 오픈소스를 실제 Production Level Deep Learning 배치 시나리오를 이용 Training 해보고 테스트 해보았는데, 아래 소개하는 TensorflowOnSpakr (made by Yahoo) 오픈소스는 그중 가장 가능성이 보이는 Approach 중 하나라 할 수 있을 것이다. (참고로, Yahoo 는 TensorflowOnSpark 을 만들기 전 CaffeOnSpark을 먼저 만들었고 테스트 하였다.)
아래는 Inception-v3 모델을 spark 멀티 노드위에서 worker 노드 갯수를 달리해가면 분산 Training 한 속도 비교 이다.

위처럼 1대에서 48시간을 돌려도 정확도가 0.73 % 정도인게, 8대에서는 7시간만에 도달되고 이후로, 85%가 넘는 정확도에 훨씬 빠른 시간에 도달 되는 것을 확인 할 수 있다.
[3] TensorflowOnSpark 설치 및 세팅 사용방법 
아래는 그런 Producion Level 에서 BigData 분산 Traing 과 RealTime Traing 부분에 강한 강점을 가지고 있는 시스템 구성으로 Tensorflow + Spark + Hadoop 구성을 설정 하고 세팅 한 후, 간단하게 사용하는 방법이다. ( Hadoop 과 Spark  는 Yarn Cluster 모드로 이미 설정이 기 완료 되어 있다고 가정하고, 그 이후의 세팅 방법만 언급 하였다.)
  1. Python3 관련 설정 및 설치
    1. 우선 SSL 관련
      1. yum install openssl openssl-devel -y
    2. Anaconda 설치
      1. https://repo.continuum.io/archive/ 위치에서 Linux 버전 최신 설치 파일 Download
      2. 각 노드에 모두 복사
      3. chmod 755 Anaconda3-4.4.0-Linux-x86_64.sh
      4. sudo ./Anaconda3-4.4.0-Linux-x86_64.sh
      5. 설치 완료 시 화면
        1. 설치 완료 화면
      6. bin 경로에 심볼릭 링크 연결 (Source 경로는 각자의 경로를 따를 것!)
        1. sudo ln -s /home/moneymall/anaconda3/bin/python3 /bin/python3
      7. 기존 python 을 un link
        1. sudo unlink /bin/python
      8. 새로 설치한 python3 로 다시 link
        1. sudo ln -s /bin/python3 /bin/python
      9. pip 도 설정
        1. sudo ln -s /home/moneymall/anaconda3/bin/pip /bin/pip

  2. Anaconda 설치에 관하여.
    1. Tensorflow 등의 기본이 되는 Python Dev 환경을 설치하는 여러가지 방법이 있지만, 내가 선호하는 방법은 우선 anaconda 를 깔아주는 것이다. 공간차지 등등 부수적인 단점이 있긴 하지만, 여러가지 추가적인 기능들이나 필수 모듈들이 동시에 깔려서 편하고, 이후 anaconda 가 제공하는 여러가지 관리 도구들을 이용하여 다양한 장점을 꽤할 수 있다.
    2. Root 로 설치시 실제 사용하는 계정으로 수행하는데 불편함이 많음.
    3. 실제 사용하는 계정으로 설치하는 것이 더 편함.
  3. Tensorflow 및 TensroflowOnSpark 설치
    1. pip install tensorflow
      1. CPU 모드일때는 그냥 간단히 저렇게 해줘도 됨.
      2. virtual env 등에 설정할 수도 있고, conda create 한 다음 설정할 수도 있으나, spark 와 연동을 위해서는 바깥에서 전역적으로 저렇게 설치하는 것이 좋음.
      3. 설치 완료 화면
    2. pip install tensorflowonspark
      1. 설치 무지 빨리 끝남.
      2. 설치 완료 화면
    3. 참고로 위 설치 방법은 Simple 설치 방법을 공유하기 위한 목적의 설치 Guide 이므로, RDMA 를 사용하는 Advanced 설정 방법은 아님.
      1. RDMA 사용 시 훨씬 성능을 극대화 할 수 있음.
  4. Spark및 Hadoop 에서 Tensorflow 의 Records 를 직접 읽고 쓰기위 한 Jar 라이브러리 설치
    1. 아래 주소에 Spark 용 해당 Open Source 가 있음.
      1. https://github.com/tensorflow/ecosystem/tree/master/spark/spark-tensorflow-connector
      2. git clone 후 spark 디렉토리로 이동.
      3. git clone https://github.com/tensorflow/ecosystem.git
      4. sbt build
        1. build.sbt 파일이 존재하는 위치까지 이동.
        2. sbt clean assembly
        3. 위 빌드 명령어 입력 하면 아래처럼 sbt 빌드 완료 되고, target 디렉토리 하위에 jar 파일 생성 됨.
        4. Jar 파일 위치
    2. 아래는 Spark 이 아닌 Hadoop 용 InputFormat/OutputFormat 모듈 for Tensorflow Records Direct Read/Write
      1. https://github.com/tensorflow/ecosystem/tree/master/hadoop
      2. 위 git clone 소스에서 Hadoop 경로로 간다.
      3. $TF_SRC_ROOT 는 Tensorflow 소스 루트.
      4. protoc 가 설치되어 있지 않다면, https://developers.google.com/protocol-buffers/ 에서 3.3.0 버전 설치 필요 함.
        1. git clone https://github.com/google/protobuf.git
        2. cd protobuf
        3. ./autogen.sh
        4. ./configure
        5. make # 무지오래걸림.
        6. make check # 더 오래걸림. 커피 먹으러 갔다 오길 추천.
          1. make check 완료시 화면
        7. sudo make install # 금방 끝남.
        8. sudo ldconfig
        9. 완료 후 확인
          1. protoc 명령어를 수행하면 저런 화면이 떠야 함.
      5. protobuf java 버전도 설치 필요
        1. 소스 위치는 앞에서 다운받았던 protobuf 소스에서 java 경로 밑에 있음.
        2. mvn test (maven 이 기 설치 되어 있어야 함.)
          1. 완료시 이런 모양.
        3. mvn install
      6. protoc --proto_path=$TF_SRC_ROOT --java_out=src/main/java/ $TF_SRC_ROOT/tensorflow/core/example/{example,feature}.proto
        1. $TF_SRC_ROOT 는 tensorflow 소스가 미리 받아져 있어야 하고 해당 경로로 set 되어 있어야 함. (.bashrc 등에...)
        2. tensorflow 소스는 https://github.com/tensorflow/tensorflow.git 이곳에 있음.
      7. mvn clean package
        1. 처음 default pom.xml 로 수행시 아래같은 에러 잔뜩 남.
          1. Cannot find symbol 이라는 문구들이 error 로그에 보이는 걸로 봐서...이건 version 오류로 추정됨.
          2. pom.xml 을 열어서 보면... version 이 1.6 으로 되어 있음. 이걸 1.8로 수정(내 환경에서의 Java 는 1.8 이었으므로...)
            1. Java 버전 1.8로 수정했음.
            2. protobuf 버전도 3.3.1 에서 내가 설치했던 버전인 3.4.0  으로 수정해 주었음.
        2. jar 생성
          1. 위 pom.xml 수정 후 빌드 성공하면 jar 생성됨.
          2. 빌드 성공시의 화면
            1. jar 파일은 target 디렉토리 아래 존재
      8. 해당 jar 를 HDFS 에 업로드
        1. hadoop fs -put tensorflow-hadoop-1.0-SNAPSHOT.jar /user/moneymall/
  5. Parallel MNIST 돌려보기
    1. 우선 데이타 준비
      1. mkdir ${HOME}/mnist
        pushd ${HOME}/mnist >/dev/null
        curl -O "http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz"
        curl -O "http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz"
        curl -O "http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz"
        curl -O "http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz"
        zip -r mnist.zip *
        popd >/dev/null
      2. 위 mnist.zip 파일은 local 에 존재 시키고, spark-submit 할때 인자로 넘길 예정이다.
    2. Pyspark 를 이용한 Data 병렬 전처리 후 CSV 포맷으로 저장
      1. Pyspark 를 이용해서 MNIST 데이타를 traing 셑과 test 셑으로 나누는 부분을 병렬로 수행 해보자.
      2. 여기에 사용되는 example 코드는 tensroflowOnSpark github 에 존재하는 코드이다.
        1. https://github.com/yahoo/TensorFlowOnSpark/blob/master/examples/mnist/mnist_data_setup.py
        2. 위 코드를 사용하였다.
      3. pySpark  로 data 전처리를 병렬로 수행하고 CSV 결과는 Hadoop 에 쓸 예정이다.
      4. 수행 Script 는 아래와 같다.
      5. ${SPARK_HOME}/bin/spark-submit \
        --master yarn \
        --deploy-mode cluster \
        --queue ${QUEUE} \
        --num-executors 13 \
        --executor-memory 22G \
        --archives ./mnist/mnist/mnist.zip#mnist \
        ./mnist/mnist_data_setup.py \
        --output mnist/csv \
        --format csv
        
      6. 위는 official manual 문서와 다소 다르다. 처음 수행을 하면 에러가 나는데, spark yarn cluster 를 이용하였으므로, hadoop job 모니터링 페이지를 통해 에러 로그를 확인 할 수 있다.
        1.   즉, mnist 다운로드한 파일의 경로 참조를 정확히 해주지 못해서 에러가 발생하고 있음을 알수있다.
        2. 경로를 수행한 python 파일과의 상대경로로 정확히 지정하고 나면, 에러가 나지 않고, pyspark yarn cluster 모드로 잘 동작이 된다.
      7. 또 official manual 과 내가 수행한 스크립트의 다른 부분은 아래 옵션을 나는 삭제 했다는 점이다.
        1. --archives hdfs:///user/${USER}/Python
        2. 우리는 앞서 모든 노드에 동일하게 Python 환경을 이미 세팅해 주었고, Path 에도 포함시켜 줬다. 때문에, 굳이 Python을 배포를 통하여 공유되게 하지 않아도 에러없이 수행이 가능하다.
      8. 최종적인 결과 메시지는 아래와 같다.
      9. hadoop 에 CSV  파일이 잘 Write 되었는지도 확인해 보자.
        1. 하이라이트 한 부분 처럼 Hadoop 에 mnist 데이타에 대한 전처리 후 결과 output 이 train 과 test 데이타로 나뉘어 잘 적재 된 것을 확인 할 수 있다.
        2. 이는 앞으로 대용량 데이타에 대한 Python 전처리를 병렬로 수행할 수 있음을 확인 한 부분이다.
    3. Pyspark 를 이용한 Data 병렬 전처리 후 Tensroflow Records 포맷으로 저장
      1. CSV 로 파일을 저장하지 않고, Tenssorflow Records 포맷으로 바로 저장할 수도 있다.
      2. 우리는 이를 하기 위해 윗부분 설치 시점에, 4.2.8 에서 protobuf 까지 설치해가며, tensorflow ecosystem github 의 소스를 내려 받아 maven 빌드 후 tensorflow-hadoop-1.0-SNAPSHOT.jar 파일을 생성한 바 있다.
      3. 해당 jar 를 pyspark submit 시 인자로 넘겨주고 해당 jar 라이브러리를 이용 아래 내용을 수행 할 예정이다.
      4. 수행 스크립트는 아래와 같다.
      5. ${SPARK_HOME}/bin/spark-submit \
        --master yarn \
        --deploy-mode cluster \
        --queue ${QUEUE} \
        --num-executors 13 \
        --executor-memory 22G \
        --archives ./mnist/mnist/mnist.zip#mnist \
        --jars hdfs:///user/moneymall/tensorflow-hadoop-1.0-SNAPSHOT.jar \
        ./mnist/mnist_data_setup.py \
        --output mnist/tfr \
        --format tfr
        
      6. 앞서 CSV 로 HDFS에 저장해보았던 예제의 수행 스크립트 내용과 매우 유사하지만 대표적으로 --jars 옵션을 사용한것이 큰 차이점이다.
      7. 그리고, 소스 내부에서 format 인자로 로직이 분기하므로 --format 값으로tfr 을 넘겨 주었으며, output 경로 또한 csv 가 아닌 tfr 로 변경해 주었다.
      8. hadoop 에 tensorflow 포맷 records 가 잘 저장되었는지 살펴보자.
        1. 스크립트를 수행해주자 위처럼 tfr 폴더가 생성 되었다.
        2. tfr 디렉토리의 상세내용을 살펴보면 아래와 같다.
          1. 역시 test 와 train 으로 구분되었으며, spark job 이 생성하는 파일 명명 규칙으로 파일이 생성 되었다. (파일 내용은 TFRecords 포맷이다.)
    4. MNIST 모델 돌려보기
      1. 위 전처리 및 아래 Tensorlfow 병렬 모델 수행에서의 수행 스크립트는 Dev Zone 에서 테스트 된 관계로 GPU 관련 옵션이 빠져 있다. GPU 모드 병렬 수행을 위해서는 아래 옵션들이 추가되어야 한다.
        1. --queue GPU
        2. --conf spark.executorEnv.LD_LIBRARY_PATH=$LIB_CUDA:$LIB_JVM:$LIB_HDFS \
          --driver-library-path=$LIB_CUDA \
        3. #infiniband 에서의 성능 향상을 위해서는 아래 옵션도 추가하는 경우 
          # 큰 성능 향상을 가져올 수 있다. (설치시에도 옵션 설정 필요)
          --rdma 
      2. Training (using feed-dict)
        1. feed-dict 을 이용한 Traing 용 수행 스크립트는 아래와 같다.
        2. # 재 수행시에는 아래 주석을 풀어주어야 한다. Overwrite error 방지.
          # hadoop fs -rm -r mnist_model
          ${SPARK_HOME}/bin/spark-submit \
          --master yarn \
          --deploy-mode cluster \
          --queue ${QUEUE} \
          --num-executors 13 \
          --executor-memory 22G \
          --py-files ./mnist/spark/mnist_dist.py \
          --conf spark.dynamicAllocation.enabled=false \
          --conf spark.yarn.maxAppAttempts=1 \
          --conf spark.executorEnv.LD_LIBRARY_PATH=$LIB_JVM:$LIB_HDFS \
          ./mnist/spark/mnist_spark.py \
          --images mnist/csv/train/images \
          --labels mnist/csv/train/labels \
          --mode train \
          --model mnist_model
          # to use infiniband, add --rdma
          
        3. 아래는 위 병렬 Training 이 수행되는 동안의 Yarn Batch Job 모니터링 페이지의 모습이다. 일반 Spark Yarn Cluster Job 과 동일한 모양이다.

        4. 최중 수행 뒤 결과 메시지는 아래와 같다.

      3. inference (using feed-dict)
        1. training 이 끝났으므로, inference 즉, 모델의 학습 결과를 확인 해 보자.
        2. 수행 스크립트는 아래와 같다.
        3. # hadoop fs -rm -r mnist_model
          ${SPARK_HOME}/bin/spark-submit \
          --master yarn \
          --deploy-mode cluster \
          --queue ${QUEUE} \
          --num-executors 13 \
          --executor-memory 22G \
          --py-files ./mnist/spark/mnist_dist.py \
          --conf spark.dynamicAllocation.enabled=false \
          --conf spark.yarn.maxAppAttempts=1 \
          --conf spark.executorEnv.LD_LIBRARY_PATH=$LIB_JVM:$LIB_HDFS \
          ./mnist/spark/mnist_spark.py \
          --images mnist/csv/train/images \
          --labels mnist/csv/train/labels \
          --mode inference \
          --model mnist_model \
          --output predictions
          # to use infiniband, add --rdma
          
        4. mode 부분과 output 부분만 차이가 있다.
        5. 주의할 점은 앞에서 mnist_model 을 training 과정에서 이미 수행하였다면, 상단 hadoop 명령어로 mnist_model 을 지우고 수행해야 한다는 점이다. (hadoop 에서의 경로는 적절히 수정 할 것)
        6. 결과는 아래와 같다.
          1. 최종 결과는 output 으로 지정해준 predictions 안에 존재한다.
          2. 아래 명령어로 내용을 살펴보자.
            1. hadoop dfs -cat predictions/part-00000
            2. 결과는 아래와 같다.
      4. training (using queueRunners)
        1. feed-dict 대신 I/O 병목에 더 강점이 있는 queueRunners 모드를 사용해 보자. 여기서는 TFRecords 를 이용하여 좀더 Tensorflow Low Level training 을 할 예정이다.
        2. 수행 스크립트는 아래와 같다.
        3. # hadoop fs -rm -r mnist_model
          ${SPARK_HOME}/bin/spark-submit \
          --master yarn \
          --deploy-mode cluster \
          --queue ${QUEUE} \
          --num-executors 13 \
          --executor-memory 22G \
          --py-files ./mnist/spark/mnist_dist.py \
          --conf spark.dynamicAllocation.enabled=false \
          --conf spark.yarn.maxAppAttempts=1 \
          --conf spark.executorEnv.LD_LIBRARY_PATH=$LIB_JVM:$LIB_HDFS \
          --jars hdfs:///user/moneymall/tensorflow-hadoop-1.0-SNAPSHOT.jar \
          ./mnist/spark/mnist_spark.py \
          --images mnist/tfr/train \
          --format tfr \
          --mode train \
          --model mnist_model
          # to use infiniband, add --rdma
          
        4. CSV 대신 tfr 즉, TensorFlow Records 를 직접 사용할 예정이다.
        5. 기존 hadoop model output 을 제거한 후 수행하자.
        6. 여기서 주의할 점은 2017년 8월 기준 official manual 에 --jars 옵션이 빠져 있어 에러가 난다는 점이다. 위처럼 jars 옵션으로 앞서 만들었던 tensorflow-hadoop-1.0-SNAPSHOT.jar 파일을 포함해 주어야 위 스크립트가 정상 동작 한다.
        7. 최종 결과는 아래와 같다.
[결론]

우선,  PySpark 와 Tensorflow 를 섞어 쓸 수 있는게 매우 편하다. Python 전처리 수시간 걸리던게 PySpark 로 수분안에 끝나는 묘미를 맛보면, 이전으로 돌아가기가 쉽지 않다.
익숙한 Jupyter Notebook 이나 Zepellin Notebook 환경 모두 tensorflowOnSpark 연동이 가능한 것도 장점이다.


그리고, 대부분의 기존 Tensorflow 모델을 10줄 미만으로 수정하여, 병렬화 가능하다는 장점이 돋보인다. Spark 클러스터는 Yarn Cluster Mode 만을 지원하고 있다. 그리고, CPU 병렬 뿐만 아니라 GPU 병렬도 지원한다.

또한, Spark Streaming Mode 도 지원한다. 즉, 앞에 Kafka Cluster Queue 등을 놓으면, site 전체의 Click Stream 등 초 Heavy 트래픽에 대한 input 을 염두하며, 실시간 realtime inference가 되는 사이트 실시간 개인화 모델등을 만든다고 할때, 그러한 연산에 있어서의 Spark-streaming Layer 의 강점을 Deep Learning 모델에도 적용가능하리라 여겨진다.

설치는 Official Document 가 그런데로 상세히 나와 있는 편이지만, Legacy 가 최신 버전일때는 약간의 에러들이 발견되었고, 그래서 위처럼 설치 과정이 좀 길어졌다, 그 경우 소스 레벨 debub 및 log 를 확인해가며 설치를 해야 마무리가 되었던 부분은 약간 아쉬웠다. 즉, 너무 최신 Legacy 버전이 아닌 Official 버전을 사용하여 설치하면 좀더 쉽게 설치가 가능 할 것이다. 그리고, github 에 답변이나 issue 해결 commit 이 거의 매일 올라오고 갱신되는 편이라, 믿음이 간다. elaphs 는 설치해서 테스트 하다가 포기한게, issue 에 대한 대응이 너무 느렸다.

BigDL  역시 SparkML 과 유사한 패턴으로 딥러닝을 할 수가 있어, general 한 모델을 만들때는 더 편할 수 도 있다. 그리고, 자사의 BigData Cluster 가 아직 GPU 는 없고,  intel cpu 기반이라고 하다면, BigDL 이 tensorflowOnSpark 보다 좀더 성능이 잘 나올 수 있다.
하지만, 다양한 고급 모델을 지원하지 못한다는 단점이 분명히 존재한다.

BigData + Deep Learning 콜라보레이션 아키텍처에 대한 고민은 거의 반년 이상 했던거 같다. 여러가지를 실험해 보았고, 결론은 BigDL 과 TensorflowOnSpark 두개로 거의 확정하였다. 둘은 장단점이 극명하여, 어느 하나로 치우칠 필요 없이, 선택적으로 사용하려고 한다.

좀더 실무레벨에서 많은 경험을 한 후 다시 한번 포스팅 해볼 기회가 생겼으면 하는 주제였다.

2017년 8월 28일 월요일

Deep Learning Text NLP with Spark Collaboration

발표한지 좀 시간이 지나긴 했지만, 한 두달여 전 Korea Spark Summit Day 에서 내가 발표했던 내용의 슬라이더 전문이다.

주로 아래 내용을 다루었었다.

1. Machine Learning Approach vs Deep Learning Approach
2. 한글 Text Classification 문제를 전통적인 Machine Learning 으로 풀어보았을때의 장단점 및 성능 수치.
3. 동일한 문제를 Deep Learning  으로 풀어보았을때의 장단점 및 성능 수치.
4. 한글 Text Classification 문제를 다양한 알려진(좀 유명한) Approach 로 각각 접근 했을때, 실무 데이타 기준(IMDB 등 논문에서 등장하는 데이타보다 훨씬 양이 많고, 훨씬 어려운 문제(138지 Top 1 분류)) 성능 수치 비교.
5. Production Level , Real World 의 Big Data Scale Large Data Set 을 가지고 Deep Learning 프로젝트를 진행하는 경우에 접하게 되는 다양한 문제점들.
6. Spark 를 활용하여 Big Data Scale Deep Learning 을 하는 방법론 소개.

아래는 해당 내용의 전문이다.



2017년 8월 5일 토요일

GCP, AZURE, AWS 그리고 BigQuery, Azure ML Studio, Data Lake 에 대한 단상

커뮤니에서 한분이 GCP 그리고 BigQuery 에 대하여 타 시스템과의 비교를 요청하셔서 장문의 답변을 하게 되었다. 해당 내용을 이곳에 옮겨 적어 보았다.

우선, 서두는 내가 시작하였다. 대략 이런 내용이었다.

3년 전 post. 당시 우리는 MapReduce기술을 버리고 당시 뜨던 기술인 Cascalog를 도입 및 전환 완료 했던 시점이었다. 이후 Scala,Spark로 옮겨가는데에도 그리 오랜 시간이 걸리진 않았다. 지금은, Scalding이나 Cascalog는 옛기술이되었고, MapReduce는 역사를 논할때나 등장한다. Spark이 세력을 확장하고, 다양한 layer의 기저 인프라역할을 하며, 존재감을 유지하고 있는 가운데, 최상위 application layer의 data science 도구들은 sas 분파를 r 분파가 밀어네고, anaconda, keras등 python 계열들이 크게 세력을 확장하였으며, tensorflow, theano, caffe, cntk, maxnet 등 중간계에 deep learning 류 분파가 끼어들면서, 이 바닥은 좀더 wide 경쟁체계에서 좀더 깊고 좀더 특화된 deep stack 체제로 전환되었다. 그로부터 language 또한 훨씬 다양해졌다. 그러던 와중 intel, yahoo 등에 의해 spark 및 cpu 진영에서의 분산 및 대용량 특화 deep learning approach가 다시 세력을 키우기 시작했으니.... 이 모든게 최근 3년 사이 있었던 일이다... 마치 미드 왕좌의 게임을 보듯 흥미진진한 이 바닥 기술 Stack 들의 흥망성쇠 이야기들 이었다.


이후 여러 말들이 오가던 중 질문...

Question ) 전문가께 GCP, 빅쿼리에 대한 간단한 인상? 감상을 여쭤도 될까요? 자투리 시간에 공부해볼까 하는 중입니다.


그리고, 답변이다. 너무 장문이었나??? 여튼 아까워서 이곳에 옮겨 적었음.

Answer )

요즘 IaaS 는 AWS나 Azure 나 비슷비슷하죠. 가격도 거의 판박이구요. 단, AWS 가 커뮤니티나 3rd Party 쪽 Pre Built 이미지가 많아서, IaaS 에서는 좀 앞서는거 같구요. GCP는 셋중에 좀 밀리구요. PaaS 로 넘어가면, Azure 가 AWS 보다 종류도 많고, 완성도도 좀더 높은게 확실히 느껴지구요. GCP 의 경우는 Serverless 아키텍처에서 카날리 배포 하는 부분이랄지, Big Query 부분 등이 확실히 차별 point가 있는거 같아요. 무엇보다 Tensorflow 를 리딩하는 곳 답게, Deep Learning 에 있어, TPU 라던지.... Tensorflow Serving Layer 를 위한 PaaS 부분이 AWS 나 Azure 와는 확실히 다른 장점을 보유하고 있습니다. Big Query 는 대용량 데이타에 대하여 확실히 속도도 빠르고, 다양한 쿼리나 연산도 지원하여, 사내 BigData 업무에 있어서 확실히 큰 역할을 해낼 수 있습니다. 단, POC나 Toy Project, 혹은 Hands on Lab 수준의 요건이 아닌 실제 BigData Scale Business 요건에서 만나는 복잡다난한 요건에 대하여는 그런류의 Query Platform 은 한계가 있는 경우가 많아서, 대체 시스템 이라기 보다는 One of Them 보완 시스템으로 positioning 하고 접근 하셔야 합니다. NoSQL에 은총알이 없는 것과 비슷한거죠. BigQuery 도 BigQuery 가 지원하지 않는 기능에 대한 보완을 위해 UDF 를 지원하지만,(Hive 도 UDF를 지원하죠..) Hive 가 그러하듯이, Hive 만 가지고, 모든 요건을 해결할 순 없으니까요. 100배 빠른 Hive 가 있다 할지라두요. 가끔 Numpy 가 필요할때도 있죠. Konlpy 가 필요할때도 있구요. R에만 구현되어 있는 어떤 알고리즘이 필요할 때도 있습니다. 그런데, single machine R로는 로딩도 안되는게 문제죠. 복잡한 실무 Real Wordl Business Logic 을 Query 로만 구현할려고 하면, 병렬시스템 최적화 Plan 짜기가 너무 복잡 할때는 Scala 같은 Function Langauage 로 일일이 Parallel 구현 Step 을 구현 해주고 싶을 때가 있습니다. (실무에서는 Dw로직을 BigData 로 옮길때, A4용지 4~5장짜리 한방 쿼리들도 많이 접합니다. 그걸 옮길때는 Query 보다 Code 가 훨씬 편합니다. 대게의 경우 그런 Mart 성 R-Olap Query를 그대로 이관하면, NoSQL 이나 Cloud DW 에서는 대부분 돌지 않거나, 매우 느려집니다.) 
또한, Java 로도 Hive 로도 Spark SQL 이나 Spark ML 로도 안되는 그러한 요건들은 Python 이나 R로 하는게 절대적일때가 있는데, 대용량이 안되면, Spark 위에 PySpark 로 Model Parallelism 이 안되면, Data Parallelism 이라도 꽤하는게 크게 도움이 될때가 있습니다. SparkR 보단 MS R on Spark 나 Spakly R로 도움을 받을 수도 있구요. 요즘은 Tensorflow 나 Keras 도 Spark 위에서 Data Parallelism 이 가능하죠. BigDL 을 쓰면 Deep Learning 에 대하여 Model Parallelism 도 되구요. 여튼 BigQuery 는 훌륭한 General 도구인 것은 맞구요. 역시 은총알은 아니다 정도만 주지하시면 될 듯 해요. 이바닥이 Wide 하게 춘추전국이 아니라, 어느정도 교통정리가 되어가는 대신, 각 분야에 Specialty 를 극대화 하는 쪽으로 치닫고 있어서, Stack 이 매우 깊어졌습니다. 그리고, 실무에서 대용량의 요건을 가지고 Machine Learning 이나 Deep Learning 을 할라손 치면, 단순한 전처리만 하더라도 Anaconda + Python 단일 머신으로는 택도없는 경우가 허다하구요. 이를 위해서는 또다른 도구도 각 Stack 에 한두개 정도씩은 익힐 필요가 있습니다. 실무에서 Deep Learning 프로젝트를 하다 보니, 느낀 점은.... 우리가 Lab 에서 논문쓰고 있는게 아니기 때문에, Deep Learning 자체는 알려진 State of Art 접근 방식 및 해당 알고리즘의 가장 잘 알려진 github 구현체를 가져다 쓰면 되기 때문에, 큰 진입 장벽이 아니었다는 거구요. 오히려 진입 장벽은 A 부터 Z 까지..그리고 AI 의 Serving Layer 까지 그 전체를 아우르는 큰 시스템이 하나로 잘 엮이게 묶는 것이었습니다. 거의 Engineering Art 에 가깝구요... Model 하이퍼 파라미터 튜닝하는것보다, 그 모델을 다수의 동접의 사용자들에게 에러없이 동접을 버티며 Serving 하고, 그 반응이 다시 모델에 input 으로 들어가며, 운영 중 무중지로 rolling upgrade 시키는 걸 잘 구성하는게 5배 쯤 더 손이 많이가고 훨씬 고 난이도 테크닉을 필요로 했다 입니다. 그러던 와중에 대용량 데이타 전처리 부에 있어서는 BigQuery 가 일부에 있어서 큰 역할을 할 수 있습니다. Data Pipe Line 에서 물리적 셔플이 많이 일어나면 안되기 때문에, IaaS 나 PaaS 는 그런 도구들과 맞물려 통일화 고려도 필요하구요. BigData Scale 전처리 요건에 R 이나 Python 등을 섞어 쓰고 싶을때는 클라우드 상에서라면, BigQuery 보다는 Azure ML Studio 나 Data Lake 가 적당할 수도 있습니다. On Premise 라면 Spark 위에서의 Collaboration 을 구성하면 되구요.
또한, Java 로도 Hive 로도 Spark SQL 이나 Spark ML 로도 안되는 그러한 요건들은 Python 이나 R로 하는게 절대적일때가 있는데, 대용량이 안되면, Spark 위에 PySpark 로 Model Parallelism 이 안되면, Data Parallelism 이라도 꽤하는게 크게 도움이 될때가 있습니다. SparkR 보단 MS R on Spark 나 Spakly R로 도움을 받을 수도 있구요. 요즘은 Tensorflow 나 Keras 도 Spark 위에서 Data Parallelism 이 가능하죠. BigDL 을 쓰면 Deep Learning 에 대하여 Model Parallelism 도 되구요. 여튼 BigQuery 는 훌륭한 General 도구인 것은 맞구요. 역시 은총알은 아니다 정도만 주지하시면 될 듯 해요. 이바닥이 Wide 하게 춘추전국이 아니라, 어느정도 교통정리가 되어가는 대신, 각 분야에 Specialty 를 극대화 하는 쪽으로 치닫고 있어서, Stack 이 매우 깊어졌습니다. 그리고, 실무에서 대용량의 요건을 가지고 Machine Learning 이나 Deep Learning 을 할라손 치면, 단순한 전처리만 하더라도 Anaconda + Python 단일 머신으로는 택도없는 경우가 허다하구요. 이를 위해서는 또다른 도구도 각 Stack 에 한두개 정도씩은 익힐 필요가 있습니다. 실무에서 Deep Learning 프로젝트를 하다 보니, 느낀 점은.... 우리가 Lab 에서 논문쓰고 있는게 아니기 때문에, Deep Learning 자체는 알려진 State of Art 접근 방식 및 해당 알고리즘의 가장 잘 알려진 github 구현체를 가져다 쓰면 되기 때문에, 큰 진입 장벽이 아니었다는 거구요. 오히려 진입 장벽은 A 부터 Z 까지..그리고 AI 의 Serving Layer 까지 그 전체를 아우르는 큰 시스템이 하나로 잘 엮이게 묶는 것이었습니다. 거의 Engineering Art 에 가깝구요... Model 하이퍼 파라미터 튜닝하는것보다, 그 모델을 다수의 동접의 사용자들에게 에러없이 동접을 버티며 Serving 하고, 그 반응이 다시 모델에 input 으로 들어가며, 운영 중 무중지로 rolling upgrade 시키는 걸 잘 구성하는게 5배 쯤 더 손이 많이가고 훨씬 고 난이도 테크닉을 필요로 했다 입니다. 그러던 와중에 대용량 데이타 전처리 부에 있어서는 BigQuery 가 일부에 있어서 큰 역할을 할 수 있습니다. Data Pipe Line 에서 물리적 셔플이 많이 일어나면 안되기 때문에, IaaS 나 PaaS 는 그런 도구들과 맞물려 통일화 고려도 필요하구요. BigData Scale 전처리 요건에 R 이나 Python 등을 섞어 쓰고 싶을때는 클라우드 상에서라면, BigQuery 보다는 Azure ML Studio 나 Data Lake 가 적당할 수도 있습니다. On Premise 라면 Spark 위에서의 Collaboration 을 구성하면 되구요.


참고로 Azure 상의 Data Lake 는 기저에 Hadoop 과 Spark 이 있다. 그래서 BigQuery  보다 느릴 순 있으나, Spark이 가지고 있는 확장성을 꽤할 수 있다. 바로 python, java, scala, R, 그리고 Hive SQL  을 쓸 수 있을 뿐 아니라, Spark Cluster  위에 약간의 부가 세팅을 하면, Deep Learning 에 있어, BigDL(made by Intel)로 Model Parallelism 을 꽤할 수 있고, tensorflow on spark(made by Yahoo) 혹은 keras + tensorflow + spark 로 Parallel 하이퍼파라미터 옵티마이제이션 및 앙상블 등을 꽤할 수 있다.

아래는 HDInsight 위에서 BigDL 을 쉽게 설치하는 가이드 문서 이다.

https://software.intel.com/en-us/articles/deploying-bigdl-on-azure-data-science-vm






2017년 5월 10일 수요일

QnA Chabot (or Text Classification) 성능 향상 Tip

요즘 블로깅 할시간이 없어, 대신 최근 Facebook 의 질문에 조금 장문으로 답변한 내용을 기록으로 남겨 보았다. 사실, 조금 시간이 있다면, 아래 짧게 짧게 언급했던것들이 실제로 테스트 했던 데이타로 어떻게 얼마나 성능향상에 기였 했는지, 실 사례들을 함께 공유하고 싶으나... 시간이 없어서 TT.













2017년 3월 14일 화요일

Azure 상에서 Tensorflow GPU instance 이용하기

Community 에 한분께서 아래와 같이 질문을 주셨습니다. 이에대한 답변을 Facebook 에 작성하다 보니, 글이 너무 길어지는 듯 하여, 이곳에 옮겨 적어 봅니다.

Q) AzureML에서 Tensorflow를 연동하는 방법을 아시는 분이 계신가요-제가 아는 범위에선 Theano 연동하는 정도만이네요 ㅠㅠ

A) 답변입니다.

안녕하세요. Data Platform MVP 인 김훈동입니다. Azure 상에서 Tensorflow 를 쓰는 몇가지 방법이 있습니다. 질문에서 AzureML 이라고 언급 주셨는데, Azure ML Studio 등에서의 사용이 아닌 Azure 상에서의 Tensorflow 구동 이라고 질문을 이해했습니다. Azure ML Studio 에서는 Tensorflow Azure 에 구축한 별도 Instance 에 원격 실행 컴멘드를 날려서 Training 을 시키고, Tensorflow Serving Layer 를 이용하여, Input 에 대한 Output Restful 하게 받아 Azure ML Studio 에서 연동하는 방법이 있을 것입니다

아래부터는 Azure Tensorflow Cluster(GPU 포함)를 구축하는 방법론입니다.

(1)   가장쉽게
A.     Azure Instance Gallery 에서 Deep Learning Toolkit for DSVM 이미지 VM을 사용하는 방법
                         i.         OS Windows 2012 RC2 입니다.
                        ii.         GPU 사용이 가능합니다.(Region east US 등으로 하면 N-Series가 보입니다.)
                       iii.         CNTK, Keras, Tensorflow, mxnet 가 모두 기본 세팅되어 있고, MS R, Jupyter Notebook, Python Anaconda등이 설치되어 있으며, Visual Studio Data Science 툴들과 Spyder IDE 등이 세팅되어 있고, 요즘 도전적인 Data Scientist 들에게 Hot Julia Lang 개발환경까지 세팅되어 있습니다.
                       iv.         Jupyter Notebook 을 열면 Tensorflow, CNTK 등의 Example 이 담긴 Notebook 들이 폴더 별로 정리되어 구동됩니다.
                        v.         Ubuntu 에서 쓰시다가 Windows 위에서 사용하는 경우 호환문제를 걱정하시는 분들이 간혹 계시는데, UTF8 한글 부분과 일부 Old 스타일 CSV 핸들링 패키지를 제외하고, 문제가 되는 경우는 별로 없습니다.

(2)   Ubuntu 가 편하다면
A.     Ubuntu Instance 에 기본 Tensorflow 가 세팅된 인스턴스는 아직 존재하지 않는 것으로 보입니다. 제가 하나 만들어서 올릴까봐요. ^^
B.      하지만, Tensorflow 설치가 그리 어렵지 않으므로, Ubuntu VM 에 직접 설치하셔도 됩니다.
C.      동남아시아나 eastUS 등에 가셔서 N-Series 를 선택하시면, GPU Ubuntu VM 을 만드실 수 있습니다. 여기서 주의할점은 이상하게 Ubuntu VM은 디스크 Type SDD가 아닌 HDD 를 선택해야 N-Series 가 보인다는 점 입니다. 그런데, 최종 만들어진 Information 을 보면 SSD 가 포함되어 있습니다.

(3)   Windows10 Instance 에 설치하여 사용하는 방법.
A.     Tensorflow 1.X 가 정식으로 릴리즈 되면서, Windows 10 에도 꽤 쉽게 설치가 가능합니다.
B.      , 현재 Windows 64비트만 지원합니다.
C.      Anaconda 64비트 설치 후 설치하면 더 쉽습니다.
D.     특히 CUDA cuDNN Windows Linux보다 훨씬 설치가 간단합니다.
                         i.         CUDA cuDNN 설치 후 내컴퓨터->우클릭->속성->환경변수 가서 path 만 잡아 주면 끝
E.      Pip GPU 버전 설치할 때,  2월 말까지만 해도, whl 파일 경로가 win_x86_64.whl 요런식으로 되어 있었고, 해당 파일은 오류가 있었는데, 현재 win_amd64.whl 로 바뀌어 있구요. 그 파일이 원래 Windows 에서 오류없이 깔리는 것으로 Blog 등에서 공유되었던 파일입니다. 현재는 공식 install guide 문서가 수정되어 있습니다. (최근에 수정되었네요2017년 3월 현재.)

(4)   Docker 사용방법
A.     영재MVP님께서 말씀해 주신 것 처럼 Docker를 이용할 수도 있습니다. Docker VM보다 유리한 점들이 분명 있죠. 장단점이 있는 것 같습니다.

(5)   좀더 고급스럽게 사용하는 방법
A.     요즘 제가 열심히 실험하고 있는 방법입니다. 실무 시나리오 사용성 검증이 끝나면 블로그 하고 공유 드리도록 하겠습니다.
B.      HDInsight Spark Cluster 가 필요합니다.
                         i.         HDinsight Spark Cluster 가 기 세팅되어 있는 Instance 를 구동합니다.
                        ii.         추가로 Tensorflow Keras 를 설치합니다.
                       iii.         오픈소스인 elephas 를 설치합니다.
                       iv.         실험해보고 있는데요. 위 조합에서는 Tensorflow Spark 의 강점을 조합할 수 있고, 추가로, Tensorflow Model에 대하여 아래와 같은 것들이 가능합니다.


답이 잘 되었으면 좋겠네요. ^^