Data2Vis는 seq2seq를 통해 입력되는 데이터를 기반으로 출력으로 차트를 자동생성한다.
개념
해당 논문을 이해하기 위해 다음과 같은 단어의 개념을 이해해야 한다. 소스에서도 같은 용어를 쓰기 때문에 소스이해를 위해서도 중요하다.
- Data2Vis의 데모 사이트에 가면 간략한 설명이 나와 있다.
- Attention mechanism을 이용한 encoder-decoder 아키텍쳐 모델이다.
- key/value 쌍의 데이터를 입력으로 하고 Vega-Lite기반의 출력을 생성한다. Vega-Lite는 JSON기반으로 차트를 생성해주는 스펙이다.
- 특징
+ encoder는 최종 context vector 하나로 만든다. 이것을 C 라고 표현한다. 위이 그림에서 가운데 위치한 C이다.
+ decoder는 학습할 때 encoder의 "C"와 "<go>답안"을 입력받아 "답안<eos>"를 출력하는 학습을 한다. (참조)
+ encoder, decoder의 길이를 정해야 한다. 무한정일 수 없다.
+ 여기서 encoder, decoder는 동시에 학습할 수 있다. (참조)
+ 정답이 있는 데이터만 S2S 학습이 가능하다.
+ 단어들에 대한 벡터화한 수치 사전이 필요하다. (참조)
- beam search
+ RNN의 학습 과정에서 트리 탐색 기법으로 쓰임
+ 최고우선탐색(Best-First-Search)기번을 기본으로 회되 기억해야 하는 노드 수를 제한해 효율성을 높이는 방식
+ beam : 사용자가 기억해야 하는 노드 수
- LSTM
+ Backward Propagation(역전파)할 때에 Gradient Vanishing이나 Exploding되는 현상을 막기 위해 LSTM을 사용한다.
+ 역전파할 때 미분한다. Gradient는 결국 기울기 이고, 미분또한 기울기를 구하는 것으로 역전파를 할 때 미분의 값이 작을 때 Gradient Vanshing이 발생하고, 클때 exploding이 발생한다.
+ Gradient Vanishing에 대한 자세한 설명은 영덕의 연구소를 참조한다.
소스 설치 및 실행
소스를 깃헙에서 클론한다.
$ git clone https://github.com/victordibia/data2vis.git
환경 설정
- Anacoda를 설치
- Python v3.6.5 사용
- Tensorflow v1.9.0 사용 (Anaconda Navigator UI에서 설치하지 않고 conda CLI로 버전을 지정해서 설치한다.)
$ conda install -c conda-forge tensorflow=1.9.0
모듈 설치
- requirements.txt는 node.js의 package.json역할
$ cd data2vis
$ pip install -r requirements.txt
실행하기
$ python webserver.py
브라우져에서 http://localhost:5016/ 호출
디버깅하기
MS Code에서 다음 항목을 추가한다.
- port: listen 포트
- model_dir: 모델이 있는곳, 이곳에 seq2seq의 환경파일인 train_options.json 파일이 존재해야 한다.
해당 파일은 training 시킨 결과를 통해 자동으로 생성된다. 훈련시키는 방법에 대해서는 두번째 글 참조.
- beam_width: 사용자가 기억해야 하는 노드수 5개
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Data2Vis - Flask (0.11.x or later)",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/webserver.py",
"env": {
"FLASK_APP": "${workspaceFolder}/webserver.py",
"FLASK_ENV": "development"
},
"args": [
"--port=5016",
"--model_dir=vizmodel",
"--beam_width=15"
]
},
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}"
},
.....
}
샘플 실행
- 좌측 examples 메뉴를 클릭하고 입력창에 1이상의 값을 넣고, "Generate Examples" 버튼을 클릭하면 차트가 생성된다.
seq2seq 모듈
구글이 개발한 tf-seq2seq 모듈 소스을 data2vis 폴더에 그대로 copy해 놓은 상태이다. 모델을 학습하고 검증하는 것은 실제 seq2seq가 하므로 tf-seq2seq 사용방법을 알아야 한다.
- tf-seq2seq 소개 블로그: Goolge NMT 논문 필수
- seq2seq에 대한 기본 설명은 Arxiv의 Neural Machine Translation 논문을 참조한다.
- Tensorflow의 seq2seq 사용법
Configuration Training
- 환경파일에는 Input data, model, training parameter를 정의한다.
- vismodel의 train_options.json 파일을 사용한다.
- optimizer 종류와 learning_rate등을 지정. Adam 옵티마이저를 사용.
- vocab_target, vocab_source 임베딩을 위한 벡터 카운트를 만들기 위해 파일 지정
- decoder, encoder class와 params을 설정. 둘 다 LSTMCell 사용
- attention class와 params 설정
- inference, bridge, embedding 설정
- source/target.max_seq_len 으로 string의 크기 지정
- 모델 옵션 설명
- 인코더 옵션 설명
- 디코더 옵션 설명
{
"model_class": "AttentionSeq2Seq",
"model_params": {
"optimizer.name": "Adam",
"decoder.class": "seq2seq.decoders.AttentionDecoder",
"inference.beam_search.beam_width": 5,
"decoder.params": {
"rnn_cell": {
"dropout_input_keep_prob": 0.5,
"num_layers": 2,
"cell_params": {
"num_units": 512
},
"dropout_output_keep_prob": 1.0,
"cell_class": "LSTMCell"
},
"max_decode_length": 2000
},
"optimizer.learning_rate": 0.0001,
"source.reverse": false,
"source.max_seq_len": 500,
"attention.params": {
"num_units": 512
},
"attention.class": "seq2seq.decoders.attention.AttentionLayerDot",
"vocab_target": "sourcedata/vocab.target",
"target.max_seq_len": 500,
"optimizer.params": {
"epsilon": 8e-07
},
"bridge.class": "seq2seq.models.bridges.ZeroBridge",
"vocab_source": "sourcedata/vocab.source",
"encoder.params": {
"rnn_cell": {
"dropout_input_keep_prob": 0.5,
"num_layers": 2,
"cell_params": {
"num_units": 512
},
"dropout_output_keep_prob": 1.0,
"cell_class": "LSTMCell"
}
},
"encoder.class": "seq2seq.encoders.BidirectionalRNNEncoder",
"embedding.dim": 512
}
}
Training
- 모델과 교육데이터가 갖추어져 있으면 훈련을 수행한다.
- /sourcedata안에 source, target의 trainig data가 존재한다.
- utils/data_gen.py에서 /examples 폴더의 vega spec을 읽어와 training data를 만들고 있다.
Prediction
- 모델 Training을 받은 후 예측을 시작할 수 있다.
- DecodeText 클래스를 사용하고, Input pipeline은 ParallelTextInputPipeline을 사용함.
+ DecodeText는 모델 예측을 가져와 표준 출력으로 추력하는 작업을 수행함
+ DumpAttention과 DumpBeams을 이용해 모델 수행시 디버깅을 할 수 있다. 파일로 쓰는 것임.
+ input pipline은 데이터를 읽는 방법을 정의한다.
Decoding with Beam Search
- 빔 검색은 번역 성능을 향상시키는 일반적으로 사용되는 디코딩 기술이다.
- 빔 검색은 메모리에 가설 또는 빔(beam)을 놓고 가장 높은 점수인 것을 선택한다.
Evaluating specific checkpoint
- Training을 통해 다양한 모델의 체크포인트를 저장한다.
- BLEU (bilingual evaluation understudy)를 통해 번역 성능 평가.
Checkpoint에 대한 설명
- Saving
+ model 을 만드는 코드 의존적인 포멧을 갖는다.
+ 체크포인트는 training하며 생성된 모델의 버전이다.
+ Estimator가 checkpoint를 model_dir 위치에 저장한다.
+ events 파일은 tensorboard가 시각시에 사용한다.
+ Saver를 통해 체크포인트를 Saving/Restoring 한다.
checkpoint
events.out.tfevents.timestamp.hostname
graph.pbtxt
model.ckpt-1.data-00000-of-00001
model.ckpt-1.index
model.ckpt-1.meta
model.ckpt-200.data-00000-of-00001
model.ckpt-200.index
model.ckpt-200.meta
- Restoring
+ Estimator는 train()을 호출하면 model의 그래프를 model_fn()을 호출해서 생성한다.
+ Estimator는 최근의 checkpoint를 통해 새로운 모델의 weight을 초기화 한다.
webserver.py 이해
파이썬 웹서비스는 Flask를 이용한다. data2vis/static 과 templates가 Flask운영을 위해 사용된다.
webserver.py 실행 순서
- port, vizmodel, beam_width를 아규먼트를 받는다.
- vizmodel/train_options.json을 기반으로 TrainOption 오브젝트를 생성
train_options = training_utils.TrainOptions.load(model_dir_input)
- model params을 사용해 model class를 생성함. AttensionSeq2Seq.py (attension_seq2seq.py)
model_params = _deep_merge_dict(model_params, _maybe_load_yaml(model_params))
model = model_cls(params=model_params, mode=tf.contrib.learn.ModeKeys.INFER)
- inference task 생성. DecodeText 생성
if (str(tdict["class"]) == "DecodeText"):
task = task_cls(tdict["params"], callback_func=_save_prediction_to_dict)
- ParallelTextInputPipeline pipeline 생성
input_pipeline_infer = input_pipeline.make_input_pipeline_from_def(
fl_input_pipeline,
mode=tf.contrib.learn.ModeKeys.INFER,
shuffle=False,
num_epochs=1)
- inference를 사용하는 (Tensorflow) graph 생성.
+ seq2seq/inference/inference.py에서 pipeline과 batch_size를 통해 input function을 만들고
+ input function의 feature와 label을 model의 파라미터로 사용해서 model의 build를 호출한다.
predictions, _, _ = create_inference_graph( model=model, input_pipeline=input_pipeline_infer, batch_size=batch_size)
- Listen을 하고, Flask의 routing을 설정한다. "Generate Examples" 버튼 클릭시 호출
+ test data를 사용한다.
+ normalize를 해준다. (foward_norm, backward_norm)
+ decode result를 가지고 vega spec을 만들어 return한다.
@app.route("/examplesdata")
def examplesdata():
source_data = data_utils.load_test_dataset()
f_names = data_utils.generate_field_types(source_data)
data_utils.forward_norm(source_data, destination_file, f_names)
run_inference()
decoded_string_post = data_utils.backward_norm(decoded_string[0], f_names)
try:
vega_spec = json.loads(decoded_string_post)
vega_spec["data"] = {"values": source_data}
response_payload = {"vegaspec": vega_spec, "status": True}
except JSONDecodeError as e:
response_payload = {
"status": False,
"reason": "Model did not produce a valid vegalite JSON",
"vegaspec": decoded_string
}
return jsonify(response_payload)
<참조>
- Data2Vis 소개글, 깃헙 소스, Arxiv 링크
- deeep 블로그
seq2seq 에 대한 쉬운 설명글
Attention 메카니즘설명 (소개한 Arxiv 링크)
- ratsgo 블로그
RNN과 LSTM 이해
seq2seq를 이용한 뉴스 제목 추출하기
설명에 대한 소스 (2018년 tensorflow 버전에 맞지않다)
beam search 이해 in Recursive Neural Network
- 구글 제공
seq2seq 문서
- Tensorflow의 seq2seq 한글 설명, 2014년 Arxiv에 소개된 seq2seq pdf
- 라온피플 블로그
RNN, LSTM, GRU 소개
- 영덕의 연구소 블로그
Gradient Vanishing 문제 개념
- Naivsphere 블로그
SGD (Stochastic Gradient Descent)에 대한 글
- 카카오 IT 브런치
BLEU: NMT 평가 방식 설명
- skymind.ai
- epoch, batch_size 용어 이해 (MNIST epoch, batch 설명)