2016년 9월 2일 금요일

최신 IT 트랜드(Language on Data Platform 측면)의 "왕좌의 게임"

Data 를 다루는 언어들, 기술들이 최근 하루가 다르게 발전하고, 또 변화하고 있습니다. 특정 기술들은 이쪽 라인에 붙어 있다가, 저 쪽 라인에 붙는가 하면, 잘나가다가 어느새 훅 사라져버리기도 하죠. 주인공들이 픽픽 죽어나가는 것이, 마치 미드 "왕좌의 게임"을 보는 듯 합니다.

어느 한 기술을 고수하다 보면(국지전에 너무 매진하다 보면), 자칫 커다랗게 밀려오는 큰 흐름을 놓치고, 그 흐름을 따라가는데 힘이 겨워 질 수도 있을 것입니다.(곧 다가올 겨울에 대한 대비를 간과하게 될 지도 모릅니다.)

그런 측면에서, 얼마전 사내 BigData 기술 전파를 위한 공지 메일에서 경각심 부각 용으로 작성했던, "최신 IT 트랜드(Language on Data Platform 측면)의 왕좌의 게임 비유"를 블로그에 옮겨 보았습니다.


언어
주요 지원 프레임워크
왕좌의 게임
비고
Java
Spring,
Netty,
MapReduce


Korea 국민 언어 Java.
저도 빅데이타하면서 3~4년전에는 Java Spring Data 위에서 MapReduce 쓰다가 흰 머리가 많이 났었습니다.조금 더 그 좋지 않았던 경험이 반복되었다면, 신생 언어를 만들어 낼뻔 한 순간, 트위터 애들이 먼저 그짓을 마무리 해주었었죠. 잠시나마 cascading 위에서 clojure 랭귀지를 다루거나, Riak 언어를 기웃거리던 계기를 Java가 제공하기도 했었습니다.
그렇게 개발자들에게 무관심하던 Java 는 왕좌의 게임의 라니스터 가문입니다. 천하를 통일했던 옛 명성이 있지만, 요즘은 왠지 좀 불안불안 합니다. 최근 1.8 이 나오면서, 서세이가 다시 녹색 물폭탄을 터트리고, 존재감을 드러내긴 했습니다만… C# 처럼 상위 프레임워크 지향 Legacy 호환성이 있는 것이 아니므로, 여러 Enterprise 기업들은 1.8을 구경하기조차 쉽지 않습니다.
Scala
Play 2,
Spark
Zeppelin Notebook


Play2 가 살짝 다시 각광을 받고 있기도 하지만, Scala.js 가 여기저기 조금씩 보이기도 하지만, 그 무엇보다 Scala 의 성장은 Spark 의 성장과 땔래야 땔 수가 없습니다. Scala 는 비록 한때 아무런 존재감이 없었으나, Spark Dragon 급 존재감에 힘입어, 현재 막강 화력을 자랑하고 있습니다. Spark는 이미 BigData Eco 시스템의 춘추전국 국지전에서 Map/Reduce Cascading, Pig 등을 제치고, 국지전 승리를 거둔바 있습니다. Spark 의 요즘 기세는 하늘을 나는 용과도 흡사합니다.
R
SparkR,
RevolutionR(MS R Server)


R 은 사실 매우 똑똑합니다. 세상의 모든 알고리즘이 다 있는 것 같습니만, 그런데 너무 작습니다. Small Data 밖에 다루지 못하는 것이, 마치 티리온 라니스터 같습니다. 라니스터에서 독립되어 최근 Python에도 밀리는 형국이지만, Spark 가 손을 벌려 SparkR 병렬성을 지원하고 있고, 최근 MS Revolution R 을 인수하고 커뮤니티를 지원하면서, 다시금 조금씩 병렬 R의 시대가 열릴 것 만 같습니다. 여전히 피는 다르지만, 아직 Spark 진영에 붙어 있는 것도 안전해 보이네요.  시즌6에서 용(Spark)과 친근함을 보여주기도 했었죠.
Python
DJango, Flask, 기타 등등..
Jupyter Notebook


Java 의 라니스터 가문만큼이나 오래된, 그러나 항상 변방의 2인자였던, Python은 마치 스타크 가문 같습니다. 더구나, 2010년 전후로는 거의 맛이 갈 정도로 존재감이 하락했던 적이 있습니다. 느려 터지기도 했었구요. 이제 몇 명 남지도 않았어요. 하지만, 그래서 소수의 몇몇은 여전히 매우 Agile 하죠. 더구나 시즌 6 마지막에 북부 연합은 스타크를 위한 대동단결의 결의를 보여 주었습니다. 이는 마치 Python의 개발자 생태계를 보는 듯 합니다. 요즘은 개발자들이 직접 만들어 서로 공개, 공유 하고, 패키지를 주고 받는 pip 모듈 생태계가, 집단지성의 힘으로 재 조명되어, Java C# 의 공룡 프레임워크의 그것을 위협하고 있습니다.
Spring 이나 .NET Framework 같은 공룡 가문은 없지만, 수많은 100만 지방 호족의 힘을 합치면, 라니스터를 쉽게 위협하고도 남습니다.
TensoFlow (Deep Learning Framework By Google),
SyntaxNet On TensorFlow ( for NLU, NLP By Google)
Anaconda ( for Machine Learning & Deep Learning )

Google 이 만들어내는 TensorFlow , SyntaxNet 같은 프레임워크는 GPU도 지원되고, 병렬 분산 컴퓨팅도 지원하며, 엔진 코어가 C/C++ 이라 무지 빠르기 까지 합니다. 그리고, 개발자들은 Python 으로 코딩합니다. Google 이라는 한개 회사가 붙었을 뿐인데도.. 그 존재감은 “존 스노우” 급 입니다. 우리의 알파고도 Lua 언어의 Torch 에서 python TensorFlow 로 갈아 탄바 있습니다. Python 입장에서는 존 스노우 처럼 죽다 살아난 말도 안 되는 존재감의 우군입니다.
Python Anaconda 는 아직은 약하지만, 뒤에 큰 활약이 예감되는 브랜이나 아리아 스타크 같습니다. 아직은 혼자(병렬처리 안됨) 놀지만, GPU 를 달아주면, 그 퍼포먼스가 장난이 아닙니다.






2016년 7월 18일 월요일

Word2Vec Vector Algebra Comparison - Python(Gensim) VS Scala(Spark)

요즘 각종 내외부 Text 데이타들이, 새롭게 재 조명 되며, 다양한 형태로 분석 활용 되고 있다. 대표적인 예가 Text Classification , Sentiment Analysis ,  Opinion Mining 등 일것이다. (이 용어들 또한 많이 겹치는 의미들 이다.) 이러한 기법들을 이용하면, 고객센터나 이메일로 접수되는 내용들을 자동분류 하고, 실시간 Dash Board 화 하여, 문제가 되는 부분을 빠르게 파악 하고 대처할 수 있다. 또한, SNS나 게시판, 댓글등을 분석하여, 평판분석을 할 수 있고, 문제 상황을 좀더 빨리 인지하여 대응 할 수 있으며, 경쟁사의 평판과도 비교해 볼 수도 있다. 좀더 적극적으로는 Chat봇 이나 토픽 검색, 추천 고도화 등으로 확장되어 활용되는 사례도 많이 보이고 있다.

오늘 정리해본 내용은 그러한 Text 처리에 있어, 전처리 Word Embedding 기법 중 간단하면서도 뛰어난 효율을 보이는 Word2Vec 에 대한 내용이다. 

  1. Word2Vec 알고리즘에 대하여?
    1. 정의는 Learning4j 에서의 정의를 인용하였다.
      1. "데이터의 양이 충분하면 Word2vec은 단어의 의미를 꽤 정확하게 파악합니다. 그리고 이를 이용하면 단어의 뜻 뿐만 아니라 여러 단어의 관계를 알아냅니다. 예를 들어 단어의 관계를 이용해 ‘남자’:’소년’ = ‘여자’:x 같은 관계식을 주면 x=’소녀’라는 답을 구할 수 있습니다. 단어 뿐만 아니라 더 큰 단위의 텍스트인 문장이나 문서를 분류하는데에도 Word2vec을 사용합니다. 예를 들어 문서를 군집화한 뒤에 결과를 이용하면 검색 엔진에서 문서의 분야별 검색(과학, 법률, 경제 등)이나 문장의 감정 분석, 추천 시스템을 만들 수 있습니다."
    2. Word2Vec 은 텍스트를 처리하는 인공 신경망이며, 두 개의 층으로 구성되어 있다. 심층 신경망은 아니지만, 심층 신경망의 전처리 단계로 많이 쓰인다. 
      1. 인공 신경망 작동 방식은 크게 위 2가지로 나뉜다.
    3. Word2Vec 알고리즘에 대하여 좀더 자세한 내용을 알고싶어 하는 분들은 이 글을 참고하면 될것 같다.
      1. 자연어 기계학습의 혁명적 진화! (나프다에 기재된 글)
      2. http://www.moreagile.net/2014/11/word2vec.html 


오늘 내가 정리하는 내용은 Word2Vec 을 실제 구현하는 2가지 큰 방법( Python vs Scala )에 대하여 비교 분석한 내용이다.


  1. 구현방법 1
    1. Python 계열로 구현해 보기.
      1. Gensim 으로 구현하면, Word2Vec 구현하기가 너무 쉽다.
      2. 게다가 다음과 같은 장점이 있다.
        1. Python 계열은 우선 설치도 간단하다.
          1. Anaconda 를 설치하자. 이거 하나로 모든게 해결된다.
          2. https://docs.continuum.io/anaconda/install
        2. Word2Vec 에서 생각해볼 수 있는 거의 모든 내용이, 매우 쉽게 사용가능한, 잘 정리된 메소드로, 거의 다 만들어져 있다.
        3. 사용예, 셈플도 매우 많다.
        4. 한글의 경우 좀 쓸만한 형태소 분석기들은 죄다, R이나 Python 계열이다. 때문에, 자연어 처리에 있어, Python으로의 선택은 이런 모듈들과 궁합이 좋아, 우선 가장 안전한 접근 일 수 있다.
          1. 특히, Konlp 나  Konlpy 가 좋다.
        5. 요즘 Python 은 GPU 를 쓰기도 좋고, CPython  등으로 인하여 속도도 매우 빠르다.
      3. 물론 다음과 같은 단점도 있다.
        1. 초 대용량으로 가는 경우 답이 없다.
        2. 기본적으로 아직 까지는 Single  머신으로 돌리는 것이 Default 이다. 물론 병렬로 돌리기 위한 몇몇 마이너한 방법들이 있으나, 아직 까지 그 길은 최적화 되어 있지 못하다.
      4. 기본적인 코드들은 인터넷에 널려 있다.
        1. 참고로 너무 쉽고, 매우 짧다.
        2. 살짝 드려다 보자면...
      5. 학습을 위해 준비한 데이타.
        1. 나무위키 데이타, 위키피디아 데이타, 그리고 모사의 블로그 크롤링 데이타 등이 사용되었다.
        2. 데이타를 조사제거하고, 의미없이 너무 긴단어 제거하고, 몇몇 전처리를 해 줘야 하는데, 이 역시 Konlpy 등을 이용하면, 어렵지 않게 전처리 가능하다. (물론 Data가 매우 매우 클 때는 Python 으로는 매우 오래 걸리는 작업이긴 하지만..)
      6. 대표적인 Vector Algebra 인 King:Man = Queen:Woman 예제를 돌려 보자. 
        1. 참고로 이 예제는 한글에서는 잘 맞지 않다. 그 이유는 왕 이라는 단어가, 한글에서는 동음 이의어가 존재하기 때문이다. (왕서방, 왕짜장, 왕 좋다. 킹 왕짱 등등 때문에 그렇다.)
      7. 그래서 중국:북경 = 대한민국:서울 의 Algebra로 실험을 해 보았다.
        중국 - 북경 = X - 서울 요렇게 표기하는 것도 가능할것이다.답은 대한민국이 나와야 한다. X 를 구하기 위해 위 식을 아래처럼 다시 바꾸어 보았다.
        X = 중국 - 북경 + 서울
    2. Algebra 수식 부분 수행코드는 아래와 같다.
      1. 코드는 허무하게시리 간단하다.
      2. 위 결과에서처럼 대한민국과 한국이 1, 2등 이다. 놀랍지 아니한가??? 나는 처음 이 결과 봤을때 깜짝 놀랐었는데...
  2. 구현방법2
    1. Scala On Spark 로 구현해 보기.
      1. Spark 로 구현해 보자. Spark ML 안에 Word2Vec 이 있으니, 망설일 필요가 없다.
      2. Spark 는 Mesos Cluster 로 구동하였고, 모든 데이타는 Hadoop 내 공유 저장소에 존재한다.
      3. 하지만, 막상 구현을 해보니, 일단 학습하고, 저장하고, 로드하는 Spark 가 제공하는 Example 외에, 실무에서 활용할 만한 Sample 이 너무 너무 없다.게다가, 메뉴얼이 매우 빈약하다.
        1. 여튼 코드는 간단하다. Sample을 찾긴 힘들지만...
      4. Algebra 예제는 2시간을 Goggling 해도 제대로 수행된는 Code를 찾기가 힘들다. 몇몇 Code가 stackoverflow 사이트 등에 메뉴얼 Base, 답변 글 형태로 Code가 존재하긴 하는데 작동하지 않는다. (아래에서 좀더 상세 설명)
      5. API Document 를 보고 Algebra 구현을 시도해 보았다.
        1. 1차 시도
          1. 메뉴얼만 보면, 위처럼 하면 되야만 한다. 
          2. 하지만 위처럼 하면, model.getVectors() 쪽에서 인자가 없다고 에러가 난다. 분명 API Doc 에는 getVectors() 가 인자 없는 메소드 인데 말이다.
          3. () 를 하지 말고 그냥 가져오면 되긴 한다. 
            1. val w2v_map = model.getVectors   # 메뉴얼상의 getVectors() 메소드는 존재하진 않는다.
            2. 소스를 까보면 getVectors 가 Map[String, Array[Float]] 형태의 자료 구조이다. 즉, 뒤에서 다시 언급하겠지만, 그냥 Map 이라고 생각하고 getVectors(key:String) 으로 변수를 끄집어 낼수는 있지만, getVectors()(key:String)는 에러가 난다.
            3. 위에서 getVectors()를 getVectors 로 고치면 위 에러는 해결 되지만, 사칙연산이 안되는 새로운 에러가 발생한다. 이는 뒤에서 다시 언급...
        2. 2차 시도.
          1. 메뉴얼을 보면 이렇게 해도 되야 될거 같은데, 일단, 에러...
          2. Vectors 를 사칙연산 가능하게 breeze Vector로 형변환 해주면 되긴 한다. 맨 뒤에서 다시 언급...
        3. IDE 로 가 보았다. (개인적으로 서버에서 Scala 코딩은 zepplin 이나 sbt 로 바로 코딩 하고 확인 하는걸 선호 하는데... 이런 경우는 IDE에서의 확인이 필요하다.)
          1. 확인 결과 getVectors 는 메소드가 아니었다. 공식 API Document 에는 getter method 처럼 되어 있음에도 말이다...
        4. Github 의 소스 코드를 직접 확인해 보니 아래와 같다.
          1. getVectors 의 형이 요런식이다. 확실히 메소드가 아니다.TT
        5. 3차시도
          1. getVectors 자체에 args(N)을 인자로 주고, vector algebra 연산을 해보았다.
          2. 역시나.... algebra 연산에서 에러가 난다. Python 이 아니니까...
          3. linear Algebra 를 위한 breeze Vector 로 형변환을 하고 시도하였다. 성공!
            1. findSynonmys 안에 넣을때는 다시 dense 로 형변환이 필요하다. Python 이 얼마나 편한지... 비교 되는 부분이다. 
        6. Algebra 를 수행한 결과는 아래와 같다. Python 의 경우와 Data Set 이 살짝 달라서 결과도 약간 다르다.(시점 차이로..) 여튼 요런식으로 결과가 나온다.

최종 결론은 다음과 같다.


  1. Word2Vec 을 구현하기 위해
    1. Gensim + Python
      1. 구현을 하기 위한 가장 손쉽고 빠른 접근 방법이다.
      2. 왠만한 모든 가공 처리가 일사천리로 진행 가능하다..막히는 부분이 거의 없다.
      3. 데이타 전처리 부 또한 걸출한 Open 모듈들이 매우 많다.
      4. 단, 데이타 크기가 수십기가가 넘어가면, 단일머신에서는 고사양이 아닌 경우 급격히 느려 진다.
      5. GPU 를 사용하여 한번 더 성능을 점프 업 할 수 있으나, 이 역시 한계가 있다.
      6. 최고사양의 GPU 머신이라 할지라도 수백기가가 넘는 텍스트는 불가능 한 것으로 보여진다. (각종 변태 같은 다른 방법은 고려하지 않음.)
    2. Spark + Scala (or Python) : (실험에 사용한 환경은 Spark + Mesos + Hadoop)
      1. Spark 의 MLlib 를 이용하는 것이므로, Scala 가 아닌 Python 으로도 가능하다. 
      2. Python on Spark 인 경우 형태소 분리 등 전처리는 Python 의 모듈을 그대로 활용 할 수 있으며, Python 형태소 분리 등의 전처리를 Gensim 과 달리 병렬 처리 구현 하기 수훨해 진다.
      3. 단일 머신에서 돌릴때, Gensim 에 비하여 매우 느리다. 일단, Spark 는 분산처리를 위한 소잡는 칼이기 때문일 것으로 위안을 삼아 본다.
      4. gensim 고사양 1대 vs Spark 고사양 5대를 비교 했는데, 극한의 Spark 튜닝을 하기 전에는 기본 비교 시 gensim 이 좀 더 빨랐다.
      5. 하지만 여러가지 튜닝을 해주니, 중사양 Spark 20대가 고사양 Gensim 1대보다 5배 정도 빠른 결과를 내 주었다. (이 부분은 별도로 Posting 을 해보겠다. 속도를 끌어 올리는데 매우 많은 실험과 극한의 config 설정 튜닝이 필요하였다.)
      6. 무엇보다, Gensim 고성능 서버 1대에서 절대 돌지 않는 양 (수백 GB 이상)의 데이타가 Spark Dev 클러스터 중사양 20대에서는 그런데로의 속도로 도는 것이 가능하였다. ( 이 부분도 별도로 Posting 해 보도록 하겠다. 각종 Memory 관련 이슈가 등장하는데, 이 부분을 해결하는것 또 한 매우 많은 실험과 극한의 설정 튜닝이 필요하였다. 속도도 속도 지만, 대 용량을 Spark ML 로 돌릴때에는 Memory 의 제약으로 인하여 각종 Trick 이 필요한데. 이 부분의 작업은 매우 지난한 작업 이었다.)
      7. 수 ~ 수십 TB 단위의 데이타로의 실험을 해보진 않았는데, 돌지 않을지도 모른다는 생각이 든다, 실험결과 Spark Submit  수행시 주는 옵션인 Driver Memory가 학습할 Text 데이타의 크기에 비례하여 많이 필요하였기 때문이다.  
    3. 결론
      1. 작은 양의 데이타는 Gensim + Python Win!
      2. 중간 이상 크기의 데이타는 어쩔 수 없이 Spark!
      3. 그 이상 크기의 데이타는, 곧 훨씬 더 큰 데이타와 훨씬 고사양의 훨씬 많은 Spark 노드에서 다시 한번 테스트 해볼 예정이지만, 위 2-7의 가설이 맞다면, 어쩔 수 없이... deeplearning4j! (물론 deeplearning4j 도 내부에서 Spark를 이용하고는 있지만..)
      4. 어느정도 이상의 데이타는 도메인을 나누어 학습을 시켜도 될 듯 싶다.
        1. 어느정도 이상의 데이타는 표본이 전수를 대표하는 성격을 가질 것이기 때문이다. 굳이 이세상의 모든 데이타를 하나의 model 로 합쳐서 학습할 필요가 없다는 생각이 든다.
        2. 백과 사전 몇개를 학습하여, 일반어 간의 거리를 관리하는 모델을 하나 만들어 놓고, 이후부터는 특정 도메인 별로 데이타를 수집하여 별개로 학습해도 될 것 같다.
          1. 예를 들어, 네이버 요리 카테고리 블로그를 따로 쭉 학습해서 요리 단어에 대한 학습을 하고 나면, 요리 박사가 될 수 있다.
          2. 상품명을 가지고 크롤링 하여 쭉 학습을 하고 나면 또 상품 박사가 될 수 있다.
          3. 결국은 중간 Classification 분류 대표명이 중요하다. 중분류 대표명이 있다면, 세상의 모든 단어에 해당하는 백과사전 Model 과 특정 분야에 특화된 Domain 사전 간에 중분류 대표 단어를 매개로 거리 Mapping 을 통하여, 다양한 조합 쿼리가 가능하기 때문이다. (단, 방향성 연산은 이 시나리오가 통하지 않는다. 복수 모델을 조합할때는 similarity 연산만 유용하다.)
          4. 백과사전 Model 로 부터 다양한 형태의 자연어 대화 질문을 Classification 대표 질문으로 분류해주고, Classfication 대표 질문으로 부터 해당 Class 에 맞는 Domain 특화 model 에 질의 하여 정확한 전문 용어를 끄집어 내는 것이 가능 할 것이기 때문이다.


2016년 4월 25일 월요일

TensorFlow - TensorBoard 로 Tensor Graph 및 각종 정보 시각화 해보기

TensorFlow 는 명령형 인터페이스 이외에도, 웹상에서 상태를 볼 수 있는 TensorBoard 를 제공한다. TensorBoard를 이용하면, TensorFlow Graph 를 시각화 해 볼 수도 있고, Quantitative metrics 를 차트(plot) 형태로 볼 수도 있으며, understand, debug, optimize 등에 활용 가능하다.

아래는 TensorBoard 를 구동 및 활용하는 방법이다.


  1. TensorBoad 데몬 구동
    1. sudo tensorboard --logdir=/home/spiccato/tensorboard &
  2. OS 내부 방화벽 해제 
    1. iptables -F : 걍 귀찮으니까 다 끈다...
  3. 외부에서 접속해 보자.
    1. http://서버URL:6006
  4. 소스에서 로그를 남겨보자.
    1. TensorBoard 는 자동으로 모든 Training 이나 Test 를 시각화 해주진 않는다. 원하는 Log 를 Serialize ( TensorBoard 는 구글 답게 Protobuf 객체로 Serialize 한다. ) 하여 적절하게 객체에 담아 Disk 에 써 주면, 해당 Serialize Data 가 존재하는 위치를 LogDirectory 로 인지하여 데몬이 구동되어야, 시각화가 가능하다.
    2. 한가지 다행인 것은 디렉토리 관리가 가능하다는 점이다.
    3. 복수의 모델을 TensorBoard 로 관리하고자 할때, LogDirectory 안에 모델별로 디렉토리가 존재하고 해당 디렉토리를 내려가야 파일이 존재한다면, 해당 ParentDirectory 를 지정하는 경우 메뉴화 접근이 가능하다.
    4. 소스에서 로그를 남기는 부분에 대한 설명은 아래에 잘 명기 되어 있음.
      1. https://www.tensorflow.org/versions/r0.8/how_tos/summaries_and_tensorboard/index.html
      2. Log 의 Summary Write 메소드 수행시 경로 직정을 적절하게 잘 해주어야 함.
        1. train_writer = tf.train.SummaryWriter(FLAGS.summaries_dir + '/train', sess.graph)
        2. test_writer = tf.train.SummaryWriter(FLAGS.summaries_dir + '/test')
  5. 위에서 지정한 logdir 로 tensorboard 구동
    1. 아래 처럼 TensorFlow Graph 시각화 가능.
      1. CNN알고리즘 for MNIST
      2. Hidden Node 를 (+)클릭하여 Drill Down 상세화 해보기
      3. 아래는 x entropy mean 값 polt 그래프

2016년 4월 22일 금요일

TensorFlow - CNN 모델 for MNIST


TensorFlow를 이용한 Deep Neural Network 의 Hellow World 격인 MNIST....
(Hellow World 라고는 했지만, 쉬운 알고리즘과 어려운 알고리즘이 있는데, 오늘 다루는 알고리즘은 알파고에서도 쓰였을 정도로, 간단하지만은 않은 알고리즘이다. 그러나, TensorFlow가 많은것을 추상화 해 주어 이 마저도 매우 간단하다.)

MNIST 는 손필기체를 인식하여 숫자를 알아맞추는 일종의 이미지 Classification 문제이다. 여러가지 알고리즘이 존재하는데.... SoftMax , SVM  등도 가능하고... 오늘 수행해본 CNN(Convolutional Neural Networks) 도 가능하다.

아래는 설치시 기 제공하는 convolutional.py example 파일로 MNIST 를 학습 수행시키는 학습 과정이다.

SoftMax 알고리즘을 가지고 training 을 수행하고(training data set으로), test 를 돌리면(test data set으로) 정확도가 약 93% 정도가 나온다. (소스 코드는 20~30줄 정도밖에 안된다.)

그리고, oeverfit 을 피하기 위한 dropout, gradient vanishing 문제의 해결책으로 나온 ReLU, 그리고 max pooling 등 여러가지 트릭 알고리즘들을 추가로 수행 시켜 주면 성능이 99.2% 정도까지 바로 향상이 된다. ( 모두 tensorflow 안에 기 구현되어 있어 한두줄 메소드 실행으로 수행 가능한 기법 들이다. 이 기법들을 모두 적용해도 전체 소스라인이 60~70줄 정도이다.)

TensorBoard 로 코드를 시각화 해보면 아래와 같다. (정말 God! Google 이다.)
데몬을 띄우고 브라우저로 볼수 있으며, URL은 http://서버URL:6006 이다.
(TensorFlow - TensorBoard 로 Tensor Graph 및 각종 정보 시각화 해보기)

사실 아래 링크에서 MNIST알고리즘들의 정확도 랭킹을 확인 할 수 있다.
http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html
아래 랭크에서도 상당히 Top 레벨에 해당하는 매우 정확도 높은 결과임을 확인 할 수 있다.


아래는 CNN 모델 수행 및 Training 과정이다.

  1. 모듈 위치 확인 및 모듈 import
    1. 메뉴얼과 다르게 나의 머신의 tensorflow 라이브러리들 위치 경로는 아래와 같았다.
      1. /usr/lib/python2.7/site-packages/tensorflow
    2. 모듈 import
      1. python -c 'import os; import inspect; import tensorflow; print(os.path.dirname(inspect.getfile(tensorflow)))'
  2. CNN 모델 수행
    1. 모델 수행
      1. CNN 수행
    2. 최종 학습 결과
      1. 최종 학습 결과
      2. 러닝이 진행되면서 error 율이 점점 줄어 들었음.

2016년 4월 15일 금요일

TensorFlow - CentOS 6.X 구버전에 설치기

TensorFlow는 CentOS 7 최신 버전에서는 그나마 쉽게 설치가 된다. 하지만, CentOS 6 후반 버전에서는 Dependency 모듈 버전 업 해줄게 많아 설치가 좀 귀찮은 작업들이 수반된다.TT

그래서, 누군가가 CentOS 6.X 에 TensorFlow를 설치한다고 한다면, 만약 테스트 목적이라면, Docker 를 쓰거나 Python 의 Virtualenv를 쓰라고 권장하고 싶다. 그렇지 않고, 실제 머신에 Fully 깔고자 한다면, CentOS 6.X 는 과감하게 포맷하고 OS 부터 버전업 하라고 권하고 싶다.

여튼 메모해놓은 내용을 정리해 보았다.
  1. Python 환경 정비
    1. 기본 설치 버전 확인
      1. python -V 로 버전 확인. TensorFlow는 2.7 이나 3.3이상의 Python 이 필요함.
      2. 버전이 낮은 경우 설치.(아래는 2.7 기준)
        1. sudo yum install gcc
        2. 소스로 깔자!. 2.X 의 최신버전은 2.7.11이넹.
        3. wget https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tgz
        4. tar xvzf Python-2.7.11.tgz
        5. cd Python-2.7.11
        6. ./configure
        7. 구버전 Overwrite 방지하면서...
          1. sudo make altinstall
        8. 잘 설치 되었나 확인
          1. python2.7 -V
          2. python -V
            1. 아직 python 컴멘드는 옛날 버전으로 연결 됨.
      3. python 구 버전 dependancy 완전 없애고 Gracefully 하게 update 하기.(CentOS 7.1 기준)
        1. yum groupinstall -y "Development tools"
        2. yum install -y zlib-devel
        3. yum install -y openssl-devel
        4. yum install -y ncurses-devel
        5. yum install -y sqlite-devel
        6. Which python 
          1. /usr/bin/python
        7. 아래 명령 수행
          1. ln -s /usr/local/bin/python2.7/usr/local/bin/python
        8. 다시 which python
          1. /usr/local/bin/python
        9. 나갔다 들어와서 python 이라고 날려보면 정상적으로 반영된걸 볼 수 있음.
          1. python 버전 변경 완료
    2. Pip Upgrade
      1. pip 또한 구 버전이 설치 되어 있음.
      2. pip 버전 확인 
        1. pip --version
          1. 구버전 2.6 이라고 나옴.
      3. 신 버전 설치
        1. wget https://bootstrap.pypa.io/get-pip.py
        2. python get-pip.py
        3. ls -al /usr/local/bin/pip* 를 해보면 새로 설치 된 2.7 버전 확인 가능.
        4. 역시 나갔다 들어오거나 bash 갱신 해주면, 정상적으로 pip --version 확인 시 2.7로 바뀐 것을 확인 할 수 있게 됨.
          1. pip 버전 변경 완료
  2. TensorFlow Install
    1. CPU Only
      1. pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.7.1-cp27-none-linux_x86_64.whl
    2. GPU enabled
      1. pip install --upgrade https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.7.1-cp27-none-linux_x86_64.whl
      2. Cuda 인스톨
        1. 링크로 대신.
        2. https://www.tensorflow.org/versions/r0.7/get_started/os_setup.html#optional-install-cuda-gpus-on-linux
      3. ~/.bash_profile 안에 cuda 아래 환경 변수 추가
        1. LD_LIBRARY_PATH
          1. /usr/local/cuda 추가
        2. CUDA_HOME
          1. /usr/local/cuda 추가
  3. TensorFlow 수행
    1. TensorFlow 로딩 해보기
      1. 우선 라이브러리 import
      2. 위와 같은 에러 남.
      3. GLIBC_2.14 설치 하자!
        1. wget http://mirror.bjtu.edu.cn/gnu/libc/glibc-2.14.tar.xz
        2. tar xvf glibc-2.14.tar.xz
        3. cd glibc-2.14
        4. mkdir build
        5. cd build
        6. ../configure --prefix=/opt/glibc-2.14
        7. make -j4
        8. make install
        9. cd ~
        10. vi .bash_profile
        11. export LD_LIBRARY_PATH=/opt/glibc-2.14/lib:$LD_LIBRARY_PATH
        12. source .bash_profile
      4. 초기 에러는 해결 되었으나, 뒤이어 아래 에러 발생
        1. 이번에는 GLIBCXX_3.4.14 모듈 필요.
        2. rpmfind 에서 libstdc 모듈 설치
      5. 기타, CentOS6.X 버전에따라 좀더 추가 모듈 Dependency 가 날 수 있으나, 일단, CentOS6.X 후반 버전에서는 위 정도로 설치 완료...
    2. Hello, TensorFlow!

2016년 2월 24일 수요일

Spark Job On Mesos - Log Handling

Spark 스탠드얼론 모드에서는 Conf 디렉토리 안의 log4j.properties 정보를 수정하면, 로그 핸들링을 개별 프로그램안에서 해주지 않아도, Log 핸들링이 가능하다.

문제는 Spark Job 을 Mesos 위에서 구동할 때 인데..

Spark 의 log4j 옵션과 Mesos 의 Log 관련 옵션을 모두 수정해 주어도, Log 핸들링이 잘 안된다. ( 아직 내가 찾지 못한 다른 이유가 있을 지도 모른다.)

여하튼, 혹시나 하고, Programmatic 하게  소스에서 로그 레벨 수정을 해보았더니...
역시 된다.

사실, 일반적인 Java 프로그램이었다면, 되는게 당연한 거지만, Scala Job 이 Spark 엔진 위에서 구동되는데, 그게 또다시 Mesos 로 추상화 된 리소스 관리하에 구동되는 상황에서 이옵션이 먹다니.....

역시, Conf 보다 Source 가 앞서는 일반적인 Spark 옵션들과 마찬가지로, Log 또한 Source 에서 잡아 주니 모든 중간 Tier 와 무관하게 전면 적용이 되었다.
(부연하자면, Spark-submit 의 옵션이나 Conf 파일보다.. Source 상의 new SparkConf().set() 옵션이 최 우선 적용되는 다른 옵션과 같은 맥락이다는 뜻이다.)

여하튼....Spark Job 을 Mesos 위에서 구동시 Log  해들링 하는 방법은 그냥 Java 에서 하듯이 아래처럼 하면 된다.

[1] import


[2] set



저렇게 하면... 네임스페이스에 따라 완전 깨끗하게 지울수도 있고....
위처럼 org.apache.spark 까지 주면, spark 관련된 로그만 깨끗하게 지울수가 있음.






2016년 1월 5일 화요일

SparkR 설치 사용기 1 - Installation Guide On Yarn Cluster & Mesos Cluster & Stand Alone Cluster

SparkR은 설치 및 사용기, 기타 내부 작동방식 등에 대한 자료가 너무 부족한거 같다. 내부 작동 방식에 대하여 너무 궁금했었는데, 여러가지 Mode 로 설치해보고 다양한 삽집을 거친 후, 조금씩 돌아가는 코드들을 만들어 돌려 보고 나서야, 조금씩 내부 구조가 감이 잡히기 시작했다.

사용을 해보기 전 가졌던 의문들은 다음과 같다. 의문에 대한 답은 정답이 아닐지도 모른다. 아직 코드 레벨에서 SparkR Core Code 까지는 까보고 확인해 보진 않았기 때문이다. 하지만, 실제 돌아가는 코드들을 하나 둘 만들어 수행해가며 실험을 해보니, 아래와 같은 유추가 가능하였다.

  1. Spark 는 Yarn 이나 Mesos 위에서 구동시 Spark 엔진을 모든 노드에 깔아줄 필요가 없다. R도 그럴가?
    1. SparkR은 R없이 동작되지 않는다. Local R과 Spark 엔진 사이에는 Layer 가 잘 나누어져 있는듯 하다. SparkR 모듈에서 R의 모든것을 처리하는 것이 아니라 인터페이스도 한다는 의미이다. 즉, bin 디렉토리에서 sparkR 을 수행하면, 로컬의 R이 반드시 있어야 그 위에서 무언가가 sparkR로서 완벽한 구동이 가능하다.
  2. R에서 사용하는 외부 Package 들은 모든 노드에 직접 설치 수행해 주어야 하나?
    1. 실험해 보니... 그렇다. 모든 노드에 설치해주지 않으면, 해당 모듈이 설치되지 않는 노드에서 계산 시 해당 노드에서만 에러가 난다.
    2. 외부 Package 설치는 일반적인 R의 그것과 동일하였다. SparkR 이 아닌 그냥 R 콘솔에서 install.package("패키지명") 하여 설치하면, SparkR 에서도 잘 인식 한다.
  3. 경로 참조는 어떤식으로 이루어 지나?
    1. 여러가지 메소드를 사용해보았는데, 동작 방식이 다소 차이가 있었다.
    2. 어떤 메소드는 해당 노드의 로컬경로를 찾는 것이 있다. (주로 R 고유 메소드 들..)
    3. 그리고, 어떤 메소드는 Hadoop 에서 해당 경로를 찾는 것도 있었다. (옵션 인자 를 확인해보진 않았지만, default 옵션이 그렇게 동작하는 것들이 있었다.)
    4. SparkR 이 제공하는 특화 메소드들은 몇몇 Hadoop 이 default 인것들이 보인다.
  4. 전통적인 R 스타일의 코드는 동작하지 않나? 예를 들어 R이 제공하는 data.frame 을 모두 SparkR 이 제공하는 dataframe(RDD Base) 로 일부 코드레벨로 치환해주어야만 동작하나?
    1. 답은 아니다 이다.
    2. 전통적인 R 스타일 코드도 동작하고, SparkR 스타일로 치환한 스타일 코드 또한 당연히 잘 동작한다.
    3. 단, 전자는 병렬처리가 안되는 것을 확인하였다. 후자는 병렬 처리가 이루어 진다.
  5. Production Level 의 실용적인 R코드를 SparkR 로 치환하는 대 진입장벽은 어느정도 인가?
    1. 계산 로직을 처음부터 만드는 경우이거나, Primitive 한 계산 로직 혹은 데이타 가공 처리 위주의 Legacy R 코드는 SparkR 스타일로 치환하기가 크게 어렵진 않다. 
    2. 단, data.frame 이나 data.read 부분의 메소드 들을 SparkR  스타일로 변경해주는 약간의 작업이 필요하다. 해당 코드들은 그러나 대부분 Legacy 코드의 5% 미만인 경우가 대부분일 것이다.
    3. 외부 Package 를 그대로 사용하는 경우는 약간 제약이 따른다. 일부 그래프 패키지 등은 SparkR 스타일로 계산을 끝내고, 자료구조에 최종 결과 Dataframe 만을 남긴 이후, 해당 data 를 R스타일 자료로 옮기고 그대로 사용가능하다. (sparkR 의 dataframe 을 input 으로 받아주지 못하는 Package 가 대부분이므로...) 초기 계산 data가 매우 크다 할지라도, 계산이 끝난 데이타는 양이 작아질 수 있으므로, 이 시나리오는 그런데로 available 할 수 있다.
    4. 하지만, 외부 Package 로 마이닝 로직을 거대 Input 데이타에 데고 수행해야 하는 경우, SparkR 의 DataFrame 은 병렬성을 지원하지만, 해당 패키지가 해당 자료구조를 Input 으로 받지 못하여 Package 사용에 제약이 따른다. 이경우 현재까지는 아래와 같은 우회 해결책 외에는 해결 방법이 없어 보인다.
      1. 우선은 Spark ML  등에서 제공하는 다른 유사 알고리즘. 혹은 Mahout 등이 제공하는 외부 모듈을 사용하여 해당 연산 Job 을 분리 수행 시키는 방법이 있을 것이다. (널리 알려진 알고리즘들은 대부분 이 방법으로 수행이 가능할 것이다.)
      2. 하지만, R 에서만 존재하는 알고리즘을 꼭 써야 하는 경우는.... 어쩔 수 없이, 패키지를 그대로 사용하지 못하고, 해당 패키지의 Primitive 한 소스 코드를 열어서 자료구조를 SparkR 스타일로 치환해주는 작업이 필요하다. (패키지의 소스 난이도에 따라 available 한 방법이 아닐 수도 있다.)

아래는 우선 각 Compute Node 에 R 설치하는 과정이다.
우선 CentOS6 장비들과 CentOS7 장비들의 설치 과정이 다소 차이가 있었다.

  1. centos 6 에서 Install
    1. wget http://mirror.us.leaseweb.net/epel/6/x86_64/epel-release-6-8.noarch.rpm
    2. wget https://www.fedoraproject.org/static/0608B895.txt
    3. sudo mv 0608B895.txt /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 <-폴더생성됨
    4. sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
    5. rpm -qa gpg*
    6. sudo rpm -ivh epel-release-6-8.noarch.rpm
    7. sudo yum install -y npm 
    8. sudo yum install -y R
  2. centos 7 에서 Install
    1. epel-release & npm 최신 버전 설치
      1. wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
      2. sudo rpm -ivh epel-release-latest-7.noarch.rpm
      3. sudo yum install -y npm
    2. 이후 R설치 시도
      1. 이 경우 몇가지 Dependency 에러가 나는 경우가 있음. 각각을 rpm 찾아서 수동 설치
      2. wget ftp://ftp.muug.mb.ca/mirror/centos/7.1.1503/os/x86_64/Packages/blas-devel-3.4.2-4.el7.x86_64.rpm
        1. sudo yum install -y blas (버전이 devel 과 일치해야 함. 일치안할때는 rpm찾아서 깔아주면 됨.)
        2. sudo yum install -y gcc-gfortran
        3. sudo rpm -ivh blas-devel-3.4.2-4.el7.x86_64.rpm
      3. wget ftp://mirror.switch.ch/pool/4/mirror/centos/7.1.1503/os/x86_64/Packages/lapack-devel-3.4.2-4.el7.x86_64.rpm
        1. sudo yum install -y lapack (버전이 devel 과 일치해야 함. 일치안할때는 rpm찾아서 깔아주면 됨.)
        2. sudo rpm -ivh lapack-devel-3.4.2-4.el7.x86_64.rpm
      4. http://rpm.pbone.net/index.php3/stat/4/idpl/26647268/dir/centos_7/com/texinfo-tex-5.1-4.el7.x86_64.rpm.html 요기에서 texinfo-tex 모듈 다운로드 하여 인스톨
        1. sudo yum install -y tex
        2. sudo yum install -y texinfo
        3. http://rpm.pbone.net/index.php3/stat/4/idpl/29077368/dir/centos_7/com/texlive-epsf-svn21461.2.7.4-32.el7.noarch.rpm.html 요기에서 tex(epsf) 모듈 다운로드 하여 인스톨
          1. sudo rpm -ivh texlive-epsf-svn21461.2.7.4-32.el7.noarch.rpm
        4. sudo rpm -ivh texinfo-tex-5.1-4.el7.x86_64.rpm
    3. Dependency 모듈 모두 설치 후 R설치 재 시도
      1. sudo yum install -y R

앞서 질문과 자답에서 언급한 것 처럼 SparkR 병렬 구동에 앞서 위와 같이 R 을 모든 Compute Node 에 설치 해주어야 한다.

그리고 나면, 아래처럼 Spark Submit 으로 R 코드를 수행 할 수 있다.

  1. SparkR 실행 On Yarn
  2. SparkR 실행 On Mesos
  3. SparkR 실행 On StandAlone
  4. 병렬 수행 후 결과 Output
    1. Legacy R 스타일 Code 수행
      1. 내부 Cat 한 로그 위주로 출력.
    2. Spark R 스타일 Code 수행
      1. 병렬 수행을 위한 Shuffle 로그도 함께 출력.
  5. R 콘솔
  6. SparkR 콘솔