2017년 8월 12일 토요일

Hive에서 GROUP_CONCAT 함수 사용하기

A. 원본 테이블
지역 업종
경기도 요식업
경기도 헬스
서울 한식
서울 학원
강원도 초등학교
강원도 커피
...
제주도 제과점

B. 변환된 결과
지역 업종
경기도 요식업, 헬스, …
서울 한식, 학원, …
강원도 초등학교, 커피, …
제주도 제과점, …

A처럼 생긴 테이블을 B와 같은 형태로 바꿀 필요가 있었다. 
일종의 텍스트 피벗이라 해야 하나(?) 

원본이 800만줄이 넘는 양이라 Hive Query 안에서 처리하고 싶어 쿼리를 복잡스럽게 짜보다가(!)
뭔가 UDF라도 있을 것 같아 재미있는 아이를 발견. 

우선, MySQL에서는 GROUP_CONCAT이라는 아이가 있었는데 이렇게 생겼다. 

GROUP_CONCAT([DISTINCT] expr [,expr ...] [ORDER BY {unsigned_integer | col_name | expr} [ASC | DESC] [,col_name ...]] [SEPARATOR str_val])

MySQL기준으로 A -> B를 해보면... 이렇게 짧게 끝난다. 

mysql> select 지역, GROUP_CONCAT (업종) from table_A GROUP BY 지역; 


Hive에서는 약간 다른데 - 
CONCAT_WS, COLLECT_SET 뭐 이런 아이들을 조합해야 한다.

hive> select 지역, CONCAT_WS(',', COLLECT_SET(업종)) from table_A GROUP BY 지역



2017년 8월 11일 금요일

Mac에서의 docker troubleshooting

Mac OS에서 종종 맞닥뜨리는 docker관련 에러들에 대한 troubleshooting을 차차 업데이트 / 정리할 예정.

1. docker container를 시작할 수 없는 경우 
(Error message) docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
See 'docker run --help'.

커맨드 라인에서 다음 명령어 실행
> eval "$(docker-machine env default)"

1.1) 위 명령어에서 또 에러가 나는 경우
(Error message) Error checking TLS connection: Host is not running

커맨드 라인에서 다음 명령어로 TLS Cert를 재생성
> docker-machine regenerate-certs default

1.1.1) TLS Cert 생성이 에러 나는 경우: 아예 docker default machine을 재생성해주자.
> docker-machine rm default
> docker-machine create --driver virtualbox default

1.1.2) 그래도 에러가 나면...
Virtual Box를 직접 실행하고 떠 있는 아이 (Running)는 reset.
다시 1.1.1 실행.

(to be updated)

2017년 3월 25일 토요일

제로카 셰어링 8개월 운영기

* 관련 지난 포스팅
1. 제로카 셰어링 당첨, 그리고 차량 인수
2. 제로카 셰어링 한달 사용기


제로카 1기에 작년 (2016년) 8월에 당첨된 이후 지금까지의 운영기록을 돌아보며...

1. 그래서, '제로카' 운영하며 차량 관련 비용은 얼마나 냈나?
1-1. 제로카 앱에서 확인할 수 있는 청구서 내역.
위에 밝힌바와 같이 2016년 8월부터 2017년 3월 현재까지 제로카를 운영중이며 동기간 동안의 청구서가 발행되어 있는 것을 확인할 수 있다.



1-2. 상세 요금 청구서 내역
12월~2월 동안의 청구서 상세 내역만 가져와 봤다. 아래에서 확인할 수 있듯이 제법(?) 납입금 제로를 달성하고 있다.


2. 셰어링과 수익 Share는 어떻게 운영되나? 
2-1. 앱에서 셰어링을 설정하고 쏘카 고객 (쏘카에서는 이를 '쏘친'이라 부른다.)에 의한 차량 예약이 발생하면 아래와 같이 앱에 나타난다. (쏘친예약 = 1건)

2-2. 셰어링 내역들을 모아보면 이런식. 아래 각 그룹들은 내가 셰어링을 설정한 Time Slot들이며, 해당 Time Slot내에서 대여가 발생하면 아래처럼 나타나게 된다.



2-3. 한개 Time Slot을 상세히 보자. '쏘친'이 언제 빌려가고 반납했는지, 그리고 그 대여건으로 수익 Sharing이 얼마나 발생했는지 확인할 수 있다.


3. 그래서 나는 어떻게 차를 쓰고 셰어링 하고 있나?  
평일에는 도심으로 대중교통을 이용하여 출퇴근 하기 때문에, 위의 3월 실적에서도 확인할 수 있듯이 (총 셰어링시간 26일 17시간 / 1개월) 주중에는 차를 탈일이 거의 없다. 때문에 주말에 차를 이용한 뒤, 일요일 오후 7시 ~ 그 다음주 일요일 오전 10시 정도까지 셰어링을 풀로 열어두는 편이다. 
한줄 댓글, 차량 이용/반납 패턴 등에서 유추해보면, 이렇게 상당히 장기로 셰어링을 하기 때문에 인근 주민 (아파트 주차장 특성상 주민들이 편리하게 이용하고 있다고 예상하고 있다.) 들은 단지 내에 왠만하면 필요할 때 이용할 수 있는 차량이 있다는 것을 점차 인지하고 상대적으로 자주 이용하는 것으로 생각된다. 

4. 총평과 소회
차량구매를 고민하던 시점에 제로카 셰어링에 선정되어 8개월째 이용하면서 대단히 경제적으로 차량을 이용해 오고 있다. 하지만 유무형의 비용도 적잖게 소요된다. 차를 남에게 빌려줌으로써 생기는 각종 불편함과 예상치 못한 일들도 - 오주차, 사고, 실내외 오염, 주유, 등등등 - 정말 빈번하게 발생한다.  

개인적으로는 공유경제의 개념에 많이 공감하며 공유 경제 서비스들이 확산되기를 바란다.  
MIT에서 뉴욕의 데이터로 연구한 결과에 따르면 13,000대에 가까운 뉴욕의 택시는 3,000대 가량의 Riding Share Car로 완전히 대체 가능하다고 한다. (http://www.theverge.com/2017/1/2/14147286/mit-research-nyc-taxi-carpool-uber-lyft)
또 다른 연구에 따르면 미국내 차량은 하루 중 95% 정도의 시간이 주차 상태로 공간만 차지하고 있다고 한다. 

한국도 크게 다르지 않을 것이다.  더욱이 미국보다 대중교통이 잘되어 있으니.
땅덩이도 좁고, 넉넉한 천연자원하나 없으며, 전국민의 50%가량이 수도권에 밀집되어 살고 있고, 요즈음 미세먼지도 심각한 우리나라야 말로 Riding Share Car와 Car Sharing 서비스가 널리 도입되어야 한다고 생각한다. 

하지만 짧지 않은 제로카 운영 경험으로 느낀 것은 아직은 모두가 원활하게 공유 경제에 참여하기에는 일부의 의식 수준이 형편없다는 사실이다. 공유물을 이용하는 이들의 의식 수준 향상과 함께 / 또는 공유 플랫폼 상에서 참여자들을 적절히 제어하고 보상할 수 있는 보완책과 함께 이런 류의 서비스가 많이 확산되어 한정적 자원이 한정적인 공간과 시간안에서 효율적으로 공유되길 바란다. 
지구를 위해, 환경을 위해.

2017년 3월 14일 화요일

박근혜 탄핵 결정문 전문 Word2Vec Visualization w/Tensorflow


https://www.lawtimes.co.kr/Legal-News/Legal-News-View…
헌법재판소의 박근혜 탄핵 결정문 전문을 이용하여,
gensim으로 word2vec model을 만들고 Tensorflow의 embedding projector에 올려봤다.

탄핵 결정문을 읽어보다가 이정미 재판관이 낭독한 판결문과는 다가오는 느낌이 또 달라서, 
- 낭독버전과는 달리 세월호를 비롯하여 불성실한 직무 수행과 관련하여 구체적으로 짚어간다 - 
겸사겸사 word2vec과 Tensorboard를 사용해 보기로 하고 konlpy를 이용한 tokenizing과 간단한 수준의 전처리만 적용하고 돌려봤다.
전처리와 파라미터 튜닝에 시간을 더 쓰면 좀 더 깔끔하게 볼 수 있지 않았을까 싶지만 뭐 간단히만..

'머리'와 '손질', 그리고 그 아래로는 '탈출', 우측으로는 '출입문' 등등이 있는게 참 씁쓸하다.

아래는 Jupyter notebook에서 python으로 export시킨 코드. 
수행 후 tensorboard를 띄우면 됨.

# coding: utf-8

# 

# #### Gensim model building

# In[98]:

# Import required modules
import gensim, codecs
import re

# In[99]:

sentences_vocab = []
for line in codecs.open('impeachment_sentence.txt', encoding='utf-8'):
    sentences = [word+'다.' for word in line.split('다. ') if word!='\n']
    for sentence in sentences:
        sentence = re.sub('\\n다.' , '' ,sentence)
        sentence = re.sub('\\u3000.' , '' ,sentence)
        sentences_vocab.append(sentence)   

# In[101]:

from konlpy.tag import Twitter
pos_tagger = Twitter()

def tokenize(doc):
    return ['/'.join(t) for t in pos_tagger.pos(doc, norm=True, stem=True) ]

# In[102]:

tokenize('전국경제인연합회(다음부터 \'전경련\'이라 한다)가 주도하여 만든 것으로 알려져있던')

# In[103]:

# Preprocessing
sentences_vocab = []
for line in codecs.open('impeachment_sentence.txt', encoding='utf-8'):
    sentences = [word+'다.' for word in line.split('다. ') if word!='\n']
    for sentence in sentences:
        sentences_vocab.append(tokenize(sentence))

# In[104]:

sentences_vocab[41]

# In[105]:

import multiprocessing 
config = { 'min_count': 1, 
          'size': 300, 
          'sg': 1, 
          'batch_words': 10, 
          'iter': 100, 
          'workers': multiprocessing.cpu_count(), } 

model = gensim.models.Word2Vec(**config)

# In[106]:

model.build_vocab(sentences_vocab)

# In[140]:

num_w2v = len(model.wv.index2word)
print (num_w2v)

# In[141]:

import numpy as np
w2v = np.zeros((num_w2v,300))
with open("./projector/metadata.tsv", 'w+') as file_metadata:
    for i,word in enumerate(model.wv.index2word):
        w2v[i] = model[word]
        file_metadata.write(word + '\n')

# #### Tensorflow Visualization

# In[134]:

import tensorflow as tf
from tensorflow.contrib.tensorboard.plugins import projector
import numpy as np

# setup a TensorFlow session
tf.reset_default_graph()
sess = tf.InteractiveSession()

X = tf.Variable([0.0], name='embedding')
place = tf.placeholder(tf.float32, shape=[None, 300])
set_x = tf.assign(X, place, validate_shape=False)

sess.run(tf.global_variables_initializer())
sess.run(set_x, feed_dict={place: w2v})

# create a TensorFlow summary writer
summary_writer = tf.summary.FileWriter('projector', sess.graph)
config = projector.ProjectorConfig()
embedding_conf = config.embeddings.add()
embedding_conf.tensor_name = 'embedding:0'
embedding_conf.metadata_path = './projector/metadata.tsv' 
projector.visualize_embeddings(summary_writer, config)

# save the model
saver = tf.train.Saver()
saver.save(sess, './projector/model.ckpt')
sess.close()

2016년 9월 1일 목요일

Tensorflow와 Docker, Jupyter 환경 설정

Docker Image를 이용하여 Tensorflow를 설치, 테스트 하는 - 몇달만에 띄우다가 까먹어서 헤깔린 내용들을 ㅠㅠ - 과정을 간단히 정리.

Docker의 특성상... 
 - 기존 환경과 완전히 격리시킬 수 있고, 
 - Light-weight container로 Host machine과 비교해도 Performance 또한 거의 손실이 없는 수준이고,  
 - 의존성 높은 tensorflow library 환경을 구축을 한번에 끝낼 수 있으니 
Tensorflow를 테스트해보고 싶은 사람에게는 Docker를 이용한 설치를 적극 추천한다. 
Production환경은 더 고려할게 많으니 논외. 

1. Docker 설치
MAC, 윈도우, 리눅스 모두 https://www.docker.com/ 에서 Installation Binary를 다운로드 받으면 쉽게 설치 가능하다. 
Docker의 Image는 Virtual Machine 이미지 자체,  이미지가 실행되어 떠 있는 아이는 Container 정도로 이해하면 쉽다. 

2. Tensorflow Docker Image Pull / Run
구글에서 제공하는 Tensorflow docker image를 다운로드 후 실행한다.
Docker는 로컬에 이미 image가 있는 경우 image를 container로 로딩, 
없으면 원격에서 image를 pulling 하여 인스톨 후 로딩한다.

간단하게 한줄이면 끝. 
$ docker run -it gcr.io/tensorflow/tensorflow  
Docker image Pull & Run
열심히 다운로드 하고, Jupyter Notebook을 띄웠다고 하고 끝난다. 

친절하게 
The Jupyter Notebook is running at: http://[all ip addresses on your system]:8888/
라고 하니, 어쩐지 늘 하던대로 http://127.0.0.1:8888/ 로 접속해 보자. 
localhost 접속 결과. 안된다.



그냥 접속하면 안된다. -_-;
docker는 container들에 virtual ip를 부여한다. 

VM IP를 확인하고... 
$ docker-machine ip default
virtual ip를 확인하자!

container port forwarding 옵션을 포함하여 다시 실행해주자.
$ docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow
port forwarding과 함께하는 docker

그리고 위에서 확인한 http://192.168.99.100:8888 로 접속해보면...
노트북 리스트가 떴다!
이렇게 jupyter가 뜨면 tensorflow 환경 간단 구축 끝. 

2016년 8월 29일 월요일

iTerm2에서 갑자기 한글이 깨질때

MAC에서 iTerm2를 사용하다가 어느날 갑자기(!) 한글이 깨지기 시작했다.

이리저리 찾다가 조치하고 해결한 방법 메모.

~/.bash_profile 에 [LC_CTYPE="ko_KR.UTF-8"] 을 추가해주고 bash를 재시작하면 해결된다.

2016년 8월 28일 일요일

제로카 셰어링 한달 사용기

제로카 셰어링의 정체와 개인적 경과는 지난번 포스팅 (제로카 셰어링 당첨, 그리고 차량 인수) 참고와 검색을 추천합니다.

제로카 셰어링 한달 운영 결과 / 소회를 메모.
8월 정산내역

주유비 정산등이 빠져있으니 아직 최종 납부 금액이 결정되지는 않았지만,
일단 지난 달 차 사용 및 2차 임대료 관련 정산 결과는 이게 최종이라고 보면 된다.

대여료 부분만 계산하면 VAT 포함 217,800원이 원래 납입금액이고,
2차 임대를 통해 발생한 할인액이 171,427원이 되어서,
결국 46,373원으로 아반떼 AD를 한달간 리스한 셈이다.

동일 차종 취득시 금액을 보수적으로 1,600만원 정도 잡아주고,
적당히 6년 감가상각으로 때려주면 한달에 23만원씩 빠져나가는  - 취등록세, 기타 초기 비용 등도 있고 가속상각으로 적용하면 초반에 훨씬 더 많이 지출될 - 계산인데 꽤 경제적인 것은 사실이다.
당연히 여기에 세금과 보험, 유지비용이 더해지면 매달 지출 비용은 훨씬 더 올라가게 된다.
비교적 모든 결정에 가성비를 생각하는 버릇이 있어, 차량 구매와 비교하면 결과적으로 훌륭한 결정이었다고 생각한다.

하지만 운영 자체는 꽤 많이 신경 쓰인다.
차가 나갔는지, 제대로 정위치에 주차를 해두기는 했는지,
사고를 내지는 않았는지, 실내를 더럽히지는 않았는지,
급가속, 정지 등 차를 험하게 몰지는 않았는지 등등등등등등.

한달이라는 짧은 기간 동안에도,
 - 범퍼를 찢어먹고 돌아오고, (게다가 일종의 뺑소니였다. 박았다는 것을 본인이 알고도 신고를 안 함)
 - 정해진 위치가 아닌 곳에 세워두고 + 밤새 창문을 활짝 열어두고 반납하고,
 - 실내에 모래가 한 가득 쌓이고,
등등 수많은 일들이 있었다.
좌측 앞범퍼 뺑소니 건
어차피 추적 가능한 시스템이라 책임과 비용을 임차인에게 귀속시킬 수 있는데,
운전 자체가 서투른거야 어쩔수 없다고 쳐도 -
도대체 왜 '너도 나도 깨끗하게 관리 잘해서 서로서로 저렴하게 오래 같이 탑시다'는 안되는지. 서비스가 아니라 렌탈 고객의 '기본'이 안된 경우가 많아 아쉬움이 남는다.


또 쏘카의 서비스 자체도 만족스럽지 않은 부분이 많고, 의혹이 생기는 부분들도 생겼다.
기본적으로 콜센터는 항상 연결이 어렵고, 서비스 초기라 내부 프로세스가 안잡혀 있는지 제로카와 쏘카의 상담은 서로 핑퐁치기 바쁘다. 당연히 각 창구를 통한 상담 내역 등도 전혀 공유되지 않고 있다.
앱과 서비스 안정성은 초기 단계라 기능이 빈약하고 불안정하며 오류가 대단히 많다.

게다가 건별로 발생하는 정산 내역에  의구심이 드는 것은..
제로카 계약서에는 분명 '대여자 지불 요금의 50%'를 제로카 요금에서 할인하는 것으로 되어 있는데, 쏘카 이용자가 조기 반납하는 경우 등에 발생하는 쏘카가 받게 되는 일종의 낙전 수입은 제로카 차주에게 정산되지 않고 있다.
쏘카에서 발행한 쿠폰을 사용하여 임차가 발생하는 경우, 쏘카 이용자의 최종 결제액에 쿠폰 할인이 적용되어 예상 금액을 밑도는 대여건이 발생하는 경우도 허다하다.
제로카 계약서

대충 세줄 요약하며 마무리하면...
서비스 전반적으로는 만족하나, 개선할점은 아직 너무 많음.
카셰어링 소비자들의 시민의식은 0점에 수렴 중인 것을 경험하고 있으며,
차량을 주말에만 쓰거나 하는 경우는 제로카 이용을 적극 검토해 볼만 함.