안녕하세요.

TensorFlow docker image 를 윈도우즈에 설치하기

지난 포스트에서  docker의 마법을 활용해 (심지어 윈도우즈에다TensorFlow를 한 방에 설치해서 바로 활용하는 법을 정리한 바 있습니다.

이번에는 생성한 컨테이너를 다시 실행하거나 업데이트 하는 방법을 소개하고자 합니다. 이번 내용은 다음 도커 가이드에서 발췌하여 적용한 사례에 관한 부분입니다.


Docker 기본 사용법


앞서 docker에 대한 개념은 이해할 필요가 있는데 상위 링크에 자세한 설명이 있으니 참고하시기 바랍니다.


1. 컨테이너 시작


가상 머신을 수행하는 기기가 종료되면 (당연히) 여기서 (몰래) 돌고 있던 jupyter with TensorFlow server 역시 종료되게 됩니다. 따라서 Docker Quickstart Terminal를 다시 수행해야 합니다.


이때 설치된 컨테이너를 확인하기 위해 다음 명령을 수행합니다.


$ docker ps -a


상기 명령의 결과로 출력된 컨테이너 리스트 중에서 STATUS 항목으로 현재 수행 여부를 NAMES 에서 지정된 이름을 알 수 있습니다. 컨테이너가 수행 중이지 않다면 아래 명령과 더불어 NAMES 에 지정된 이름으로 해당 컨테이너를 실행시킬 수 있습니다.


$ docker start {컨테이너 이름}


 

2. 컨테이너 업데이트 하기


기본 사용법에 따르면 docker attach {컨테이터 이름} 을 통해 컨테이너에 접속할 수 있으나 활용 중인 TensorFlow container는 접속 시 console 없이 jupyter log 메시지만 출력하고 있는 관계로 아무런 명령을 수행할 수 없습니다. 따라서, 다음과 같이 외부에서 컨테이너에 명령을 수행할 수 있는 인터페이스를 활용하고자합니다.


docker exec {컨테이너 이름} {명령어 ... }


명령어는 bash shell에서 동작하는 대부분이 전달되는 것으로 보입니다. 

확인 차원에서 jupyter 의 확장 기능인 IPython Clusters 를 설치해 보았습니다.

자세한 설치 방법은 ipyparallel github guide를 참조했습니다.


$ docker ps

CONTAINER ID        IMAGE                            COMMAND             CREATED
             STATUS              PORTS                              NAMES
8eb60a8f3211        b.gcr.io/tensorflow/tensorflow   "/run_jupyter.sh"   5 weeks
 ago         Up 29 minutes       6006/tcp, 0.0.0.0:8888->8888/tcp   focused_yonath
$ docker exec focused_yonath pip ipyparallel


이와 같은 방식으로 컨테이너 외부에서도 추가 모듈을 설치하거나 업데이트할 수 있습니다.

안녕하세요. "생각의 웹"입니다.


요즘 핫 이슈인 TensorFlow의 백서(white paper)를 기반으로 속살(source code)을 파헤쳐 보고 정리한 자료를 다음과 같이 공유합니다.

잘못된 분석이 있다면 댓글로 남겨주시면 감사드리겠습니다.





아래는 각 슬라이드 별 내용을 간략히 설명한 것입니다. 참고하시기 바랍니다.


TensorFlow의 주요 특징 


  1. Dataflow 형태의 모델을 기반으로 손쉽게 딥러닝 프로그래밍할 수 있도록 제공 
  2. 모델을 다양한 디바이스(CPU, GPU, 원격)에서 효율적으로 분산 처리
전자를 통해 분석할 데이터를 효과적으로 처리(Extract, Transform, Load - ETL)하고 다양한 학습 모델을 활용할 수 있으며 추후 손쉽게 도식화할 수 있도록 초상위 프로그래밍 언어(VHLL)인 python API를 제공하고, 학습된 모델을 안드로이드와 같은 embedded system 에서 수행할 수 있는 C++ API를 제공합니다. 
후자의 경우는 계산 비용(computation cost)이 많이 드는 학습(training) 과정을 가용한 리소스를 효과적으로 활용하여 빠르게 분산처리할수 있습니다. 

TensorFlow의 기본 개념 


 Tensor, Operation, Attribute, Kernel, Device, Variable, Session, Client, Server 등이 있는데 간략히 요약하면 다음과 같습니다.
  • Tensor: 원래 의미는 2차원 이상의 배열이지만 여기에서는 임의의 차원을 가진 배열을 뜻합니다. TensorFlow는 방향성이 있는 그래프 구조로써 모델을 구성하는데 이때 이 그래프는 0개 이상의 입출력을 갖는 노드들의 연결체이며 노드는 operation의 instance 라고 할 수 있습니다.   
  • Operation: 임의의 계산을 수행하는 것으로 다양한 속성 값(attribute)을 가질 수 있습니다.
  • Kernel: 커널은 operation을 디바이스 별로 실제 구현한 것으로 가속화를 위해 다양한 분산 최적화 알고리즘을 활용하고 있습니다. 실제 코드 상에서는 처리되는 곳이 CPU인지, GPU 인지에 따라 다른 구현을 활용하도록 되어 있습니다.
  • Variable: 변수란 학습을 통해 변화하는 배열 값을 저장하기 위한 operation입니다. TensorFlow가 학습할 때 다양한 디바이스에 분산하여 처리하는 구조를 띄기 때문에 명시적으로 type을 지정해 줍니다. 
  • Session: TensorFlow 그래프를 구성한 후 실제 수행을 할 때 다양한 실행 환경(CPU, CPU/GPU, 원격 분산처리) 하에서 처리하기 위해서 Client 에서 session을 만들어 전달하는 개념입니다. 

Sample TensorFlow Code and Graph 



상단 좌측의 예제의 코드처럼 Python으로 구현하면 해당 코드가 상단 우측과 같은 그래프 형태의 구조로 구성되게 됩니다. 그리고 Session을 이용해 하나의 디바이스 혹은 여러 개의 디바이스로 수행됩니다.


Previous Work 



TensorFlow는 google의 대용량 분산 ML 서비스 (구글 이미지 등)에 활용된 바 있는 DistBrief의 개발 경험을 바탕으로 핵심 기술인 Downpour SDG (Stochastic Gradient Descent) 와 Sandbluster L-BFGS 알고리즘을 활용하고 MS 연구소의 Project Adam과 Parameter Server Project를 참고하였습니다.


Feature Comparison 



백서에 따르면 표와 같이 TensorFlow 와 유사 플랫폼의 기능을 비교해 두었으나 시간에 따라 다른 플랫폼들 역시 기능을 추가하고 있는 관계로 최신 비교는 wikipedia를 참고하기 바랍니다.


Execution Mode 



앞서 언급한 바와 같이 TensorFlow의 특장점은 다양한 디바이스에서 수행된다는 점입니다. Single Device (CPU only), Multiple Devices (CPU & GPU), 분산 환경(distributed)에서 자원을 효과적으로 활용하여 수행할 수 있습니다. 이를 위해 operation을 어느 디바이스에 할당할 것인가에 대한 전략부터 디바이스 간 오류 없는 커뮤니케이션을 제공하기 위핸 기능들이 활용되고 있습니다. 특히 분산환경에서는 Multiple Devices의 고려 사항 외에도 오류 발생 시 대응하기 위해 메시지가 손상되었을 때의 복구, worker process의 상태 점검 기능들을 추가 고려하였습니다.



Programming Idioms 



내부적으로 최적의 수행 방안을 찾기 위한 기능들이 구현되어 있지만 사용자가 딥러닝 알고리즘의 특성에 따라 적절한 형태로 분산처리 되도록 코드를 구현할 것을 제안합니다.  예를 들어 학습 모델에 따라 데이터나 모델을 적절히 쪼개 병렬 처리하거나 비동기 함수를 이용해 동시성 처리할 수 있도록 하면 좋습니다.


Source Code Metrics 



github에 공개된 v0.8를 기준으로 코드 사이즈는 약 114 MB 수준이며 대부분 C++과 python으로 구현되어 있습니다. cloc 도구로 분석하면 이외에도 다양한 개발 언어 (bash, HTML, javascript, typescript, object C 등등) 이 등장하는데 process/언어 간 data communication (IPC, RPC)으로 활용하고 있는 Protocol Buffer에 속한 코드입니다.


How It Works 


핵심 코드인 C++과 python은 SWIG 인터페이스를 통해 상호 호출할 수 있도록 구현되어 있습니다. SWIG wrapper은 *.i 파일에 인터페이스 연결 고리를 명시해 두면 compile time에 관련 코드를 생성해 연결합니다. C++과 python 간의 형(type) 과 C++ 인터페이스를 연결하기 위한 코드도 볼 수 있습니다. 추후 설명하겠지만 모델을 통해 학습하는 선언 부(declaration)는 python에서, 실제 수행하는 부분은 C++ 에서 처리하고 있습니다. 


C++ Code Structure   



먼저 기반 프레임워크와 알고리즘이 실제 수행되는 코드를 담고 있는 core 부분은 대부분 C++로 구현되어 있습니다.


C++ Framework 



TensorFlow의 데이터 구조의 기반이 되는 클래스들과 dynamic allocation이 필요한 구성요소에 대해  smart pointer 를 활용한 Reference Counter 를 상속 받아 활용합니다. C++ 코드의 대부분을 차지하는 kernel 코드의 기반 클래스 역시 여기에 구현되어 있습니다. 가장 기본이 되는 Tensor 클래스에서는 배열 연산의 편의를 위한 다양한 메소드가 구현되어 있음을 볼 수 있습니다.


C++ Kernels 


   

이 폴더에는 알고리즘을 CPU/GPU를 통해 고속처리하기 위한 다양한 구현체가 존재하며 CUDA를 활용한 알고리즘은 별도의 {알고리즘 명}_op.cc 파일에 구현하고 있습니다. 고속 알고리즘을 구현하는 개발자들을 위해 이 영역에서만 따로 빌드하고 테스트할 수 있도록 구성되어 있습니다. 자세한 내용은 How To에서 확인할 수 있습니다.


Python Code Structure 



/python 폴더 아래 대부분의 *.py 파일들이 존재하며 operation이 있는 ops/ 와 training/ 에 가장 많은 코드가 존재합니다. 일부 SWIG 을 통해 C++ 간의 연결을 위한 C++ 코드들도 보입니다.


Python Implementation 



Operation에는 tensor 연산을 빠르게 수행할 수 있는 다양한 함수를 제공하고 있으며 Trainings 에는 알려진 다양한 ML 알고리즘과 분산처리를 위한 코드들이 존재합니다. 


Code Summary 



요약하면 python code에는 operation과 training 관련 코드들이 대부분이고 그래프를 만들어 훈련하기 위한 손쉬운 python API들이 제공됩니다.

반면 C++ code에는 기초 프레임워크 코드와 디바이스에서 고속 배열 연산이 가능하도록 구현된 코드들이 있습니다. 또한 임베디드 환경에서 테스트를 수행할 수 있도록 간단한 C++ API를 제공합니다.


 

  1. Archtectist 2017.02.18 16:46 신고

    좋은 글 감사합니다. 자료 모으고 있어서 퍼갑니다. 저작권에 문제되면 연락주시면 삭제하겠습니다.

  2. Kim Jin Hwan 2019.03.19 12:37 신고

    깔끔하게 정리해 주셔서 공부에 많은 도움이 됐습니다!!
    감사합니다.

[그림1] 취학 아동 사례



안녕하세요. "생각의웹"입니다.


 근 몇 년간 핫 이슈였던 빅데이터에 대해 환상이 사그라지는 분위기지만 데이터 기반 접근법(data approach)는 모든 분야에 있어 원칙으로 자리잡고 있습니다. 2015년 가트너의 경우, 매년 발표하는 Hype Cycle for Emerging Tech. 에서 빅 데이터를 제외했는데 그 이유로 더이상 빅 데이터가 특정 기술이 아닌 모든 산업의 기반 기술로써 편재하게 되었기 때문이라고 언급한 바 있습니다.


[그림 2] Gatner Hype Cycle 2015 - 더이상 Big data를 찾아 볼 수 없다


 빅데이터와 더불어 미래를 이끌 것으로 예견되는 기술들 역시 막연한 환상에서 벗어나 가치에 대해 재조명되어가는 형국입니다. 그림2는 사물인터넷(IoT)와 기계학습(ML) 그리고 웨어러블 등이 죽음의 골짜기(death valley)를 향하고 있음을 보여주는데 이 모든 기술들이 근 몇 년동안 세상을 바꿀 신기술들로 빠르게 성장(hype)했음을 주목할 필요가 있습니다.


앞서 언급한 빅데이터, 사물인터넷, 기계학습, 웨어러블 기술은 상호 밀접한 관계를 가지고 있습니다. 예를 들어, 웨어러블 기기가 생체신호 및 위치 정보를 다수의 사람들에게서 수집하여 빅데이터 화하고 기계학습을 이용해 데이터마이닝(data mining)한 후 찾은 인사이트를 기반으로 가설(hypothesis)을 만들고 실험(experiments)을 통해 증명하게 됩니다. 이때, 사물인터넷을 이용해 다양한 기기들과 상호작용하여 실험 결과를 도출하는 과정이라고 할 수 있겠습니다. 이 모든 과정의 본질은 데이터에서 가치를 추출하는 과정 즉, 데이터 분석입니다. 이번 포스팅에서는 간략하게 등하교 알림 데이터로 실 사례로 이 과정을 예시해 보도록 하겠습니다. 



[그림3] SMS 메시지와 SMS dump 도구 (SMS to Text)



0. 준비물

  • 아이의 등하교 알림 메세지 (by JT통신 i알리미 서비스)
  • SMS to Text (from google Play 스토어)
  • MS Excel 


1. 배경


올 해 아이가 초등학교에 입학하게 되어 명실상부 학부모가 되었습니다. 대부분 초등학교는 집에서 멀지 않은 곳으로 배정받게 되는데 제가 살고 있는 곳에서 초등학교 가는 길이 걸어서 통학하기에는 위험요소가 많습니다. 따라서, 학원 차량 편을 통해 통학하고 있는데 혹시 차량 이동 간에 있을 수 있는 사고에 신경이 쓰입니다. 

이런 이유에서인지 해당 학교에서는 비콘 기반의 등하교 확인 서비스를 시작했는데 그림 3과 같이 아이의 등하교 시 등록된 부모의 연락처에 SMS를 보내주는 서비스입니다.


2. 전처리


SMS를 가공하기 위해서 SMS log를 텍스트 파일로 저장해주는 도구를 다운로드 받습니다. (그림 3은 SMS to Text 라는 도구를 보여줍니다.) 이 도구를 통해 관련된 메시지를 csv파일로 저장하고 이 파일을 컴퓨터로 가져옵니다.

csv파일을 엑셀로 열면 한글이 깨져 보입니다. 따라서 텍스트 에디터로 열어 한글을 제거하고 중복되는 문구를 의미에 맞도록 바꿉니다.



Date,Time,Type,Number,Name,Who,Date2,At,Where,Count
2016-04-27,13:21:27,in,16444265,16444265,joyan,4/27,13:21,front gate,-1
2016-04-28,08:44:54,in,16444265,16444265,joyan,4/28,08:44,front gate,1
2016-04-28,13:56:45,in,16444265,16444265,joyan,4/28,13:56,front gate,-1

 


[그림4] 전처리 후 데이터 


그림4는 메세지 내용을 정리해서 누가 언제 어디로 출입했는지로 정리했음을 보여줍니다.


3. Tidy data table로 변경 


전처리를 완료된 데이터셋을 excel로 불러들인 후, 분석에 불필요한 정보를 제거 합니다. 앞서 그림4에서 Type, Number, Name은 모두 동일한 값들이라 제거합니다.

또한 등교를 학교에 학생이 증가한다는 의미로 +1를, 하교를 -1로 바꾸어 Count 항목으로 명시합니다. 


4. Feature engineering


Feature engineering이란 기계학습 알고리즘에 활용하기 위한 features를 생성하는 것으로 이때 domain knowledge를 활용[Wikipedia]합니다. 여기에서 추가 설계한 feature는 다음과 같습니다.


  • 요일: 해당 날짜의 요일을 1~7로 표현. (일: 1, 월: 2, 화: 3, 수: 4, 목: 5, 금: 6, 토: 7)
  • 출입시간과 SMS 수신 시간의 차: SMS는 지연이나 누락될 수 있는 서비스라서 지연 시간을 계산

[그림5] Feature Engineering 결과


5. 탐색적 데이터 분석 (Exploratory Data Analysis, EDA)


데이터의 일부를 발췌하여 보거나 통계적 특성을 살피면서 데이터의 특성을 파악하는 작업입니다. 시각화(visualization)을 활용해서 시각적 특성을 찾으면 좋은 인사이트를 발굴할 수 있습니다. 먼저, 통계적 특성을 확인하기 위해 사용하는 시각화 기법으로 상자수염그림(boxplot), 산점도(scatterplot)이 있어서 이것을 그려보기로 했습니다.

[그림6] At과 Count로 그린 상자 수염 그림


그림6은 등하교시간과 등하교 형태로 그린 상자 수염 그림[위키] 입니다. 그림에서 보듯 하교(-1)는 평균 (mean) 시간은 오후 1시 29분이고 1사분위와 3사분위 값이 각각 오후 12시 46분에서 1시 58분임을 보여줍니다. 반대로 등교시간은 상대적으로 일정한데 평균 값은 8시 45분입니다. 약 15분 전에 정문을 통과한다고 볼 수 있겠네요. 0 값으로 표시된 경우는 정문에 설치된 비콘에 등교 이후 관찰되었을 경우 메시지를 전달하는 경우로 보이는데 유용성을 이해하기 힘듭니다. 일단 하교 시간의 변화(variance)가 커서 이를 요일 별로 분석해 보도록 하겠습니다.


[그림7] At 과 Count로 그린 산점도


그림7은 요일별로 관찰된 출입시간을 점으로 표시한 것입니다. 앞서 그림6에서처럼 등교 시간은 일정하게 모이는 반면, 하교 시간은 월/수 (2/4)와 수/목(3/5), 금(6)이 사뭇 다르게 보입니다. 이는 아이의 시간표에 따라 귀가 시간이 변하기 때문에 나타나는 당연한 결과라고 볼 수 있습니다. 다만, 수요일 1시 21분에 하교한 사례나 금요일 오후 2시 39분 사례처럼 특이점이 있으니 이유를 살펴 보아야 할 것 같습니다. 



6. Findings


앞서 EDA에서 보여주듯 관찰을 통해 일상의 통학 시간을 확인할 수 있습니다. 이는 기계학습을 통해 정상적으로 통학했음을 확인할 수 있는 모델을 만들 수 있다는 의미로 해석할 수 있습니다. 지금은 데이터가 매우 적은 관계로 일반화할 수 없지만 같은 반이나 같은 학년의 데이터를 활용할 수 있으면 가능할 것이라고 기대합니다.


일상적인 등하교 시간에 대한 모델을 학습할 수 있게 된다면 이를 통해 비정상 상황을 예측할 수 있습니다. 예를 들면 등교 시간이 평소보다 많이 지연되었을 경우 확인 요청 문자를 발송한다거나, 하교 시간이 평소보다 늦어질 경우, 교사에게 확인 요청 메시지를 발송해서 학부모들의 우려를 먼저 대처할 수 있습니다.   


비콘을 이용한 통학 안전 관련 서비스의 핵심은 특이점 찾기(outlier detection) 입니다. 좀 더 쉽게 말하면, 등교 시간이 넘었음에도 관찰이 되지 않거나, 하교 시간이 매우 지연되는 사례 혹은 관찰이 되지 않는 경우를 들 수 있습니다. 이때 공휴일 여부/비콘 기기 정상 동작 여부 등의 외부 정보가 매우 중요한데 잘못된 알림이 시스템의 신뢰도에 치명적인 손상을 가져오기 때문입니다.


7. Future Works


이 문자 메세지는 정상 상황에서만 알림을 주도록 설계되어 있습니다. 하지만 정작 중요한 정보는 비정상 상황에서의 알림입니다. 그럼에도 불구하고 이상 알림(False Alarm)에 대한 부담감 때문에 이런 서비스를 제공하기 쉽지 않다는 게 현실입니다. 

이에 대해 활용자가 위험을 부담하는 DIY 서비스를 만들 수 있도록 하면 어떨까요? SMS 정보를 입력으로 학습하고 알람에 대한 평가를 반영해 성능을 개선해 가는 기계학습 시스템을 생각해 보게 됩니다.     


  



 

  




 



   


안녕하세요.  생각의 웹입니다.


홍콩과기대 김성훈 교수님의 텐서플로우 강의 중 Softmax classifier를 이용해 classification 하는 강의를 듣고 실습한 과정을 정리합니다.


https://www.youtube.com/watch?v=FiPpqSqR_1c

여기서 문제는 어떤 학생의 수업 시간과 공부 시간을 입력 값으로 해서 학점을 예측해 보는 것입니다. 데이터셋은 6개의 행으로 나눠져 있는데 x1과 x2를 각각, 학생의 수업 참여 시간과 공부 시간으로 볼 경우, A, B, C 중 하나의 학점을 얻게 되는 것을 0, 1로 기록하고 있습니다.  데이터의 내용은 첨부된 파일을 참고하시기 바랍니다.


그럼 본격적으로 코딩에 들어가보도록 하겠습니다. 처음은 텐서플로우를 사용하기 위해서 tensorflow 모듈과 csv 파일 처리 및 가공 편의성을 위해 numpy 모듈을 불러들입니다.


입력:

import tensorflow as tf

import numpy as np



이제 데이터 파일을 읽어들여 입력 값과 출력 값으로 분리하는데 이때 데이터를 처리하기 쉽도록 전치 행렬(transposed matrix)로 바꿉니다.  


입력:

xy = np.loadtxt('train.csv', unpack=True, dtype='float32')

x_data = np.transpose(xy[0:3])

y_data = np.transpose(xy[3:])

print x_data

print y_data 


결과:


[[ 1.  2.  1.]
 [ 1.  3.  2.]
 [ 1.  3.  4.]
 [ 1.  5.  5.]
 [ 1.  7.  5.]
 [ 1.  2.  5.]
 [ 1.  6.  6.]
 [ 1.  7.  7.]]
[[ 0.  0.  1.]
 [ 0.  0.  1.]
 [ 0.  0.  1.]
 [ 0.  1.  0.]
 [ 0.  1.  0.]
 [ 0.  1.  0.]
 [ 1.  0.  0.]
 [ 1.  0.  0.]]


  

데이터를 불러들이는 것을 마쳤으니 데이터를 가공할 영역을 만듭니다. 텐서플로우는 placeholder라는 생성함수를 통해 데이터의 type과 갯수등을 지정할 수 있습니다.


입력:

X = tf.placeholder("float", [None, 3])

Y = tf.placeholder("float", [None, 3])

이제 본격적으로 모델을 만들고 gradient descent 방식으로 최적 해를 찾아가는 것을 구현합니다. 여기서 가설은 Y = WX 인데 찾고자하는 값이 변수인 W이기 때문에 Variable 생성함수로 선언합니다. 행렬 곱 함수인 matmul() 에서 순서가 바뀐 부분을 주의해서 볼 필요가 있습니다. 텐서플로우 구현 상의 trick인데 강의를 보면 그 이유에 대해 간략히 설명하고 있습니다. cost 함수는 예측 치와 실제 값의 차이를 최소화 하도록 차이가 커지면 무한대로, 작아지면 0에 수렴하도록 만들어 gradient descent 방식으로 최적 해를 찾는 데 활용됩니다.  


입력:

W = tf.Variable(tf.zeros([3, 3]))

hypothesis = tf.nn.softmax(tf.matmul(X, W))

learning_rate = 0.001

cost = tf.reduce_mean(-tf.reduce_sum(Y*tf.log(hypothesis), reduction_indices=1)) 
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

텐서플로우는 코드를 선언한다고 해서 수행되는 것이 아니라 Session 인스턴스에 전달해야 수행됩니다. 또한 먼저 모든 값을 초기화 해주어야 합니다. 아래 코드는 초기화 수행 후 2000번의 반복을 통해 최적 해를 찾아가는 과정을 구현했는데 매 200번마다 진행상황을 출력하게 됩니다. 출력은 이 과정을 통해 cost 함수 값이 감소하는 것을 보여줍니다. 

마지막으로 코드는 11시간의 수업시간과 7시간의 공부 시간을 투입했을 때 어떤 학점을 맞게될지에 대해 예측하고 있습니다. 이를 통해 약 46%의 확률로 A 학점을, 35% 확률로 B 학점을, 18% 확률로 C 학점을 맡게 됨을 알 수 있습니다.


입력:

init = tf.initialize_all_variables()


with tf.Session() as sess:

    sess.run(init)

    

    for step in xrange(2001):

        sess.run(optimizer, feed_dict={X:x_data, Y:y_data})

        if step % 200 == 0:

            print step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W)

   

# prediction

    a = sess.run(hypothesis, feed_dict={X:[[1, 11, 7]]})

    print a, sess.run(tf.arg_max(a, 1)) 

출력:

0 1.09774 [[ -8.33333252e-05   4.16666626e-05   4.16666480e-05]
 [  1.66666694e-04   2.91666773e-04  -4.58333408e-04]
 [  1.66666636e-04   4.16666706e-04  -5.83333429e-04]]
200 1.05962 [[-0.02051384 -0.00103983  0.02155367]
 [ 0.01406439  0.01097753 -0.0250419 ]
 [ 0.01431208  0.03574874 -0.05006079]]
400 1.04985 [[-0.04282598 -0.00625899  0.04908497]
 [ 0.01747187  0.00156368 -0.01903554]
 [ 0.01831204  0.04954104 -0.06785305]]
600 1.0407 [[-0.06517859 -0.01176361  0.07694223]
 [ 0.01943521 -0.00848972 -0.01094547]
 [ 0.0211558   0.06118308 -0.0823388 ]]
800 1.03194 [[-0.08734013 -0.01729389  0.10463406]
 [ 0.0211172  -0.01796171 -0.00315547]
 [ 0.02396628  0.07198346 -0.09594975]]
1000 1.02354 [[-0.10928574 -0.02282182  0.13210759]
 [ 0.02266255 -0.02678035  0.00411784]
 [ 0.02685851  0.08210357 -0.10896213]]
1200 1.01547 [[-0.13101467 -0.02834093  0.15935563]
 [ 0.02409704 -0.03497621  0.01087924]
 [ 0.02983199  0.091598   -0.12143002]]
1400 1.0077 [[-0.15252906 -0.03384716  0.1863762 ]
 [ 0.02543302 -0.04258838  0.01715543]
 [ 0.03287464  0.10050804 -0.13338274]]
1600 1.00021 [[-0.1738314  -0.03933693  0.21316831]
 [ 0.02668083 -0.04965464  0.02297391]
 [ 0.03597423  0.10887134 -0.14484566]]
1800 0.992979 [[-0.19492455 -0.04480689  0.23973146]
 [ 0.02784995 -0.05621057  0.02836075]
 [ 0.0391195   0.11672312 -0.15584266]]
2000 0.985988 [[-0.21581143 -0.05025397  0.26606542]
 [ 0.02894918 -0.06228961  0.03334056]
 [ 0.04230016  0.12409624 -0.16639641]]
[[ 0.46272627  0.35483009  0.18244369]] [0]
지금까지 발견한 텐서플로우의 코딩 패턴은 다음과 같습니다.


  • 데이터가 달라지더라도 데이터를 담는 그릇(placeholder)를 통해 대응
  • 데이터의 형식을 생성함수로 지정
  • cost 함수, 모델 변경 시, 손 쉽게 대응할 수 있는 구조
  • Session에 전달해서 수행해야 실행이 이뤄짐.


Happy Coding!



안녕하세요. "생각의 웹"입니다.


Facebook TensorFlow KR 그룹에서 본 학습자료 중 제가 보고 있는 자료들의 일부를 정리 차원에서 기재합니다.

출처: https://www.facebook.com/groups/TensorFlowKR/?fref=nf







안녕하세요. "생각의웹"입니다.


docker를 활용해 윈도우즈에서 TensorFlow가 설치된 iPython Jupiter를 설치해 활용하는 법 정리합니다.


먼저 원문은 다음과 같습니다: 

http://www.netinstructions.com/how-to-install-and-run-tensorflow-on-a-windows-pc/



원문을 따라서 수행하다보면 다음과 같은 문제점들이 발생합니다.

1) 계정 정보가 한글 ID인 경우, 경로 이상 문제 발생

2) TensorFlow docker image 설치 후 python 이 아닌 ipython server가 수행되고 shell이 뜨지 않음


이 현상들을 해결하고 다음과 같이 설치 및 활용 절차를 재정리합니다.


  1. Docker toolbox for Windows 설치: docker toolbox 설치 후 바탕화면에 등장하는 Docker Quickstart Terminal 을 실행합니다.
  2. default docker machine이 자동으로 생성됩니다. 다음 명령어로 생성된 docker machine을 확인합니다
    docker-machine ls
  3. TensorFlow가 preset 되어 있는 docker image를 cloning 하고 port forwarding 해서 수행합니다. 이때 8888 포트는 jupyter를 위해 6006 포트는 tensorboard를 위해 사용됩니다.
  4. docker run -p 8888:8888 -p 6006:6006 -it b.gcr.io/tensorflow/tensorflow
  5. 정상적으로 동작하면 다음과 같은 메세지가 표시됩니다.

  6. ...
    The Jupyter Notebook is running at : http:..[all ip addresses on your system]:8888/
    
  7. tensorboard를 사용하기 위해 다음과 같이 tensorboard를 활성화합니다.
     
  8. docker machine의 IP address를 확인합니다. 여기의 적힌 IP address가 접근 가능한 서버 주소가 됩니다.
  9. docker-machine ip default
  10. 만일 ip address가 192.168.99.100 이라면 browser를 열어 다음과 같이 tensorflow가 설치된 jupyter server에 접근할 수 있습니다.

  11. 192.168.99.100:8888

참고로 여기에 설치되어 있는 TensorFlow는 non-GPU 버전에 0.8입니다. 

GPU 사용 버전을 활용하시려면 github 가이드를 확인하시기 바랍니다.



이상입니다.

이제부터 tensorflow 공부를 제대로 해봐야 겠네요. 


  1. 생각의 웹 WebofThink 2016.05.03 21:24 신고

    ㅎㅎㅎ 간만에 포스팅했더니 비슷한 행동을 하고 있었나보군요. 부디 즐텐플하길!

  2. 파이팅건맨 2016.05.04 11:28

    앗, 저도 시도했다가 iPython 서버가 뜨는 문제 때문에 찾아낸 우회 방법입니다. 제것보다 이곳의 방법이 더 나아 보이기도 하고...ㅋ
    여튼, 참고 부탁드립니다~

    http://airpage.org/xe/language_data/20725

안녕하세요, 생각의 웹입니다.


앞서 python을 이용 해 open API 로 얻어온 social data를 가공한 포스팅을 한 바 있습니다.


이런 기법(?)를 통해 얻은 정량적인 데이터로 사회의 현상을 분석하고 통찰하는 융합적 학문 영역을 Social Computing 이라고 하는데 

현재 제가 이 과목을 수강하는 중이라 이전의 포스팅은 제가 했던 일들 중 몇 가지를 포스팅한 사례라고 보시면 됩니다.


이번에는 좀 더 심화적인 내용으로 이런 빅 데이터 분석 기법이 어떻게 응용되어 

미처 깨닫지 못했던 재밌는 결과를 발견해 낼 수 있는 지에 대해 논문의 초안 형식으로 작성해 보았습니다.


가볍게 보시고 제가 얻은 통찰 이상의 것을 얻으시길 바라며...

감사합니다.  

 



A Butterfly of the Dawn: "레 미제라블 등장 인물 관계 분석을 통한 임계 사회에서의 나비 효과 통찰"



Abstract

  • 소설 작품은 작성 시점의의 시대 상을 보여주고 '레 미제라블'은 프랑스 혁명을 앞둔 임계 시대 상황을 장 발장이라는 인물을 통해 보여 줌
  • 소설의 등장 인물들의 사회적 관계를 정량 / 정성 분석함으로써 나비 효과를 일으키는 존재를 통찰해 보임



1. Introduction


    Do you hear the people sing?
    Singing the song of angry men?
    It is the music of a people
    who will not be slaves again!
    When the beating of your heart
    echoes the beating of the drums 
    There is a life about to start
    when tomorrow comes!

[Fig.1] Lyric of 'Do You Hear The People Sing' (excerpted from 'Les Miserables: The Motion Picture Soundtrack' )


  • 흥미롭지만 논쟁 거리가 많은 엔하 위키1)에 따르면, 레 미제라블은 소설을 원작으로 동화, 뮤지컬, 영화 등의 다양한 장르로 해석되어 소비되는 고전 중의 고전
    • 원작의 상당한 분량 때문에 성경 다음으로 많이 읽혔다는 프랑스 조차도 원작이 아닌 요약 본으로 주로 소비
    • 사실 동화의 영향으로 원작의 서두인 장발장의 회심까지만 알려져 있으나 원작은 상당히 사회제도의 비판을 중심으로 서정적인 스토리가 주를 이룸.
  • 작가인 빅토르 휴고는 본 작품의 서문에서 " 한 비천한 인간이 어떻게 성자가 되고, 어떻게 예수가 되며 어떻게 하느님이 되는지를 그려낸 이야기. 이 지상에 무지와 비참이 있는 한, 이러한 책들이 쓸모 없지는 않을 것이다." 라고 논평함.
  • 본 소설의 배경은 역사적으로 프랑스 대혁명에 앞서 닥친 불황과 영국에서 촉발된 산업 혁명으로 인해 생산성 측면에서 지위를 잃은 농민들의 도시 이주가 사회 문제로 대두되는 시점이고 이에 걸맞는 정치 사회 시스템의 부재로 인해 언제 터질 지 모르는 임계 사회 속에서 벌어지는 군상들의 개인적, 사회적 갈증을 그림
  • 한국에는 이 작품이 일제강점기 육당 최남선에 의해 일본어 중역을 통해서 최초로 소개했으며 <너 참 불쌍타>라는, 원제를 살린 제목으로 출간되어 국권 피탈의 시대를 살았던 선조들에게 카타르시스를 제공해 줌.
  • 신 자유주의와 글로벌 무한 경쟁에 따른 피로감과 불안감이 쌓이고 있는 현재에도 공감대를 형성하고 있으며 이 작품의 등장 인물들 간의 사회적 관계를 정성적/정량적으로 연구해 봄으로써 인해 임계 시대 상황의 인간 관계적 요인들을 조명해 볼 수 있을 것으로 기대
  • 이후로 2장에서 본 연구의 동기와 문제 제기, 3장에서 이 문제를 살펴보기 위한 접근 방식, 4장에서 구현 방식과 이에 대한 해석을 진행하고 5장에서 논의하며 6장에서 결론 짓기로 함



2. Motivation

  • 심각한 사고 1 건, 사소한 사고 29건, 위험 300건이 벌어진다는 하인리히(Heinrich)의 원칙에 따르면 큰 변혁이 일어나기 이전 빈번한 징후들이 포착됨을 알 수 있음
  • 마크 뷰캐넌은 그의 저서 우발과 패턴2)에서 "거대한 격변이 역사의 다음 모퉁이에 도사리고 있다. 지금 나의 결정과 행동은 아무리 작은 것이라도 임계상태의 세계에 그 어떤 변화도 불러일으킬 가능성이 있다"라고 언급
  • 이런 격변이 일어나는 배경에는 우리가 네트워크인 사회적 관계 속에서 끝임없이 영향을 주고 받으며 엔트로피를 증가시켜 가기 때문임.
  • 이런 관계성은 한 개인이 다른 개인과의 묶임(tie)를 통해 도식화가 가능하나 너무 많은 개체 간의 관계가 가져오는 복잡성 때문에 정량적인 분석이 불가능하다고 여겨짐
  • 컴퓨팅 능력의 비약적인 향상과 Web 2.0 으로 대변되는 social network service의 편재가 데이터와 알고리즘을 이용해 정량적 통계 분석이 가능한 시대가 도래 3)
  • 이에 앞서, 소설 레 미제라블의 지문 분석을 통해 등장 인물간의 상관 관계 (relationship)을 정리한 데이터를 기반으로 경제적 불황기의 사회 상을 그린 소설을 통해 사회 대 변혁(프랑스 혁명)을 앞둔 시대 상을 등장 인물들의 정성적 특성(character)와 그 들간의 사회적 관계를 통해 이런 징후의 함의(inference)들을 유추해 보고자 함




3. Approach

  • 다양한 등장 인물들이 등장하는 대작이나 엔하 위키 1)에 따르면 주요 인물들과 그 특성은 다음 Table 1.과 같음.


    [Table 1. 레 미제라블 주요 등장 인물 - Excerpt from enha wiki 2) ]


영문 명 한글 명 특성 기타
Jean Valjean 장발장 주인공, 무시무시한 괴력의 소유자, 빈곤으로 죄를 저지른 다음 오랜 투옥으로 원망과 증오를 품다가 미리엘 주교의 용서로 개과천선. 이후 사업가로 성공해 마들렌 시장까지 역임. 추후 엄청난 부자가 되는데 본인이 사업으로 벌어서 예금한 돈이 물경 60만 프랑에 달함. (이게 얼마나 많냐면 1500프랑이 3년 생활비다.) 신분을 들통나 자베르에게 쫒김에도 백만 프랑도 넘는 돈을 자선사업, 복지사업에 쏟아부음. 팡틴의 딸인 코제트를 입양해 죽을 때까지 보살핌 죄수 번호 24601(소설은 9430)로 불림. 이름이 장이고 성은 '발장'이다.
Myriel 미리엘 주교 소설 속에서 디뉴 교구(Digne)의 주교로 등장. 디뉴의 성당에 나타난 장 발장이 은식기를 훔친 뒤 잡혀오자, 미리엘 주교는 오히려 장 발장에게 은촛대 2개를 줬다. 소설의 배경이 되는 시기의 실제 디뉴 주교였던 비앵브뉘 드 미올리(1753년~1843년)이 모델
Javert 자베르 범죄자는 절대로 용서하지 않는 엄정한 경찰관, 주인공 장 발장과 대립하다 자살, 어머니가 점쟁이(1998년 영화판에서는 창녀), 아버지가 범죄자로 감옥에서 태어났는데, 이 태생에 대한 콤플렉스가 집요하고 이분법적인 성격을 야기. 거짓말을 한 번도 하지 않는 사람 (예를 들면 원작에서 바리케이트에 숨어들었을 때 "너 밀정이지" 한 마디에 바로 "난 정부 관리다."라고 말 함) 옳은 일을 하기 위해 평생을 노력했으나 법으로 대표되는 사회 구조에 결함이 있을 수 있다는 사실과 법 너머의 정의가 있을 수 있다는 사실에 대해서 이해하지 못했기 때문에 결국 법을 어겼지만 정의로운 사람이라는 모순에 빠짐
Fantine 팡틴 고아인 여직공, 장발장의 공장에서 직공으로 일을 하지만, 사생아를 갖고 있다는 게 들통나서 일자리를 잃고 매춘부로 전락. 헤어진 딸 코제트를 기다리다 자수한 장 발장을 잡으러 온 자베르가 들려준 그의 정체에 충격을 받고 사망 모성애의 아이콘, 이름 "Fantine"은 프랑스어의 "enfantine"에서 온 것으로 보이며, 뜻은 "아이."
Cosette 코제트 팡틴의 딸. 본명은 외프라지(Euphrasie). 테나르디에 부부 밑에서 온갖 학대를 당하며 노예처럼 살다가 장 발장이 데리러 와서 구해줌. 마리우스와 사랑에 빠짐 메인 등장인물 중 그나마 덜 불쌍한 인물
Les Thénardiers 테나르디에 부부 팡틴이 코제트를 맡긴 여관집 부부. 코제트를 노예처럼 부리며 과대한 양육비를 요구해 팡틴이 나락에 빠지도록 함. 돈만 된다면 어지간한 범죄는 다 저지르는 작품 내 부동의 악역.
Marius Pontmercy 마리우스 퐁메르시 골수 왕당파인 외할아버지 밑에서 자라난 청년. 집을 나와 가난하지만 성실하게 살면서 자유주의자인 친구들을 사귀다 코제트와 사랑에 빠짐. 자유주의자들의 시내 반란에 가담했다가 부상을 당하나 장 발장이 와서 구해 줌 딸 가진 아빠들의 공공의 적 (작품을 보다보면 은혜도 모르는 놈이라는 소리가 절로 나온다)
Éponine Thénardier 에포닌 테나르디에 테나르디에 부부 사이에서 태어난 다섯 남매 중 장녀. 코제트가 있을 때는 공주 대접 받다 망한 후 반대 신세. 코제트와 사랑에 빠진 마리우스를 짝사랑. 마리우스가 정부군의 총격을 당할 위험에 놓이자 자신이 그 총을 대신 맞고 숨을 거둠. 뮤지컬과 영화의 On My Own 우로 부각된 인물
Enjolras 앙졸라스 아베쎄의 벗들(Les amis de l'ABC)의 리더. 인데, 십대 소년과 같은, 아름다운 미모의 금발 벽안 미청년으로 묘사. 공화주의자들의 거목이었던 라마르크 장군이 죽자 그의 장례식 당일 시민군을 결성하고 바리케이드를 쌓아서 혁명을 일으킴, 혁명 현장에서 총살 당함 위고가 가장 외모 찬양에 공을 들인 인물 가운데 하나 - 피크말리온?
Combeferre 콩브페르 의대생. 앙졸라스가 혁명의 논리를 대변하는 리더라면 콩브페르는 혁명의 이상을 대변하는 안내자 고요히 타오르는 불빛이라고 언급
Gavroche 가브로슈 테나르디에 부부의 세 아들중 한 명. 정의로운 마음을 가졌지만 엉뚱한 소년 영화에서 활약이 돋보임
Courfeyrac 쿠르페락 귀족 출신임을 거부하는 귀족으로 앙졸라스가 리더이고 콩브페르가 안내자라면 쿠르페락은 중심(Centre)으로 일컬어진다 재치있고 입담이 좋으며, 마당발이라 아베쎄의 벗들의 모든 이들과 두루두루 친하다.
Lesgle 레글르 대학에서는 법학을 공부해 변호사를 목표하나 잘 안됨. 단골 술집에서 식사를 하고 있다가, 지나가는 앙졸라스와 그 일행들을 불러서 그 자리에 바리케이드를 쌓음 손대는 일마다 되는 일이 없는 안습 인생
Joly 졸리 예민한 성격의 의대생. 의사보다는 환자에 더 가깝다고 묘사
Feuilly 푀이 아베쎄의 벗들의 핵심멤버들 가운데 유일하게 노동자 계급. 혼자서도 읽고 쓰는 법을 깨우쳐, 독학을 하며 교양을 쌓아옴. 혁명을 통해 더 나은 세상을 만들 수 있다는 굳은 믿음을 가지고 살아 감
Bahorel 바오렐 거칠고 격정적인 성격을 가졌으며 '입담만으로도 모든 것을 깨부술 수 있는' 인물. 정부군과 첫번째 전투를 벌이던 도중 사망 한마디로 키보드 워리어
Jean Prouvaire 장 프루베르 다양한 외국어를 구사할 줄 알며 시도 쓰고 식물도 키우는 부드러운 남자. 혁명 후 정부군 측에서 벌인 즉결재판에서 곧바로 처형 당함 역사 덕후.
Grantaire 그랑테르 주정뱅이. 세상 일에 회의적이고 도박과 음주에 빠져 방탕하게 굴지만 리더인 앙졸라스만큼은 항상 동경. 하는 일 없이 혁명 당시 술에 절어 자기만 했으나 실패 후 정부군에게 혁명군 가운데 한 사람임을 자처하고 앙졸라스와 함께 총살당함 무능하나 의리에 살고 죽는 순박한 인물
  • github에는 이 인물들 간의 동시 등장 (Co-occurrence) 빈도를 PageRank 알고리즘을 통해 분석하는 오픈소스 프로젝트 4) 가 존재하고 이 데이터를 csv 파일로 제공함
  • csv를 통해 PageRank score를 계산한 결과로 도식화(visualization)한 내용과 함께 Table 1.의 정성적 분석을 혼합해 (hybrid analysis) insight 를 도출하려 함.



4. Implemetation & Analysis

  • Python 언어로 구현한 PageRank Algorithm 은 Fig. 2 과 같음

##
# Ranking node with page rank algorithm
#
# @param graph the graph to be page-ranked
# @param k the steps
# @return the ranking dictionary
#
def rank_nodes(graph, k=10):
    # Assign initial values
    ranks = dict()
    V = float(len(graph))
    s = 0.85

    for key, node in graph.nodes(data=True):
        ranks[key] = node.get('rank')

    for _ in range(k):
        for key, node in graph.nodes(data=True):
            rank_sum = 0.0
            curr_rank = node.get('rank')
            #print curr_rank

            neighbors = graph[key]
            for n in neighbors: # for each neighbors, gather its pagerank
                if graph.node[n].has_key('rank'):
                    if graph.node[n]['rank'] is not None:
                        out_links = len(graph.neighbors(n))
                        rank_sum += (1 / float(out_links)) * graph.node[n]['rank']
            ranks[key] = ((1 - s) * (1 / V)) + s * rank_sum

            for key, rank in ranks.iteritems():
                graph.node[key]['rank'] = rank
    return ranks
 

[Fig. 2 PageRank Algorithm]


[Fig. 3 Soicial network which argumented with PageRank score]


  • Fig. 3은 PageRank score 를 이용해 각 등장인물 들 간의 상관 관계를 D3 Visualization tool을 이용해 node와 edge로 도식화 5)
    • 주인공인 발장(Valjean - 농담하듯이 '장씨 가문의 발장 씨'도 아니고 머리가 길어서 '장발 장'도 아니다.1) )이 가장 중심 부에 위치
    • 은인인 미리엘 주교(Myriel)과 천적인 자베르(Javert), 양녀 코제트(Cosette)를 괴롭힌 테나르디에 부부(Thénardiers) 들과 빈번한 교류를 보여 줌
    • 소설의 초반부 (동화의 전부)에 핵심 인물인 미리엘 주교(Myriel)은 발장 외 다른 인물들과 관계를 갖지 않음
      • 등장인물 요약을 기반한 맥락적 분석으로 보면 소설의 전체 얼개 중 핵심 발단을 제공하는 인물
    • 발장의 사위인 마리우스(Marius)는 발장과 아베쎄의 벗들의 연결자(hub)이며 혁명의 소용돌이로 이끄는 문제적 인물
      • 아내이자 발장의 양녀인 코제트(Cosette)와의 관계 만큼 발장과 관계가 강함 (strong tie)
    • 아베쎄의 벗들은 리더는 앙졸라스(Enjolras)이나 중심(Cente)이라 일컬어지는 콩브페르(Combeferre)에 의해 더 많은 벗들과 연결되고 있음을 보임
    • 테나르디에 가족의 일원인 가브르슈 (Gavroche)는 역할은 미미하나 미리엘 주교 (Myriel) 다음으로 강한 점수를 보여주며 임계 지점 (tipping point) 역할 수행
      • 가족들 보다 혁명을 이끄는 아베쎄의 벗들 간 관계가 강하고 다양한 인물들과 약한 관계 (weak tie)를 맺고 있음.


[Fig. 4 Co-occurence matrix]


  • Fig. 4은 matrix 형태로 등장 인물 간의 관계 성을 색깔의 농도로 표현
    • 소설의 중후반 부에 등장하는 아베쎄의 벗들과 장발장의 겪는 혁명에 관한 네러티브가 소설의 핵심임을 보여 줌
    • 소설 속에서 팡틴 (Fantine)은 딸인 코제트(Cosette)와 함께 등장하지 않는다는 것이 특이



5. Discussion

  • 정량 분석을 통해서는 한 인물의 전반적 정보를 투영할 수 있으나 연대기 별로 (초년, 성년, 중년, 노년 등) 관계를 갖는 인물이 다를 수 있고 이런 특징적 정보는 안 보임
  • 동화 장발장이나 영화 레 미제라블이 아닌 원작 소설을 읽지 않아 기타 등장 인물들의 관계가 분석이 되지 않아 보다 근원적인 나비 효과를 분석하기 힘듦.
  • 사건이나 등장 인물들의 급격한 변화를 보이는 지점 (tipping point) 를 기준으로 데이터를 나눠 이 때 가장 강한 상관 관계를 갖는 인물에 대한 분석(영향력 분석)이 필요함.



6. Conclusion

  • 소설의 인물들의 관계를 정량/정성 분석함으로써 나비 효과처럼 임계 상황에서 의도치 않게 핵심 역할을 수행하는 인물 - 가브르슈 - 를 찾아 낼 수 있었음.
  • 정량 분석을 통해 소설의 원작자의 입장(전지적 작가 시점)에서 관망할 수 있는 효과 확인
  • 올바른 정량 분석을 위해서는 정성 분석이 함께 수행되어야 효과적임
  • 후속 연구로 분기 상황에 대한 데이터를 확보해서 해당 상황 별로 정량 분석을 하면 추가 insight 기대 됨.



7. References


안녕하세요. "생각의 웹"입니다.


이번 포스팅에서는 facebook의 graph API(https://developers.facebook.com/tools/explorer/)를 이용해 특정 fan page에 게시된 feed 글들을 word cloud로 만들어 보았습니다.




분석 대상 fan page: https://www.facebook.com/VisionMobile

 

참고 삼아 이 회사는 모바일 앱 및 IoT 관련 산업 및 개발자 동향을 분석해 인사이트 리포트를 제공하는 영국 회사로 깔끔한 시각화 (visualization) 과 핵심을 관통하는 분석으로 평소 많은 도움을 받고 있습니다.


코드 설명에 앞서, facebook의 경우 주기적으로 access token를 발급 받아서 유효한 값을 query parameter로 전송해야만 정상적으로 결과를 얻을 수 있습니다.

자세한 사항은 doc (https://developers.facebook.com/docs/graph-api?locale=ko_KR) 를 참고하시기 바랍니다.


1. feed data를 가져오는 class 만들기 

facebook의 특정 page에서 feeds를 가져오기 위해 PsyCharm 혹은 pip 로 'requests', 'urllib3' 를 설치 후 다음과 같이 구현했습니다.


import requests
import json
import facebook
import urllib3
import urllib3.contrib.pyopenssl # due to https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning
urllib3.contrib.pyopenssl.inject_into_urllib3()
urllib3.disable_warnings()

class FacebookRequester:
    base_url = 'https://graph.facebook.com/'
    version = 'v2.3'
    content = []
    def __init__(self, token):
        self.access_token = token
        self.page = 'me'
    def setPage(self, page):
        self.page = page
    def getFeeds(self, limit, times):
        fields = 'feed.limit(%s)' % limit
        url = '%s/%s/%s?fields=%s&access_token=%s' % \
              (self.base_url, self.version, self.page, fields, self.access_token)
        counter = 0
        print url
        while counter < times:
            response = requests.get(url).json()
            print response

            try:
                content = response['feed']['data']
                paging = response['feed']['paging']
            except KeyError: # in case of retrieving by next page
                content = response['data']
                paging = response['paging']

            #print content
            #print paging

            self.content = self.content + content
            next_page_url = paging['next']
            if not next_page_url:
                break
            else :
                counter += 1
                url = next_page_url
                #print url
        return self.content

상기 코드에서 유심히 볼 부분은 urllib3 입니다. 

이 라이브러리가 없으면 python 2.* 에서 https 로 전송 시도 시 TLS 보안 관련 결함이 있기 때문에 insecure platform warning 과 함께 전송이 되지 않습니다. 따라서 관련 가이드 (https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning) 에 따라 필요한 warning skip code가 추가되었습니다.


두 번째로 facebook은 한번의 요청으로 가져올 수 있는 데이터 양이 정해져 있기 때문에 그 다음 데이터를 가져올 수 있도록 paging property의 next attribute에 다음 요청의 URL 를 제공합니다. 따라서 다음 요청 시에는 이 값을 사용하도록 구현했습니다.

2. feed 가져와서 word 추출하기 


import os.path
import json
import sys
import nltk

import jsonreader

from prettytable import PrettyTable
from fb_requester import FacebookRequester

##
# Get feeds using facebook graph API
#
def get_feeds():

    ACCESS_TOKEN = ''
    requester = FacebookRequester(ACCESS_TOKEN)
    requester.setPage('VisionMobile')
    feeds = requester.getFeeds(100, 5)
    return feeds


##
# Tokenize all feed messages
#
def tokenize(feeds):

    feed_texts = []
    for feed in feeds:
        try:
            feed_message = feed['description'] # message attribute contains URL but description doesn't
            feed_texts.append(feed_message)

        except KeyError:
            #print feed # if feed has no message field
            continue

    tokens = []
    for s in feed_texts:
        tokens += nltk.tokenize.word_tokenize(s.lower())
    return tokens

##
# Get stemmed list
#
def get_stemmed_list(tokens):
    from nltk.corpus import stopwords

    stop_words = stopwords.words('english') + ['.', ',', '--', '\'s', '?', ')', '(', ':', '\'', '\'re', '"',
                                               '-', '}', '{', u'—', 'rt', 'http', '%', 'co', '@', '#', '/', u'…',
                                               u'#', u';', u'amp', u't', u'co', u']', u'[', u'`', u'`', u'&', u'|',
                                               u'\u265b', u"''", u'$', u'//', u'/', u'%',
                                                                              u'via', u'...', u'!', u'``', u'http']

    from nltk.stem import PorterStemmer

    stemmer = PorterStemmer()
    stemmed = []
    for token in tokens:
        # try to decode token
        try:
            decoded = token.decode('utf8')
            #print decoded
        except UnicodeError:
            decoded = token

        if decoded is '' or decoded in stop_words:
            continue
        stem = stemmer.stem(decoded)
        #print stem
        # Skip a few text. I don't know why stopwords are not working :(
        #skip facebook things
        if stem.find(u'facebook.com') > 0:
            continue
        #skip http things
        elif stem.find(u'http') >= 0:
            #print stem
            continue
        else:
            stemmed.append(stem)
    return stemmed


def write_file(filename, lines):
    f = file(filename, 'w')
    for word in lines:
        try:
            f.write(word.encode('utf-8') + '\n')
        except UnicodeEncodeError, e:
            print 'Encoding error ' + word + '\n'
    f.close()

# Simple test
feeds = get_feeds()
tokens = tokenize(feeds)
print tokens
stemmed = get_stemmed_list(tokens)
print stemmed
write_file('feed-word.txt', stemmed)


이 코드는 앞서 포스팅한 tweet으로 word cloud 만들기 코드와 거의 유사하며 tweeter와 facebook의 JSON shema 차이 부분만 변경되었으니 참고해 보시기 바랍니다.


이처럼 양대 SNS 서비스인 tweeter 와 facebook에서 추출한 비정형 데이터에서 문자열 추출을 통해 분석하는 예제를 수행해 보았습니다.

이제는 다양한 이유로 충분한 데이터를 모으려면 제약이 심한 관계로 아주 작은 데이터를 가지고 한 실습에 불과 하지만 이와 같은 방식으로 데이터를 모으고 분석할 수 있는 기반을 경험했다는 점에서 의의를 두고 싶습니다.


이상입니다.


감사합니다.

행복한 하루 되시길!

안녕하세요, "생각의 웹"입니다.


한글 윈도우즈 8.1 64bit 버전에서 nltk 설치 관련해 이전 포스팅(http://webofthink.tistory.com/59)을 작성한 바 있으나

pycharm 설치 이후에도 nltk 관련 다양한 문제가 있어 해결 방안(이라기 보다 제가 해결 했던 방법)을 공유하고자 이렇게 글을 시작합니다.



먼저 시스템 > 시스템 속성 > 환경 변수에 다음과 같은 사용자 변수를 추가해 줍니다.


HOME

PYTHONHOME


이 변수에는 한글이 포함되지 않은 임의의 존재하는 경로를 입력합니다.



이후 nltk 설치 이후 정상 설치 여부를 확인하기 위해서는 python console 에서 (pycharm의 Tools > Python Console을 추천합니다.) 

다음과 같은 명령어를 수행하면 됩니다.



import nltk

저 같은 경우는 상기 명령 수행 이후 DecodingError가 발생했는데 에러가 발생한 위치를 보면 python 설치 경로\Lib\site-packages\nltk\downloader.py의 아래 줄이 문제를 발생시킵니다.


933  return os.path.join(homedir, 'nltk_data')


문제의 원인은 제 home 경로에 해당하는 위치에 한글이 포함되어 있고 windows 8.1의 경우 이 경로를 임의로 바꿀 수 없기 때문입니다.

따라서 문제를 발생시키는 homedir 변수의 값에 한글 경로가 포함되지 않는 경로를 할당해서 우회합니다.


933  homedir = os.environ['PYTHONHOME']
934  return os.path.join(homedir, 'nltk_data')



이로써 (저의 경우) nltk import 가 정상적으로 수행되었습니다. 이후 관련 package룰 다운로드 받기 위해 아래와 같이 download() 함수를 수행하면 새로운 다운로드 창에서 관련 package들을 다운로드 받을 수 있습니다.


import nltk
nltk.download()


몇 번에 걸쳐 python 설치/제거 작업을 반복하며 얻은 노하우니 만큼 유용하게 쓰였으면 합니다.

이상입니다.


감사합니다.

행복한 하루 되세요!


안녕하세요, "생각의 웹"입니다.


이번에는 갖은 시행 착오 끝에 설치를 완료한 NLTK를 활용해 IoT로 검색해 얻은 600 건의 트윗의 내용을 

word cloud로 만든 사례를 소개하고자 합니다.





이를 위해 python의 tweeter module을 이용해 아래와 같이 코딩했습니다.


# coding=UTF-8

import os.path
import json
import sys
import nltk

import collecttweets
import jsonreader

from collections import Counter
from prettytable import PrettyTable

##
# Get tweets from JSON dump file or twitter API
#
def get_tweets() :
	file_path = "tweets.json"
	if os.path.exists(file_path) :
		return jsonreader.read(file_path)
	else:
		return collecttweets.search_tweets_by_hash_tag('IoT', 5, 100)

##
# Tokenize all tweet messages
#
def tokenize(statuses) :
    status_texts = [ status['text']
        for status in statuses ]

    tokens = []
    for s in status_texts:
        tokens += nltk.tokenize.word_tokenize(s.lower())
    return tokens

##
# Get stemmed list
#
def get_stemmed_list(tokens) :
    from nltk.corpus import stopwords
    stop_words = stopwords.words('english') + ['.', ',', '--', '\'s', '?', ')', '(', ':', '\'', '\'re', '"',
        '-', '}', '{', u'—', 'rt', 'http', 't', 'co', '@', '#', '/', u'…',
        u'#', u';',  u'amp', u't', u'co', u']', u'[', u'`', u'`', u'&', u'|', u'\u265b', u"''", u'$', u'//', u'/'
        u'via',  u'...', u'!', u'``', u'http']

    from nltk.stem import PorterStemmer
    stemmer = PorterStemmer()
    stemmed = []
    for token in tokens:
        # try to decode token
        try:
            decoded = token.decode('utf8')
            #print decoded
        except UnicodeError:
            decoded = token

        if decoded is '' or decoded in stop_words:
            continue
        stem = stemmer.stem(decoded)
        #print stem
        # Skip a few text. I don't know why stopwords are not working :(
        #skip t.co things
        if stem.find(u't.co') > 0:
            continue
        #skip http things
        elif stem.find(u'http') >= 0:
            #print stem
            continue
        else:
            stemmed.append(stem)
    return stemmed

def write_file(filename, lines) :
    f = file(filename, 'w')
    for word in lines:
        try:
            f.write(word.encode('utf-8') + '\n')
        except UnicodeEncodeError, e:
            print 'Encoding error ' + word + '\n'
    f.close()

# Simple test
statuses = get_tweets()
tokens = tokenize(statuses)
print tokens
stemmed = get_stemmed_list(tokens)
print stemmed
write_file('word.txt', stemmed)



간략히 설명하면 

1) twitter API로 관심주제 (저 같은 경우는 IoT)로 tweet를 수집한다. 

2) tweet의 내용을 token으로 쪼개 모은다.

3) stemmer로 token를 분석해 불필요한 단어들을 제거한다. 

4) 남은 word들을 파일로 출력한다. 만들어진 word.txt를 아래 사이트에서 word cloud로 만들면 앞서 그림과 같이 예쁜 그림을 얻을 수 있습니다. 

(silverlight로 제작된 사이트니 IE에서 접속하는 걸 추천합니다 ;-) ) 

http://www.tagxedo.com/app.html 


이상입니다. 


감사합니다.

  1. 파이팅건맨 2015.03.28 20:49

    멋지네요, 제 홈에도 써 먹어야 겠어요~!ㅋㅋ

  2. 김진형 2015.06.01 21:39

    collecttweets 는 뭔지 알 수 있을까요?

    • 생각의 웹 WebofThink 2015.06.04 01:24 신고

      요즘 통 바삐 살다 보니 답글 늦었네요 ^^; 다음 코드 참조하시기 바랍니다 https://github.com/hyunghunny/wordcloud/blob/master/twitter/collecttweets.py

+ Recent posts