Repository: naver/claf Branch: master Commit: 6f45b1ecca0a Files: 660 Total size: 7.8 MB Directory structure: gitextract_t48_1t0e/ ├── .coveragerc ├── .gitignore ├── .nojekyll ├── .readthedocs.yml ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── NOTICE ├── README.md ├── base_config/ │ ├── cola/ │ │ ├── bert_base_uncased.json │ │ ├── bert_large_uncased.json │ │ └── structured_self_attention.json │ ├── conll2003/ │ │ └── bert_large_cased.json │ ├── glue/ │ │ ├── cola_bert.json │ │ ├── cola_roberta.json │ │ ├── mnlim_bert.json │ │ ├── mnlim_roberta.json │ │ ├── mnlimm_bert.json │ │ ├── mnlimm_roberta.json │ │ ├── mrpc_bert.json │ │ ├── mrpc_roberta.json │ │ ├── qnli_bert.json │ │ ├── qnli_roberta.json │ │ ├── qqp_bert.json │ │ ├── qqp_roberta.json │ │ ├── rte_bert.json │ │ ├── rte_roberta.json │ │ ├── sst_bert.json │ │ ├── sst_roberta.json │ │ ├── stsb_bert.json │ │ ├── stsb_roberta.json │ │ ├── wnli_bert.json │ │ └── wnli_roberta.json │ ├── korquad/ │ │ ├── bert_base_multilingual_cased.yaml │ │ ├── bert_base_multilingual_uncased.json │ │ ├── bidaf.json │ │ └── docqa.json │ ├── multi_task/ │ │ ├── bert_base_glue+squad.json │ │ ├── bert_base_glue.json │ │ ├── bert_large_glue+squad.json │ │ └── bert_large_glue.json │ ├── squad/ │ │ ├── bert_base_uncased.json │ │ ├── bert_large_uncased.json │ │ ├── bidaf+elmo.json │ │ ├── bidaf.json │ │ ├── bidaf_no_answer.json │ │ ├── docqa+elmo.json │ │ ├── docqa.json │ │ ├── docqa_no_answer.json │ │ ├── drqa.json │ │ ├── drqa_paper.json │ │ ├── qanet.json │ │ ├── qanet_paper.json │ │ ├── roberta_base.json │ │ └── roberta_large.json │ ├── test/ │ │ ├── bert_for_multi_task.json │ │ ├── bert_for_qa.yaml │ │ ├── bert_for_seq_cls.json │ │ ├── bert_for_tok_cls.json │ │ ├── bidaf+bert.json │ │ ├── bidaf+cove.json │ │ ├── bidaf+elmo.json │ │ ├── bidaf.yaml │ │ ├── bidaf_no_answer.json │ │ ├── cola_bert.json │ │ ├── cola_roberta.json │ │ ├── docqa.json │ │ ├── docqa_no_answer.json │ │ ├── drqa.json │ │ ├── drqa_sparse_to_embedding.json │ │ ├── mnlim_bert.json │ │ ├── mrpc_bert.json │ │ ├── mt_bert.json │ │ ├── open_qa.json │ │ ├── qanet.json │ │ ├── qnli_bert.json │ │ ├── qqp_bert.json │ │ ├── roberta_for_qa.json │ │ ├── rte_bert.json │ │ ├── rte_roberta.json │ │ ├── sqlnet.json │ │ ├── ssa.json │ │ ├── sst_bert.json │ │ ├── stsb_bert.json │ │ ├── stsb_roberta.json │ │ └── wnli_bert.json │ └── wikisql/ │ └── sqlnet.json ├── claf/ │ ├── __init__.py │ ├── __version__.py │ ├── config/ │ │ ├── __init__.py │ │ ├── args.py │ │ ├── namespace.py │ │ ├── pattern.py │ │ ├── registry.py │ │ └── utils.py │ ├── data/ │ │ ├── __init__.py │ │ ├── collate.py │ │ ├── data_handler.py │ │ ├── dataset/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── bert/ │ │ │ │ ├── __init__.py │ │ │ │ ├── multi_task.py │ │ │ │ ├── regression.py │ │ │ │ ├── seq_cls.py │ │ │ │ ├── squad.py │ │ │ │ └── tok_cls.py │ │ │ ├── seq_cls.py │ │ │ ├── squad.py │ │ │ └── wikisql.py │ │ ├── dto/ │ │ │ ├── __init__.py │ │ │ ├── batch.py │ │ │ ├── bert_feature.py │ │ │ └── helper.py │ │ ├── reader/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── bert/ │ │ │ │ ├── __init__.py │ │ │ │ ├── conll2003.py │ │ │ │ ├── glue/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── cola.py │ │ │ │ │ ├── mnli.py │ │ │ │ │ ├── mrpc.py │ │ │ │ │ ├── qnli.py │ │ │ │ │ ├── qqp.py │ │ │ │ │ ├── rte.py │ │ │ │ │ ├── sst.py │ │ │ │ │ ├── stsb.py │ │ │ │ │ └── wnli.py │ │ │ │ ├── multi_task.py │ │ │ │ ├── regression.py │ │ │ │ ├── seq_cls.py │ │ │ │ ├── squad.py │ │ │ │ └── tok_cls.py │ │ │ ├── cola.py │ │ │ ├── seq_cls.py │ │ │ ├── squad.py │ │ │ └── wikisql.py │ │ └── utils.py │ ├── decorator/ │ │ ├── __init__.py │ │ ├── arguments.py │ │ └── register.py │ ├── factory/ │ │ ├── __init__.py │ │ ├── base.py │ │ ├── data_loader.py │ │ ├── data_reader.py │ │ ├── model.py │ │ ├── optimizer.py │ │ └── tokens.py │ ├── learn/ │ │ ├── __init__.py │ │ ├── experiment.py │ │ ├── mode.py │ │ ├── optimization/ │ │ │ ├── __init__.py │ │ │ ├── exponential_moving_avarage.py │ │ │ ├── learning_rate_scheduler.py │ │ │ └── optimizer.py │ │ ├── tensorboard.py │ │ ├── trainer.py │ │ └── utils.py │ ├── machine/ │ │ ├── __init__.py │ │ ├── base.py │ │ ├── components/ │ │ │ ├── __init__.py │ │ │ └── retrieval/ │ │ │ ├── __init__.py │ │ │ └── tfidf.py │ │ ├── ensemble_topk.py │ │ ├── knowlege_base/ │ │ │ ├── __init__.py │ │ │ └── docs.py │ │ ├── module.py │ │ ├── nlu.py │ │ └── open_qa.py │ ├── metric/ │ │ ├── __init__.py │ │ ├── classification.py │ │ ├── glue.py │ │ ├── korquad_v1_official.py │ │ ├── regression.py │ │ ├── squad_v1_official.py │ │ ├── squad_v2_official.py │ │ ├── wikisql_lib/ │ │ │ ├── __init__.py │ │ │ ├── dbengine.py │ │ │ └── query.py │ │ └── wikisql_official.py │ ├── model/ │ │ ├── __init__.py │ │ ├── base.py │ │ ├── cls_utils.py │ │ ├── multi_task/ │ │ │ ├── __init__.py │ │ │ ├── bert.py │ │ │ ├── category.py │ │ │ └── mixin.py │ │ ├── reading_comprehension/ │ │ │ ├── __init__.py │ │ │ ├── bert.py │ │ │ ├── bidaf.py │ │ │ ├── bidaf_no_answer.py │ │ │ ├── docqa.py │ │ │ ├── docqa_no_answer.py │ │ │ ├── drqa.py │ │ │ ├── mixin.py │ │ │ ├── qanet.py │ │ │ └── roberta.py │ │ ├── regression/ │ │ │ ├── __init__.py │ │ │ ├── bert.py │ │ │ ├── mixin.py │ │ │ └── roberta.py │ │ ├── semantic_parsing/ │ │ │ ├── __init__.py │ │ │ ├── mixin.py │ │ │ ├── sqlnet.py │ │ │ └── utils.py │ │ ├── sequence_classification/ │ │ │ ├── __init__.py │ │ │ ├── bert.py │ │ │ ├── mixin.py │ │ │ ├── roberta.py │ │ │ └── structured_self_attention.py │ │ └── token_classification/ │ │ ├── __init__.py │ │ ├── bert.py │ │ └── mixin.py │ ├── modules/ │ │ ├── __init__.py │ │ ├── activation.py │ │ ├── attention/ │ │ │ ├── __init__.py │ │ │ ├── bi_attention.py │ │ │ ├── co_attention.py │ │ │ ├── docqa_attention.py │ │ │ ├── multi_head_attention.py │ │ │ └── seq_attention.py │ │ ├── conv/ │ │ │ ├── __init__.py │ │ │ ├── depthwise_separable_conv.py │ │ │ └── pointwise_conv.py │ │ ├── encoder/ │ │ │ ├── __init__.py │ │ │ ├── lstm_cell_with_projection.py │ │ │ └── positional.py │ │ ├── functional.py │ │ ├── initializer.py │ │ └── layer/ │ │ ├── __init__.py │ │ ├── highway.py │ │ ├── normalization.py │ │ ├── positionwise.py │ │ ├── residual.py │ │ └── scalar_mix.py │ ├── nsml.py │ ├── tokens/ │ │ ├── __init__.py │ │ ├── cove.py │ │ ├── elmo.py │ │ ├── embedding/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── bert_embedding.py │ │ │ ├── char_embedding.py │ │ │ ├── cove_embedding.py │ │ │ ├── elmo_embedding.py │ │ │ ├── frequent_word_embedding.py │ │ │ ├── sparse_feature.py │ │ │ └── word_embedding.py │ │ ├── hangul.py │ │ ├── indexer/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── bert_indexer.py │ │ │ ├── char_indexer.py │ │ │ ├── elmo_indexer.py │ │ │ ├── exact_match_indexer.py │ │ │ ├── linguistic_indexer.py │ │ │ └── word_indexer.py │ │ ├── linguistic.py │ │ ├── text_handler.py │ │ ├── token_embedder/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── basic_embedder.py │ │ │ └── reading_comprehension_embedder.py │ │ ├── token_maker.py │ │ ├── tokenizer/ │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── bpe.py │ │ │ ├── char.py │ │ │ ├── pass_text.py │ │ │ ├── sent.py │ │ │ ├── subword.py │ │ │ ├── utils.py │ │ │ └── word.py │ │ └── vocabulary.py │ └── utils.py ├── docs/ │ ├── Makefile │ ├── _build/ │ │ ├── doctrees/ │ │ │ ├── claf.config.doctree │ │ │ ├── claf.config.factory.doctree │ │ │ ├── claf.data.dataset.doctree │ │ │ ├── claf.data.doctree │ │ │ ├── claf.data.reader.bert.doctree │ │ │ ├── claf.data.reader.doctree │ │ │ ├── claf.decorator.doctree │ │ │ ├── claf.doctree │ │ │ ├── claf.learn.doctree │ │ │ ├── claf.machine.components.doctree │ │ │ ├── claf.machine.components.retrieval.doctree │ │ │ ├── claf.machine.doctree │ │ │ ├── claf.metric.doctree │ │ │ ├── claf.model.doctree │ │ │ ├── claf.model.reading_comprehension.doctree │ │ │ ├── claf.model.semantic_parsing.doctree │ │ │ ├── claf.model.sequence_classification.doctree │ │ │ ├── claf.model.token_classification.doctree │ │ │ ├── claf.modules.attention.doctree │ │ │ ├── claf.modules.conv.doctree │ │ │ ├── claf.modules.doctree │ │ │ ├── claf.modules.encoder.doctree │ │ │ ├── claf.modules.layer.doctree │ │ │ ├── claf.tokens.doctree │ │ │ ├── claf.tokens.embedding.doctree │ │ │ ├── claf.tokens.indexer.doctree │ │ │ ├── claf.tokens.token_embedder.doctree │ │ │ ├── claf.tokens.tokenizer.doctree │ │ │ ├── contents/ │ │ │ │ ├── dataset_and_model.doctree │ │ │ │ ├── pretrained_vector.doctree │ │ │ │ └── tokens.doctree │ │ │ ├── environment.pickle │ │ │ ├── index.doctree │ │ │ ├── modules.doctree │ │ │ ├── references.doctree │ │ │ ├── reports/ │ │ │ │ ├── glue.doctree │ │ │ │ ├── historyqa.doctree │ │ │ │ ├── korquad.doctree │ │ │ │ ├── squad.doctree │ │ │ │ └── wikisql.doctree │ │ │ └── summary/ │ │ │ └── reading_comprehension.doctree │ │ └── html/ │ │ ├── .buildinfo │ │ ├── .nojekyll │ │ ├── _modules/ │ │ │ ├── claf/ │ │ │ │ ├── config/ │ │ │ │ │ ├── args.html │ │ │ │ │ ├── factory/ │ │ │ │ │ │ ├── base.html │ │ │ │ │ │ ├── data_loader.html │ │ │ │ │ │ ├── data_reader.html │ │ │ │ │ │ ├── model.html │ │ │ │ │ │ ├── optimizer.html │ │ │ │ │ │ └── tokens.html │ │ │ │ │ ├── namespace.html │ │ │ │ │ ├── pattern.html │ │ │ │ │ ├── registry.html │ │ │ │ │ └── utils.html │ │ │ │ ├── data/ │ │ │ │ │ ├── batch.html │ │ │ │ │ ├── collate.html │ │ │ │ │ ├── data_handler.html │ │ │ │ │ ├── dataset/ │ │ │ │ │ │ ├── base.html │ │ │ │ │ │ ├── bert/ │ │ │ │ │ │ │ ├── multi_task.html │ │ │ │ │ │ │ ├── regression.html │ │ │ │ │ │ │ ├── seq_cls.html │ │ │ │ │ │ │ ├── squad.html │ │ │ │ │ │ │ └── tok_cls.html │ │ │ │ │ │ ├── seq_cls.html │ │ │ │ │ │ ├── seq_cls_bert.html │ │ │ │ │ │ ├── squad.html │ │ │ │ │ │ ├── squad_bert.html │ │ │ │ │ │ ├── tok_cls_bert.html │ │ │ │ │ │ └── wikisql.html │ │ │ │ │ ├── reader/ │ │ │ │ │ │ ├── base.html │ │ │ │ │ │ ├── bert/ │ │ │ │ │ │ │ ├── cola.html │ │ │ │ │ │ │ ├── conll2003.html │ │ │ │ │ │ │ ├── glue/ │ │ │ │ │ │ │ │ ├── cola.html │ │ │ │ │ │ │ │ ├── mnli.html │ │ │ │ │ │ │ │ ├── mrpc.html │ │ │ │ │ │ │ │ ├── qnli.html │ │ │ │ │ │ │ │ ├── qqp.html │ │ │ │ │ │ │ │ ├── rte.html │ │ │ │ │ │ │ │ ├── sst.html │ │ │ │ │ │ │ │ ├── stsb.html │ │ │ │ │ │ │ │ └── wnli.html │ │ │ │ │ │ │ ├── mnli.html │ │ │ │ │ │ │ ├── mrpc.html │ │ │ │ │ │ │ ├── multi_task.html │ │ │ │ │ │ │ ├── qnli.html │ │ │ │ │ │ │ ├── qqp.html │ │ │ │ │ │ │ ├── regression.html │ │ │ │ │ │ │ ├── rte.html │ │ │ │ │ │ │ ├── seq_cls.html │ │ │ │ │ │ │ ├── squad.html │ │ │ │ │ │ │ ├── sst.html │ │ │ │ │ │ │ ├── stsb.html │ │ │ │ │ │ │ ├── tok_cls.html │ │ │ │ │ │ │ └── wnli.html │ │ │ │ │ │ ├── cola.html │ │ │ │ │ │ ├── seq_cls.html │ │ │ │ │ │ ├── squad.html │ │ │ │ │ │ └── wikisql.html │ │ │ │ │ └── utils.html │ │ │ │ ├── decorator/ │ │ │ │ │ ├── arguments.html │ │ │ │ │ └── register.html │ │ │ │ ├── learn/ │ │ │ │ │ ├── experiment.html │ │ │ │ │ ├── mode.html │ │ │ │ │ ├── tensorboard.html │ │ │ │ │ ├── trainer.html │ │ │ │ │ └── utils.html │ │ │ │ ├── machine/ │ │ │ │ │ ├── base.html │ │ │ │ │ ├── components/ │ │ │ │ │ │ └── retrieval/ │ │ │ │ │ │ └── tfidf.html │ │ │ │ │ ├── module.html │ │ │ │ │ ├── nlu.html │ │ │ │ │ └── open_qa.html │ │ │ │ ├── metric/ │ │ │ │ │ ├── classification.html │ │ │ │ │ ├── squad_v1_official.html │ │ │ │ │ ├── squad_v2_official.html │ │ │ │ │ └── wikisql_official.html │ │ │ │ ├── model/ │ │ │ │ │ ├── base.html │ │ │ │ │ ├── cls_utils.html │ │ │ │ │ ├── reading_comprehension/ │ │ │ │ │ │ ├── bert.html │ │ │ │ │ │ ├── bert_for_qa.html │ │ │ │ │ │ ├── bidaf.html │ │ │ │ │ │ ├── bidaf_no_answer.html │ │ │ │ │ │ ├── docqa.html │ │ │ │ │ │ ├── docqa_no_answer.html │ │ │ │ │ │ ├── drqa.html │ │ │ │ │ │ ├── mixin.html │ │ │ │ │ │ ├── qanet.html │ │ │ │ │ │ └── roberta.html │ │ │ │ │ ├── semantic_parsing/ │ │ │ │ │ │ ├── mixin.html │ │ │ │ │ │ ├── sqlnet.html │ │ │ │ │ │ └── utils.html │ │ │ │ │ ├── sequence_classification/ │ │ │ │ │ │ ├── bert.html │ │ │ │ │ │ ├── bert_for_seq_cls.html │ │ │ │ │ │ ├── mixin.html │ │ │ │ │ │ ├── roberta.html │ │ │ │ │ │ └── structured_self_attention.html │ │ │ │ │ └── token_classification/ │ │ │ │ │ ├── bert.html │ │ │ │ │ ├── bert_for_tok_cls.html │ │ │ │ │ └── mixin.html │ │ │ │ ├── modules/ │ │ │ │ │ ├── activation.html │ │ │ │ │ ├── attention/ │ │ │ │ │ │ ├── bi_attention.html │ │ │ │ │ │ ├── co_attention.html │ │ │ │ │ │ ├── docqa_attention.html │ │ │ │ │ │ ├── multi_head_attention.html │ │ │ │ │ │ └── seq_attention.html │ │ │ │ │ ├── conv/ │ │ │ │ │ │ ├── depthwise_separable_conv.html │ │ │ │ │ │ └── pointwise_conv.html │ │ │ │ │ ├── encoder/ │ │ │ │ │ │ ├── lstm_cell_with_projection.html │ │ │ │ │ │ └── positional.html │ │ │ │ │ ├── functional.html │ │ │ │ │ ├── initializer.html │ │ │ │ │ └── layer/ │ │ │ │ │ ├── highway.html │ │ │ │ │ ├── normalization.html │ │ │ │ │ ├── positionwise.html │ │ │ │ │ ├── residual.html │ │ │ │ │ └── scalar_mix.html │ │ │ │ ├── tokens/ │ │ │ │ │ ├── cove.html │ │ │ │ │ ├── elmo.html │ │ │ │ │ ├── embedding/ │ │ │ │ │ │ ├── base.html │ │ │ │ │ │ ├── bert_embedding.html │ │ │ │ │ │ ├── char_embedding.html │ │ │ │ │ │ ├── cove_embedding.html │ │ │ │ │ │ ├── elmo_embedding.html │ │ │ │ │ │ ├── frequent_word_embedding.html │ │ │ │ │ │ ├── sparse_feature.html │ │ │ │ │ │ └── word_embedding.html │ │ │ │ │ ├── hangul.html │ │ │ │ │ ├── indexer/ │ │ │ │ │ │ ├── base.html │ │ │ │ │ │ ├── bert_indexer.html │ │ │ │ │ │ ├── char_indexer.html │ │ │ │ │ │ ├── elmo_indexer.html │ │ │ │ │ │ ├── exact_match_indexer.html │ │ │ │ │ │ ├── linguistic_indexer.html │ │ │ │ │ │ └── word_indexer.html │ │ │ │ │ ├── linguistic.html │ │ │ │ │ ├── text_handler.html │ │ │ │ │ ├── token_embedder/ │ │ │ │ │ │ ├── base.html │ │ │ │ │ │ ├── basic_embedder.html │ │ │ │ │ │ └── reading_comprehension_embedder.html │ │ │ │ │ ├── token_maker.html │ │ │ │ │ ├── tokenizer/ │ │ │ │ │ │ ├── base.html │ │ │ │ │ │ ├── bpe.html │ │ │ │ │ │ ├── char.html │ │ │ │ │ │ ├── pass_text.html │ │ │ │ │ │ ├── sent.html │ │ │ │ │ │ ├── subword.html │ │ │ │ │ │ ├── utils.html │ │ │ │ │ │ └── word.html │ │ │ │ │ └── vocabulary.html │ │ │ │ ├── tokens.html │ │ │ │ └── utils.html │ │ │ ├── index.html │ │ │ ├── logging.html │ │ │ └── pathlib.html │ │ ├── _sources/ │ │ │ ├── claf.config.factory.rst.txt │ │ │ ├── claf.config.rst.txt │ │ │ ├── claf.data.dataset.rst.txt │ │ │ ├── claf.data.reader.bert.rst.txt │ │ │ ├── claf.data.reader.rst.txt │ │ │ ├── claf.data.rst.txt │ │ │ ├── claf.decorator.rst.txt │ │ │ ├── claf.learn.rst.txt │ │ │ ├── claf.machine.components.retrieval.rst.txt │ │ │ ├── claf.machine.components.rst.txt │ │ │ ├── claf.machine.rst.txt │ │ │ ├── claf.metric.rst.txt │ │ │ ├── claf.model.reading_comprehension.rst.txt │ │ │ ├── claf.model.rst.txt │ │ │ ├── claf.model.semantic_parsing.rst.txt │ │ │ ├── claf.model.sequence_classification.rst.txt │ │ │ ├── claf.model.token_classification.rst.txt │ │ │ ├── claf.modules.attention.rst.txt │ │ │ ├── claf.modules.conv.rst.txt │ │ │ ├── claf.modules.encoder.rst.txt │ │ │ ├── claf.modules.layer.rst.txt │ │ │ ├── claf.modules.rst.txt │ │ │ ├── claf.rst.txt │ │ │ ├── claf.tokens.embedding.rst.txt │ │ │ ├── claf.tokens.indexer.rst.txt │ │ │ ├── claf.tokens.rst.txt │ │ │ ├── claf.tokens.token_embedder.rst.txt │ │ │ ├── claf.tokens.tokenizer.rst.txt │ │ │ ├── contents/ │ │ │ │ ├── dataset_and_model.md.txt │ │ │ │ ├── pretrained_vector.md.txt │ │ │ │ └── tokens.md.txt │ │ │ ├── index.rst.txt │ │ │ ├── modules.rst.txt │ │ │ ├── references.md.txt │ │ │ ├── reports/ │ │ │ │ ├── glue.md.txt │ │ │ │ ├── historyqa.md.txt │ │ │ │ ├── korquad.md.txt │ │ │ │ ├── squad.md.txt │ │ │ │ └── wikisql.md.txt │ │ │ └── summary/ │ │ │ └── reading_comprehension.md.txt │ │ ├── _static/ │ │ │ ├── basic.css │ │ │ ├── css/ │ │ │ │ ├── badge_only.css │ │ │ │ └── theme.css │ │ │ ├── doctools.js │ │ │ ├── documentation_options.js │ │ │ ├── jquery-3.2.1.js │ │ │ ├── jquery-3.4.1.js │ │ │ ├── jquery.js │ │ │ ├── js/ │ │ │ │ └── theme.js │ │ │ ├── language_data.js │ │ │ ├── pygments.css │ │ │ ├── searchtools.js │ │ │ ├── theme_overrides.css │ │ │ ├── underscore-1.3.1.js │ │ │ ├── underscore.js │ │ │ └── websupport.js │ │ ├── claf.config.factory.html │ │ ├── claf.config.html │ │ ├── claf.data.dataset.html │ │ ├── claf.data.html │ │ ├── claf.data.reader.bert.html │ │ ├── claf.data.reader.html │ │ ├── claf.decorator.html │ │ ├── claf.html │ │ ├── claf.learn.html │ │ ├── claf.machine.components.html │ │ ├── claf.machine.components.retrieval.html │ │ ├── claf.machine.html │ │ ├── claf.metric.html │ │ ├── claf.model.html │ │ ├── claf.model.reading_comprehension.html │ │ ├── claf.model.semantic_parsing.html │ │ ├── claf.model.sequence_classification.html │ │ ├── claf.model.token_classification.html │ │ ├── claf.modules.attention.html │ │ ├── claf.modules.conv.html │ │ ├── claf.modules.encoder.html │ │ ├── claf.modules.html │ │ ├── claf.modules.layer.html │ │ ├── claf.tokens.embedding.html │ │ ├── claf.tokens.html │ │ ├── claf.tokens.indexer.html │ │ ├── claf.tokens.token_embedder.html │ │ ├── claf.tokens.tokenizer.html │ │ ├── contents/ │ │ │ ├── dataset_and_model.html │ │ │ ├── pretrained_vector.html │ │ │ └── tokens.html │ │ ├── genindex.html │ │ ├── index.html │ │ ├── modules.html │ │ ├── objects.inv │ │ ├── py-modindex.html │ │ ├── references.html │ │ ├── reports/ │ │ │ ├── glue.html │ │ │ ├── historyqa.html │ │ │ ├── korquad.html │ │ │ ├── squad.html │ │ │ └── wikisql.html │ │ ├── search.html │ │ ├── searchindex.js │ │ └── summary/ │ │ └── reading_comprehension.html │ ├── _static/ │ │ └── theme_overrides.css │ ├── _templates/ │ │ ├── modules.rst │ │ └── package.rst │ ├── claf.config.factory.rst │ ├── claf.config.rst │ ├── claf.data.dataset.rst │ ├── claf.data.reader.bert.rst │ ├── claf.data.reader.rst │ ├── claf.data.rst │ ├── claf.decorator.rst │ ├── claf.learn.rst │ ├── claf.machine.components.retrieval.rst │ ├── claf.machine.components.rst │ ├── claf.machine.rst │ ├── claf.metric.rst │ ├── claf.model.reading_comprehension.rst │ ├── claf.model.rst │ ├── claf.model.semantic_parsing.rst │ ├── claf.model.sequence_classification.rst │ ├── claf.model.token_classification.rst │ ├── claf.modules.attention.rst │ ├── claf.modules.conv.rst │ ├── claf.modules.encoder.rst │ ├── claf.modules.layer.rst │ ├── claf.modules.rst │ ├── claf.rst │ ├── claf.tokens.embedding.rst │ ├── claf.tokens.indexer.rst │ ├── claf.tokens.rst │ ├── claf.tokens.token_embedder.rst │ ├── claf.tokens.tokenizer.rst │ ├── conf.py │ ├── contents/ │ │ ├── dataset_and_model.md │ │ ├── pretrained_vector.md │ │ └── tokens.md │ ├── index.rst │ ├── make.bat │ ├── modules.rst │ ├── references.md │ ├── reports/ │ │ ├── glue.md │ │ ├── historyqa.md │ │ ├── korquad.md │ │ ├── squad.md │ │ └── wikisql.md │ ├── requirements.txt │ └── summary/ │ └── reading_comprehension.md ├── eval.py ├── index.html ├── machine.py ├── machine_config/ │ ├── ko_wiki.json │ └── nlu.json ├── predict.py ├── pyproject.toml ├── reports/ │ ├── inference_result/ │ │ ├── bert_for_qa-cpu.json │ │ ├── bidaf+elmo-cpu.json │ │ ├── bidaf-cpu.json │ │ ├── docqa+elmo-cpu.json │ │ ├── docqa-cpu.json │ │ ├── drqa-cpu.json │ │ └── qanet-cpu.json │ └── summary/ │ ├── bert_for_qa.json │ ├── bidaf+elmo.json │ ├── bidaf.json │ ├── docqa+elmo.json │ ├── docqa.json │ ├── drqa.json │ └── qanet.json ├── requirements.txt ├── script/ │ ├── convert_checkpoint_to_bert_model.py │ ├── convert_embedding_to_vocab_txt.py │ ├── download_wikisql.sh │ ├── install_mecab.sh │ ├── make_squad_synthetic_data.py │ └── plot.py ├── setup.py ├── tests/ │ ├── __init__.py │ ├── claf/ │ │ ├── data/ │ │ │ └── test_batch.py │ │ ├── machine/ │ │ │ └── knowlege_base/ │ │ │ └── test_docs.py │ │ ├── modules/ │ │ │ └── test_functional.py │ │ └── tokens/ │ │ └── test_vocabulary.py │ └── integration/ │ ├── test_config.py │ ├── test_machine.py │ ├── test_multi_task.py │ ├── test_reading_comprehension.py │ ├── test_semantic_parsing.py │ ├── test_sequence_classification.py │ ├── test_token_classification.py │ ├── test_tokenizers.py │ └── utils.py └── train.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .coveragerc ================================================ # .coveragerc to control coverage.py [run] branch = True [report] # Regexes for lines to exclude from consideration exclude_lines = # Have to re-enable the standard pragma pragma: no cover # Don't complain about missing debug-only code: def __repr__ if self\.debug # Don't complain if tests don't hit defensive assertion code: raise AssertionError raise NotImplementedError raise ValueError # Don't complain pass logger.info # Dont't complain NSML and GPU env if IS_ON_NSML if torch.cuda.is_available() if self.use_multi_gpu # Don't complain if non-runnable code isn't run: if 0: if __name__ == .__main__.: ignore_errors = True [html] directory = coverage_html_report ================================================ FILE: .gitignore ================================================ # Created by https://www.gitignore.io/api/macos,python,jupyternotebook ### CLaF: Clova Language Framework ### /data/ logs/ /inference_result/hide model_config/cache model_config/short /mecab /src ### pytest cov_html/ ### JupyterNotebook ### .ipynb_checkpoints */.ipynb_checkpoints/* # Remove previous ipynb_checkpoints # git rm -r .ipynb_checkpoints/ # ### macOS ### *.DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear in the root of a volume .DocumentRevisions-V100 .fseventsd .Spotlight-V100 .TemporaryItems .Trashes .VolumeIcon.icns .com.apple.timemachine.donotpresent # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache .pytest_cache/ nosetests.xml coverage.xml *.cover .hypothesis/ # Translations *.mo *.pot # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation # docs/_build/ # PyBuilder target/ # Jupyter Notebook # pyenv .python-version # celery beat schedule file celerybeat-schedule.* # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ # End of https://www.gitignore.io/api/macos,python,jupyternotebook ================================================ FILE: .nojekyll ================================================ ================================================ FILE: .readthedocs.yml ================================================ # .readthedocs.yml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py # Build documentation with MkDocs #mkdocs: # configuration: mkdocs.yml # Optionally build your docs in additional formats such as PDF and ePub formats: all # Optionally set the version of Python and requirements required to build your docs python: version: 3.6 install: - requirements: docs/requirements.txt ================================================ FILE: .travis.yml ================================================ language: python python: - "3.6" # command to install dependencies install: - pip install --upgrade pip - pip install --progress-bar off -r requirements.txt - pip install --progress-bar off codecov - python -m nltk.downloader punkt - python -m nltk.downloader wordnet - export BOTO_CONFIG=/dev/nul # command to run tests script: python -m pytest tests --cov-report term --cov claf after_success: codecov -t 2a4a166c-cd15-4121-b4a7-c2eed4c7390f ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to CLAF First of all, thank you for considering contributing to CLAF. It's people like you that make CLaF such a great framework. Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. If you are not familiar with creating a Pull Request, here are some guides: - [Create a Pull Request](https://help.github.com/articles/creating-a-pull-request/) ## Bug & Simple features 1. Search on [Issues](https://github.com/naver/claf/issues) 2. If there are similar issues, add Comments to those issues, otherwise, create new ones 3. Check `pytest`, `black (lint)` before Pull Request - [pytest](https://github.com/pytest-dev/pytest) - Add unittest to the `tests/claf` folder and integration test code if necessary - Run test with coverage ```pytest --cov-config .coveragerc --cov-report html:cov_html --cov=rqa tests``` - [Black](https://github.com/ambv/black) (lint) - ```black claf -l 120 ``` (reformat your code) 4. Clean up your work to create a Pull Request (* When adding a new function (model, optimizer and so on), add it to `claf.config.ars` with a description.) e.g. Exponential Learning Rate Scheduler ``` # ExponentialLR: --exponential.gamma OPTIMIZER.EXPONENTIAL.GAMMA Multiplicative factor of learning rate decay. Default: 0.1. --exponential.last_epoch OPTIMIZER.EXPONENTIAL.LAST_EPOCH The index of last epoch. Default: -1. ``` ## The structure of the framework 1. Post it on the issue and discuss it with maintainers. 2. After discuss, organize according to priority and start working on. ================================================ FILE: Dockerfile ================================================ FROM jmin/pytorch:apex RUN git clone https://github.com/naver/claf && cd claf && pip install -r requirements.txt && python setup.py install RUN apt-get install g++ default-jdk RUN bash <(curl -s https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh) RUN python -m nltk.downloader punkt --dir /usr/share/nltk_data RUN python -m nltk.downloader wordnet --dir /usr/share/nltk_data ================================================ FILE: LICENSE ================================================ Copyright (c) 2019-present NAVER Corp. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: NOTICE ================================================ CLaF Copyright 2019-present NAVER Corp. This project contains subcomponents with separate copyright notices and license terms. Your use of the source code for these subcomponents is subject to the terms and conditions of the following licenses. ======================================================================= rhobot/Hangulpy from https://github.com/rhobot/Hangulpy ======================================================================= Copyright (C) 2012 Ryan Rho, Hyunwoo Cho Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ======================================================================= allenai/allennlp from https://github.com/allenai/allennlp ======================================================================= Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ======================================================================= facebookresearch/DrQA from https://github.com/facebookresearch/DrQA ======================================================================= BSD License For DrQA software Copyright (c) 2017-present, Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Facebook nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ===== ================================================ FILE: README.md ================================================

Clova Language Framework

Documentation Status Code style: black

--- # CLaF: Clova Language Framework - [Full Documentation](https://naver.github.io/claf/) - [Dataset And Model](https://naver.github.io/claf/docs/_build/html/contents/dataset_and_model.html) - [Pretrained Vector](https://naver.github.io/claf/docs/_build/html/contents/pretrained_vector.html) - [Tokens](https://naver.github.io/claf/docs/_build/html/contents/tokens.html): `Tokenizers` and `TokenMakers` - List of [BaseConfig](#baseconfig) | Task | Language | Dataset | Model | | ---- | -------- | ------- | ----- | | Multi-Task Learning | English | [GLUE Benchmark](https://gluebenchmark.com/), [SQuAD v1.1](https://rajpurkar.github.io/SQuAD-explorer/) | `MT-DNN (BERT)` | | Natural Language Understanding | English | [GLUE Benchmark](https://gluebenchmark.com/) | `BERT`, `RoBERTa` | | Named Entity Recognition | English | CoNLL 2003 | `BERT` | | Question Answering | Korean | [KorQuAD v1.0](https://korquad.github.io/category/1.0_KOR.html) | `BiDAF`, `DocQA`, `BERT` | | Question Answering | Engilsh | [SQuAD v1.1 and v2.0](https://rajpurkar.github.io/SQuAD-explorer/) | - v1.1: `BiDAF`, `DrQA`, `DocQA`, `DocQA+ELMo`, `QANet`, `BERT`, `RoBERTa`
- v2.0: `BiDAF + No Answer`, `DocQA + No Answer` | | Semantic Parsing | English | [WikiSQL](https://github.com/salesforce/WikiSQL) | `SQLNet` | - Reports - [GLUE](https://naver.github.io/claf/docs/_build/html/reports/glue.html) - [KorQuAD](https://naver.github.io/claf/docs/_build/html/reports/korquad.html) - [SQuAD](https://naver.github.io/claf/docs/_build/html/reports/squad.html) - [WikiSQL](https://naver.github.io/claf/docs/_build/html/reports/wikisql.html) - Summary (1-example Inference Latency) - [Reading Comprehension](https://naver.github.io/claf/docs/_build/html/summary/reading_comprehension.html) - List of [MachineConfig](#machine) | Name | Language | Pipeline | Note | | ---- | -------- | ------- | ----- | | KoWiki | Korean | `Wiki Dumps` -> `Document Retrieval` -> `Reading Comprehension` | - | | NLU | All | `Query` -> `Intent Classification` & `Token Classification (Slot)` -> `Template Matching` | - | --- ## Table of Contents - [Overview](#overview) - [Features](#features) - [Installation](#installation) - [Requirements](#requirements) - [Install via pip](#install-via-pip) - [Experiment](#experiment) - [Usage](#usage) - [Training](#training) - [Evaluate](#evaluate) - [Predict](#predict) - [Docker Images](#docker-images) - [Machine](#machine) - [Contributing](#contributing) - [Maintainers](#maintainers) - [Citing](#citing) - [License](#license) --- ## Overview **CLaF** is a Language Framework built on PyTorch that provides following two high-level features: - `Experiment` enables the control of training flow in general NLP by offering various `TokenMaker` methods. - CLaF is inspired by the design principle of [AllenNLP](https://github.com/allenai/allennlp) such as the higher level concepts and reusable code, but mostly based on PyTorch’s common module, so that user can easily modify the code on their demands. - `Machine` helps to combine various modules to build a NLP Machine in one place. - There are knowledge-based, components and trained experiments which infer 1-example in modules. ### Features - **Multilingual** modeling support (currently, English and Korean are supported). - Light weighted **Systemization** and Modularization. - Easy extension and implementation of models. - A wide variation of **Experiments** with reproducible and comprehensive logging - The metrics for services such as "1\-example inference latency" are provided. - Easy to build of a NLP **Machine** by combining modules. ## Installation ### Requirements - Python 3.6 - PyTorch >= 1.3.1 - [MeCab](https://bitbucket.org/eunjeon/mecab-ko) for Korean Tokenizer - ```sh script/install_mecab.sh``` It is recommended to use the virtual environment. [Conda](https://conda.io/docs/download.html) is the easiest way to set up a virtual environment. ``` conda create -n claf python=3.6 conda activate claf (claf) ✗ pip install -r requirements.txt ``` ### Install via pip Commands to install via pip ``` pip install claf ``` ## Experiment - Training Flow ![images](images/claf-experiment.001.png) ### Usage #### Training ![images](images/training_config_mapping.png) 1. only Arguments ``` python train.py --train_file_path {file_path} --valid_file_path {file_path} --model_name {name} ... ``` 2. only BaseConfig (skip `/base_config` path) ``` python train.py --base_config {base_config} ``` 3. BaseConfig + Arguments ``` python train.py --base_config {base_config} --learning_rate 0.002 ``` - Load BaseConfig then overwrite `learning_rate` to 0.002 #### BaseConfig Declarative experiment config (.json, .ymal) - Simply matching with object's parameters - Exists samples in `/base_config` directory ##### Defined BaseConfig ``` Base Config: --base_config BASE_CONFIG Use pre-defined base_config: [] * CoNLL 2003: ['conll2003/bert_large_cased'] * GLUE: ['glue/qqp_roberta_base', 'glue/qnli_bert_base', 'glue/rte_bert_base', 'glue/wnli_roberta_base', 'glue/mnlim_roberta_base', 'glue/wnli_bert_base', 'glue/mnlimm_roberta_base', 'glue/cola_bert_base', 'glue/mrpc_bert_base', 'glue/mnlimm_bert_base', 'glue/stsb_bert_base', 'glue/mnlim_bert_base', 'glue/qqp_bert_base', 'glue/rte_roberta_base', 'glue/qnli_roberta_base', 'glue/sst_bert_base', 'glue/mrpc_roberta_base', 'glue/cola_roberta_base', 'glue/stsb_roberta_base', 'glue/sst_roberta_base'] * KorQuAD: ['korquad/bert_base_multilingual_cased', 'korquad/bidaf', 'korquad/bert_base_multilingual_uncased', 'korquad/docqa'] * SQuAD: ['squad/bert_large_uncased', 'squad/bidaf', 'squad/drqa_paper', 'squad/drqa', 'squad/bert_base_uncased', 'squad/qanet', 'squad/docqa+elmo', 'squad/bidaf_no_answer', 'squad/docqa_no_answer', 'squad/qanet_paper', 'squad/bidaf+elmo', 'squad/docqa'] * WikiSQL: ['wikisql/sqlnet'] ``` #### Evaluate ``` python eval.py ``` - Example ``` ✗ python eval.py data/squad/dev-v1.1.json logs/squad/bidaf/checkpoint/model_19.pkl ... [INFO] - { "valid/loss": 2.59111491665019, "valid/epoch_time": 60.7434446811676, "valid/start_acc": 63.17880794701987, "valid/end_acc": 67.19016083254493, "valid/span_acc": 54.45600756859035, "valid/em": 68.10785241248817, "valid/f1": 77.77963381714842 } # write predictions files (/predictions/predictions-valid-19.json) ``` - 1-example Inference Latency ([Summary](docs/_build/html/reports/summary.html)) ``` ✗ python eval.py data/squad/dev-v1.1.json logs/squad/bidaf/checkpoint/model_19.pkl ... # Evaluate Inference Latency Mode. ... [INFO] - saved inference_latency results. bidaf-cpu.json # file_format: {model_name}-{env}.json ``` #### Predict ``` python predict.py -- ``` - Example ``` ✗ python predict.py logs/squad/bidaf/checkpoint/model_19.pkl \ --question "When was the last Super Bowl in California?" \ --context "On May 21, 2013, NFL owners at their spring meetings in Boston voted and awarded the game to Levi's Stadium. The $1.2 billion stadium opened in 2014. It is the first Super Bowl held in the San Francisco Bay Area since Super Bowl XIX in 1985, and the first in California since Super Bowl XXXVII took place in San Diego in 2003." >>> Predict: {'text': '2003', 'score': 4.1640071868896484} ``` #### Docker Images - [Docker Hub](https://hub.docker.com/u/claf) - Run with Docker Image - Pull docker image ```✗ docker pull claf/claf:latest``` - Run ``` docker run --rm -i -t claf/claf:latest /bin/bash ``` --- ### Machine - Machine Architecture ![images](images/claf-machine.001.png) #### Usage - Define the config file (.json) like [BaseConfig](#baseconfig) in `machine_config/` directory - Run CLaF Machine (skip `/machine_config` path) ``` ✗ python machine.py --machine_config {machine_config} ``` * The list of pre-defined `Machine`: ``` Machine Config: --machine_config MACHINE_CONFIG Use pre-defined machine_config (.json (.json)) ['ko_wiki', 'nlu'] ``` #### Open QA (DrQA Style) DrQA is a system for reading comprehension applied to open-domain question answering. The system has to combine the challenges of document retrieval (finding the relevant documents) with that of machine comprehension of text (identifying the answers from those documents). - ko_wiki: Korean Wiki Version ``` ✗ python machine.py --machine_config ko_wiki ... Completed! Question > 동학의 2대 교주 이름은? -------------------------------------------------- Doc Scores: - 교주 : 0.5347289443016052 - 이교주 : 0.4967213571071625 - 교주도 : 0.49036136269569397 - 동학 : 0.4800325632095337 - 동학중학교 : 0.4352934956550598 -------------------------------------------------- Answer: [ { "text": "최시형", "score": 11.073444366455078 }, { "text": "충주목", "score": 9.443866729736328 }, { "text": "반월동", "score": 9.37778091430664 }, { "text": "환조 이자춘", "score": 4.64817476272583 }, { "text": "합포군", "score": 3.3186707496643066 } ] ``` #### NLU (Dialog) The reason why NLU machine does not return the full response is that response generation may require various task-specific post-processing techniques or additional logic(e.g. API calls, template-decision rules, template filling rules, nn-based response generation model) Therefore, for flexible usage, NLU machine returns only the NLU result. ``` ✗ python machine.py --machine_config nlu ... Utterance > "looking for a flight from Boston to Seoul or Incheon" NLU Result: { "intent": "flight", "slots": { "city.depart": ["Boston"], "city.dest": ["Seoul", "Incheon"] } } ``` ## Contributing Thanks for your interest in contributing! There are many ways to contribute to this project. Get started [here](./CONTRIBUTING.md). ## Maintainers CLaF is currently maintained by - [Dongjun Lee](https://github.com/DongjunLee) (Author) - [Sohee Yang](https://github.com/soheeyang) - [Minjeong Kim](https://github.com/Mjkim88) ## Citing If you use CLaF for your work, please cite: ```bibtex @misc{claf, author = {Lee, Dongjun and Yang, Sohee and Kim, Minjeong}, title = {CLaF: Open-Source Clova Language Framework}, year = {2019}, publisher = {GitHub}, journal = {GitHub repository}, howpublished = {\url{https://github.com/naver/claf}} } ``` We will update this bibtex with our paper. ## Acknowledgements `docs/` directory which includes documentation created by [Sphinx](http://www.sphinx-doc.org/). ## License MIT license ``` Copyright (c) 2019-present NAVER Corp. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` ================================================ FILE: base_config/cola/bert_base_uncased.json ================================================ { "data_reader": { "dataset": "cola_bert", "train_file_path": "", "valid_file_path": "", "cola_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/cola_bert", "num_epochs": 3, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10000 } }, "seed_num": 42 } ================================================ FILE: base_config/cola/bert_large_uncased.json ================================================ { "data_reader": { "dataset": "cola_bert", "train_file_path": "", "valid_file_path": "", "cola_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-large-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/cola_bert", "num_epochs": 3, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10000 } }, "seed_num": 42 } ================================================ FILE: base_config/cola/structured_self_attention.json ================================================ { "data_reader": { "dataset": "cola", "train_file_path": "", "valid_file_path": "", "cola": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "vocab": { "pretrained_path": "http://dev-reasoning-qa-data-ncl.nfra.io:7778/data/glove.6B.vocab.txt", "pretrained_token": "intersect" }, "indexer": { "lowercase": true }, "embedding": { "embed_dim": 100, "pretrained_path": "http://dev-reasoning-qa-data-ncl.nfra.io:7778/data/glove.6B.100d.txt", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "structured_self_attention", "structured_self_attention": { "encoding_rnn_hidden_dim": 300, "encoding_rnn_num_layer": 2, "encoding_rnn_dropout": 0, "attention_dim": 350, "num_attention_heads": 30, "sequence_embed_dim": 2000, "dropout": 0.5, "penalization_coefficient": 1 } }, "trainer": { "log_dir": "logs/cola", "num_epochs": 50, "early_stopping_threshold": 10, "grad_max_norm": 5.0, "metric_key": "accuracy", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adam", "learning_rate": 0.001, "exponential_moving_average": 0.999 }, "seed_num": 42 } ================================================ FILE: base_config/conll2003/bert_large_cased.json ================================================ { "data_reader": { "dataset": "conll2003_bert", "train_file_path": "https://raw.githubusercontent.com/Franck-Dernoncourt/NeuroNER/master/data/conll2003/en/train.txt", "valid_file_path": "https://raw.githubusercontent.com/Franck-Dernoncourt/NeuroNER/master/data/conll2003/en/valid.txt", "conll2003_bert": { "sequence_max_length": 128, "ignore_tag_idx": -1 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-cased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": false } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-cased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_tok_cls", "bert_for_tok_cls": { "pretrained_model_name": "bert-large-cased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/conll2003_bert", "num_epochs": 3, "early_stopping_threshold": 10, "metric_key": "conlleval_f1", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10000 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/cola_bert.json ================================================ { "data_reader": { "dataset": "cola_bert", "train_file_path": "CoLA/train.tsv", "valid_file_path": "CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/cola_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "matthews_corr", "eval_and_save_step_count": 100 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/cola_roberta.json ================================================ { "data_reader": { "dataset": "cola_bert", "train_file_path": "CoLA/train.tsv", "valid_file_path": "CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "", "cls_token": "", "sep_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/cola_roberta", "num_epochs": 10, "early_stopping_threshold": 20, "metric_key": "matthews_corr", "eval_and_save_step_count": 100 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/mnlim_bert.json ================================================ { "data_reader": { "dataset": "mnli_bert", "train_file_path": "MNLI/train.tsv", "valid_file_path": "MNLI/dev_matched.tsv", "mnli_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/mnlim_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/mnlim_roberta.json ================================================ { "data_reader": { "dataset": "mnli_bert", "train_file_path": "MNLI/train.tsv", "valid_file_path": "MNLI/dev_matched.tsv", "mnli_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/mnlim_roberta", "num_epochs": 10, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/mnlimm_bert.json ================================================ { "data_reader": { "dataset": "mnli_bert", "train_file_path": "MNLI/train.tsv", "valid_file_path": "MNLI/dev_mismatched.tsv", "mnli_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/mnlimm_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/mnlimm_roberta.json ================================================ { "data_reader": { "dataset": "mnli_bert", "train_file_path": "MNLI/train.tsv", "valid_file_path": "MNLI/dev_mismatched.tsv", "mnli_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/mnlimm_roberta", "num_epochs": 10, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/mrpc_bert.json ================================================ { "data_reader": { "dataset": "mrpc_bert", "train_file_path": "MRPC/train.tsv", "valid_file_path": "MRPC/dev.tsv", "mrpc_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/mrpc_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "f1", "eval_and_save_step_count": 50 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/mrpc_roberta.json ================================================ { "data_reader": { "dataset": "mrpc_bert", "train_file_path": "MRPC/train.tsv", "valid_file_path": "MRPC/dev.tsv", "mrpc_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/mrpc_roberta", "num_epochs": 10, "early_stopping_threshold": 10, "metric_key": "f1", "eval_and_save_step_count": 100 }, "optimizer": { "learning_rate": 1e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/qnli_bert.json ================================================ { "data_reader": { "dataset": "qnli_bert", "train_file_path": "QNLI/train.tsv", "valid_file_path": "QNLI/dev.tsv", "qnli_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/qnli_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/qnli_roberta.json ================================================ { "data_reader": { "dataset": "qnli_bert", "train_file_path": "QNLI/train.tsv", "valid_file_path": "QNLI/dev.tsv", "qnli_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/qnli_roberta", "num_epochs": 10, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/qqp_bert.json ================================================ { "data_reader": { "dataset": "qqp_bert", "train_file_path": "QQP/train.tsv", "valid_file_path": "QQP/dev.tsv", "qqp_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/qqp_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "f1", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/qqp_roberta.json ================================================ { "data_reader": { "dataset": "qqp_bert", "train_file_path": "QQP/train.tsv", "valid_file_path": "QQP/dev.tsv", "qqp_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/qqp_roberta", "num_epochs": 10, "early_stopping_threshold": 10, "metric_key": "f1", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/rte_bert.json ================================================ { "data_reader": { "dataset": "rte_bert", "train_file_path": "RTE/train.tsv", "valid_file_path": "RTE/dev.tsv", "rte_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/rte_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 30 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/rte_roberta.json ================================================ { "data_reader": { "dataset": "rte_bert", "train_file_path": "RTE/train.tsv", "valid_file_path": "RTE/dev.tsv", "rte_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/rte_roberta", "num_epochs": 20, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 50 }, "optimizer": { "learning_rate": 1e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 21 } ================================================ FILE: base_config/glue/sst_bert.json ================================================ { "data_reader": { "dataset": "sst_bert", "train_file_path": "SST-2/train.tsv", "valid_file_path": "SST-2/dev.tsv", "sst_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/sst_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/sst_roberta.json ================================================ { "data_reader": { "dataset": "sst_bert", "train_file_path": "SST-2/train.tsv", "valid_file_path": "SST-2/dev.tsv", "sst_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/sst_roberta", "num_epochs": 10, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/stsb_bert.json ================================================ { "data_reader": { "dataset": "stsb_bert", "train_file_path": "STS-B/train.tsv", "valid_file_path": "STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_reg", "bert_for_reg": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/stsb_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "pearson_spearman_corr", "eval_and_save_step_count": 100 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 22 } ================================================ FILE: base_config/glue/stsb_roberta.json ================================================ { "data_reader": { "dataset": "stsb_bert", "train_file_path": "STS-B/train.tsv", "valid_file_path": "STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_reg", "roberta_for_reg": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/stsb_roberta", "num_epochs": 10, "early_stopping_threshold": 10, "metric_key": "pearson_spearman_corr", "eval_and_save_step_count": 100 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 21 } ================================================ FILE: base_config/glue/wnli_bert.json ================================================ { "data_reader": { "dataset": "wnli_bert", "train_file_path": "WNLI/train.tsv", "valid_file_path": "WNLI/dev.tsv", "wnli_bert": { "sequence_max_length": 128 } }, "iterator": { "batch_size": 16 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/wnli_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": 10 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/glue/wnli_roberta.json ================================================ { "data_reader": { "dataset": "wnli_bert", "train_file_path": "WNLI/train.tsv", "valid_file_path": "WNLI/dev.tsv", "wnli_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta" } }, "iterator": { "batch_size": 16 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.1 } }, "trainer": { "log_dir": "logs/glue/wnli_roberta", "num_epochs": 10, "early_stopping_threshold": 30, "metric_key": "accuracy", "eval_and_save_step_count": 20 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.98], "eps": 1e-6, "weight_decay": 0.1 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 21 } ================================================ FILE: base_config/korquad/bert_base_multilingual_cased.yaml ================================================ data_reader: dataset: "squad_bert" train_file_path: "https://korquad.github.io/dataset/KorQuAD_v1.0_train.json" valid_file_path: "https://korquad.github.io/dataset/KorQuAD_v1.0_dev.json" squad_bert: lang_code: "ko" max_seq_length: 512 context_stride: 64 max_question_length: 64 iterator: batch_size: 12 token: names: - "feature" types: - "feature" tokenizer: subword: name: "wordpiece" wordpiece: vocab_path: "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased-vocab.txt" word: name: "bert_basic" bert_basic: do_lower_case: true feature: vocab: pretrained_path: "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased-vocab.txt" pretrained_token: "all" indexer": do_tokenize: false model: name: "bert_for_qa" bert_for_qa: pretrained_model_name: "bert-base-multilingual-cased" answer_maxlen: 30 trainer: log_dir: "logs/test/bert_for_qa/" num_epochs: 5 early_stopping_threshold: 10 metric_key: "f1" verbose_step_count: 100 eval_and_save_step_count: 1000 optimizer: learning_rate: 0.00003 op_type: "adamw" adamw: weight_decay: 0.01 lr_scheduler_type: "warmup_linear" warmup_linear: warmup_proportion: 0.1 seed_num: 42 ================================================ FILE: base_config/korquad/bert_base_multilingual_uncased.json ================================================ { "data_reader": { "dataset": "squad_bert", "train_file_path": "https://korquad.github.io/dataset/KorQuAD_v1.0_train.json", "valid_file_path": "https://korquad.github.io/dataset/KorQuAD_v1.0_dev.json", "squad_bert": { "lang_code": "ko", "max_seq_length": 512, "context_stride": 64, "max_question_length": 64 } }, "iterator": { "batch_size": 12 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_qa", "bert_for_qa": { "pretrained_model_name": "bert-base-multilingual-uncased", "answer_maxlen": 30 } }, "trainer": { "log_dir": "logs/squad_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 0.00003, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/korquad/bidaf.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://korquad.github.io/dataset/KorQuAD_v1.0_train.json", "valid_file_path": "https://korquad.github.io/dataset/KorQuAD_v1.0_dev.json", "squad": { "lang_code": "ko", "context_max_length": 1000 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "fasttext"], "types": ["char", "word"], "tokenizer": { "char": { "name": "jamo_ko" }, "word": { "name": "mecab_ko", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 70 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "fasttext": { "embedding": { "embed_dim": 300, "pretrained_path": "", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "bidaf", "bidaf": { "model_dim": 100, "contextual_rnn_num_layer": 1, "modeling_rnn_num_layer": 2, "predict_rnn_num_layer": 1, "dropout": 0.2 } }, "trainer": { "log_dir": "logs/korquad_bidaf", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adadelta", "learning_rate": 0.5, "exponential_moving_average": 0.999 }, "seed_num": 2 } ================================================ FILE: base_config/korquad/docqa.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://korquad.github.io/dataset/KorQuAD_v1.0_train.json", "valid_file_path": "https://korquad.github.io/dataset/KorQuAD_v1.0_dev.json", "squad": { "lang_code": "ko", "context_max_length": 1000 } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "fasttext"], "types": ["char", "word"], "tokenizer": { "char": { "name": "jamo_ko" }, "word": { "name": "mecab_ko", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 70 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "fasttext": { "embedding": { "embed_dim": 300, "pretrained_path": "", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "docqa", "docqa": { "answer_maxlen": 17, "rnn_dim": 100, "linear_dim": 200, "preprocess_rnn_num_layer": 1, "modeling_rnn_num_layer": 1, "predict_rnn_num_layer": 1, "dropout": 0.2, "weight_init": true } }, "trainer": { "log_dir": "logs/korquad_docqa", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 2 } ================================================ FILE: base_config/multi_task/bert_base_glue+squad.json ================================================ { "data_reader": { "dataset": "multitask_bert", "train_file_path": "train", "valid_file_path": "valid", "multitask_bert": { "batch_sizes": [32, 32, 32, 32, 32, 32, 32, 32, 16, 12], "readers": [{ "dataset": "cola_bert", "train_file_path": "CoLA/train.tsv", "valid_file_path": "CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128 } }, { "dataset": "mnli_bert", "train_file_path": "MNLI/train.tsv", "valid_file_path": "MNLI/dev_matched.tsv", "mnli_bert": { "sequence_max_length": 128 } }, { "dataset": "mrpc_bert", "train_file_path": "MRPC/train.tsv", "valid_file_path": "MRPC/dev.tsv", "mrpc_bert": { "sequence_max_length": 128 } }, { "dataset": "qnli_bert", "train_file_path": "QNLI/train.tsv", "valid_file_path": "QNLI/dev.tsv", "qnli_bert": { "sequence_max_length": 128 } }, { "dataset": "qqp_bert", "train_file_path": "QQP/train.tsv", "valid_file_path": "QQP/dev.tsv", "qqp_bert": { "sequence_max_length": 128 } }, { "dataset": "rte_bert", "train_file_path": "RTE/train.tsv", "valid_file_path": "RTE/dev.tsv", "rte_bert": { "sequence_max_length": 128 } }, { "dataset": "sst_bert", "train_file_path": "SST-2/train.tsv", "valid_file_path": "SST-2/dev.tsv", "sst_bert": { "sequence_max_length": 128 } }, { "dataset": "stsb_bert", "train_file_path": "STS-B/train.tsv", "valid_file_path": "STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128 } }, { "dataset": "wnli_bert", "train_file_path": "WNLI/train.tsv", "valid_file_path": "WNLI/dev.tsv", "wnli_bert": { "sequence_max_length": 128 } }, { "dataset": "squad_bert", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64 } }] } }, "iterator": { "batch_size": 1 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_multi", "bert_for_multi": { "pretrained_model_name": "bert-base-uncased", "dropouts": [0.05, 0.3, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0] } }, "trainer": { "log_dir": "logs/multi_task/bert_glue+squad", "num_epochs": 5, "early_stopping_threshold": 10, "grad_max_norm": 1, "metric_key": "average", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.999], "eps": 1e-6, "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/multi_task/bert_base_glue.json ================================================ { "data_reader": { "dataset": "multitask_bert", "train_file_path": "train", "valid_file_path": "valid", "multitask_bert": { "batch_sizes": [32, 32, 32, 32, 32, 32, 32, 32, 16], "readers": [{ "dataset": "cola_bert", "train_file_path": "CoLA/train.tsv", "valid_file_path": "CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128 } }, { "dataset": "mnli_bert", "train_file_path": "MNLI/train.tsv", "valid_file_path": "MNLI/dev_matched.tsv", "mnli_bert": { "sequence_max_length": 128 } }, { "dataset": "mrpc_bert", "train_file_path": "MRPC/train.tsv", "valid_file_path": "MRPC/dev.tsv", "mrpc_bert": { "sequence_max_length": 128 } }, { "dataset": "qnli_bert", "train_file_path": "QNLI/train.tsv", "valid_file_path": "QNLI/dev.tsv", "qnli_bert": { "sequence_max_length": 128 } }, { "dataset": "qqp_bert", "train_file_path": "QQP/train.tsv", "valid_file_path": "QQP/dev.tsv", "qqp_bert": { "sequence_max_length": 128 } }, { "dataset": "rte_bert", "train_file_path": "RTE/train.tsv", "valid_file_path": "RTE/dev.tsv", "rte_bert": { "sequence_max_length": 128 } }, { "dataset": "sst_bert", "train_file_path": "SST-2/train.tsv", "valid_file_path": "SST-2/dev.tsv", "sst_bert": { "sequence_max_length": 128 } }, { "dataset": "stsb_bert", "train_file_path": "STS-B/train.tsv", "valid_file_path": "STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128 } }, { "dataset": "wnli_bert", "train_file_path": "WNLI/train.tsv", "valid_file_path": "WNLI/dev.tsv", "wnli_bert": { "sequence_max_length": 128 } }] } }, "iterator": { "batch_size": 1 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_multi", "bert_for_multi": { "pretrained_model_name": "bert-base-uncased", "dropouts": [0.05, 0.3, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] } }, "trainer": { "log_dir": "logs/multi_task/bert_glue", "num_epochs": 5, "early_stopping_threshold": 10, "grad_max_norm": 1, "metric_key": "average", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.999], "eps": 1e-6, "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/multi_task/bert_large_glue+squad.json ================================================ { "data_reader": { "dataset": "multitask_bert", "train_file_path": "train", "valid_file_path": "valid", "multitask_bert": { "batch_sizes": [32, 32, 32, 32, 32, 32, 32, 32, 16, 6], "readers": [{ "dataset": "cola_bert", "train_file_path": "CoLA/train.tsv", "valid_file_path": "CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128 } }, { "dataset": "mnli_bert", "train_file_path": "MNLI/train.tsv", "valid_file_path": "MNLI/dev_matched.tsv", "mnli_bert": { "sequence_max_length": 128 } }, { "dataset": "mrpc_bert", "train_file_path": "MRPC/train.tsv", "valid_file_path": "MRPC/dev.tsv", "mrpc_bert": { "sequence_max_length": 128 } }, { "dataset": "qnli_bert", "train_file_path": "QNLI/train.tsv", "valid_file_path": "QNLI/dev.tsv", "qnli_bert": { "sequence_max_length": 128 } }, { "dataset": "qqp_bert", "train_file_path": "QQP/train.tsv", "valid_file_path": "QQP/dev.tsv", "qqp_bert": { "sequence_max_length": 128 } }, { "dataset": "rte_bert", "train_file_path": "RTE/train.tsv", "valid_file_path": "RTE/dev.tsv", "rte_bert": { "sequence_max_length": 128 } }, { "dataset": "sst_bert", "train_file_path": "SST-2/train.tsv", "valid_file_path": "SST-2/dev.tsv", "sst_bert": { "sequence_max_length": 128 } }, { "dataset": "stsb_bert", "train_file_path": "STS-B/train.tsv", "valid_file_path": "STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128 } }, { "dataset": "wnli_bert", "train_file_path": "WNLI/train.tsv", "valid_file_path": "WNLI/dev.tsv", "wnli_bert": { "sequence_max_length": 128 } }, { "dataset": "squad_bert", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64 } }] } }, "iterator": { "batch_size": 1 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_multi", "bert_for_multi": { "pretrained_model_name": "bert-large-uncased", "dropouts": [0.05, 0.3, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0] } }, "trainer": { "log_dir": "logs/multi_task/bert_glue+squad", "num_epochs": 5, "early_stopping_threshold": 10, "grad_max_norm": 1, "metric_key": "average", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.999], "eps": 1e-6, "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/multi_task/bert_large_glue.json ================================================ { "data_reader": { "dataset": "multitask_bert", "train_file_path": "train", "valid_file_path": "valid", "multitask_bert": { "batch_sizes": [32, 32, 32, 32, 32, 32, 32, 32, 16], "readers": [{ "dataset": "cola_bert", "train_file_path": "CoLA/train.tsv", "valid_file_path": "CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128 } }, { "dataset": "mnli_bert", "train_file_path": "MNLI/train.tsv", "valid_file_path": "MNLI/dev_matched.tsv", "mnli_bert": { "sequence_max_length": 128 } }, { "dataset": "mrpc_bert", "train_file_path": "MRPC/train.tsv", "valid_file_path": "MRPC/dev.tsv", "mrpc_bert": { "sequence_max_length": 128 } }, { "dataset": "qnli_bert", "train_file_path": "QNLI/train.tsv", "valid_file_path": "QNLI/dev.tsv", "qnli_bert": { "sequence_max_length": 128 } }, { "dataset": "qqp_bert", "train_file_path": "QQP/train.tsv", "valid_file_path": "QQP/dev.tsv", "qqp_bert": { "sequence_max_length": 128 } }, { "dataset": "rte_bert", "train_file_path": "RTE/train.tsv", "valid_file_path": "RTE/dev.tsv", "rte_bert": { "sequence_max_length": 128 } }, { "dataset": "sst_bert", "train_file_path": "SST-2/train.tsv", "valid_file_path": "SST-2/dev.tsv", "sst_bert": { "sequence_max_length": 128 } }, { "dataset": "stsb_bert", "train_file_path": "STS-B/train.tsv", "valid_file_path": "STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128 } }, { "dataset": "wnli_bert", "train_file_path": "WNLI/train.tsv", "valid_file_path": "WNLI/dev.tsv", "wnli_bert": { "sequence_max_length": 128 } }] } }, "iterator": { "batch_size": 1 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_multi", "bert_for_multi": { "pretrained_model_name": "bert-large-uncased", "dropouts": [0.05, 0.3, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] } }, "trainer": { "log_dir": "logs/multi_task/bert_glue", "num_epochs": 5, "early_stopping_threshold": 10, "grad_max_norm": 1, "metric_key": "average", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.999], "eps": 1e-6, "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/squad/bert_base_uncased.json ================================================ { "data_reader": { "dataset": "squad_bert", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64 } }, "iterator": { "batch_size": 12 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_qa", "bert_for_qa": { "pretrained_model_name": "bert-base-uncased", "answer_maxlen": 30 } }, "trainer": { "log_dir": "logs/squad_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 5e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.999], "eps": 1e-6, "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/squad/bert_large_uncased.json ================================================ { "data_reader": { "dataset": "squad_bert", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64 } }, "iterator": { "batch_size": 8 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_qa", "bert_for_qa": { "pretrained_model_name": "bert-large-uncased", "answer_maxlen": 30 } }, "trainer": { "log_dir": "logs/squad_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 5e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.999], "eps": 1e-6, "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/squad/bidaf+elmo.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove", "elmo"], "types": ["char", "word", "elmo"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": true }, "embedding": { "embed_dim": 100, "pretrained_path": "", "trainable": false, "dropout": 0.2 } }, "elmo": { "embedding": { "options_file": "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_options.json", "weight_file": "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5", "trainable": false, "dropout": 0.5 } } }, "model": { "name": "bidaf", "bidaf": { "model_dim": 200, "dropout": 0.3 } }, "trainer": { "log_dir": "logs/squad_bidaf+elmo", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "adam": { "betas": [0.9, 0.9] }, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 31 } ================================================ FILE: base_config/squad/bidaf.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "vocab": { "pretrained_path": "", "pretrained_token": "intersect" }, "indexer": { "lowercase": true }, "embedding": { "embed_dim": 100, "pretrained_path": "", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "bidaf", "bidaf": { "model_dim": 100, "contextual_rnn_num_layer": 1, "modeling_rnn_num_layer": 2, "predict_rnn_num_layer": 1, "dropout": 0.2 } }, "trainer": { "log_dir": "logs/squad_bidaf", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adadelta", "learning_rate": 0.5, "exponential_moving_average": 0.999 }, "seed_num": 2 } ================================================ FILE: base_config/squad/bidaf_no_answer.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v2.0.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json" }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": true }, "embedding": { "embed_dim": 100, "pretrained_path": "", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "bidaf_no_answer", "bidaf": { "model_dim": 100, "dropout": 0.2 } }, "trainer": { "log_dir": "logs/squad_bidaf_no_answer", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "best_f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adadelta", "learning_rate": 0.5, "exponential_moving_average": 0.999 }, "seed_num": 2 } ================================================ FILE: base_config/squad/docqa+elmo.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove", "elmo"], "types": ["char", "word", "elmo"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "", "trainable": false } }, "elmo": { "embedding": { "options_file": "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_options.json", "weight_file": "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5", "trainable": false, "dropout": 0.5 } } }, "model": { "name": "docqa", "docqa": { "rnn_dim": 200, "linear_dim": 400, "dropout": 0.25, "weight_init": true } }, "trainer": { "log_dir": "logs/squad_docqa+elmo", "num_epochs": 30, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 2 } ================================================ FILE: base_config/squad/docqa.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "docqa", "docqa": { "answer_maxlen": 17, "rnn_dim": 100, "linear_dim": 200, "preprocess_rnn_num_layer": 1, "modeling_rnn_num_layer": 1, "predict_rnn_num_layer": 1, "dropout": 0.2, "weight_init": true } }, "trainer": { "log_dir": "logs/squad_docqa", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 2 } ================================================ FILE: base_config/squad/docqa_no_answer.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v2.0.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "docqa_no_answer", "docqa": { "answer_maxlen": 17, "rnn_dim": 100, "linear_dim": 200, "dropout": 0.2, "weight_init": true } }, "trainer": { "log_dir": "logs/squad_docqa_no_answer", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "best_f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 2 } ================================================ FILE: base_config/squad/drqa.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["frequent_glove", "exact_match"], "types": ["frequent_word", "exact_match"], "tokenizer": { "word": { "name": "spacy_en", "split_with_regex": true } }, "frequent_glove": { "vocab": { "frequent_count": 1000 }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "", "dropout": 0.3 } }, "exact_match": { "indexer": { "lower": true, "lemma": true }, "embedding": { "type": "sparse" } } }, "model": { "name": "drqa", "drqa": { "aligned_query_embedding": true, "answer_maxlen": 15, "model_dim": 128, "dropout": 0.3 } }, "trainer": { "log_dir": "logs/squad_drqa", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.002, "adamax": { "betas": [0.9, 0.999], "eps": 1e-08, "weight_decay": 0 }, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 21 } ================================================ FILE: base_config/squad/drqa_paper.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["frequent_glove", "exact_match", "linguistic"], "types": ["frequent_word", "exact_match", "linguistic"], "tokenizer": { "word": { "name": "spacy_en", "split_with_regex": true } }, "frequent_glove": { "vocab": { "frequent_count": 1000 }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "", "dropout": 0.3 } }, "exact_match": { "indexer": { "lower": true, "lemma": true }, "embedding": { "type": "sparse" } }, "linguistic": { "indexer": { "pos_tag": true, "ner": true }, "embedding": { "type": "sparse" } } }, "model": { "name": "drqa", "drqa": { "aligned_query_embedding": true, "answer_maxlen": 15, "model_dim": 128, "dropout": 0.3 } }, "trainer": { "log_dir": "logs/squad_drqa_paper", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.003, "adamax": { "betas": [0.9, 0.999], "eps": 1e-08, "weight_decay": 0 }, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 21 } ================================================ FILE: base_config/squad/qanet.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en", "context_max_length": 400 } }, "iterator": { "batch_size": 6 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 64, "kernel_sizes": [5], "num_filter": 200, "activation": "relu", "dropout": 0.05 } }, "glove": { "vocab": { "pretrained_path": "", "pretrained_token": "intersect" }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "", "trainable": false, "dropout": 0.1 } } }, "model": { "name": "qanet", "qanet": { "answer_maxlen": 30, "model_dim": 128, "kernel_size_in_embedding": 7, "num_head_in_embedding": 8, "num_conv_block_in_embedding": 4, "num_embedding_encoder_block": 1, "kernel_size_in_modeling": 5, "num_head_in_modeling": 8, "num_conv_block_in_modeling": 2, "num_modeling_encoder_block": 7, "layer_dropout": 0.9, "dropout": 0.1 } }, "trainer": { "log_dir": "logs/squad_qanet", "num_epochs": 100, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.002, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 2 } ================================================ FILE: base_config/squad/qanet_paper.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en", "context_max_length": 400 } }, "iterator": { "batch_size": 6 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 64, "kernel_sizes": [5], "num_filter": 200, "activation": "relu", "dropout": 0.05 } }, "glove": { "vocab": { "pretrained_path": "", "pretrained_token": "intersect" }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "", "trainable": false, "dropout": 0.1 } } }, "model": { "name": "qanet", "qanet": { "answer_maxlen": 30, "model_dim": 128, "kernel_size_in_embedding": 7, "num_head_in_embedding": 8, "num_conv_block_in_embedding": 4, "num_embedding_encoder_block": 1, "kernel_size_in_modeling": 5, "num_head_in_modeling": 8, "num_conv_block_in_modeling": 2, "num_modeling_encoder_block": 7, "layer_dropout": 0.9, "dropout": 0.1 } }, "trainer": { "log_dir": "logs/squad_qanet_paper", "num_epochs": 100, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adam", "learning_rate": 0.001, "adam": { "betas": [0.8, 0.999], "eps": 1e-7, "weight_decay": 3e-7 }, "exponential_moving_average": 0.9999, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 1000 } }, "seed_num": 2 } ================================================ FILE: base_config/squad/roberta_base.json ================================================ { "data_reader": { "dataset": "squad_bert", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64, "cls_token": "", "sep_token": "" } }, "iterator": { "batch_size": 12 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "", "cls_token": "", "sep_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_qa", "roberta_for_qa": { "pretrained_model_name": "roberta-base", "answer_maxlen": 30 } }, "trainer": { "log_dir": "logs/squad_roberta_base", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 1.5e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/squad/roberta_large.json ================================================ { "data_reader": { "dataset": "squad_bert", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64, "cls_token": "", "sep_token": "" } }, "iterator": { "batch_size": 8 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-large-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-large-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-large-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "", "cls_token": "", "sep_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_qa", "roberta_for_qa": { "pretrained_model_name": "roberta-large", "answer_maxlen": 30 } }, "trainer": { "log_dir": "logs/squad_roberta_large", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": 1000 }, "optimizer": { "learning_rate": 1.5e-5, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.06 } }, "seed_num": 42 } ================================================ FILE: base_config/test/bert_for_multi_task.json ================================================ { "data_reader": { "dataset": "multitask_bert", "train_file_path": "train", "valid_file_path": "valid", "multitask_bert": { "batch_sizes": [15, 13, 11], "readers": [{ "dataset": "seq_cls_bert", "train_file_path": "train.tsv", "valid_file_path": "dev.tsv", "seq_cls_bert": { "sequence_max_length": 128, "is_test": true } }, { "dataset": "regression_bert", "train_file_path": "train.tsv", "valid_file_path": "dev.tsv", "regression_bert": { "sequence_max_length": 128, "is_test": true } }, { "dataset": "squad_bert", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64 } }] } }, "iterator": { "batch_size": 1 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_multi", "bert_for_multi": { "pretrained_model_name": "bert-base-uncased", "dropouts": [0.05, 0.3, 0.1] } }, "trainer": { "log_dir": "logs/test/bert_for_multi_task", "num_epochs": 1, "early_stopping_threshold": 5, "grad_max_norm": 1, "metric_key": "average", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "betas": [0.9, 0.999], "eps": 1e-6, "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_proportion": 0.1 } }, "seed_num": 42 } ================================================ FILE: base_config/test/bert_for_qa.yaml ================================================ data_reader: dataset: "squad_bert" train_file_path: "data/bert/squad_synthetic_data.json" valid_file_path: "data/bert/squad_synthetic_data.json" squad_bert: lang_code: "en" max_seq_length: 384 context_stride: 128 max_question_length: 64 iterator: batch_size: 10 token: names: - "feature" types: - "feature" tokenizer: subword: name: "wordpiece" wordpiece: vocab_path: "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" word: name: "bert_basic" bert_basic: do_lower_case: true feature: vocab: pretrained_path: "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" pretrained_token: "all" indexer: do_tokenize: false model: name: "bert_for_qa" bert_for_qa: pretrained_model_name: "bert-base-uncased" trainer: log_dir: "logs/test/bert_for_qa/" num_epochs: 2 early_stopping_threshold: 2 metric_key: "em" verbose_step_count: 1 eval_and_save_step_count: 1 optimizer: learning_rate: 0.00005 op_type: "adamw" adamw: weight_decay: 0.01 lr_scheduler_type: "warmup_linear" warmup_linear: warmup_steps: 10000 gradient_accumulation_steps: 2 seed_num: 25 ================================================ FILE: base_config/test/bert_for_seq_cls.json ================================================ { "data_reader": { "dataset": "seq_cls_bert", "train_file_path": "logs/test/seq_cls/synthetic_data.json", "valid_file_path": "logs/test/seq_cls/synthetic_data.json", "seq_cls_bert": { "sequence_max_length": 128, "class_key": "label" } }, "iterator": { "batch_size": 64 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": false } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/seq_cls/bert", "num_epochs": 2, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 0.00001, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10000 } }, "seed_num": 42 } ================================================ FILE: base_config/test/bert_for_tok_cls.json ================================================ { "data_reader": { "dataset": "tok_cls_bert", "train_file_path": "logs/test/tok_cls/synthetic_data.json", "valid_file_path": "logs/test/tok_cls/synthetic_data.json", "tok_cls_bert": { "sequence_max_length": 128, "tag_key": "label", "ignore_tag_idx": -1 } }, "iterator": { "batch_size": 64 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": false } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_tok_cls", "bert_for_tok_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.2 } }, "trainer": { "log_dir": "logs/test/tok_cls/bert", "num_epochs": 2, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 0.00001, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10000 } }, "seed_num": 42 } ================================================ FILE: base_config/test/bidaf+bert.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["char", "glove", "bert"], "types": ["char", "word", "bert"], "tokenizer": { "char": { "name": "character" }, "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "treebank_en" } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "vocab": {}, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 50, "trainable": false, "dropout": 0.2 } }, "bert": { "vocab": { "pad_token": "[PAD]", "oov_token": "[UNK]", "cls_token": "[CLS]", "sep_token": "[SEP]", "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-cased-vocab.txt", "pretrained_token": "all" }, "embedding": { "pretrained_model_name": "bert-base-cased", "trainable": false } } }, "model": { "name": "bidaf", "bidaf": { "model_dim": 50, "dropout": 0.2 } }, "trainer": { "log_dir": "logs/test/bidaf+bert/", "num_epochs": 1, "early_stopping_threshold": 2, "metric_key": "f1", "verbose_step_count": 1, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adadelta", "learning_rate": 1, "exponential_moving_average": 0.999 }, "seed_num": 25 } ================================================ FILE: base_config/test/bidaf+cove.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["char", "glove", "cove"], "types": ["char", "word", "cove"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": true }, "embedding": { "embed_dim": 50, "trainable": false, "dropout": 0.2 } }, "cove": { "embedding": { "glove_pretrained_path": "", "model_pretrained_path": "https://s3.amazonaws.com/research.metamind.io/cove/wmtlstm-8f474287.pth", "dropout": 0.2, "trainable": false } } }, "model": { "name": "bidaf", "bidaf": { "model_dim": 50, "contextual_rnn_num_layer": 1, "modeling_rnn_num_layer": 2, "predict_rnn_num_layer": 1, "dropout": 0.2 } }, "trainer": { "log_dir": "logs/test/bidaf+cove/", "num_epochs": 2, "early_stopping_threshold": 2, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 5 }, "optimizer": { "op_type": "adadelta", "learning_rate": 1, "exponential_moving_average": 0.999 }, "seed_num": 25 } ================================================ FILE: base_config/test/bidaf+elmo.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["char", "glove", "elmo"], "types": ["char", "word", "elmo"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "vocab": {}, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 50, "trainable": false, "dropout": 0.2 } }, "elmo": { "indexer": {}, "embedding": { "options_file": "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_options.json", "weight_file": "https://s3-us-west-2.amazonaws.com/allennlp/models/elmo/2x4096_512_2048cnn_2xhighway/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5", "trainable": false, "dropout": 0.5 } } }, "model": { "name": "bidaf", "bidaf": { "model_dim": 50, "dropout": 0.2 } }, "trainer": { "log_dir": "logs/test/bidaf+elmo/", "num_epochs": 1, "early_stopping_threshold": 2, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 5 }, "optimizer": { "op_type": "adadelta", "learning_rate": 1, "exponential_moving_average": 0.999 }, "seed_num": 25 } ================================================ FILE: base_config/test/bidaf.yaml ================================================ data_reader: dataset: "squad" train_file_path: "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json" valid_file_path: "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json" squad: lang_code: "ko" iterator: batch_size: 10 token: names: - "char" - "glove" types: - "char" - "word" tokenizer: char: name: "character" word: name: "treebank_en" split_with_regex: true char: vocab: start_token: "" end_token: "" max_vocab_size: 260 indexer: insert_char_start: true insert_char_end: true embedding: embed_dim: 16 kernel_sizes: - 5 num_filter: 100 activation: "relu" dropout: 0.2 glove: indexer: lowercase: true embedding: embed_dim: 50 trainable: false dropout: 0.2 model: name: "bidaf" bidaf: model_dim: 50 contextual_rnn_num_layer: 1 modeling_rnn_num_layer: 2 predict_rnn_num_layer: 1 dropout: 0.2 trainer: log_dir: "logs/test/bidaf/" num_epochs: 2 early_stopping_threshold: 2 grad_max_norm: 0.5 metric_key: "em" verbose_step_count: 1 eval_and_save_step_count: "epoch" optimizer: learning_rate: 1 op_type: "adadelta" exponential_moving_average: 0.999 seed_num: 25 ================================================ FILE: base_config/test/bidaf_no_answer.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "vocab": {}, "indexer": { "lowercase": true }, "embedding": { "embed_dim": 50, "trainable": false, "dropout": 0.2 } } }, "model": { "name": "bidaf_no_answer", "bidaf": { "model_dim": 50, "dropout": 0.2 } }, "trainer": { "log_dir": "logs/test/bidaf_no_answer/", "num_epochs": 2, "early_stopping_threshold": 2, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 3 }, "optimizer": { "op_type": "adadelta", "learning_rate": 1, "exponential_moving_average": 0.999 }, "seed_num": 25 } ================================================ FILE: base_config/test/cola_bert.json ================================================ { "data_reader": { "dataset": "cola_bert", "train_file_path": "data/glue/CoLA/train.tsv", "valid_file_path": "data/glue/CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/cola_bert", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "matthews_corr", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10 } }, "seed_num": 42 } ================================================ FILE: base_config/test/cola_roberta.json ================================================ { "data_reader": { "dataset": "cola_bert", "train_file_path": "data/glue/CoLA/train.tsv", "valid_file_path": "data/glue/CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta", "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "", "cls_token": "", "sep_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/cola_roberta", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "matthews_corr", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10 } }, "seed_num": 42 } ================================================ FILE: base_config/test/docqa.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "vocab": {}, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 50, "trainable": false, "dropout": 0.2 } } }, "model": { "name": "docqa", "docqa": { "preprocess_rnn_num_layer": 1, "modeling_rnn_num_layer": 2, "predict_rnn_num_layer": 1 } }, "trainer": { "log_dir": "logs/test/docqa/", "num_epochs": 1, "early_stopping_threshold": 1, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 1 }, "optimizer": { "op_type": "adamax", "learning_rate": 0.002 }, "seed_num": 25 } ================================================ FILE: base_config/test/docqa_no_answer.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "vocab": {}, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 50, "trainable": false, "dropout": 0.2 } } }, "model": { "name": "docqa_no_answer" }, "trainer": { "log_dir": "logs/test/docqa_no_answer/", "num_epochs": 1, "early_stopping_threshold": 1, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 1 }, "optimizer": { "op_type": "adamax", "learning_rate": 0.002 }, "seed_num": 25 } ================================================ FILE: base_config/test/drqa.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["frequent_word", "exact_match", "linguistic"], "types": ["frequent_word", "exact_match", "linguistic"], "tokenizer": { "word": { "name": "spacy_en", "split_with_regex": true } }, "frequent_word": { "vocab": { "frequent_count": 1000 }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 50, "dropout": 0.3 } }, "exact_match": { "indexer": { "lower": true, "lemma": true }, "embedding": { "type": "sparse" } }, "linguistic": { "indexer": { "pos_tag": true, "ner": true }, "embedding": { "type": "sparse" } } }, "model": { "name": "drqa", "drqa": { "aligned_query_embedding": false, "answer_maxlen": 15, "model_dim": 128, "dropout": 0.3 } }, "trainer": { "log_dir": "logs/test/drqa/", "num_epochs": 1, "early_stopping_threshold": 1, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 1 }, "optimizer": { "op_type": "adamax", "learning_rate": 0.003, "adamax": { "betas": [0.9, 0.999], "eps": 1e-08, "weight_decay": 0 } }, "seed_num": 21 } ================================================ FILE: base_config/test/drqa_sparse_to_embedding.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["frequent_word", "exact_match", "linguistic"], "types": ["frequent_word", "exact_match", "linguistic"], "tokenizer": { "word": { "name": "spacy_en", "split_with_regex": true } }, "frequent_word": { "vocab": { "frequent_count": 1000 }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 50, "dropout": 0.3 } }, "exact_match": { "indexer": { "lower": true, "lemma": true }, "embedding": { "type": "sparse" } }, "linguistic": { "indexer": { "pos_tag": true, "ner": true }, "embedding": { "type": "embedding", "embed_dim": 10 } } }, "model": { "name": "drqa", "drqa": { "aligned_query_embedding": true, "answer_maxlen": 15, "model_dim": 128, "dropout": 0.3 } }, "trainer": { "log_dir": "logs/test/drqa_with_sparse_to_embedding/", "num_epochs": 1, "early_stopping_threshold": 1, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 1 }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 21 } ================================================ FILE: base_config/test/mnlim_bert.json ================================================ { "data_reader": { "dataset": "mnli_bert", "train_file_path": "data/glue/MNLI/train.tsv", "valid_file_path": "data/glue/MNLI/dev_matched.tsv", "mnli_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/mnlim_bert", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 100 } }, "seed_num": 42 } ================================================ FILE: base_config/test/mrpc_bert.json ================================================ { "data_reader": { "dataset": "mrpc_bert", "train_file_path": "data/glue/MRPC/train.tsv", "valid_file_path": "data/glue/MRPC/dev.tsv", "mrpc_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/mrpc_bert", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "f1", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10 } }, "seed_num": 42 } ================================================ FILE: base_config/test/mt_bert.json ================================================ { "data_reader": { "dataset": "multitask_bert", "train_file_path": "train", "valid_file_path": "valid", "multitask_bert": { "batch_sizes": [2, 3, 4], "readers": [{ "dataset": "cola_bert", "train_file_path": "data/glue/CoLA/train.tsv", "valid_file_path": "data/glue/CoLA/dev.tsv", "cola_bert": { "sequence_max_length": 128, "is_test": true } }, { "dataset": "stsb_bert", "train_file_path": "data/glue/STS-B/train.tsv", "valid_file_path": "data/glue/STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128, "is_test": true } }, { "dataset": "squad_bert", "train_file_path": "data/squad/dev-v1.1.json", "valid_file_path": "data/squad/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64 } }] } }, "iterator": { "batch_size": 1 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_multi", "bert_for_multi": { "pretrained_model_name": "bert-base-uncased", "dropouts": [0.1, 0.2, 0] } }, "trainer": { "log_dir": "logs/test/mt_bert", "num_epochs": 2, "early_stopping_threshold": 10, "metric_key": "average", "verbose_step_count": 1, "eval_and_save_step_count": 5 }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10 } }, "seed_num": 42 } ================================================ FILE: base_config/test/open_qa.json ================================================ { "name": "open_qa", "open_qa": { "tokenizers": { "sent": { "name": "punkt" }, "word": { "name": "space_all", "split_with_regex": true } }, "knowledge_base": { "wiki": "" }, "reasoning": { "document_retrieval": { "type": "component", "name": "tfidf", "tfidf": { "k": 3 } }, "reading_comprehension": { "type": "experiment", "checkpoint_path": "" } } } } ================================================ FILE: base_config/test/qanet.json ================================================ { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "lang_code": "en" } }, "iterator": { "batch_size": 10 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 50, "activation": "relu", "dropout": 0.05 } }, "glove": { "vocab": {}, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 50, "trainable": true, "dropout": 0.1 } } }, "model": { "name": "qanet", "qanet": { "answer_maxlen": 30, "model_dim": 128, "kernel_size_in_embedding": 7, "num_head_in_embedding": 8, "num_conv_block_in_embedding": 4, "num_embedding_encoder_block": 1, "kernel_size_in_modeling": 5, "num_head_in_modeling": 8, "num_conv_block_in_modeling": 2, "num_modeling_encoder_block": 7, "layer_dropout": 0.9, "dropout": 0.1 } }, "trainer": { "log_dir": "logs/test/qanet/", "num_epochs": 1, "early_stopping_threshold": 1, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 1 }, "optimizer": { "op_type": "adam", "learning_rate": 0.001, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 1000 } }, "seed_num": 25 } ================================================ FILE: base_config/test/qnli_bert.json ================================================ { "data_reader": { "dataset": "qnli_bert", "train_file_path": "data/glue/QNLI/train.tsv", "valid_file_path": "data/glue/QNLI/dev.tsv", "qnli_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/qnli_bert", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 100 } }, "seed_num": 42 } ================================================ FILE: base_config/test/qqp_bert.json ================================================ { "data_reader": { "dataset": "qqp_bert", "train_file_path": "data/glue/QQP/train.tsv", "valid_file_path": "data/glue/QQP/dev.tsv", "qqp_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/qqp_bert_base", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "f1", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 100 } }, "seed_num": 42 } ================================================ FILE: base_config/test/roberta_for_qa.json ================================================ { "data_reader": { "dataset": "squad_bert", "train_file_path": "data/squad/dev-v1.1.json", "valid_file_path": "data/squad/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64 } }, "iterator": { "batch_size": 10 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_qa", "roberta_for_qa": { "pretrained_model_name": "roberta-base" } }, "trainer": { "log_dir": "logs/test/bert_for_qa/", "num_epochs": 2, "early_stopping_threshold": 2, "metric_key": "em", "verbose_step_count": 1, "eval_and_save_step_count": 1 }, "optimizer": { "learning_rate": 0.00005, "op_type": "adamw", "adamw": { "weight_decay": 0.01 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10000 }, "gradient_accumulation_steps": 2 }, "seed_num": 25 } ================================================ FILE: base_config/test/rte_bert.json ================================================ { "data_reader": { "dataset": "rte_bert", "train_file_path": "data/glue/RTE/train.tsv", "valid_file_path": "data/glue/RTE/dev.tsv", "rte_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/rte_bert", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 5 } }, "seed_num": 42 } ================================================ FILE: base_config/test/rte_roberta.json ================================================ { "data_reader": { "dataset": "rte_bert", "train_file_path": "data/glue/RTE/train.tsv", "valid_file_path": "data/glue/RTE/dev.tsv", "rte_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta", "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_seq_cls", "roberta_for_seq_cls": { "pretrained_model_name": "roberta-base", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/rte_roberta", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 5 } }, "seed_num": 42 } ================================================ FILE: base_config/test/sqlnet.json ================================================ { "data_reader": { "dataset": "wikisql", "train_file_path": "data/wikisql/dev.jsonl", "valid_file_path": "data/wikisql/dev.jsonl", "wikisql": { "is_test": true } }, "iterator": { "batch_size": 10 }, "token": { "names": ["glove"], "types": ["word"], "tokenizer": { "word": { "name": "treebank_en", "split_with_regex": true } }, "glove": { "vocab": { "start_token": "", "end_token": "" }, "indexer": { "lowercase": true, "do_tokenize": true }, "embedding": { "embed_dim": 50, "trainable": false, "dropout": 0.2 } } }, "model": { "name": "sqlnet", "sqlnet": { "column_attention": true, "model_dim": 100, "rnn_num_layer": 2, "dropout": 0.3, "column_maxlen": 4, "token_maxlen": 200, "conds_column_loss_alpha": 3 } }, "trainer": { "log_dir": "logs/test/sqlnet/", "num_epochs": 2, "early_stopping_threshold": 2, "metric_key": "ex_accuracy", "verbose_step_count": 1, "eval_and_save_step_count": 1 }, "optimizer": { "op_type": "adam", "learning_rate": 0.001 }, "seed_num": 25 } ================================================ FILE: base_config/test/ssa.json ================================================ { "data_reader": { "dataset": "seq_cls", "train_file_path": "logs/test/seq_cls/synthetic_data.json", "valid_file_path": "logs/test/seq_cls/synthetic_data.json", "seq_cls": { "class_key": "label" } }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "fasttext"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "indexer": { "insert_char_start": false, "insert_char_end": false }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "fasttext": { "embedding": { "embed_dim": 300, "trainable": false, "dropout": 0.2 } } }, "model": { "name": "structured_self_attention", "structured_self_attention": { "encoding_rnn_hidden_dim": 300, "encoding_rnn_num_layer": 2, "encoding_rnn_dropout": 0, "attention_dim": 350, "num_attention_heads": 30, "sequence_embed_dim": 2000, "dropout": 0.5, "penalization_coefficient": 1 } }, "trainer": { "log_dir": "logs/test/seq_cls/ssa", "num_epochs": 1, "early_stopping_threshold": 10, "grad_max_norm": 5.0, "metric_key": "accuracy", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adam", "learning_rate": 0.001, "exponential_moving_average": 0.999 }, "seed_num": 42 } ================================================ FILE: base_config/test/sst_bert.json ================================================ { "data_reader": { "dataset": "sst_bert", "train_file_path": "data/glue/SST-2/train.tsv", "valid_file_path": "data/glue/SST-2/dev.tsv", "sst_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/sst_bert", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 100 } }, "seed_num": 42 } ================================================ FILE: base_config/test/stsb_bert.json ================================================ { "data_reader": { "dataset": "stsb_bert", "train_file_path": "data/glue/STS-B/train.tsv", "valid_file_path": "data/glue/STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_reg", "bert_for_reg": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/stsb_bert", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "pearson_spearman_corr", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 100 } }, "seed_num": 42 } ================================================ FILE: base_config/test/stsb_roberta.json ================================================ { "data_reader": { "dataset": "stsb_bert", "train_file_path": "data/glue/STS-B/train.tsv", "valid_file_path": "data/glue/STS-B/dev.tsv", "stsb_bert": { "sequence_max_length": 128, "cls_token": "", "sep_token": "", "input_type": "roberta", "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "bpe": { "name": "roberta", "roberta": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "pretrained_token": "all", "pad_token": "", "oov_token": "" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "roberta_for_reg", "roberta_for_reg": { "pretrained_model_name": "roberta-base", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/stsb_roberta", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "pearson_spearman_corr", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 100 } }, "seed_num": 42 } ================================================ FILE: base_config/test/wnli_bert.json ================================================ { "data_reader": { "dataset": "wnli_bert", "train_file_path": "data/glue/WNLI/train.tsv", "valid_file_path": "data/glue/WNLI/dev.tsv", "wnli_bert": { "sequence_max_length": 128, "is_test": true } }, "iterator": { "batch_size": 2 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_seq_cls", "bert_for_seq_cls": { "pretrained_model_name": "bert-base-uncased", "dropout": 0.0 } }, "trainer": { "log_dir": "logs/test/wnli_bert", "num_epochs": 1, "early_stopping_threshold": 10, "metric_key": "accuracy", "eval_and_save_step_count": "epoch" }, "optimizer": { "learning_rate": 2e-5, "op_type": "adamw", "adamw": { "weight_decay": 0 }, "lr_scheduler_type": "warmup_linear", "warmup_linear": { "warmup_steps": 10 } }, "seed_num": 42 } ================================================ FILE: base_config/wikisql/sqlnet.json ================================================ { "data_reader": { "dataset": "wikisql", "train_file_path": "wikisql/train.jsonl", "valid_file_path": "wikisql/dev.jsonl" }, "iterator": { "batch_size": 64 }, "token": { "names": ["glove"], "types": ["word"], "tokenizer": { "word": { "name": "treebank_en", "split_with_regex": true } }, "glove": { "vocab": { "start_token": "", "end_token": "" }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "", "trainable": false } } }, "model": { "name": "sqlnet", "sqlnet": { "column_attention": true, "model_dim": 100, "rnn_num_layer": 2, "dropout": 0.3, "column_maxlen": 4, "token_maxlen": 200, "conds_column_loss_alpha": 3 } }, "trainer": { "log_dir": "logs/experiment/sqlnet/", "num_epochs": 500, "early_stopping_threshold": 50, "metric_key": "ex_accuracy", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adam", "learning_rate": 0.001 }, "seed_num": 25 } ================================================ FILE: claf/__init__.py ================================================ # -*- coding: utf-8 -*- # register components from claf.data.reader import * from claf.machine import * from claf.machine.components import * from claf.model import * ================================================ FILE: claf/__version__.py ================================================ # CLaF: Clova Language Framework VERSION = (0, 2, 0) __version__ = ".".join(map(str, VERSION)) ================================================ FILE: claf/config/__init__.py ================================================ ================================================ FILE: claf/config/args.py ================================================ import argparse from argparse import RawTextHelpFormatter import os import sys import torch from claf import nsml from claf.config import utils from claf.config.namespace import NestedNamespace from claf.learn.mode import Mode def config(argv=None, mode=None): if argv is None: argv = sys.argv[1:] # 0 is excute file_name parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter) general(parser) if mode == Mode.EVAL: evaluate(parser) return parser.parse_args(argv, namespace=NestedNamespace()) if mode == Mode.PREDICT: predict(parser) return parser.parse_args(argv, namespace=NestedNamespace()) if mode == Mode.MACHINE: machine(parser) config = parser.parse_args(argv, namespace=NestedNamespace()) if config.machine_config is None: raise ValueError("--machine_config is required.") machine_config_path = os.path.join("machine_config", config.machine_config) machine_config_path = utils.add_config_extension(machine_config_path) defined_config = utils.read_config(machine_config_path) config.overwrite(defined_config) return config return train_config(parser, input_argv=argv) def train_config(parser, input_argv=None): """ Add argument only for hyperparameter tuning. """ data(parser) token(parser) model(parser) if nsml.IS_ON_NSML: nsml_for_internal(parser) trainer(parser) # Use from config file base_config(parser) config = parser.parse_args(input_argv, namespace=NestedNamespace()) use_base_config = config.base_config # use pre-defined base_config if use_base_config: base_config_path = os.path.join("base_config", config.base_config) base_config_path = utils.add_config_extension(base_config_path) defined_config = utils.read_config() # config.overwrite(defined_config) config = NestedNamespace() config.load_from_json(defined_config) # overwrite input argument when base_config and arguments are provided. # (eg. --base_config bidaf --learning_rate 2) -> set bidaf.json then overwrite learning_rate 2) input_args = get_input_arguments(parser, input_argv) for k, v in input_args.items(): setattr(config, k, v) if not use_base_config: config = optimize_config(config) set_gpu_env(config) set_batch_size(config) return config def get_input_arguments(parser, input_arguments): flat_config = parser.parse_args(input_arguments) config_dict = utils.convert_config2dict(flat_config) config_default_none = {k: None for k in config_dict.keys()} input_parser = argparse.ArgumentParser(parents=[parser], conflict_handler="resolve") input_parser.set_defaults(**config_default_none) input_config = input_parser.parse_args(input_arguments) input_config = utils.convert_config2dict(input_config) if "base_config" in input_config: del input_config["base_config"] return {k: v for k, v in input_config.items() if v is not None} def optimize_config(config, is_test=False): if not is_test: # Remove unselected argument token_excepts = config.token.names + ["names", "types", "tokenizer"] config.delete_unselected(config.token, excepts=token_excepts) config.delete_unselected(config.model, excepts=["name", config.model.name]) config.delete_unselected( config.optimizer, excepts=[ "op_type", config.optimizer.op_type, "learning_rate", "lr_scheduler_type", config.optimizer.lr_scheduler_type, "exponential_moving_average", ], ) return config def set_gpu_env(config): # GPU & NSML config.use_gpu = torch.cuda.is_available() or nsml.IS_ON_NSML if nsml.IS_ON_NSML: if getattr(config, "nsml", None) is None: config.nsml = NestedNamespace() config.nsml.dataset_path = nsml.DATASET_PATH config.gpu_num = int(nsml.GPU_NUM) else: config.gpu_num = len(getattr(config, "cuda_devices", [])) if not config.use_gpu: config.gpu_num = 0 config.cuda_devices = None def set_batch_size(config): # dynamic batch_size (multi-gpu and gradient_accumulation_steps) batch_size = config.iterator.batch_size if config.gpu_num > 1: batch_size *= config.gpu_num if getattr(config.optimizer, "gradient_accumulation_steps", None): batch_size = batch_size // config.optimizer.gradient_accumulation_steps config.iterator.batch_size = int(batch_size) def arg_str2bool(v): if v.lower() in ("yes", "true", "True", "t", "y", "1"): return True elif v.lower() in ("no", "false", "False", "f", "n", "0"): return False else: raise argparse.ArgumentTypeError("Boolean value expected.") # fmt: off def general(parser): group = parser.add_argument_group("General") group.add_argument( "--seed_num", type=int, default=21, dest="seed_num", help=""" Manually set seed_num (Python, Numpy, Pytorch) default is 21 """, ) group.add_argument( "--cuda_devices", nargs="+", type=int, default=[], dest="cuda_devices", help=""" Set cuda_devices ids (use GPU). if you use NSML, use GPU_NUM""", ) group.add_argument( "--slack_url", type=str, default=None, dest="slack_url", help=""" Slack notification (Incoming Webhook) """, ) def data(parser): group = parser.add_argument_group("Data Reader") group.add_argument( "--dataset", type=str, default="squad", dest="data_reader.dataset", help=""" Dataset Name [squad|squad2] """, ) group.add_argument( "--train_file_path", type=str, default="train-v1.1.json", dest="data_reader.train_file_path", help=""" train file path. """, ) group.add_argument( "--valid_file_path", type=str, default="dev-v1.1.json", dest="data_reader.valid_file_path", help=""" validation file path. """, ) group.add_argument( "--test_file_path", type=str, default=None, dest="data_reader.test_file_path", help=""" test file path. """, ) group = parser.add_argument_group(" # SQuAD DataSet") group.add_argument( "--squad.context_max_length", type=int, default=None, dest="data_reader.squad.context_max_length", help=""" The number of SQuAD Context maximum length. """, ) group = parser.add_argument_group(" # HistoryQA DataSet") group.add_argument( "--history.context_max_length", type=int, default=None, dest="data_reader.history.context_max_length", help=""" The number of HistoryQA Context maximum length. """, ) group = parser.add_argument_group(" # SeqCls DataSet") group.add_argument( "--seq_cls.class_key", type=int, default=None, dest="data_reader.seq_cls.class_key", help=""" Name of the label to use for classification. """, ) group.add_argument( "--seq_cls.sequence_max_length", type=int, default=None, dest="data_reader.seq_cls.sequence_max_length", help=""" The number of maximum sequence length. """, ) group = parser.add_argument_group(" # SeqClsBert DataSet") group.add_argument( "--seq_cls_bert.class_key", type=int, default=None, dest="data_reader.seq_cls_bert.class_key", help=""" Name of the label to use for classification. """, ) group.add_argument( "--seq_cls_bert.sequence_max_length", type=int, default=None, dest="data_reader.seq_cls_bert.sequence_max_length", help=""" The number of maximum sequence length. """, ) group = parser.add_argument_group(" # TokClsBert DataSet") group.add_argument( "--tok_cls_bert.tag_key", type=int, default=None, dest="data_reader.tok_cls_bert.tag_key", help=""" Name of the label to use for classification. """, ) group.add_argument( "--tok_cls_bert.ignore_tag_idx", type=int, default=None, dest="data_reader.tok_cls_bert.ignore_tag_idx", help=""" Index of the tag to ignore when calculating loss. (tag pad value) """, ) group.add_argument( "--tok_cls_bert.sequence_max_length", type=int, default=None, dest="data_reader.tok_cls_bert.sequence_max_length", help=""" The number of maximum sequence length. """, ) group = parser.add_argument_group("Iterator") group.add_argument( "--batch_size", type=int, default=32, dest="iterator.batch_size", help=""" Maximum batch size for trainer""", ) def token(parser): group = parser.add_argument_group("Token") group.add_argument( "--token_names", nargs="+", type=str, default=["char", "word"], dest="token.names", help=""" Define tokens name""", ) group.add_argument( "--token_types", nargs="+", type=str, default=["char", "word"], dest="token.types", help="""\ Use pre-defined token (tokenizer -> indexer -> embedder) [char|cove|elmo|exact_match|frequent_word|word]""", ) group = parser.add_argument_group(" # Vocabulary") group.add_argument( "--char.pad_token", type=str, default=None, dest="token.char.vocab.pad_token", help=""" Padding Token value""", ) group.add_argument( "--char.oov_token", type=str, default=None, dest="token.char.vocab.oov_token", help=""" Out-of-Vocabulary Token value""", ) group.add_argument( "--char.start_token", type=str, default=None, dest="token.char.vocab.start_token", help=""" Start Token value""", ) group.add_argument( "--char.end_token", type=str, default=None, dest="token.char.vocab.end_token", help=""" End Token value""", ) group.add_argument( "--char.min_count", type=int, default=None, dest="token.char.vocab.min_count", help=""" The number of token's min count""", ) group.add_argument( "--char.max_vocab_size", type=int, default=260, dest="token.char.vocab.max_vocab_size", help=""" The number of vocab's max size""", ) group.add_argument( "--feature.pretrained_path", type=str, default=None, dest="token.feature.vocab.pretrained_path", help=""" Add pretrained vocab_path""", ) group.add_argument( "--feature.pad_token", type=str, default=None, dest="token.feature.vocab.pad_token", help=""" Set pad_token""", ) group.add_argument( "--feature.oov_token", type=str, default=None, dest="token.feature.vocab.oov_token", help=""" Set oov_token""", ) group.add_argument( "--feature.cls_token", type=str, default=None, dest="token.feature.vocab.cls_token", help=""" Set cls_token""", ) group.add_argument( "--feature.sep_token", type=str, default=None, dest="token.feature.vocab.sep_token", help=""" Set sep_token""", ) group.add_argument( "--word.pad_token", type=str, default=None, dest="token.word.vocab.pad_token", help=""" Padding Token value""", ) group.add_argument( "--word.oov_token", type=str, default=None, dest="token.word.vocab.oov_token", help=""" Out-of-Vocabulary Token value""", ) group.add_argument( "--word.min_count", type=int, default=None, dest="token.word.vocab.min_count", help=""" The number of token's min count""", ) group.add_argument( "--word.max_vocab_size", type=int, default=None, dest="token.word.vocab.max_vocab_size", help=""" The number of vocab's max size""", ) group.add_argument( "--frequent_word.frequent_count", type=int, default=1000, dest="token.frequent_word.vocab.frequent_count", help="""\ The number of threshold frequent count (>= threshold -> fine-tune, < threshold -> fixed)""", ) group = parser.add_argument_group(" # Tokenizer") group.add_argument( "--tokenizer.bpe.name", type=str, default="roberta", dest="token.tokenizer.bpe.name", help="""\ BPE Tokenizer package name [roberta] Default is 'roberta' """, ) group.add_argument( "--tokenizer.bpe.roberta.vocab_path", type=str, default=None, dest="token.tokenizer.bpe.roberta.vocab_path", help="""\ RoBERTa BPE Tokenizer vocab_path Default is 'None' """, ) group.add_argument( "--tokenizer.bpe.roberta.merges_path", type=str, default=None, dest="token.tokenizer.bpe.roberta.merges_path", help="""\ RoBERTa BPE Tokenizer merges_path Default is 'None' """, ) group.add_argument( "--tokenizer.char.name", type=str, default="character", dest="token.tokenizer.char.name", help="""\ CharTokenizer package name [character|jamo_ko] Default is 'character' """, ) group.add_argument( "--tokenizer.subword.name", type=str, default="wordpiece", dest="token.tokenizer.subword.name", help="""\ SubWordTokenizer package name [wordpiece] Default is 'wordpiece' """, ) group.add_argument( "--tokenizer.subword.wordpiece.vocab_path", type=str, default=None, dest="token.tokenizer.subword.wordpiece.vocab_path", help="""\ Wordpiece Tokenizer vocab_path Default is 'None' """, ) group.add_argument( "--tokenizer.word.name", type=str, default="treebank_en", dest="token.tokenizer.word.name", help="""\ WordTokenizer package name [treebank_en|spacy_en|mecab_ko] Default is 'treebank_en' """, ) group.add_argument( "--tokenizer.word.split_with_regex", type=arg_str2bool, default=False, dest="token.tokenizer.word.split_with_regex", help=""" preprocess for SQuAD Context data (simple regex) """, ) group.add_argument( "--tokenizer.word.bert_basic.do_lower_case", type=arg_str2bool, default=True, dest="token.tokenizer.word.bert_basic.do_lower_case", help="""\ Wordpiece Tokenizer do_lower_case or not Default is 'True' """, ) group.add_argument( "--tokenizer.sent.name", type=str, default="punkt", dest="token.tokenizer.sent.name", help="""\ SentTokenizer package name [punkt] Default is 'punkt' """, ) group = parser.add_argument_group(" # Indexer") group.add_argument( "--char.insert_char_start", type=arg_str2bool, default=False, dest="token.char.indexer.insert_char_start", help=""" insert first start_token to tokens""", ) group.add_argument( "--char.insert_char_end", type=arg_str2bool, default=False, dest="token.char.indexer.insert_char_end", help=""" append end_token to tokens""", ) group.add_argument( "--exact_match.lower", type=arg_str2bool, default=True, dest="token.exact_match.indexer.lower", help=""" add lower case feature """, ) group.add_argument( "--exact_match.lemma", type=arg_str2bool, default=True, dest="token.exact_match.indexer.lemma", help=""" add lemma case feature """, ) group.add_argument( "--linguistic.pos_tag", type=arg_str2bool, default=True, dest="token.linguistic.indexer.pos_tag", help=""" add POS Tagging feature """, ) group.add_argument( "--linguistic.ner", type=arg_str2bool, default=True, dest="token.linguistic.indexer.ner", help=""" add Named Entity Recognition feature """, ) group.add_argument( "--linguistic.dep", type=arg_str2bool, default=False, dest="token.linguistic.indexer.dep", help=""" add Dependency Parser feature """, ) group.add_argument( "--word.lowercase", type=arg_str2bool, default=False, dest="token.word.indexer.lowercase", help=""" Apply word token to lowercase""", ) group.add_argument( "--word.insert_start", type=arg_str2bool, default=False, dest="token.word.indexer.insert_start", help=""" insert first start_token to tokens""", ) group.add_argument( "--word.insert_end", type=arg_str2bool, default=False, dest="token.word.indexer.insert_end", help=""" append end_token to tokens""", ) group = parser.add_argument_group(" # Embedding") group.add_argument( "--char.embed_dim", type=int, default=16, dest="token.char.embedding.embed_dim", help=""" The number of Embedding dimension""", ) group.add_argument( "--char.kernel_sizes", nargs="+", type=int, default=[5], dest="token.char.embedding.kernel_sizes", help=""" CharCNN kernel_sizes (n-gram)""", ) group.add_argument( "--char.num_filter", type=int, default=100, dest="token.char.embedding.num_filter", help=""" The number of CNN filter""", ) group.add_argument( "--char.activation", type=str, default="relu", dest="token.char.embedding.activation", help=""" CharCNN activation Function (default: ReLU)""", ) group.add_argument( "--char.dropout", type=float, default=0.2, dest="token.char.embedding.dropout", help=""" Embedding dropout prob (default: 0.2)""", ) group.add_argument( "--cove.glove_pretrained_path", type=str, default=None, dest="token.cove.embedding.glove_pretrained_path", help=""" CoVe's word embedding pretrained_path (GloVE 840B.300d)""", ) group.add_argument( "--cove.model_pretrained_path", type=str, default=None, dest="token.cove.embedding.model_pretrained_path", help=""" CoVe Model pretrained_path """, ) group.add_argument( "--cove.trainable", type=arg_str2bool, default=True, dest="token.cove.embedding.trainable", help=""" CoVe Embedding Trainable""", ) group.add_argument( "--cove.dropout", type=float, default=0.2, dest="token.cove.embedding.dropout", help=""" Embedding dropout prob (default: 0.2)""", ) group.add_argument( "--cove.project_dim", type=int, default=None, dest="token.cove.embedding.project_dim", help=""" The number of projection dimension""", ) group.add_argument( "--elmo.options_file", type=str, default="elmo_2x4096_512_2048cnn_2xhighway_options.json", dest="token.elmo.embedding.options_file", help=""" The option file path of ELMo""", ) group.add_argument( "--elmo.weight_file", type=str, default="elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5", dest="token.elmo.embedding.weight_file", help=""" The weight file path of ELMo""", ) group.add_argument( "--elmo.trainable", type=arg_str2bool, default=False, dest="token.elmo.embedding.trainable", help=""" elmo Embedding Trainable""", ) group.add_argument( "--elmo.dropout", type=float, default=0.5, dest="token.elmo.embedding.dropout", help=""" Embedding dropout prob (default: 0.5)""", ) group.add_argument( "--elmo.project_dim", type=int, default=None, dest="token.elmo.embedding.project_dim", help=""" The number of projection dimension (default is None)""", ) group.add_argument( "--word_permeability.memory_clip", type=int, default=3, dest="token.word_permeability.embedding.memory_clip", help=""" The number of memory cell clip value """, ) group.add_argument( "--word_permeability.proj_clip", type=int, default=3, dest="token.word_permeability.embedding.proj_clip", help=""" The number of p clip value after projection """, ) group.add_argument( "--word_permeability.embed_dim", type=int, default=1024, dest="token.word_permeability.embedding.embed_dim", help=""" The number of Embedding dimension""", ) group.add_argument( "--word_permeability.linear_dim", type=int, default=None, dest="token.word_permeability.embedding.linear_dim", help=""" The number of linear projection dimension""", ) group.add_argument( "--word_permeability.trainable", type=arg_str2bool, default=False, dest="token.word_permeability.embedding.trainable", help=""" word_permeability Embedding Trainable """, ) group.add_argument( "--word_permeability.dropout", type=float, default=0.5, dest="token.word_permeability.embedding.dropout", help=""" Embedding dropout prob (default: 0.5)""", ) group.add_argument( "--word_permeability.activation", type=str, default="tanh", dest="token.word_permeability.embedding.activation", help=""" Activation Function (default is 'tanh') """, ) group.add_argument( "--word_permeability.bidirectional", type=arg_str2bool, default=False, dest="token.word_permeability.embedding.bidirectional", help=""" bidirectional use or not ([forward;backward]) (default is False) """, ) group.add_argument( "--frequent_word.embed_dim", type=int, default=100, dest="token.frequent_word.embedding.embed_dim", help=""" The number of Embedding dimension""", ) group.add_argument( "--frequent_word.pretrained_path", type=str, default=None, dest="token.frequent_word.embedding.pretrained_path", help=""" Add pretrained Word vector model's path. (support file format like Glove)""", ) group.add_argument( "--frequent_word.dropout", type=float, default=0.2, dest="token.frequent_word.embedding.dropout", help=""" Embedding dropout prob (default: 0.2)""", ) group.add_argument( "--word.embed_dim", type=int, default=100, dest="token.word.embedding.embed_dim", help=""" The number of Embedding dimension""", ) group.add_argument( "--word.pretrained_path", type=str, default=None, dest="token.word.embedding.pretrained_path", help=""" Add pretrained word vector model's path. (support file format like Glove)""", ) group.add_argument( "--word.trainable", type=arg_str2bool, default=True, dest="token.word.embedding.trainable", help=""" Word Embedding Trainable""", ) group.add_argument( "--word.dropout", type=float, default=0.2, dest="token.word.embedding.dropout", help=""" Embedding dropout prob (default: 0.2)""", ) def model(parser): group = parser.add_argument_group("Model") group.add_argument( "--model_name", type=str, default="bidaf", dest="model.name", help="""\ Pre-defined model * Reading Comprehension [bert_for_qa|bidaf|bidaf_no_answer|docqa|docqa_no_answer|dclaf|qanet|simple] * Regression [bert_for_reg|roberta_for_reg] * Semantic Parsing [sqlnet] * Sequence Classification [bert_for_seq_cls|roberta_for_seq_cls|structured_self_attention] * Token Classification [bert_for_tok_cls] """, ) reading_comprehension_title = "ㅁReading Comprehension" group = parser.add_argument_group(f"{reading_comprehension_title}\n # BERT for QuestionAnswering") group.add_argument( "--bert_for_qa.pretrained_model_name", type=str, default=None, dest="model.bert_for_qa.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `bert-base-uncased` . `bert-large-uncased` . `bert-base-cased` . `bert-base-multilingual` . `bert-base-chinese` """, ) group.add_argument( "--bert_for_qa.answer_maxlen", type=int, default=None, dest="model.bert_for_qa.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group = parser.add_argument_group(f" # RoBERTa") group.add_argument( "--roberta_for_qa.pretrained_model_name", type=str, default=None, dest="model.roberta_for_qa.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `roberta-base` . `roberta-large` """, ) group.add_argument( "--roberta_for_qa.answer_maxlen", type=int, default=None, dest="model.roberta_for_qa.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group = parser.add_argument_group(f" # BiDAF") group.add_argument( "--bidaf.aligned_query_embedding", type=int, default=False, dest="model.bidaf.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--bidaf.answer_maxlen", type=int, default=None, dest="model.bidaf.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--bidaf.model_dim", type=int, default=100, dest="model.bidaf.model_dim", help=""" The number of BiDAF model dimension""", ) group.add_argument( "--bidaf.contextual_rnn_num_layer", type=int, default=1, dest="model.bidaf.contextual_rnn_num_layer", help=""" The number of BiDAF model contextual_rnn's recurrent layers""", ) group.add_argument( "--bidaf.modeling_rnn_num_layer", type=int, default=2, dest="model.bidaf.modeling_rnn_num_layer", help=""" The number of BiDAF model modeling_rnn's recurrent layers""", ) group.add_argument( "--bidaf.predict_rnn_num_layer", type=int, default=1, dest="model.bidaf.predict_rnn_num_layer", help=""" The number of BiDAF model predict_rnn's recurrent layers""", ) group.add_argument( "--bidaf.dropout", type=float, default=0.2, dest="model.bidaf.dropout", help=""" The prob of BiDAF dropout""", ) group = parser.add_argument_group(" # BiDAF + Simple bias") group.add_argument( "--bidaf_no_answer.aligned_query_embedding", type=int, default=False, dest="model.bidaf_no_answer.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--bidaf_no_answer.answer_maxlen", type=int, default=None, dest="model.bidaf_no_answer.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--bidaf_no_answer.model_dim", type=int, default=100, dest="model.bidaf_no_answer.model_dim", help=""" The number of BiDAF model dimension""", ) group.add_argument( "--bidaf_no_answer.contextual_rnn_num_layer", type=int, default=1, dest="model.bidaf_no_answer.contextual_rnn_num_layer", help=""" The number of BiDAF model contextual_rnn's recurrent layers""", ) group.add_argument( "--bidaf_no_answer.modeling_rnn_num_layer", type=int, default=2, dest="model.bidaf_no_answer.modeling_rnn_num_layer", help=""" The number of BiDAF model modeling_rnn's recurrent layers""", ) group.add_argument( "--bidaf_no_answer.predict_rnn_num_layer", type=int, default=1, dest="model.bidaf_no_answer.predict_rnn_num_layer", help=""" The number of BiDAF model predict_rnn's recurrent layers""", ) group.add_argument( "--bidaf_no_answer.dropout", type=float, default=0.2, dest="model.bidaf_no_answer.dropout", help=""" The prob of BiDAF dropout""", ) group = parser.add_argument_group(" # Simple") group.add_argument( "--simple.answer_maxlen", type=int, default=None, dest="model.simple.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--simple.model_dim", type=int, default=100, dest="model.simple.model_dim", help=""" The number of Simple model dimension""", ) group.add_argument( "--simple.dropout", type=float, default=0.2, dest="model.simple.dropout", help=""" The prob of Simple dropout""", ) group = parser.add_argument_group(" # QANet") group.add_argument( "--qanet.aligned_query_embedding", type=int, default=False, dest="model.qanet.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--qanet.answer_maxlen", type=int, default=30, dest="model.qanet.answer_maxlen", help=""" The number of maximum answer's length (default: 30)""", ) group.add_argument( "--qanet.model_dim", type=int, default=128, dest="model.qanet.model_dim", help=""" The number of QANet model dimension""", ) group.add_argument( "--qanet.kernel_size_in_embedding", type=int, default=7, dest="model.qanet.kernel_size_in_embedding", help=""" The number of QANet model Embed Encoder kernel_size""", ) group.add_argument( "--qanet.num_head_in_embedding", type=int, default=8, dest="model.qanet.num_head_in_embedding", help=""" The number of QANet model Multi-Head Attention's head in Embedding Block""", ) group.add_argument( "--qanet.num_conv_block_in_embedding", type=int, default=4, dest="model.qanet.num_conv_block_in_embedding", help=""" The number of QANet model Conv Blocks in Embedding Block""", ) group.add_argument( "--qanet.num_embedding_encoder_block", type=int, default=1, dest="model.qanet.num_embedding_encoder_block", help=""" The number of QANet model Embedding Encoder Blocks""", ) group.add_argument( "--qanet.kernel_size_in_modeling", type=int, default=5, dest="model.qanet.kernel_size_in_modeling", help=""" The number of QANet model Model Encoder kernel_size""", ) group.add_argument( "--qanet.num_head_in_modeling", type=int, default=8, dest="model.qanet.num_head_in_modeling", help=""" The number of QANet model Multi-Head Attention's head in Modeling Block""", ) group.add_argument( "--qanet.num_conv_block_in_modeling", type=int, default=2, dest="model.qanet.num_conv_block_in_modeling", help=""" The number of QANet model Conv Blocks in Modeling Block""", ) group.add_argument( "--qanet.num_modeling_encoder_block", type=int, default=7, dest="model.qanet.num_modeling_encoder_block", help=""" The number of QANet model Modeling Encoder Blocks""", ) group.add_argument( "--qanet.layer_dropout", type=float, default=0.9, dest="model.qanet.layer_dropout", help=""" The prob of QANet model layer dropout""", ) group.add_argument( "--qanet.dropout", type=float, default=0.1, dest="model.qanet.dropout", help=""" The prob of QANet dropout""", ) group = parser.add_argument_group(" # DocQA") group.add_argument( "--docqa.aligned_query_embedding", type=arg_str2bool, default=False, dest="model.docqa.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--docqa.answer_maxlen", type=int, default=17, dest="model.docqa.answer_maxlen", help=""" The number of maximum answer's length (default: 17)""", ) group.add_argument( "--docqa.rnn_dim", type=int, default=100, dest="model.docqa.rnn_dim", help=""" The number of DocQA model rnn dimension""", ) group.add_argument( "--docqa.linear_dim", type=int, default=200, dest="model.docqa.linear_dim", help=""" The number of DocQA model linear dimension""", ) group.add_argument( "--docqa.preprocess_rnn_num_layer", type=int, default=1, dest="model.docqa.preprocess_rnn_num_layer", help=""" The number of DocQA model preprocess_rnn's recurrent layers""", ) group.add_argument( "--docqa.modeling_rnn_num_layer", type=int, default=1, dest="model.docqa.modeling_rnn_num_layer", help=""" The number of DocQA model modeling_rnn's recurrent layers""", ) group.add_argument( "--docqa.predict_rnn_num_layer", type=int, default=1, dest="model.docqa.predict_rnn_num_layer", help=""" The number of DocQA model predict_rnn's recurrent layers""", ) group.add_argument( "--docqa.dropout", type=float, default=0.2, dest="model.docqa.dropout", help=""" The prob of DocQA dropout""", ) group.add_argument( "--docqa.weight_init", type=arg_str2bool, default=True, dest="model.docqa.weight_init", help=""" Weight Init""", ) group = parser.add_argument_group(" # DocQA + No_Answer Option") group.add_argument( "--docqa_no_answer.aligned_query_embedding", type=arg_str2bool, default=False, dest="model.docqa_no_answer.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--docqa_no_answer.answer_maxlen", type=int, default=17, dest="model.docqa_no_answer.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--docqa_no_answer.rnn_dim", type=int, default=100, dest="model.docqa_no_answer.rnn_dim", help=""" The number of docqa_no_answer model rnn dimension""", ) group.add_argument( "--docqa_no_answer.linear_dim", type=int, default=200, dest="model.docqa_no_answer.linear_dim", help=""" The number of docqa_no_answer model linear dimension""", ) group.add_argument( "--docqa_no_answer.dropout", type=float, default=0.2, dest="model.docqa_no_answer.dropout", help=""" The prob of QANet dropout""", ) group.add_argument( "--docqa_no_answer.weight_init", type=arg_str2bool, default=True, dest="model.docqa_no_answer.weight_init", help=""" Weight Init""", ) group = parser.add_argument_group(" # DrQA") group.add_argument( "--drqa.aligned_query_embedding", type=int, default=True, dest="model.drqa.aligned_query_embedding", help=""" Aligned Question Embedding (default: True)""", ) group.add_argument( "--drqa.answer_maxlen", type=int, default=15, dest="model.drqa.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--drqa.model_dim", type=int, default=128, dest="model.drqa.model_dim", help=""" The number of document reader model dimension""", ) group.add_argument( "--drqa.dropout", type=int, default=0.3, dest="model.drqa.dropout", help=""" The number of document reader model dropout""", ) regression_title = "ㅁRegression" group = parser.add_argument_group(f"{regression_title}\n # BERT for Regression") group.add_argument( "--bert_for_reg.pretrained_model_name", type=str, default=None, dest="model.bert_for_reg.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `bert-base-uncased` . `bert-large-uncased` . `bert-base-cased` . `bert-base-multilingual` . `bert-base-chinese` """, ) group.add_argument( "--bert_for_reg.dropout", type=float, default=0.2, dest="model.bert_for_reg.dropout", help=""" The prob of fc layer dropout """ ) group = parser.add_argument_group(f" # RoBERTa") group.add_argument( "--roberta_for_reg.pretrained_model_name", type=str, default=None, dest="model.roberta_for_reg.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `roberta-base` . `roberta-large` """, ) group.add_argument( "--roberta_for_reg.dropout", type=float, default=0.2, dest="model.roberta_for_reg.dropout", help=""" The prob of fc layer dropout """ ) semantic_parsing_title = "ㅁSemantic Parsing" group = parser.add_argument_group(f"{semantic_parsing_title}\n # SQLNet") group.add_argument( "--sqlnet.column_attention", type=int, default=True, dest="model.sqlnet.column_attention", help=""" Compute attention map on a question conditioned on the column names (default: True)""", ) group.add_argument( "--sqlnet.model_dim", type=int, default=100, dest="model.sqlnet.model_dim", help=""" The number of document reader model dimension""", ) group.add_argument( "--sqlnet.rnn_num_layer", type=int, default=2, dest="model.sqlnet.rnn_num_layer", help=""" The number of SQLNet model rnn's recurrent layers""", ) group.add_argument( "--sqlnet.dropout", type=int, default=0.3, dest="model.sqlnet.dropout", help=""" The prob of model dropout """, ) group.add_argument( "--sqlnet.column_maxlen", type=int, default=4, dest="model.sqlnet.column_maxlen", help=""" The number of maximum column's length (default: 4)""", ) group.add_argument( "--sqlnet.token_maxlen", type=int, default=200, dest="model.sqlnet.token_maxlen", help=""" An upper-bound N on the number of decoder tokeni """, ) group.add_argument( "--sqlnet.conds_column_loss_alpha", type=int, default=0.3, dest="model.sqlnet.conds_column_loss_alpha", help=""" balance the positive data versus negative data """, ) sequence_classification_title = "ㅁSequence Classification" group = parser.add_argument_group(f"{sequence_classification_title}\n # BERT for Sequence Classification") group.add_argument( "--bert_for_seq_cls.pretrained_model_name", type=str, default=None, dest="model.bert_for_seq_cls.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `bert-base-uncased` . `bert-large-uncased` . `bert-base-cased` . `bert-base-multilingual` . `bert-base-chinese` """, ) group.add_argument( "--bert_for_seq_cls.dropout", type=float, default=0.2, dest="model.bert_for_seq_cls.dropout", help=""" The prob of fc layer dropout """ ) group = parser.add_argument_group(f" # RoBERTa") group.add_argument( "--roberta_for_seq_cls.pretrained_model_name", type=str, default=None, dest="model.roberta_for_seq_cls.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `roberta-base` . `roberta-large` """, ) group.add_argument( "--roberta_for_seq_cls.dropout", type=float, default=0.2, dest="model.roberta_for_seq_cls.dropout", help=""" The prob of fc layer dropout """ ) group = parser.add_argument_group(f"{sequence_classification_title}\n # Structured Self Attention") group.add_argument( "--structured_self_attention.token_encoder", type=str, default="bilstm", dest="model.structured_self_attention.token_encoder", help=""" Token encoder type [none|bilstm] """ ) group.add_argument( "--structured_self_attention.encoding_rnn_hidden_dim", type=int, default=600, dest="model.structured_self_attention.encoding_rnn_hidden_dim", help=""" The number of hidden dimension for each token """ ) group.add_argument( "--structured_self_attention.encoding_rnn_num_layer", type=int, default=2, dest="model.structured_self_attention.encoding_rnn_num_layer", help=""" The number of layers of token encoding rnn """ ) group.add_argument( "--structured_self_attention.encoding_rnn_dropout", type=float, default=0., dest="model.structured_self_attention.encoding_rnn_dropout", help=""" The prob of token encoding rnn dropout (between layers) """ ) group.add_argument( "--structured_self_attention.attention_dim", type=int, default=350, dest="model.structured_self_attention.attention_dim", help=""" The number of embedding dimension for attention """ ) group.add_argument( "--structured_self_attention.num_attention_heads", type=int, default=30, dest="model.structured_self_attention.num_attention_heads", help=""" The number of rows for attention (attention heads) """ ) group.add_argument( "--structured_self_attention.project_dim", type=int, default=2000, dest="model.structured_self_attention.project_dim", help=""" The number of bottleneck layer embedding dimension """ ) group.add_argument( "--structured_self_attention.dropout", type=float, default=0.5, dest="model.structured_self_attention.dropout", help=""" The prob of bottleneck-making fnn dropout """ ) group.add_argument( "--structured_self_attention.penalization_coefficient", type=float, default=1., dest="model.structured_self_attention.penalization_coefficient", help=""" The coefficient of penalization term """ ) token_classification_title = "ㅁToken Classification" group = parser.add_argument_group(f"{token_classification_title}\n # BERT for Token Classification") group.add_argument( "--bert_for_tok_cls.pretrained_model_name", type=str, default=None, dest="model.bert_for_tok_cls.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `bert-base-uncased` . `bert-large-uncased` . `bert-base-cased` . `bert-base-multilingual` . `bert-base-chinese` """, ) group.add_argument( "--bert_for_tok_cls.dropout", type=float, default=0.2, dest="model.bert_for_tok_cls.dropout", help=""" The prob of fc layer dropout """ ) group = parser.add_argument_group(f" # RoBERTa") group.add_argument( "--roberta_for_tok_cls.pretrained_model_name", type=str, default=None, dest="model.roberta_for_tok_cls.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `roberta-base` . `roberta-large` """, ) group.add_argument( "--roberta_for_tok_cls.dropout", type=float, default=0.2, dest="model.roberta_for_tok_cls.dropout", help=""" The prob of fc layer dropout """ ) def nsml_for_internal(parser): group = parser.add_argument_group("NSML") group.add_argument( "--pause", type=int, default=0, dest="nsml.pause", help=""" NSML default setting""" ) group.add_argument( "--iteration", type=int, default=0, dest="nsml.iteration", help=""" Start from NSML epoch count""", ) def trainer(parser): group = parser.add_argument_group("Trainer") group.add_argument( "--num_epochs", type=int, default=20, dest="trainer.num_epochs", help=""" The number of training epochs""", ) group.add_argument( "--patience", type=int, default=10, dest="trainer.early_stopping_threshold", help=""" The number of early stopping threshold""", ) group.add_argument( "--metric_key", type=str, default="em", dest="trainer.metric_key", help=""" The key of metric for model's score""", ) group.add_argument( "--verbose_step_count", type=int, default=100, dest="trainer.verbose_step_count", help=""" The number of training verbose""", ) group.add_argument( "--eval_and_save_step_count", type=int, default=1, dest="trainer.eval_and_save_step_count", help=""" The number of save and evaluate step_count (e.g. 'epoch' or 1000)""", ) group.add_argument( "--save_checkpoint", type=arg_str2bool, default=True, dest="trainer.save_checkpoint", help=""" The boolean value of save checkpoint""", ) group.add_argument( "--log_dir", type=str, default="logs/experiment_1", dest="trainer.log_dir", help=""" TensorBoard and Checkpoint log directory""", ) group = parser.add_argument_group("Gradient") group.add_argument( "--grad_max_norm", type=float, default=None, dest="trainer.grad_max_norm", help=""" Clips gradient norm of an iterable of parameters. (Default: None)""") group = parser.add_argument_group("Optimizer") group.add_argument( "--optimizer_type", type=str, default="adam", dest="optimizer.op_type", help=""" Optimizer (https://pytorch.org/docs/stable/optim.html#algorithms) - adadelta: ADADELTA: An Adaptive Learning Rate Method (https://arxiv.org/abs/1212.5701) - adagrad: Adaptive Subgradient Methods for Online Learning and Stochastic Optimization (http://jmlr.org/papers/v12/duchi11a.html) - adam: Adam: A Method for Stochastic Optimization (https://arxiv.org/abs/1412.6980) - adamw: Adam: Adam algorithm with weight decay fix. (BertAdam) - sparse_adam: Implements lazy version of Adam algorithm suitable for sparse tensors. In this variant, only moments that show up in the gradient get updated, and only those portions of the gradient get applied to the parameters. - adamax: Implements Adamax algorithm (a variant of Adam based on infinity norm). - averaged_sgd: Acceleration of stochastic approximation by averaging (http://dl.acm.org/citation.cfm?id=131098) - rmsprop: Implements RMSprop algorithm. (https://arxiv.org/pdf/1308.0850v5.pdf) - rprop: Implements the resilient backpropagation algorithm. - sgd: Implements stochastic gradient descent (optionally with momentum). Nesterov momentum: (http://www.cs.toronto.edu/~hinton/absps/momentum.pdf) [adadelta|adagrad|adam|adamw|sparse_adam|adamax|averaged_sgd|rmsprop|rprop|sgd]""", ) group.add_argument( "--learning_rate", type=float, default=0.5, dest="optimizer.learning_rate", help="""\ Starting learning rate. Recommended settings: sgd = 1, adagrad = 0.1, adadelta = 1, adam = 0.001 """, ) group = parser.add_argument_group(" # Adadelta") group.add_argument( "--adadelta.rho", type=float, default=0.9, dest="optimizer.adadelta.rho", help="""\ coefficient used for computing a running average of squared gradients Default: 0.9 """, ) group.add_argument( "--adadelta.eps", type=float, default=1e-6, dest="optimizer.adadelta.eps", help="""\ term added to the denominator to improve numerical stability Default: 1e-6 """, ) group.add_argument( "--adadelta.weight_decay", type=float, default=0, dest="optimizer.adadelta.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # Adagrad") group.add_argument( "--adagrad.lr_decay", type=float, default=0, dest="optimizer.adagrad.lr_decay", help="""\ learning rate decay Default: 0 """, ) group.add_argument( "--adagrad.weight_decay", type=float, default=0, dest="optimizer.adagrad.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # Adam") group.add_argument( "--adam.betas", nargs="+", type=float, default=[0.9, 0.999], dest="optimizer.adam.betas", help="""\ coefficients used for computing running averages of gradient and its square Default: (0.9, 0.999) """, ) group.add_argument( "--adam.eps", type=float, default=1e-8, dest="optimizer.adam.eps", help="""\ term added to the denominator to improve numerical stability Default: 1e-8 """, ) group.add_argument( "--adam.weight_decay", type=float, default=0, dest="optimizer.adam.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # AdamW") group.add_argument( "--adamw.betas", nargs="+", type=float, default=[0.9, 0.999], dest="optimizer.adamw.betas", help="""\ coefficients used for computing running averages of gradient and its square Default: (0.9, 0.999) """, ) group.add_argument( "--adamw.eps", type=float, default=1e-6, dest="optimizer.adamw.eps", help="""\ term added to the denominator to improve numerical stability Default: 1e-8 """, ) group.add_argument( "--adamw.weight_decay", type=float, default=0.0, dest="optimizer.adamw.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group.add_argument( "--adamw.correct_bias", type=arg_str2bool, default=True, dest="optimizer.adamw.correct_bias", help="""\ can be set to False to avoid correcting bias in Adam (e.g. like in Bert TF repository). Default: True """, ) group = parser.add_argument_group(" # SparseAdam") group.add_argument( "--sparse_adam.betas", nargs="+", type=float, default=[0.9, 0.999], dest="optimizer.sparse_adam.betas", help="""\ coefficients used for computing running averages of gradient and its square Default: (0.9, 0.999) """, ) group.add_argument( "--sparse_adam.eps", type=float, default=1e-8, dest="optimizer.sparse_adam.eps", help="""\ term added to the denominator to improve numerical stability Default: 1e-8 """, ) group = parser.add_argument_group(" # Adamax") group.add_argument( "--adamax.betas", nargs="+", type=float, default=[0.9, 0.999], dest="optimizer.adamax.betas", help="""\ coefficients used for computing running averages of gradient and its square. Default: (0.9, 0.999) """, ) group.add_argument( "--adamax.eps", type=float, default=1e-8, dest="optimizer.adamax.eps", help="""\ term added to the denominator to improve numerical stability. Default: 1e-8 """, ) group.add_argument( "--adamax.weight_decay", type=float, default=0, dest="optimizer.adamax.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # ASGD (Averaged Stochastic Gradient Descent)") group.add_argument( "--averaged_sgd.lambd", type=float, default=1e-4, dest="optimizer.averaged_sgd.lambd", help="""\ decay term Default: 1e-4 """, ) group.add_argument( "--averaged_sgd.alpha", type=float, default=0.75, dest="optimizer.averaged_sgd.alpha", help="""\ power for eta update Default: 0.75 """, ) group.add_argument( "--averaged_sgd.t0", type=float, default=1e6, dest="optimizer.averaged_sgd.t0", help="""\ point at which to start averaging Default: 1e6 """, ) group.add_argument( "--averaged_sgd.weight_decay", type=float, default=0, dest="optimizer.averaged_sgd.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # RMSprop") group.add_argument( "--rmsprop.momentum", type=float, default=0, dest="optimizer.rmsprop.momentum", help="""\ momentum factor Default: 0 """, ) group.add_argument( "--rmsprop.alpha", type=float, default=0.99, dest="optimizer.rmsprop.alpha", help="""\ smoothing constant Default: 0.99 """, ) group.add_argument( "--rmsprop.eps", type=float, default=1e-8, dest="optimizer.rmsprop.eps", help="""\ term added to the denominator to improve numerical stability. Default: 1e-8 """, ) group.add_argument( "--rmsprop.centered", type=arg_str2bool, default=False, dest="optimizer.rmsprop.centered", help="""\ if True, compute the centered RMSProp, the gradient is normalized by an estimation of its variance Default: False """, ) group.add_argument( "--rmsprop.weight_decay", type=float, default=0, dest="optimizer.rmsprop.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # SGD (Stochastic Gradient Descent)") group.add_argument( "--sgd.momentum", type=float, default=0, dest="optimizer.sgd.momentum", help="""\ momentum factor Default: 0 """, ) group.add_argument( "--sgd.dampening", type=float, default=0, dest="optimizer.sgd.dampening", help="""\ dampening for momentum Default: 0 """, ) group.add_argument( "--sgd.nesterov", type=arg_str2bool, default=False, dest="optimizer.sgd.nesterov", help="""\ enables Nesterov momentum Default: False """, ) group.add_argument( "--sgd.weight_decay", type=float, default=0, dest="optimizer.sgd.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group("Learning Rate Scheduler") group.add_argument( "--lr_scheduler_type", type=str, default=None, dest="optimizer.lr_scheduler_type", help="""Learning Rate Schedule (https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate) \n - lambda: Sets the learning rate of each parameter group to the initial lr times a given function. - step: Sets the learning rate of each parameter group to the initial lr decayed by gamma every step_size epochs. - multi_step: Set the learning rate of each parameter group to the initial lr decayed by gamma once the number of epoch reaches one of the milestones. - exponential: Set the learning rate of each parameter group to the initial lr decayed by gamma every epoch. - cosine: Set the learning rate of each parameter group using a cosine annealing schedule, where ηmax is set to the initial lr and Tcur is the number of epochs since the last restart in SGDR: SGDR: Stochastic Gradient Descent with Warm Restarts (https://arxiv.org/abs/1608.03983) When last_epoch=-1, sets initial lr as lr. - reduce_on_plateau: Reduce learning rate when a metric has stopped improving. Models often benefit from reducing the learning rate by a factor of 2-10 once learning stagnates. This scheduler reads a metrics quantity and if no improvement is seen for a ‘patience’ number of epochs, the learning rate is reduced. - warmup_constant: Linear warmup and then constant. Linearly increases learning rate schedule from 0 to 1 over `warmup_steps` training steps. Keeps learning rate schedule equal to 1. after warmup_steps. - warmup_linear: Linear warmup and then linear decay. Linearly increases learning rate from 0 to 1 over `warmup_steps` training steps. Linearly decreases learning rate from 1. to 0. over remaining `t_total - warmup_steps` steps. - warmup_consine: Linear warmup and then cosine decay. Linearly increases learning rate from 0 to 1 over `warmup_steps` training steps. Decreases learning rate from 1. to 0. over remaining `t_total - warmup_steps` steps following a cosine curve. If `cycles` (default=0.5) is different from default, learning rate follows cosine function after warmup. - warmup_consine_with_hard_restart: Linear warmup and then cosine cycles with hard restarts. Linearly increases learning rate from 0 to 1 over `warmup_steps` training steps. If `cycles` (default=1.) is different from default, learning rate follows `cycles` times a cosine decaying learning rate (with hard restarts). [step|multi_step|exponential|reduce_on_plateau|cosine| warmup_constant|warmup_linear|warmup_consine|warmup_consine_with_hard_restart] """, ) group = parser.add_argument_group(" # StepLR") group.add_argument( "--step.step_size", type=int, default=1, dest="optimizer.step.step_size", help="""\ Period of learning rate decay. Default: 1""", ) group.add_argument( "--step.gamma", type=float, default=0.1, dest="optimizer.step.gamma", help="""\ Multiplicative factor of learning rate decay. Default: 0.1. """, ) group.add_argument( "--step.last_epoch", type=int, default=-1, dest="optimizer.step.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # MultiStepLR") group.add_argument( "--multi_step.milestones", nargs="+", type=int, dest="optimizer.multi_step.milestones", help="""\ List of epoch indices. Must be increasing list of int""", ) group.add_argument( "--multi_step.gamma", type=float, default=0.1, dest="optimizer.multi_step.gamma", help="""\ Multiplicative factor of learning rate decay. Default: 0.1. """, ) group.add_argument( "--multi_step.last_epoch", type=int, default=-1, dest="optimizer.multi_step.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # ExponentialLR") group.add_argument( "--exponential.gamma", type=float, default=0.1, dest="optimizer.exponential.gamma", help="""\ Multiplicative factor of learning rate decay. Default: 0.1. """, ) group.add_argument( "--exponential.last_epoch", type=int, default=-1, dest="optimizer.exponential.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # CosineAnnealingLR") group.add_argument( "--cosine.T_max", type=int, default=50, dest="optimizer.cosine.T_max", help="""\ Maximum number of iterations. Default: 50""", ) group.add_argument( "--cosine.eta_min", type=float, default=0, dest="optimizer.cosine.eta_min", help="""\ Minimum learning rate. Default: 0. """, ) group.add_argument( "--cosine.last_epoch", type=int, default=-1, dest="optimizer.cosine.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # ReduceLROnPlateau") group.add_argument( "--reduce_on_plateau.factor", type=float, default=0.1, dest="optimizer.reduce_on_plateau.factor", help=""" Factor by which the learning rate will be reduced. new_lr = lr * factor. Default: 0.1. """, ) group.add_argument( "--reduce_on_plateau.mode", type=str, default="min", dest="optimizer.reduce_on_plateau.mode", help="""\ One of `min`, `max`. In `min` mode, lr will be reduced when the quantity monitored has stopped decreasing; in `max` mode it will be reduced when the quantity monitored has stopped increasing. Default: 'min'. """, ) group.add_argument( "--reduce_on_plateau.patience", type=int, default=10, dest="optimizer.reduce_on_plateau.patience", help="""\ Number of epochs with no improvement after which learning rate will be reduced. Default: 10. """, ) group.add_argument( "--reduce_on_plateau.threshold", type=float, default=1e-4, dest="optimizer.reduce_on_plateau.threshold", help="""\ Threshold for measuring the new optimum, to only focus on significant changes. Default: 1e-4 """, ) group.add_argument( "--reduce_on_plateau.threshold_mode", type=str, default="rel", dest="optimizer.reduce_on_plateau.threshold_mode", help="""\ One of rel, abs. In rel mode, dynamic_threshold = best * ( 1 + threshold ) in ‘max’ mode or best * ( 1 - threshold ) in min mode. In abs mode, dynamic_threshold = best + threshold in max mode or best - threshold in min mode. Default: ‘rel’. """ ) group.add_argument( "--reduce_on_plateau.cooldown", type=int, default=0, dest="optimizer.reduce_on_plateau.cooldown", help="""\ Number of epochs to wait before resuming normal operation after lr has been reduced. Default: 0. """, ) group.add_argument( "--reduce_on_plateau.min_lr", nargs="+", type=float, default=0, dest="optimizer.reduce_on_plateau.min_lr", help="""\ A scalar or a list of scalars. A lower bound on the learning rate of all param groups or each group respectively. Default: 0. """, ) group.add_argument( "--reduce_on_plateau.eps", type=float, default=1e-8, dest="optimizer.reduce_on_plateau.eps", help="""\ Minimal decay applied to lr. If the difference between new and old lr is smaller than eps, the update is ignored. Default: 1e-8 """, ) group = parser.add_argument_group(" # WarmUp Constant") group.add_argument( "--warmup_constant.warmup_steps", type=int, default=None, dest="optimizer.warmup_constant.warmup_steps", help="""\ The number of steps to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_constant.last_epoch", type=int, default=-1, dest="optimizer.warmup_constant.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # WarmUp Linear") group.add_argument( "--warmup_linear.warmup_steps", type=int, default=None, dest="optimizer.warmup_linear.warmup_steps", help="""\ The number of steps to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_linear_warmup_proportion", type=float, default=None, dest="optimizer.warmup_linear.warmup_proportion", help="""\ The number of steps (proportion of total_step) to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_linear.last_epoch", type=int, default=-1, dest="optimizer.warmup_linear.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # WarmUp Cosine") group.add_argument( "--warmup_cosine.warmup_steps", type=int, default=None, dest="optimizer.warmup_cosine.warmup_steps", help="""\ The number of steps to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_cosine.last_epoch", type=int, default=-1, dest="optimizer.warmup_cosine.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group.add_argument( "--warmup_cosine.cycles", type=float, default=.5, dest="optimizer.warmup_cosine.cycles", help="""\ If `cycles` is different from default, learning rate follows cosine function after warmup Default: .5 """ ) group = parser.add_argument_group(" # WarmUp Cosine with hard restarts") group.add_argument( "--warmup_cosine_with_hard_restart.warmup_steps", type=int, default=None, dest="optimizer.warmup_cosine_with_hard_restart.warmup_steps", help="""\ The number of steps to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_cosine_with_hard_restart.last_epoch", type=int, default=-1, dest="optimizer.warmup_cosine_with_hard_restart.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group.add_argument( "--warmup_cosine_with_hard_restart.cycles", type=float, default=1., dest="optimizer.warmup_cosine_with_hard_restart.cycles", help="""\ If `cycles` is different from default, learning rate follows cosine_with_hard_restart function after warmup Default: 1. """ ) group = parser.add_argument_group("Exponential Moving Average") group.add_argument( "--ema", type=float, default=None, dest="optimizer.exponential_moving_average", help="""\ Exponential Moving Average Default: None (don't use)""", ) def base_config(parser): group = parser.add_argument_group("Base Config") group.add_argument( "--base_config", type=str, default=None, dest="base_config", help=f"""\ Use pre-defined base_config: {_get_define_config()} * CoNLL 2003: {_get_define_config(category='conll2003')} * GLUE: {_get_define_config(category='glue')} * KorQuAD: {_get_define_config(category='korquad')} * SQuAD: {_get_define_config(category='squad')} * WikiSQL: {_get_define_config(category='wikisql')} """, ) def _get_define_config(category=None, config_dir="base_config"): if category is not None: config_dir = os.path.join(config_dir, category) config_files = [ config_path.replace(".json", "") for config_path in os.listdir(config_dir) if config_path.endswith(".json") ] if category is not None: config_files = [category + "/" + fname for fname in config_files] return config_files def evaluate(parser): group = parser.add_argument_group("Run evaluate") group.add_argument( "data_file_path", type=str, help=" Path to the file containing the evaluation data" ) group.add_argument("checkpoint_path", type=str, help="Path to an checkpoint trained model") group.add_argument( "--infer", default=None, dest="inference_latency", type=int, help=""" Evaluate with inference-latency with maximum value (ms)""", ) group.add_argument( "--prev_cuda_device_id", type=int, default=0, dest="prev_cuda_device_id", help=""" Previous cuda device id (need to mapping)""", ) def predict(parser): group = parser.add_argument_group("Run inference") group.add_argument( "checkpoint_path", type=str, help=" Path to an checkpoint trained model") group.add_argument( "-i", "--interactive", default=False, dest="interactive", action="store_true", help=""" Interactive Mode """, ) group.add_argument( "--prev_cuda_device_id", type=int, default=0, dest="prev_cuda_device_id", help=""" Previous cuda device id (need to mapping)""", ) group.add_argument("--question", type=str, dest="question", help=""" Input Question (required)""") group = parser.add_argument_group(" # Reading Comprehension") group.add_argument("--context", type=str, dest="context", help=""" Input Context """) group = parser.add_argument_group(" # Semantic Parsing") group.add_argument("--column", nargs="+", type=str, dest="column", help=""" Input Database Columns """) group.add_argument("--db_path", type=str, dest="db_path", help=""" Input Database file path """) group.add_argument("--table_id", type=str, dest="table_id", help=""" Input Database Table Id """) group = parser.add_argument_group(" # Document Retrieval") group.add_argument("--doc_path", type=str, dest="doc_path", help=""" Document file Path """) group.add_argument( "--retrieval", type=str, default=None, dest="doc_retrieval", help=""" Document Retrieval Model [tfidf] """, ) group.add_argument("--k", type=int, default=1, dest="top_k", help=""" Return Top K results """) group = parser.add_argument_group(" # Sequence/Token Classification") group.add_argument("--sequence", type=str, dest="sequence", help=""" Input Sequence """) def machine(parser): group = parser.add_argument_group("Machine Config") group.add_argument( "--machine_config", type=str, default=None, dest="machine_config", help=f"""\ Use pre-defined machine_config (.json) {_get_define_config(config_dir="./machine_config")} """) # fmt: on ================================================ FILE: claf/config/namespace.py ================================================ import argparse class NestedNamespace(argparse.Namespace): """ Nested Namespace (Simple class used by default by parse_args() to create an object holding attributes and return it.) """ def __setattr__(self, name, value): if "." in name: group, name = name.split(".", 1) namespace = getattr(self, group, NestedNamespace()) setattr(namespace, name, value) self.__dict__[group] = namespace else: self.__dict__[name] = value def delete_unselected(self, namespace, excepts=[]): delete_keys = [] for key in namespace.__dict__: if key not in excepts: delete_keys.append(key) for key in delete_keys: delattr(namespace, key) def overwrite(self, config): def _overwrite(namespace, d): for k, v in d.items(): if type(v) == dict: nested_namespace = getattr(namespace, k, None) if nested_namespace is None: nested_namespace = NestedNamespace() nested_namespace.load_from_json(v) setattr(namespace, k, nested_namespace) else: _overwrite(nested_namespace, v) else: setattr(namespace, k, v) return namespace return _overwrite(self, config) def load_from_json(self, dict_data): name_value_pairs = [] def make_key_value_pairs(d, prefix=""): for k, v in d.items(): if type(v) == dict: next_prefix = k if prefix != "": next_prefix = f"{prefix}.{k}" make_key_value_pairs(v, prefix=next_prefix) else: key_with_prefix = k if prefix != "": key_with_prefix = f"{prefix}.{k}" name_value_pairs.append((key_with_prefix, v)) make_key_value_pairs(dict_data) for (name, value) in name_value_pairs: self.__setattr__(name, value) ================================================ FILE: claf/config/pattern.py ================================================ class Singleton(type): """ Design Pattern Base Singleton Meta Class the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. """ _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] ================================================ FILE: claf/config/registry.py ================================================ import logging from claf.config.pattern import Singleton logger = logging.getLogger(__name__) class Registry(metaclass=Singleton): """ Registry class (Singleton) """ def __init__(self): self._name_to_subclass = { "component": {}, "reader": {}, "machine": {}, "model": {}, "token": {}, } def add(self, name, obj): component_type, component_name = self._split_component_type_and_name(name) if component_name in self._name_to_subclass[component_type]: logger.info( f"{component_name} is already included in Registry. It override with {obj}." ) self._name_to_subclass[component_type][component_name] = obj def get(self, name): component_type, component_name = self._split_component_type_and_name(name) if component_type not in self._name_to_subclass: raise ValueError(f"There is no {component_type} in _name_to_subclass.") if component_name not in self._name_to_subclass[component_type]: raise ValueError(f"There is no {component_name} object in {component_type}.") return self._name_to_subclass[component_type][component_name] def _split_component_type_and_name(self, name): if ":" in name: names = name.split(":") return names[0], names[1] else: raise ValueError("do not recognize component_type.") ================================================ FILE: claf/config/utils.py ================================================ from argparse import Namespace import copy import json import os import jsbeautifier import numpy as np import random import torch import yaml _CONFIG_EXTENSIONS = [".json", ".yaml"] def add_config_extension(file_path): for ext in _CONFIG_EXTENSIONS: if ext in file_path: return file_path full_path = file_path + ext if os.path.exists(full_path): return full_path raise ValueError(f"{file_path} is not valid extensions {_CONFIG_EXTENSIONS}") def read_config(file_path): if file_path.endswith(".json"): with open(file_path, "r") as f: return json.load(f) if file_path.endswith(".yaml"): with open(file_path, "r") as f: return yaml.load(f) raise ValueError(f"{file_path} is not valid extensions {_CONFIG_EXTENSIONS}") def pretty_json_dumps(inputs): js_opts = jsbeautifier.default_options() js_opts.indent_size = 2 inputs = remove_none(inputs) return jsbeautifier.beautify(json.dumps(inputs)) def remove_none(obj): if isinstance(obj, (list, tuple, set)): return type(obj)(remove_none(x) for x in obj if x is not None) elif isinstance(obj, dict): return type(obj)( (remove_none(k), remove_none(v)) for k, v in obj.items() if k is not None and v is not None ) else: return obj def convert_config2dict(config): config_dict = copy.deepcopy(config) if isinstance(config_dict, Namespace): config_dict = vars(config_dict) for k, v in config_dict.items(): if isinstance(v, Namespace): config_dict[k] = convert_config2dict(v) return config_dict def set_global_seed(seed=21): # Tensorflow try: import tensorflow as tf except ImportError: pass else: tf.set_random_seed(seed) # PyTorch torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) # NumPy np.random.seed(seed) # Python random.seed(seed) ================================================ FILE: claf/data/__init__.py ================================================ ================================================ FILE: claf/data/collate.py ================================================ from overrides import overrides import torch from torch.autograd import Variable from claf.data import utils class PadCollator: """ Collator apply pad and make tensor Minimizes amount of padding needed while producing mini-batch. * Kwargs: cuda_device_id: tensor assign to cuda device id Default is None (CPU) skip_keys: skip to make tensor """ def __init__(self, cuda_device_id=None, pad_value=0, skip_keys=["text"]): self.cuda_device_id = cuda_device_id self.pad_value = pad_value self.skip_keys = skip_keys def __call__(self, features, labels): self.collate(features, pad_value=self.pad_value) self.collate(labels, apply_pad=False, pad_value=self.pad_value) return utils.make_batch(features, labels) def collate(self, datas, apply_pad=True, pad_value=0): for data_name, data in datas.items(): if isinstance(data, dict): for key, value in data.items(): data[key] = self._collate( value, apply_pad=apply_pad, token_name=key, pad_value=pad_value) else: datas[data_name] = self._collate(data, apply_pad=apply_pad) def _collate(self, value, apply_pad=True, token_name=None, pad_value=0): if apply_pad: value = self._apply_pad(value, token_name=token_name, pad_value=pad_value) return self._make_tensor(value) def _apply_pad(self, value, token_name=None, pad_value=0): return utils.padding_tokens(value, token_name=token_name, pad_value=pad_value) def _make_tensor(self, value): if not isinstance(value, torch.Tensor): value_type = utils.get_token_type(value) if value_type == int: value = torch.LongTensor(value) else: value = torch.FloatTensor(value) value = Variable(value, requires_grad=False) if self.cuda_device_id is not None: value = value.cuda(self.cuda_device_id) return value class FeatLabelPadCollator(PadCollator): """ Collator apply pad and make tensor Minimizes amount of padding needed while producing mini-batch. FeatLabelPadCollator allows applying pad to not only features, but also labels. * Kwargs: cuda_device_id: tensor assign to cuda device id Default is None (CPU) skip_keys: skip to make tensor """ @overrides def __call__(self, features, labels, apply_pad_labels=(), apply_pad_values=()): self.collate(features) self.collate(labels, apply_pad=False, apply_pad_labels=apply_pad_labels, apply_pad_values=apply_pad_values) return utils.make_batch(features, labels) @overrides def collate(self, datas, apply_pad=True, apply_pad_labels=(), apply_pad_values=()): for data_name, data in datas.items(): if not apply_pad and data_name in apply_pad_labels: _apply_pad = True # ignore apply_pad pad_value = apply_pad_values[apply_pad_labels.index(data_name)] else: _apply_pad = apply_pad pad_value = 0 if isinstance(data, dict): for key, value in data.items(): data[key] = self._collate( value, apply_pad=_apply_pad, token_name=key, pad_value=pad_value) else: datas[data_name] = self._collate(data, apply_pad=_apply_pad, pad_value=pad_value) ================================================ FILE: claf/data/data_handler.py ================================================ import logging import pickle import os from pathlib import Path, PosixPath import shutil import tempfile import msgpack import requests from tqdm import tqdm from claf import nsml logger = logging.getLogger(__name__) class CachePath: if nsml.IS_ON_NSML: ROOT = Path("./claf_cache") else: ROOT = Path.home() / ".claf_cache" DATASET = ROOT / "dataset" MACHINE = ROOT / "machine" PRETRAINED_VECTOR = ROOT / "pretrained_vector" TOKEN_COUNTER = ROOT / "token_counter" VOCAB = ROOT / "vocab" class DataHandler: """ DataHandler with CachePath - read (from_path, from_http) - dump (.msgpack or .pkl (pickle)) - load """ def __init__(self, cache_path=CachePath.ROOT): if type(cache_path) != PosixPath: raise ValueError(f"cache_path type is PosixPath (use pathlib.Path). not f{type(cache_path)}") self.cache_path = cache_path cache_path.mkdir(parents=True, exist_ok=True) def convert_cache_path(self, path): cache_data_path = self.cache_path / Path(path) return cache_data_path def read_embedding(self, file_path): raise NotImplementedError() def read(self, file_path, encoding="utf-8", return_path=False): if file_path.startswith("http"): file_path = self._read_from_http(file_path, encoding) path = Path(file_path) if path.exists(): if return_path: return path return path.read_bytes().decode(encoding) if nsml.IS_ON_NSML: dataset_path = Path(nsml.DATASET_PATH) path = dataset_path / file_path if not path.exists(): path = dataset_path / "train" / file_path if not path.exists(): raise FileNotFoundError(path) if path.exists(): if return_path: return path return path.read_bytes().decode(encoding) else: raise FileNotFoundError(f"{file_path} is not found.") def _read_from_http(self, file_path, encoding, return_path=False): cache_data_path = self.cache_path / Path(file_path).name if cache_data_path.exists(): logger.info(f"'{file_path}' is already downloaded.") pass else: with tempfile.TemporaryFile() as temp_file: self._download_from_http(temp_file, file_path) temp_file.flush() temp_file.seek(0) with open(cache_data_path, 'wb') as cache_file: shutil.copyfileobj(temp_file, cache_file) return cache_data_path def _download_from_http(self, temp_file, url): req = requests.get(url, stream=True) content_length = req.headers.get('Content-Length') total = int(content_length) if content_length is not None else None with tqdm(total=total, unit="B", unit_scale=True, desc="download...") as pbar: for chunk in req.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks temp_file.write(chunk) pbar.update(len(chunk)) def cache_token_counter(self, data_reader_config, tokenizer_name, obj=None): data_paths = os.path.basename(data_reader_config.train_file_path) if getattr(data_reader_config, "valid_file_path", None): data_paths += "#" + os.path.basename(data_reader_config.valid_file_path) path = self.cache_path / data_reader_config.dataset / data_paths path.mkdir(parents=True, exist_ok=True) path = path / tokenizer_name if obj: self.dump(path, obj) else: return self.load(path) def load(self, file_path, encoding="utf-8"): path = self.cache_path / file_path logger.info(f"load path: {path}") msgpack_path = path.with_suffix(".msgpack") if msgpack_path.exists(): return self._load_msgpack(msgpack_path, encoding) pickle_path = path.with_suffix(".pkl") if pickle_path.exists(): return self._load_pickle(pickle_path, encoding) return None def _load_msgpack(self, path, encoding): with open(path, "rb") as in_file: return msgpack.unpack(in_file, encoding=encoding) def _load_pickle(self, path, encoding): with open(path, "rb") as in_file: return pickle.load(in_file, encoding=encoding) def dump(self, file_path, obj, encoding="utf-8"): path = self.cache_path / file_path path.parent.mkdir(parents=True, exist_ok=True) try: with open(path.with_suffix(".msgpack"), "wb") as out_file: msgpack.pack(obj, out_file, encoding=encoding) except TypeError: os.remove(path.with_suffix(".msgpack")) with open(path.with_suffix(".pkl"), "wb") as out_file: pickle.dump(obj, out_file, protocol=pickle.HIGHEST_PROTOCOL) ================================================ FILE: claf/data/dataset/__init__.py ================================================ from claf.data.dataset.squad import SQuADDataset from claf.data.dataset.wikisql import WikiSQLDataset from claf.data.dataset.seq_cls import SeqClsDataset from claf.data.dataset.bert.multi_task import MultiTaskBertDataset from claf.data.dataset.bert.regression import RegressionBertDataset from claf.data.dataset.bert.squad import SQuADBertDataset from claf.data.dataset.bert.seq_cls import SeqClsBertDataset from claf.data.dataset.bert.tok_cls import TokClsBertDataset # fmt: off __all__ = [ "MultiTaskBertDataset", "RegressionBertDataset", "SeqClsDataset", "SeqClsBertDataset", "SQuADDataset", "SQuADBertDataset", "TokClsBertDataset", "WikiSQLDataset", ] # fmt: on ================================================ FILE: claf/data/dataset/base.py ================================================ from torch.utils.data.dataset import Dataset from claf.data import utils class DatasetBase(Dataset): """ Dataset Base Model An abstract class representing a Dataset. """ def __init__(self): # Features - Lazy Evaluation self.f_count = 0 self.features = [] def __getitem__(self, index): raise NotImplementedError def _get_feature_maxlen(self, features): max_len = -1 for feature in features: for token_name, sentence in feature.items(): if token_name == "text": continue if callable(sentence): continue max_len = max(max_len, len(sentence)) return max_len def collate_fn(self, cuda_device_id): raise NotImplementedError def get_ground_truths(self, data_idxs): data_idxs_dim = utils.get_token_dim(data_idxs) if data_idxs_dim > 2: raise ValueError(f"data_idxs dimension can't be larger than 2.({data_idxs_dim})") if data_idxs_dim == 2: return [self.get_ground_truth(data_id) for data_id in data_idxs] elif data_idxs_dim == 1: return self.get_ground_truth(data_idxs) else: raise ValueError(f"data_idxs dimension must be 1 or 2. not {data_idxs_dim}") def get_ground_truth(self): raise NotImplementedError def get_predict(self): raise NotImplementedError def lazy_evaluation(self, index): if self.f_count < self.__len__(): self.f_count += 1 for feature in self.features: for k, v in feature[index].items(): if utils.is_lazy(v): feature[index][k] = v() ================================================ FILE: claf/data/dataset/bert/__init__.py ================================================ ================================================ FILE: claf/data/dataset/bert/multi_task.py ================================================ import json from overrides import overrides import torch import random from claf.factory.data_loader import make_data_loader from claf.data.dataset.base import DatasetBase class MultiTaskBertDataset(DatasetBase): """ Dataset for Multi-Task GLUE using BERT * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batches, vocab, helper=None): super(MultiTaskBertDataset, self).__init__() self.name = "multitask_bert" self.vocab = vocab task_helpers = helper["task_helpers"] self.multi_dataset_size = 0 self.batch_sizes = [] self.task_datasets = [] for b, h in zip(batches, task_helpers): batch_size = h["batch_size"] self.batch_sizes.append(batch_size) dataset_cls = h["dataset"] dataset = dataset_cls(b, vocab, helper=h) self.task_datasets.append(dataset) task_dataset_size, remain = divmod(len(dataset), batch_size) if remain > 0: task_dataset_size += 1 self.multi_dataset_size += task_dataset_size self.init_iterators() def init_iterators(self): cuda_device_id = None if torch.cuda.is_available(): cuda_device_id = 0 # TODO: Hard-code self.iterators = [] for batch_size, dataset in zip(self.batch_sizes, self.task_datasets): data_loader = make_data_loader(dataset, batch_size=batch_size, cuda_device_id=cuda_device_id) # TODO: cuda_device_id self.iterators.append(iter(data_loader)) self.available_iterators = list(range(len(self.iterators))) @overrides def collate_fn(self, cuda_device_id=None): def pass_tensor(data): task_idx, tensor_datas = zip(*data) tensor_batch = tensor_datas[0] task_id_tensor = torch.LongTensor(list(task_idx)) if torch.cuda.is_available(): task_id_tensor.cuda(cuda_device_id) tensor_batch.features["task_index"] = task_id_tensor return tensor_batch return pass_tensor @overrides def __getitem__(self, index): # self.lazy_evaluation(index) if len(self.available_iterators) == 0: self.init_iterators() random_index = random.choice(self.available_iterators) task_iterator = self.iterators[random_index] try: return random_index, next(task_iterator) except StopIteration: self.available_iterators.remove(random_index) return self.__getitem__(index) def __len__(self): return self.multi_dataset_size def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "dataset_count": len(self.iterators), "task_dataset_sizes": [len(dataset) for dataset in self.task_datasets], } return json.dumps(dataset_properties, indent=4) ================================================ FILE: claf/data/dataset/bert/regression.py ================================================ import json from overrides import overrides from claf.data import utils from claf.data.collate import PadCollator from claf.data.dataset.base import DatasetBase class RegressionBertDataset(DatasetBase): """ Dataset for Regression using BERT * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(RegressionBertDataset, self).__init__() self.name = "reg_bert" self.vocab = vocab self.helper = helper # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.features = [self.bert_input_idx, self.token_type_idx] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.labels = { label["id"]: { "score": label["score"], } for label in batch.labels } self.label_scores = [label["score"] for label in batch.labels] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): data_idxs, bert_input_idxs, token_type_idxs, label_scores = zip(*data) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), } labels = { "data_idx": data_idxs, "score": label_scores, } return collator(features, labels) return make_tensor_fn @overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.bert_input_idx[index], self.token_type_idx[index], self.label_scores[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "sequence_maxlen": self.sequence_maxlen, } return json.dumps(dataset_properties, indent=4) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx) def get_id(self, data_index): return self.data_ids[data_index] @overrides def get_ground_truth(self, data_id): return self.labels[data_id] ================================================ FILE: claf/data/dataset/bert/seq_cls.py ================================================ import json from overrides import overrides from claf.data import utils from claf.data.collate import PadCollator from claf.data.dataset.base import DatasetBase class SeqClsBertDataset(DatasetBase): """ Dataset for Sequence Classification using BERT * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(SeqClsBertDataset, self).__init__() self.name = "seq_cls_bert" self.vocab = vocab self.helper = helper self.class_idx2text = helper["class_idx2text"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.features = [self.bert_input_idx, self.token_type_idx] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.classes = { label["id"]: { "class_idx": label["class_idx"], "class_text": label["class_text"], } for label in batch.labels } self.class_text = [label["class_text"] for label in batch.labels] self.class_idx = [label["class_idx"] for label in batch.labels] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): data_idxs, bert_input_idxs, token_type_idxs, class_idxs = zip(*data) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), } labels = { "class_idx": class_idxs, "data_idx": data_idxs, } return collator(features, labels) return make_tensor_fn @overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.bert_input_idx[index], self.token_type_idx[index], self.class_idx[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "num_classes": self.num_classes, "sequence_maxlen": self.sequence_maxlen, "classes": self.class_idx2text, } return json.dumps(dataset_properties, indent=4) @property def num_classes(self): return len(self.class_idx2text) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx) def get_id(self, data_index): return self.data_ids[data_index] @overrides def get_ground_truth(self, data_id): return self.classes[data_id] def get_class_text_with_idx(self, class_index): if class_index is None: raise ValueError("class_index is required.") return self.class_idx2text[class_index] ================================================ FILE: claf/data/dataset/bert/squad.py ================================================ import json from overrides import overrides from claf.data import utils from claf.data.collate import PadCollator from claf.data.dataset.base import DatasetBase class SQuADBertDataset(DatasetBase): """ SQuAD Dataset for BERT compatible with v1.1 and v2.0 * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(SQuADBertDataset, self).__init__() self.name = "squad_bert" self.vocab = vocab self.helper = helper self.raw_dataset = helper["raw_dataset"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.features = [self.bert_input_idx, self.token_type_idx] # for lazy_evaluation # Labels self.qids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.qids.keys()) self.answers = { label["id"]: ( label["answerable"], (label["answer_start"], label["answer_end"]), ) for label in batch.labels } self.answer_starts = [label["answer_start"] for label in batch.labels] self.answer_ends = [label["answer_end"] for label in batch.labels] self.answerables = [label["answerable"] for label in batch.labels] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): bert_input_idxs, token_type_idxs, data_idxs, answer_starts, answer_ends, answerables = zip( *data ) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), } labels = { "data_idx": data_idxs, "answer_start_idx": answer_starts, "answer_end_idx": answer_ends, "answerable": answerables, } return collator(features, labels) return make_tensor_fn @overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.bert_input_idx[index], self.token_type_idx[index], self.data_indices[index], self.answer_starts[index], self.answer_ends[index], self.answerables[index], ) def __len__(self): return len(self.qids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "HasAns_count": len([True for k, v in self.answers.items() if v[1] == 1]), "NoAns_count": len([False for k, v in self.answers.items() if v[1] == 0]), "bert_input_maxlen": self.bert_input_maxlen, } return json.dumps(dataset_properties, indent=4) @property def bert_input_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx) def get_qid(self, data_index): qid = self.qids[data_index] if "#" in qid: qid = qid.split("#")[0] return qid def get_id(self, data_index): return self.get_qid(data_index) def get_qid_index(self, data_index): qid = self.qids[data_index] if "#" in qid: return qid.split("#")[1] return None def get_context(self, data_index): qid = self.get_qid(data_index) return self.helper["examples"][qid]["context"] @overrides def get_ground_truths(self, data_index): qid = self.get_qid(data_index) answer_texts = self.helper["examples"][qid]["answers"] answerable, answer_span = self.answers[qid] return answer_texts, answerable, answer_span @overrides def get_predict(self, data_index, start, end): return self.get_text_with_index(data_index, start, end) def get_text_with_index(self, data_index, start, end): if data_index is None: raise ValueError("data_id or text is required.") context_text = self.get_context(data_index) bert_token = self.get_bert_tokens(data_index) if ( start <= 0 or end >= len(bert_token) or bert_token[start].text_span is None or bert_token[end].text_span is None ): # No_Answer Case return "" char_start = bert_token[start].text_span[0] char_end = bert_token[end].text_span[1] if char_start > char_end or len(context_text) <= char_end: return "" return context_text[char_start:char_end] def get_bert_tokens(self, data_index): qid = self.get_qid(data_index) index = self.get_qid_index(data_index) if index is None: raise ValueError("bert_qid must have 'bert_index' (bert_id: qid#bert_index)") bert_index = f"bert_tokens_{index}" return self.helper["examples"][qid][bert_index] ================================================ FILE: claf/data/dataset/bert/tok_cls.py ================================================ import json from overrides import overrides from claf.data import utils from claf.data.collate import FeatLabelPadCollator from claf.data.dataset.base import DatasetBase class TokClsBertDataset(DatasetBase): """ Dataset for Token Classification * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(TokClsBertDataset, self).__init__() self.name = "tok_cls_bert" self.vocab = vocab self.helper = helper self.tag_idx2text = helper["tag_idx2text"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.tagged_sub_token_idxs = [{"feature": feature["tagged_sub_token_idxs"]} for feature in batch.features] self.num_tokens = [{"feature": feature["num_tokens"]} for feature in batch.features] self.features = [self.bert_input_idx, self.token_type_idx] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.tags = { label["id"]: { "tag_idxs": label["tag_idxs"], "tag_texts": label["tag_texts"], } for label in batch.labels } self.tag_texts = [label["tag_texts"] for label in batch.labels] self.tag_idxs = [label["tag_idxs"] for label in batch.labels] self.ignore_tag_idx = helper["ignore_tag_idx"] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = FeatLabelPadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): data_idxs, bert_input_idxs, token_type_idxs, tagged_token_idxs, num_tokens, tag_idxs_list = zip(*data) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), "tagged_sub_token_idxs": utils.transpose(tagged_token_idxs, skip_keys=["text"]), "num_tokens": utils.transpose(num_tokens, skip_keys=["text"]), } labels = { "tag_idxs": tag_idxs_list, "data_idx": data_idxs, } return collator( features, labels, apply_pad_labels=["tag_idxs"], apply_pad_values=[self.ignore_tag_idx] ) return make_tensor_fn @overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.bert_input_idx[index], self.token_type_idx[index], self.tagged_sub_token_idxs[index], self.num_tokens[index], self.tag_idxs[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "num_tags": self.num_tags, "sequence_maxlen": self.sequence_maxlen, "tags": self.tag_idx2text, } return json.dumps(dataset_properties, indent=4) @property def num_tags(self): return len(self.tag_idx2text) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx) def get_id(self, data_index): return self.data_ids[data_index] @overrides def get_ground_truth(self, data_id): return self.tags[data_id] def get_tag_texts_with_idxs(self, tag_idxs): return [self.get_tag_text_with_idx(tag_idx)for tag_idx in tag_idxs] def get_tag_text_with_idx(self, tag_index): if tag_index is None: raise ValueError("tag_index is required.") return self.tag_idx2text[tag_index] ================================================ FILE: claf/data/dataset/seq_cls.py ================================================ import json from overrides import overrides import torch from claf.data import utils from claf.data.collate import PadCollator from claf.data.dataset.base import DatasetBase class SeqClsDataset(DatasetBase): """ Dataset for Sequence Classification * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(SeqClsDataset, self).__init__() self.name = "seq_cls" self.vocab = vocab self.helper = helper self.class_idx2text = helper["class_idx2text"] self.sequences = {feature["id"]: feature["sequence"]["text"] for feature in batch.features} # Features self.sequence_idxs = [feature["sequence"] for feature in batch.features] self.features = [self.sequence_idxs] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.classes = { label["id"]: { "class_idx": label["class_idx"], "class_text": label["class_text"], } for label in batch.labels } self.class_text = [label["class_text"] for label in batch.labels] self.class_idx = [label["class_idx"] for label in batch.labels] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): data_idxs, sequence_idxs, class_idxs = zip(*data) features = { "sequence": utils.transpose(sequence_idxs, skip_keys=["text"]), } labels = { "class_idx": class_idxs, "data_idx": data_idxs, } return collator(features, labels) return make_tensor_fn @overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.sequence_idxs[index], self.class_idx[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "num_classes": self.num_classes, "sequence_maxlen": self.sequence_maxlen, "classes": self.class_idx2text, } return json.dumps(dataset_properties, indent=4) @property def num_classes(self): return len(self.class_idx2text) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.sequence_idxs) def get_id(self, data_index): return self.data_ids[data_index] @overrides def get_ground_truth(self, data_id): return self.classes[data_id] def get_class_text_with_idx(self, class_index): if class_index is None: raise ValueError("class_index is required.") return self.class_idx2text[class_index] ================================================ FILE: claf/data/dataset/squad.py ================================================ import json from overrides import overrides from claf.data import utils from claf.data.collate import PadCollator from claf.data.dataset.base import DatasetBase class SQuADDataset(DatasetBase): """ SQuAD Dataset compatible with v1.1 and v2.0 * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(SQuADDataset, self).__init__() self.name = "squad" self.vocab = vocab self.helper = helper self.raw_dataset = helper["raw_dataset"] # for SQuAD official metric # Features self.context_idx = [feature["context"] for feature in batch.features] self.question_idx = [feature["question"] for feature in batch.features] self.features = [self.context_idx, self.question_idx] # for lazy_evaluation # Labels self.qids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.qids.keys()) self.answers = { label["id"]: ( label["answerable"], (label["answer_start"], label["answer_end"]), ) for label in batch.labels } self.answer_starts = [label["answer_start"] for label in batch.labels] self.answer_ends = [label["answer_end"] for label in batch.labels] self.answerables = [label["answerable"] for label in batch.labels] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): context_idxs, question_idxs, data_idxs, \ answer_starts, answer_ends, answerables = zip(*data) features = { "context": utils.transpose(context_idxs, skip_keys=["text"]), "question": utils.transpose(question_idxs, skip_keys=["text"]), } labels = { "data_idx": data_idxs, "answer_start_idx": answer_starts, "answer_end_idx": answer_ends, "answerable": answerables, } return collator(features, labels) return make_tensor_fn @overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.context_idx[index], self.question_idx[index], self.data_indices[index], self.answer_starts[index], self.answer_ends[index], self.answerables[index], ) def __len__(self): return len(self.qids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "HasAns_count": len([True for item in self.answerables if item == 1]), "NoAns_count": len([False for item in self.answerables if item == 0]), "context_maxlen": self.context_maxlen, "question_maxlen": self.question_maxlen, } return json.dumps(dataset_properties, indent=4) @property def context_maxlen(self): return self._get_feature_maxlen(self.context_idx) @property def question_maxlen(self): return self._get_feature_maxlen(self.question_idx) def get_qid(self, data_index): return self.qids[data_index] def get_context(self, data_index): qid = self.get_qid(data_index) return self.helper["examples"][qid]["context"] def get_text_span(self, data_index): qid = self.get_qid(data_index) return self.helper["examples"][qid]["text_span"] @overrides def get_ground_truths(self, data_index): qid = self.get_qid(data_index) answer_texts = self.helper["examples"][qid]["answers"] answerable, answer_span = self.answers[qid] return answer_texts, answerable, answer_span @overrides def get_predict(self, data_index, start, end): return self.get_text_with_index(data_index, start, end) def get_text_with_index(self, data_index, start, end): if data_index is None: raise ValueError("qid or text is required.") context_text = self.get_context(data_index) text_span = self.get_text_span(data_index) if start >= len(text_span) or end >= len(text_span): # No_Answer Case return "" char_start = text_span[start][0] char_end = text_span[end][1] if char_start > char_end or len(context_text) <= char_end: return "" return context_text[char_start:char_end] ================================================ FILE: claf/data/dataset/wikisql.py ================================================ import json from overrides import overrides import torch from claf.data import utils from claf.data.collate import PadCollator from claf.data.dataset.base import DatasetBase class WikiSQLDataset(DatasetBase): """ WikiSQL Dataset * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(WikiSQLDataset, self).__init__() self.name = "wikisql" self.vocab = vocab self.helper = helper # Features self.column_idx = [feature["column"] for feature in batch.features] self.question_idx = [feature["question"] for feature in batch.features] self.features = [self.column_idx, self.question_idx] # Labels self.data_idx = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_idx.keys()) self.table_idx = {data_index: label["table_id"] for (data_index, label) in enumerate(batch.labels)} self.tokenized_question = {label["id"]: label["tokenized_question"] for label in batch.labels} self.labels = { label["id"]: { "agg_idx": label["aggregator_idx"], "sel_idx": label["select_column_idx"], "conds_num": label["conditions_num"], "conds_col": label["conditions_column_idx"], "conds_op": label["conditions_operator_idx"], "conds_val_str": label["conditions_value_string"], "conds_val_pos": label["conditions_value_position"], "sql_query": label["sql_query"], "execution_result": label["execution_result"], } for label in batch.labels } @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): column_idxs, question_idxs, data_idxs = zip(*data) features = { "column": utils.transpose(column_idxs, skip_keys=["text"]), "question": utils.transpose(question_idxs, skip_keys=["text"]), } labels = { "data_idx": data_idxs, } return collator(features, labels) return make_tensor_fn @overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.column_idx[index], self.question_idx[index], self.data_indices[index], ) def __len__(self): return len(self.data_idx) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "question_maxlen": self.question_maxlen, } return json.dumps(dataset_properties, indent=4) @property def question_maxlen(self): return self._get_feature_maxlen(self.question_idx) def get_id(self, data_index): if type(data_index) == torch.Tensor: data_index = data_index.item() return self.data_idx[data_index] def get_table_id(self, data_index): if type(data_index) == torch.Tensor: data_index = data_index.item() return self.table_idx[data_index] def get_tokenized_question(self, data_index): data_id = self.get_id(data_index) return self.tokenized_question[data_id] @overrides def get_ground_truth(self, data_index): if type(data_index) == torch.Tensor: data_id = self.get_id(data_index) else: data_id = data_index return self.labels[data_id] ================================================ FILE: claf/data/dto/__init__.py ================================================ from claf.data.dto.batch import Batch from claf.data.dto.bert_feature import BertFeature from claf.data.dto.helper import Helper # fmt: off __all__ = [ "Batch", "BertFeature", "Helper", ] # fmt: on ================================================ FILE: claf/data/dto/batch.py ================================================ import logging logger = logging.getLogger(__name__) class Batch: """ Batch Data Transfer Object (DTO) Class dictionary consisting of - features: (dict) input - labels: (dict) output """ def __init__(self, **kwargs): if set(kwargs.keys()) != set(["features", "labels"]): raise ValueError("You can use only 'features' and 'labels' as dictionary key.") self.__dict__ = kwargs def __repr__(self): return str(self.__dict__) def __len__(self): return len(self.__dict__) def sort_by_key(self, sort_key): logger.info(f"Start sort by key: {sort_key}'s length") zipped = zip(self.__dict__["features"], self.__dict__["labels"]) features = self.__dict__["features"] if type(features) == list: feature_keys = list(features[0].keys()) else: feature_keys = features.keys() key_index = 0 if sort_key in feature_keys else 1 # sort_key in features or labels sorted_features, sorted_labels = [], [] for data in sorted(zipped, key=lambda x: len(x[key_index][sort_key])): feature, label = data sorted_features.append(feature) sorted_labels.append(label) self.__dict__["features"] = sorted_features self.__dict__["labels"] = sorted_labels zipped = None logger.info("Complete sorting...") def to_dict(self, flatten=False, recursive=True): def _flatten(d): if d == {}: return d k, v = d.popitem() if isinstance(v, dict): flat_v = _flatten(v) for f_k in list(flat_v.keys()): flat_v[k + "#" + f_k] = flat_v[f_k] del flat_v[f_k] return {**flat_v, **_flatten(d)} else: return {k: v, **_flatten(d)} def _recursive(d): if not isinstance(d, dict): return d for k, v in d.items(): if isinstance(v, dict): dict_v = dict(v) d[k] = _recursive(dict_v) return d if flatten: d = {} d.update(_flatten(self.__dict__["features"])) d.update(_flatten(self.__dict__["labels"])) return d if recursive: return _recursive(self.__dict__) return dict(self.__dict__) ================================================ FILE: claf/data/dto/bert_feature.py ================================================ from claf.data import utils class BertFeature: """ BertFeature Data Transfer Object (DTO) Class dictionary consisting of - bert_input: indexed bert_input feature - token_type: segment_ids feature """ BERT_INPUT = "bert_input" TOKEN_TYPE = "token_type" #segment_id def __init__(self, **kwargs): self.__dict__ = kwargs def set_input(self, bert_input): self.__dict__[self.BERT_INPUT] = bert_input self.set_feature(self.TOKEN_TYPE, utils.make_bert_token_type(bert_input)) def set_input_with_speical_token(self, *args, **kwargs): bert_input = utils.make_bert_input(*args, **kwargs) self.set_input(bert_input) def set_feature(self, key, value): self.__dict__[key] = {"feature": value, "text": ""} def to_dict(self): return dict(self.__dict__) ================================================ FILE: claf/data/dto/helper.py ================================================ class Helper: """ Helper Data Transfer Object (DTO) Class (include model parameter - value defined by data, predict_helper and etc.) dictionary consisting of - model: (dict) model parameter (ex. num_classes) - predict_helper: (dict) predict_helper (ex. class_idx2text) """ EXAMPLES = "examples" MODEL = "model" PREDICT_HELPER = "predict_helper" def __init__(self, **kwargs): self.__dict__ = kwargs default_keys = [self.EXAMPLES, self.MODEL, self.PREDICT_HELPER] for key in default_keys: if key not in self.__dict__: self.__dict__[key] = {} def set_example(self, uid, example, update=False): if update: self.__dict__[self.EXAMPLES][uid].update(example) else: self.__dict__[self.EXAMPLES][uid] = example def set_model_parameter(self, parameters): self.__dict__[self.MODEL] = parameters def set_predict_helper(self, predict_helper): self.__dict__[self.PREDICT_HELPER] = predict_helper def to_dict(self): return dict(self.__dict__) ================================================ FILE: claf/data/reader/__init__.py ================================================ from claf.data.reader.seq_cls import SeqClsReader from claf.data.reader.cola import CoLAReader from claf.data.reader.squad import SQuADReader from claf.data.reader.wikisql import WikiSQLReader from claf.data.reader.bert.multi_task import MultiTaskBertReader from claf.data.reader.bert.seq_cls import SeqClsBertReader from claf.data.reader.bert.glue.cola import CoLABertReader from claf.data.reader.bert.glue.mrpc import MRPCBertReader from claf.data.reader.bert.glue.mnli import MNLIBertReader from claf.data.reader.bert.glue.qnli import QNLIBertReader from claf.data.reader.bert.glue.qqp import QQPBertReader from claf.data.reader.bert.glue.sst import SSTBertReader from claf.data.reader.bert.glue.rte import RTEBertReader from claf.data.reader.bert.glue.wnli import WNLIBertReader from claf.data.reader.bert.regression import RegressionBertReader from claf.data.reader.bert.glue.stsb import STSBBertReader from claf.data.reader.bert.squad import SQuADBertReader from claf.data.reader.bert.tok_cls import TokClsBertReader from claf.data.reader.bert.conll2003 import CoNLL2003BertReader # fmt: off __all__ = [ "MultiTaskBertReader", "RegressionBertReader", "STSBBertReader", "SeqClsReader", "CoLAReader", "SeqClsBertReader", "CoLABertReader", "MRPCBertReader", "MNLIBertReader", "QNLIBertReader", "QQPBertReader", "RTEBertReader", "SSTBertReader", "STSBBertReader", "WNLIBertReader", "SQuADReader", "SQuADBertReader", "TokClsBertReader", "CoNLL2003BertReader", "WikiSQLReader", ] # fmt: on ================================================ FILE: claf/data/reader/base.py ================================================ import logging from claf.data.data_handler import CachePath, DataHandler from claf import utils as common_utils logger = logging.getLogger(__name__) class DataReader: """ DataReader Base Class * Args: file_paths: dictionary of consisting ('train' and 'vaild') file_path dataset_obj: Dataset Object (claf.data.dataset.base) """ def __init__(self, file_paths, dataset_obj): self.file_paths = file_paths self.dataset_obj = dataset_obj self.data_handler = DataHandler(cache_path=CachePath.DATASET) # for Concrete DataReader self.text_columns = None def filter_texts(self, dataset): texts = [] def append_texts(datas): for data in datas: for key, value in data.items(): if key in self.text_columns: texts.append(value) for data_type, dataset in dataset.items(): append_texts(dataset.features) # append_texts(dataset.labels) texts = list(common_utils.flatten(texts)) texts = list(set(texts)) # remove duplicate return texts def read(self): """ read with Concrete DataReader each type """ if type(self.file_paths) != dict: raise ValueError(f"file_paths type is must be dict. not {type(self.file_paths)}") logger.info("Start read dataset") datasets, helpers = {}, {} for data_type, file_path in self.file_paths.items(): if data_type is None: continue batch, helper = self._read(file_path, data_type=data_type) datasets[data_type] = batch helpers[data_type] = helper logger.info("Complete read dataset...\n") return datasets, helpers def _read(self, file_path, desc=None): raise NotImplementedError def read_one_example(self, inputs): helper = None return inputs, helper def convert_to_dataset(self, datas, vocab, helpers=None): """ Batch to Dataset """ datasets = {} for k, batch in datas.items(): if batch is None: continue datasets[k] = self.dataset_obj(batch, vocab, helper=helpers[k]) logger.info(f"{k} dataset. {datasets[k]}") return datasets ================================================ FILE: claf/data/reader/bert/__init__.py ================================================ ================================================ FILE: claf/data/reader/bert/conll2003.py ================================================ import logging from itertools import chain from overrides import overrides from claf.data.reader import TokClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:conll2003_bert") class CoNLL2003BertReader(TokClsBertReader): """ CoNLL2003 for BERT * Args: file_paths: file paths (train and dev) * Kwargs: ignore_tag_idx: prediction results that have this number as ground-truth idx are ignored """ def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", ignore_tag_idx=-1, ): super(CoNLL2003BertReader, self).__init__( file_paths, tokenizers, lang_code=None, sequence_max_length=sequence_max_length, cls_token=cls_token, sep_token=sep_token, ignore_tag_idx=ignore_tag_idx, ) @overrides def _get_data(self, file_path): _file = self.data_handler.read(file_path) texts = _file.split("\n\n") texts.pop(0) data = [] for text in texts: tokens = text.split("\n") if len(tokens) > 1: example = list(zip(*[token.split() for token in tokens])) data.append({ "sequence": " ".join(example[0]), self.tag_key: list(example[-1]), }) return data, data @overrides def _get_tag_dicts(self, **kwargs): data = kwargs["data"] tags = sorted(list(set(chain.from_iterable(d[self.tag_key] for d in data)))) tag_idx2text = {tag_idx: tag_text for tag_idx, tag_text in enumerate(tags)} tag_text2idx = {tag_text: tag_idx for tag_idx, tag_text in tag_idx2text.items()} return tag_idx2text, tag_text2idx ================================================ FILE: claf/data/reader/bert/glue/__init__.py ================================================ ================================================ FILE: claf/data/reader/bert/glue/cola.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:cola_bert") class CoLABertReader(SeqClsBertReader): """ CoLA DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "matthews_corr" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(CoLABertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): line_tokens = line.split("\t") if len(line_tokens) <= 3: continue data.append({ "uid": f"cola-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[3], self.class_key: str(line_tokens[1]) }) return data ================================================ FILE: claf/data/reader/bert/glue/mnli.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:mnli_bert") class MNLIBertReader(SeqClsBertReader): """ MNLI DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["contradiction", "entailment", "neutral"] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(MNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"mnli-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[8], "sequence_b": line_tokens[9], self.class_key: str(line_tokens[-1]), }) return data ================================================ FILE: claf/data/reader/bert/glue/mrpc.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:mrpc_bert") class MRPCBertReader(SeqClsBertReader): """ MRPC DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "f1" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(MRPCBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) != 5: continue data.append({ "uid": f"mrpc-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[3], "sequence_b": line_tokens[4], self.class_key: str(line_tokens[0]), }) return data ================================================ FILE: claf/data/reader/bert/glue/qnli.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:qnli_bert") class QNLIBertReader(SeqClsBertReader): """ QNLI DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["entailment", "not_entailment"] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(QNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"qnli-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data ================================================ FILE: claf/data/reader/bert/glue/qqp.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:qqp_bert") class QQPBertReader(SeqClsBertReader): """ Quora Question Pairs DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "f1" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(QQPBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") try: data.append({ "uid": f"qqp-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[3], "sequence_b": line_tokens[4], self.class_key: str(line_tokens[5]) }) except IndexError: continue return data ================================================ FILE: claf/data/reader/bert/glue/rte.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:rte_bert") class RTEBertReader(SeqClsBertReader): """ RTE (Recognizing Textual Entailment) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["entailment", "not_entailment"] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(RTEBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"rte-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data ================================================ FILE: claf/data/reader/bert/glue/sst.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:sst_bert") class SSTBertReader(SeqClsBertReader): """ SST DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(SSTBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") if data_type == "train": lines.pop(0) data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"sst-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[0], self.class_key: str(line_tokens[1]), }) return data ================================================ FILE: claf/data/reader/bert/glue/stsb.py ================================================ import logging from overrides import overrides from claf.data.reader import RegressionBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:stsb_bert") class STSBBertReader(RegressionBertReader): """ STS-B (Semantic Textual Similarity Benchmark) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ METRIC_KEY = "pearson_spearman_corr" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(STSBBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, label_key="score", cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"stsb-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[7], "sequence_b": line_tokens[8], "score": float(line_tokens[-1]), }) return data ================================================ FILE: claf/data/reader/bert/glue/wnli.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsBertReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:wnli_bert") class WNLIBertReader(SeqClsBertReader): """ WNLI (Winograd NLI) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(WNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"wnli-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data ================================================ FILE: claf/data/reader/bert/multi_task.py ================================================ import logging from overrides import overrides from claf.config.namespace import NestedNamespace from claf.config.registry import Registry from claf.data.dataset import MultiTaskBertDataset from claf.data.dto import Helper from claf.data.reader.base import DataReader from claf.decorator import register from claf.factory import DataReaderFactory from claf.model.multi_task.category import TaskCategory from .seq_cls import SeqClsBertReader from .squad import SQuADBertReader from .regression import RegressionBertReader from .tok_cls import TokClsBertReader logger = logging.getLogger(__name__) @register("reader:multitask_bert") class MultiTaskBertReader(DataReader): """ DataReader for Multi-Task using BERT * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword) * Kwargs: class_key: name of the label in .json file to use for classification """ CLASS_DATA = None def __init__( self, file_paths, tokenizers, batch_sizes=[], readers=[], ): super(MultiTaskBertReader, self).__init__(file_paths, MultiTaskBertDataset) assert len(batch_sizes) == len(readers) self.registry = Registry() self.text_columns = ["bert_input"] self.data_reader_factory = DataReaderFactory() self.tokenizers = tokenizers self.batch_sizes = batch_sizes self.dataset_batches = [] self.dataset_helpers = [] self.tasks = [] for reader in readers: data_reader = self.make_data_reader(reader) batches, helpers = data_reader.read() self.dataset_batches.append(batches) self.dataset_helpers.append(helpers) dataset_name = reader["dataset"] helper = helpers["train"] task = self.make_task_by_reader(dataset_name, data_reader, helper) self.tasks.append(task) def make_data_reader(self, config_dict): config = NestedNamespace() config.load_from_json(config_dict) config.tokenizers = self.tokenizers return self.data_reader_factory.create(config) def make_task_by_reader(self, name, data_reader, helper): task = {} task["name"] = name task["metric_key"] = data_reader.METRIC_KEY if isinstance(data_reader, SeqClsBertReader): task["category"] = TaskCategory.SEQUENCE_CLASSIFICATION task["num_label"] = helper["model"]["num_classes"] elif isinstance(data_reader, SQuADBertReader): task["category"] = TaskCategory.READING_COMPREHENSION task["num_label"] = None elif isinstance(data_reader, RegressionBertReader): task["category"] = TaskCategory.REGRESSION task["num_label"] = 1 elif isinstance(data_reader, TokClsBertReader): task["category"] = TaskCategory.TOKEN_CLASSIFICATION task["num_label"] = helper["model"]["num_tags"] else: raise ValueError("Check data_reader.") task["model_params"] = helper.get("model", {}) return task @overrides def _read(self, file_path, data_type=None): """ TODO: Doc-String """ batches = [] helper = Helper() helper.task_helpers = [] for b in self.dataset_batches: batches.append(b[data_type]) for i, h in enumerate(self.dataset_helpers): task_helper = h[data_type] task_helper["batch_size"] = self.batch_sizes[i] helper.task_helpers.append(task_helper) helper.set_model_parameter({ "tasks": self.tasks, }) return batches, helper.to_dict() def read_one_example(self, inputs): pass ================================================ FILE: claf/data/reader/bert/regression.py ================================================ import logging import json import uuid from overrides import overrides from tqdm import tqdm from claf.data.dataset import RegressionBertDataset from claf.data.dto import BertFeature, Helper from claf.data.reader.base import DataReader from claf.data import utils from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:regression_bert") class RegressionBertReader(DataReader): """ Regression DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ METRIC_KEY = None def __init__( self, file_paths, tokenizers, sequence_max_length=None, label_key="score", cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(RegressionBertReader, self).__init__(file_paths, RegressionBertDataset) self.sequence_max_length = sequence_max_length self.text_columns = ["bert_input", "sequence"] # Tokenizers # - BERT: Word + Subword or Word + Char # - RoBERTa: BPE if input_type == "bert": self.tokenizer = tokenizers.get("subword", None) if self.tokenizer is None: self.tokenizer["char"] elif input_type == "roberta": self.tokenizer = tokenizers["bpe"] else: raise ValueError("'bert' and 'roberta' are available input_type.") self.label_key = label_key self.cls_token = cls_token self.sep_token = sep_token self.input_type = input_type self.is_test = is_test def _get_data(self, file_path, **kwargs): data = self.data_handler.read(file_path) seq_cls_data = json.loads(data) return seq_cls_data["data"] @overrides def _read(self, file_path, data_type=None): """ .json file structure should be something like this: { "data": [ { "sequence_a": "what a wonderful day!", "sequence_b": "what a great day!", "score": 0.9 }, ... ] } """ data = self._get_data(file_path, data_type=data_type) helper = Helper(**{ "file_path": file_path, "cls_token": self.cls_token, "sep_token": self.sep_token, "dataset": RegressionBertDataset, "metric_key": self.METRIC_KEY, }) features, labels = [], [] for example in tqdm(data, desc=data_type): sequence_a = utils.get_sequence_a(example) sequence_b = example.get("sequence_b", None) sequence_a_tokens = self.tokenizer.tokenize(sequence_a) sequence_b_tokens = None if sequence_b: sequence_b_tokens = self.tokenizer.tokenize(sequence_b) bert_input = utils.make_bert_input( sequence_a, sequence_b, self.tokenizer, max_seq_length=self.sequence_max_length, data_type=data_type, cls_token=self.cls_token, sep_token=self.sep_token, input_type=self.input_type, ) if bert_input is None: continue if "uid" in example: data_uid = example["uid"] else: data_uid = str(uuid.uuid1()) feature_row = { "id": data_uid, "bert_input": bert_input, } features.append(feature_row) score = example[self.label_key] label_row = { "id": data_uid, "score": score, } labels.append(label_row) helper.set_example(data_uid, { "sequence_a": sequence_a, "sequence_a_tokens": sequence_a_tokens, "sequence_b": sequence_b, "sequence_b_tokens": sequence_b_tokens, "score": score, }) if self.is_test and len(features) >= 10: break return utils.make_batch(features, labels), helper.to_dict() def read_one_example(self, inputs): """ inputs keys: sequence_a and sequence_b """ sequence_a = utils.get_sequence_a(inputs) sequence_b = inputs.get("sequence_b", None) bert_feature = BertFeature() bert_feature.set_input_with_speical_token( sequence_a, sequence_b, self.tokenizer, max_seq_length=self.sequence_max_length, data_type="predict", cls_token=self.cls_token, sep_token=self.sep_token, input_type=self.input_type, ) features = [bert_feature.to_dict()] helper = {} return features, helper ================================================ FILE: claf/data/reader/bert/seq_cls.py ================================================ import json import logging import uuid from overrides import overrides from tqdm import tqdm from claf.data.dataset import SeqClsBertDataset from claf.data.dto import BertFeature, Helper from claf.data.reader.base import DataReader from claf.data import utils from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:seq_cls_bert") class SeqClsBertReader(DataReader): """ DataReader for Sequence (Single and Pair) Classification using BERT * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword) * Kwargs: class_key: name of the label in .json file to use for classification """ CLASS_DATA = None METRIC_KEY = None def __init__( self, file_paths, tokenizers, sequence_max_length=None, class_key="class", cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(SeqClsBertReader, self).__init__(file_paths, SeqClsBertDataset) self.sequence_max_length = sequence_max_length self.text_columns = ["bert_input", "sequence"] # Tokenizers # - BERT: Word + Subword or Word + Char # - RoBERTa: BPE if input_type == "bert": self.tokenizer = tokenizers.get("subword", None) if self.tokenizer is None: self.tokenizer["char"] elif input_type == "roberta": self.tokenizer = tokenizers["bpe"] else: raise ValueError("'bert' and 'roberta' are available input_type.") self.class_key = class_key self.cls_token = cls_token self.sep_token = sep_token self.input_type = input_type self.is_test = is_test def _get_data(self, file_path, **kwargs): data = self.data_handler.read(file_path) seq_cls_data = json.loads(data) return seq_cls_data["data"] def _get_class_dicts(self, **kwargs): seq_cls_data = kwargs["data"] if self.class_key is None: class_data = self.CLASS_DATA else: class_data = [item[self.class_key] for item in seq_cls_data] class_data = list(set(class_data)) # remove duplicate class_idx2text = { class_idx: str(class_text) for class_idx, class_text in enumerate(class_data) } class_text2idx = {class_text: class_idx for class_idx, class_text in class_idx2text.items()} return class_idx2text, class_text2idx @overrides def _read(self, file_path, data_type=None): """ .json file structure should be something like this: { "data": [ { "sequence": "what a wonderful day!", "emotion": "happy" }, ... ], "emotion": [ // class_key "angry", "happy", "sad", ... ] } """ data = self._get_data(file_path, data_type=data_type) class_idx2text, class_text2idx = self._get_class_dicts(data=data) helper = Helper(**{ "file_path": file_path, "class_idx2text": class_idx2text, "class_text2idx": class_text2idx, "cls_token": self.cls_token, "sep_token": self.sep_token, "dataset": SeqClsBertDataset, "metric_key": self.METRIC_KEY, }) helper.set_model_parameter({ "num_classes": len(class_idx2text), }) helper.set_predict_helper({ "class_idx2text": class_idx2text, }) features, labels = [], [] for example in tqdm(data, desc=data_type): sequence_a = utils.get_sequence_a(example) sequence_b = example.get("sequence_b", None) sequence_a_tokens = self.tokenizer.tokenize(sequence_a) sequence_b_tokens = None if sequence_b: sequence_b_tokens = self.tokenizer.tokenize(sequence_b) bert_input = utils.make_bert_input( sequence_a, sequence_b, self.tokenizer, max_seq_length=self.sequence_max_length, data_type=data_type, cls_token=self.cls_token, sep_token=self.sep_token, input_type=self.input_type, ) if bert_input is None: continue if "uid" in example: data_uid = example["uid"] else: data_uid = str(uuid.uuid1()) # token_type(segment_ids) will be added in dataset feature_row = { "id": data_uid, "bert_input": bert_input, } features.append(feature_row) class_text = example[self.class_key] label_row = { "id": data_uid, "class_idx": class_text2idx[class_text], "class_text": class_text, } labels.append(label_row) helper.set_example(data_uid, { "sequence_a": sequence_a, "sequence_a_tokens": sequence_a_tokens, "sequence_b": sequence_b, "sequence_b_tokens": sequence_b_tokens, "class_idx": class_text2idx[class_text], "class_text": class_text, }) if self.is_test and len(features) >= 10: break return utils.make_batch(features, labels), helper.to_dict() def read_one_example(self, inputs): """ inputs keys: sequence_a and sequence_b """ sequence_a = utils.get_sequence_a(inputs) sequence_b = inputs.get("sequence_b", None) bert_feature = BertFeature() bert_feature.set_input_with_speical_token( sequence_a, sequence_b, self.tokenizer, max_seq_length=self.sequence_max_length, data_type="predict", cls_token=self.cls_token, sep_token=self.sep_token, input_type=self.input_type, ) features = [bert_feature.to_dict()] helper = {} return features, helper ================================================ FILE: claf/data/reader/bert/squad.py ================================================ from collections import Counter import json import logging import re from overrides import overrides from tqdm import tqdm from claf.data.dataset import SQuADBertDataset from claf.data.dto import BertFeature, Helper from claf.data.reader.base import DataReader from claf.data import utils from claf.decorator import register from claf.metric.squad_v1_official import normalize_answer from claf.tokens.tokenizer import SentTokenizer, WordTokenizer logger = logging.getLogger(__name__) class Token: def __init__(self, text, text_span=None): self.text = text self.text_span = text_span @register("reader:squad_bert") class SQuADBertReader(DataReader): """ SQuAD DataReader for BERT * Args: file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word) """ METRIC_KEY = "f1" def __init__( self, file_paths, lang_code, tokenizers, max_seq_length=384, context_stride=128, max_question_length=64, cls_token="[CLS]", sep_token="[SEP]", ): super(SQuADBertReader, self).__init__(file_paths, SQuADBertDataset) self.lang_code = lang_code self.max_seq_length = max_seq_length self.context_stride = context_stride self.max_question_length = max_question_length self.cls_token = cls_token self.sep_token = sep_token self.text_columns = ["bert_input", "context", "question"] sent_tokenizer = SentTokenizer("punkt", {}) if lang_code == "ko": self.word_tokenizer = WordTokenizer("mecab_ko", sent_tokenizer, split_with_regex=True) else: self.word_tokenizer = WordTokenizer( "treebank_en", sent_tokenizer, split_with_regex=True ) if tokenizers["bpe"] is not None: self.sub_level_tokenizer = tokenizers["bpe"] # RoBERTa elif tokenizers["subword"] is not None: self.sub_level_tokenizer = tokenizers["subword"] # BERT else: raise ValueError("'bpe' or 'subword' tokenizer is required.") @overrides def _read(self, file_path, data_type=None): word_tokenized_error_count, sub_level_tokenized_error_count = 0, 0 data = self.data_handler.read(file_path) squad = json.loads(data) if "data" in squad: squad = squad["data"] helper = Helper(**{ "file_path": file_path, "raw_dataset": squad, "cls_token": self.cls_token, "sep_token": self.sep_token, "dataset": SQuADBertDataset, }) helper.set_model_parameter({ "lang_code": self.lang_code, }) features, labels = [], [] is_training = data_type == "train" for article in tqdm(squad, desc=data_type): for paragraph in article["paragraphs"]: context_text = paragraph["context"].replace("``", '" ').replace("''", '" ') context_tokens = self.word_tokenizer.tokenize(context_text) context_spans, char_to_word_offset = self._convert_to_spans( context_text, context_tokens ) context_tokens = [ Token(text, span) for (text, span) in zip(context_tokens, context_spans) ] context_sub_tokens = [] for token in context_tokens: for sub_token in self.sub_level_tokenizer.tokenize(token.text): context_sub_tokens.append(Token(sub_token, token.text_span)) for qa in paragraph["qas"]: question_text = qa["question"] question_text = " ".join(self.word_tokenizer.tokenize(question_text)) question_sub_tokens = [ Token(sub_token) for sub_token in self.sub_level_tokenizer.tokenize(question_text) ] id_ = qa["id"] answers = qa["answers"] answer_texts, answer_indices = [], [] if qa.get("is_impossible", None): answers = qa["plausible_answers"] answerable = 0 else: answers = qa["answers"] answerable = 1 for answer in answers: answer_start = answer["answer_start"] answer_end = answer_start + len(answer["text"]) - 1 answer_texts.append(answer["text"]) answer_indices.append((answer_start, answer_end)) if len(answer_indices) > 0: answer_char_start, answer_char_end = self._find_one_most_common( answer_indices ) answer_word_start = char_to_word_offset[answer_char_start] answer_word_end = char_to_word_offset[answer_char_end] char_answer_text = context_text[answer_char_start : answer_char_end + 1] word_answer_text = context_text[ context_spans[answer_word_start][0] : context_spans[answer_word_end][1] ] if not self._is_rebuild(char_answer_text, word_answer_text): logger.warning(f"word_tokenized_error: {char_answer_text} ### {word_answer_text}") word_tokenized_error_count += 1 else: # Unanswerable answers = [""] answer_char_start, answer_char_end = -1, -1 answer_word_start, answer_word_end = -1, -1 bert_features, bert_labels = self._make_features_and_labels( context_sub_tokens, question_sub_tokens, answer_char_start, answer_char_end + 1, ) for (index, (feature, label)) in enumerate(zip(bert_features, bert_labels)): bert_tokens = feature answer_start, answer_end = label if is_training and ( answer_start < 0 or answer_start >= len(bert_tokens) or answer_end >= len(bert_tokens) or bert_tokens[answer_start].text_span is None or bert_tokens[answer_end].text_span is None ): continue if is_training: char_start = bert_tokens[answer_start].text_span[0] char_end = bert_tokens[answer_end].text_span[1] bert_answer = context_text[char_start:char_end] if char_answer_text != bert_answer: logger.warning(f"sub_level_tokenized_error: {char_answer_text} ### {word_answer_text})") sub_level_tokenized_error_count += 1 feature_row = { "bert_input": [token.text for token in bert_tokens], "bert_token": bert_tokens, } features.append(feature_row) bert_id = id_ + f"#{index}" label_row = { "id": bert_id, # question_id + bert_index "answer_texts": "\t".join(answer_texts), "answer_start": answer_start, "answer_end": answer_end, "answerable": answerable, } labels.append(label_row) if id_ not in helper.examples: helper.set_example(id_, { "context": context_text, "question": question_text, "answers": answer_texts, }) helper.set_example(id_, { f"bert_tokens_{index}": bert_tokens, }, update=True) logger.info( f"tokenized_error_count - word: {word_tokenized_error_count} | sub_level: {sub_level_tokenized_error_count}" ) return utils.make_batch(features, labels), helper.to_dict() @overrides def read_one_example(self, inputs): """ inputs keys: question, context """ context_text = inputs["context"].replace("``", '" ').replace("''", '" ') tokenized_context = self.word_tokenizer.tokenize(context_text) context_spans, char_to_word_offset = self._convert_to_spans(context_text, tokenized_context) context_tokens = [ Token(text, span) for (text, span) in zip(tokenized_context, context_spans) ] context_sub_tokens = [] for token in context_tokens: for sub_token in self.sub_level_tokenizer.tokenize(token.text): context_sub_tokens.append(Token(sub_token, token.text_span)) question_text = inputs["question"] question_text = " ".join(self.word_tokenizer.tokenize(question_text)) question_sub_tokens = [ Token(sub_token) for sub_token in self.sub_level_tokenizer.tokenize(question_text) ] bert_tokens, _ = self._make_features_and_labels( context_sub_tokens, question_sub_tokens, -1, -1 ) features = [] helper = Helper(**{ "bert_token": [], "tokenized_context": tokenized_context, "token_key": "tokenized_context" # for 1-example inference latency key }) for bert_token in bert_tokens: bert_input = [token.text for token in bert_token] bert_feature = BertFeature() bert_feature.set_input(bert_input) features.append(bert_feature.to_dict()) helper.bert_token.append(bert_token) return features, helper.to_dict() def _find_one_most_common(self, answers): answer_counter = Counter(answers) value = answer_counter.most_common(1)[0][0] return value[0], value[1] def _convert_to_spans(self, raw_text, tokenized_text): """ Convert a tokenized version of `raw_text` into a series character spans referencing the `raw_text` """ double_quote_re = re.compile("\"|``|''") curr_idx = 0 spans = [] char_to_words = [-1 for _ in range(len(raw_text))] for token in tokenized_text: # Tokenizer might transform double quotes, for this case search over several # possible encodings if double_quote_re.match(token): span = double_quote_re.search(raw_text[curr_idx:]) temp = curr_idx + span.start() token_length = span.end() - span.start() else: temp = raw_text.find(token, curr_idx) token_length = len(token) if temp < curr_idx: joined_tokenized_text = " ".join(tokenized_text) raise ValueError( f"\n{raw_text} \n\n{joined_tokenized_text} \nToken: {token}, Index: {temp}, Current Index: {curr_idx}" ) curr_idx = temp spans.append((curr_idx, curr_idx + token_length)) curr_idx += token_length start, end = spans[-1] for i in range(start, end): char_to_words[i] = len(spans) - 1 for i in range(len(raw_text)): if char_to_words[i] != -1: continue for j, span in enumerate(spans): start, end = span if start < i <= end: char_to_words[i] = j return spans, char_to_words def _is_rebuild(self, char_answer_text, word_answer_text): norm_char_answer_text = normalize_answer(char_answer_text) norm_word_answer_text = normalize_answer(word_answer_text) if norm_char_answer_text != norm_word_answer_text: return False else: return True def _make_features_and_labels( self, context_sub_tokens, question_sub_tokens, answer_char_start, answer_char_end ): # sub_token, context_stride logic with context_max_length context_max_length = ( self.max_seq_length - len(question_sub_tokens) - 3 ) # [CLS], [SEP], [SEP] start_offset = 0 context_stride_spans = [] while start_offset < len(context_sub_tokens): strided_context_length = len(context_sub_tokens) - start_offset if strided_context_length > context_max_length: strided_context_length = context_max_length context_stride_spans.append((start_offset, strided_context_length)) if start_offset + strided_context_length == len(context_sub_tokens): break start_offset += min(strided_context_length, self.context_stride) features, labels = [], [] for (start_offset, length) in context_stride_spans: bert_tokens = [Token(self.cls_token)] bert_tokens += question_sub_tokens[: self.max_question_length] bert_tokens += [Token(self.sep_token)] bert_tokens += context_sub_tokens[start_offset : start_offset + length] bert_tokens += [Token(self.sep_token)] features.append(bert_tokens) if answer_char_start == -1 and answer_char_end == -1: answer_start, answer_end = 0, 0 else: answer_start, answer_end = self._get_closest_answer_spans( bert_tokens, answer_char_start, answer_char_end ) labels.append((answer_start, answer_end)) return features, labels def _get_closest_answer_spans(self, tokens, char_start, char_end): NONE_VALUE, DISTANCE_THRESHOLD = -100, 2 text_spans = [ (NONE_VALUE, NONE_VALUE) if token.text_span is None else token.text_span for token in tokens ] start_distances = [abs(span[0] - char_start) for span in text_spans] end_distances = [abs(span[1] - char_end) for span in text_spans] min_start_distance, min_end_distance = min(start_distances), min(end_distances) if min_start_distance < DISTANCE_THRESHOLD: answer_start = start_distances.index(min_start_distance) else: answer_start = 0 if min_end_distance < DISTANCE_THRESHOLD: answer_end = end_distances.index(min_end_distance) start_from = answer_end + 1 try: # e.g.) end_distances: [3, 1, 1, 4], min_end_distance = 1 => use 2 index instead of 1 answer_end = end_distances.index(min_end_distance, start_from) except ValueError: pass else: answer_end = 0 return answer_start, answer_end ================================================ FILE: claf/data/reader/bert/tok_cls.py ================================================ from itertools import chain import json import logging import uuid from overrides import overrides from tqdm import tqdm from claf.data.dataset import TokClsBertDataset from claf.data.dto import BertFeature, Helper from claf.data.reader.base import DataReader from claf.decorator import register from claf.tokens.tokenizer import WordTokenizer import claf.data.utils as utils logger = logging.getLogger(__name__) @register("reader:tok_cls_bert") class TokClsBertReader(DataReader): """ DataReader for Token Classification using BERT * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword) * Kwargs: lang_code: language code: set as 'ko' if using BERT model trained with mecab-tokenized data tag_key: name of the label in .json file to use for classification ignore_tag_idx: prediction results that have this number as ground-truth idx are ignored """ def __init__( self, file_paths, tokenizers, lang_code=None, sequence_max_length=None, tag_key="tags", cls_token="[CLS]", sep_token="[SEP]", ignore_tag_idx=-1, ): super(TokClsBertReader, self).__init__(file_paths, TokClsBertDataset) self.sequence_max_length = sequence_max_length self.text_columns = ["bert_input", "sequence"] if "subword" not in tokenizers: raise ValueError("WordTokenizer and SubwordTokenizer is required.") self.subword_tokenizer = tokenizers["subword"] self.sent_tokenizer = tokenizers["sent"] self.word_tokenizer = tokenizers["word"] if lang_code == "ko": self.mecab_tokenizer = WordTokenizer("mecab_ko", self.sent_tokenizer, split_with_regex=False) self.lang_code = lang_code self.tag_key = tag_key self.cls_token = cls_token self.sep_token = sep_token self.ignore_tag_idx = ignore_tag_idx def _get_data(self, file_path): data = self.data_handler.read(file_path) tok_cls_data = json.loads(data) return tok_cls_data["data"] def _get_tag_dicts(self, **kwargs): data = kwargs["data"] if type(data) == dict: tag_idx2text = {tag_idx: tag_text for tag_idx, tag_text in enumerate(data[self.tag_key])} elif type(data) == list: tags = sorted(list(set(chain.from_iterable(d[self.tag_key] for d in data)))) tag_idx2text = {tag_idx: tag_text for tag_idx, tag_text in enumerate(tags)} else: raise ValueError("check _get_data return type.") tag_text2idx = {tag_text: tag_idx for tag_idx, tag_text in tag_idx2text.items()} return tag_idx2text, tag_text2idx @overrides def _read(self, file_path, data_type=None): """ .json file structure should be something like this: { "data": [ { "sequence": "i'm looking for a flight from New York to London.", "slots": ["O", "O", "O", "O", "O", "O", "B-city.dept", "I-city.dept" "O", "B-city.dest"] // the number of tokens in sequence.split() and tags must match }, ... ], "slots": [ // tag_key "O", // tags should be in IOB format "B-city.dept", "I-city.dept", "B-city.dest", "I-city.dest", ... ] } """ data = self._get_data(file_path) tag_idx2text, tag_text2idx = self._get_tag_dicts(data=data) helper = Helper(**{ "file_path": file_path, "tag_idx2text": tag_idx2text, "ignore_tag_idx": self.ignore_tag_idx, "cls_token": self.cls_token, "sep_token": self.sep_token, }) helper.set_model_parameter({ "num_tags": len(tag_idx2text), "ignore_tag_idx": self.ignore_tag_idx, }) helper.set_predict_helper({ "tag_idx2text": tag_idx2text, }) features, labels = [], [] for example in tqdm(data, desc=data_type): sequence_text = example["sequence"].strip().replace("\n", "") sequence_tokens = self.word_tokenizer.tokenize(sequence_text) naive_tokens = sequence_text.split() is_head_word = utils.get_is_head_of_word(naive_tokens, sequence_tokens) sequence_sub_tokens = [] tagged_sub_token_idxs = [] curr_sub_token_idx = 1 # skip CLS_TOKEN for token_idx, token in enumerate(sequence_tokens): for sub_token_pos, sub_token in enumerate( self.subword_tokenizer.tokenize(token, unit="word") ): sequence_sub_tokens.append(sub_token) if is_head_word[token_idx] and sub_token_pos == 0: tagged_sub_token_idxs.append(curr_sub_token_idx) curr_sub_token_idx += 1 bert_input = [self.cls_token] + sequence_sub_tokens + [self.sep_token] if ( self.sequence_max_length is not None and data_type == "train" and len(bert_input) > self.sequence_max_length ): continue if "uid" in example: data_uid = example["uid"] else: data_uid = str(uuid.uuid1()) tag_texts = example[self.tag_key] tag_idxs = [tag_text2idx[tag_text] for tag_text in tag_texts] utils.sanity_check_iob(naive_tokens, tag_texts) assert len(naive_tokens) == len(tagged_sub_token_idxs), \ f"""Wrong tagged_sub_token_idxs: followings mismatch. naive_tokens: {naive_tokens} sequence_sub_tokens: {sequence_sub_tokens} tagged_sub_token_idxs: {tagged_sub_token_idxs}""" feature_row = { "id": data_uid, "bert_input": bert_input, "tagged_sub_token_idxs": tagged_sub_token_idxs, "num_tokens": len(naive_tokens), } features.append(feature_row) label_row = { "id": data_uid, "tag_idxs": tag_idxs, "tag_texts": tag_texts, } labels.append(label_row) helper.set_example(data_uid, { "sequence": sequence_text, "sequence_sub_tokens": sequence_sub_tokens, "tag_idxs": tag_idxs, "tag_texts": tag_texts, }) return utils.make_batch(features, labels), helper.to_dict() def read_one_example(self, inputs): """ inputs keys: sequence """ sequence_text = inputs["sequence"].strip().replace("\n", "") sequence_tokens = self.word_tokenizer.tokenize(sequence_text) naive_tokens = sequence_text.split() is_head_word = utils.get_is_head_of_word(naive_tokens, sequence_tokens) sequence_sub_tokens = [] tagged_sub_token_idxs = [] curr_sub_token_idx = 1 # skip CLS_TOKEN for token_idx, token in enumerate(sequence_tokens): for sub_token_pos, sub_token in enumerate( self.subword_tokenizer.tokenize(token, unit="word") ): sequence_sub_tokens.append(sub_token) if is_head_word[token_idx] and sub_token_pos == 0: tagged_sub_token_idxs.append(curr_sub_token_idx) curr_sub_token_idx += 1 if len(sequence_sub_tokens) > self.sequence_max_length: sequence_sub_tokens = sequence_sub_tokens[:self.sequence_max_length] bert_input = [self.cls_token] + sequence_sub_tokens + [self.sep_token] assert len(naive_tokens) == len(tagged_sub_token_idxs), \ f"""Wrong tagged_sub_token_idxs: followings mismatch. naive_tokens: {naive_tokens} sequence_sub_tokens: {sequence_sub_tokens} tagged_sub_token_idxs: {tagged_sub_token_idxs}""" bert_feature = BertFeature() bert_feature.set_input(bert_input) bert_feature.set_feature("tagged_sub_token_idxs", tagged_sub_token_idxs) bert_feature.set_feature("num_tokens", len(naive_tokens)) features = [bert_feature.to_dict()] helper = {} return features, helper ================================================ FILE: claf/data/reader/cola.py ================================================ import logging from overrides import overrides from claf.data.reader import SeqClsReader from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:cola") class CoLAReader(SeqClsReader): """ CoLA DataReader * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (word) """ CLASS_DATA = [0, 1] def __init__( self, file_paths, tokenizers, sequence_max_length=None, ): super(CoLAReader, self).__init__( file_paths, tokenizers, sequence_max_length=sequence_max_length, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") if data_type == "train": lines.pop(0) data = [] for i, line in enumerate(lines): line_tokens = line.split("\t") if len(line_tokens) > 1: data.append({ "uid": f"{data_type}-{i}", "sequence": line_tokens[1] if data_type == "test" else line_tokens[3], self.class_key: str(0) if data_type == "test" else str(line_tokens[1]) }) return data ================================================ FILE: claf/data/reader/seq_cls.py ================================================ import json import logging import uuid from overrides import overrides from tqdm import tqdm from claf.data.dataset.seq_cls import SeqClsDataset from claf.data.dto import Helper from claf.data.reader.base import DataReader from claf.data import utils from claf.decorator import register logger = logging.getLogger(__name__) @register("reader:seq_cls") class SeqClsReader(DataReader): """ DataReader for Sequence Classification * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (word) * Kwargs: class_key: name of the label in .json file to use for classification """ CLASS_DATA = None def __init__(self, file_paths, tokenizers, sequence_max_length=None, class_key="class"): super(SeqClsReader, self).__init__(file_paths, SeqClsDataset) self.sequence_max_length = sequence_max_length self.text_columns = ["sequence"] if "word" not in tokenizers: raise ValueError("WordTokenizer is required. define WordTokenizer") self.word_tokenizer = tokenizers["word"] self.class_key = class_key def _get_data(self, file_path, **kwargs): data = self.data_handler.read(file_path) seq_cls_data = json.loads(data) return seq_cls_data["data"] def _get_class_dicts(self, **kwargs): seq_cls_data = kwargs["data"] if self.class_key is None: class_data = self.CLASS_DATA else: class_data = [item[self.class_key] for item in seq_cls_data] class_data = list(set(class_data)) # remove duplicate class_idx2text = { class_idx: str(class_text) for class_idx, class_text in enumerate(class_data) } class_text2idx = {class_text: class_idx for class_idx, class_text in class_idx2text.items()} return class_idx2text, class_text2idx @overrides def _read(self, file_path, data_type=None): """ .json file structure should be something like this: { "data": [ { "sequence": "what a wonderful day!", "emotion": "happy" }, ... ], "emotion": [ // class_key "angry", "happy", "sad", ... ] } """ data = self._get_data(file_path, data_type=data_type) class_idx2text, class_text2idx = self._get_class_dicts(data=data) helper = Helper(**{ "file_path": file_path, "class_idx2text": class_idx2text, "class_text2idx": class_text2idx, }) helper.set_model_parameter({ "num_classes": len(class_idx2text), }) helper.set_predict_helper({ "class_idx2text": class_idx2text, }) features, labels = [], [] for example in tqdm(data, desc=data_type): sequence = example["sequence"].strip().replace("\n", "") sequence_words = self.word_tokenizer.tokenize(sequence) if ( self.sequence_max_length is not None and data_type == "train" and len(sequence_words) > self.sequence_max_length ): continue if "uid" in example: data_uid = example["uid"] else: data_uid = str(uuid.uuid1()) feature_row = { "id": data_uid, "sequence": sequence, } features.append(feature_row) class_text = example[self.class_key] label_row = { "id": data_uid, "class_idx": class_text2idx[class_text], "class_text": class_text, } labels.append(label_row) helper.set_example(data_uid, { "sequence": sequence, "class_idx": class_text2idx[class_text], "class_text": class_text, }) return utils.make_batch(features, labels), helper.to_dict() def read_one_example(self, inputs): """ inputs keys: sequence """ sequence = inputs["sequence"].strip().replace("\n", "") inputs["sequence"] = sequence return inputs, {} ================================================ FILE: claf/data/reader/squad.py ================================================ from collections import Counter import json import logging import re from overrides import overrides from tqdm import tqdm from claf.data.dataset import SQuADDataset from claf.data.dto import Helper from claf.data.reader.base import DataReader from claf.data import utils from claf.decorator import register from claf.metric.squad_v1_official import normalize_answer logger = logging.getLogger(__name__) @register("reader:squad") class SQuADReader(DataReader): """ SQuAD DataReader * Args: file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word) """ def __init__(self, file_paths, lang_code, tokenizers, context_max_length=None): super(SQuADReader, self).__init__(file_paths, SQuADDataset) self.lang_code = lang_code self.context_max_length = context_max_length self.text_columns = ["context", "question"] if "word" not in tokenizers: raise ValueError("WordTokenizer is required. define English WordTokenizer") self.word_tokenizer = tokenizers["word"] @overrides def _read(self, file_path, data_type=None): tokenized_error_count = 0 data = self.data_handler.read(file_path) squad = json.loads(data) if "data" in squad: squad = squad["data"] helper = Helper(**{ "file_path": file_path, "raw_dataset": squad, }) helper.set_model_parameter({ "lang_code": self.lang_code, }) features, labels = [], [] for article in tqdm(squad, desc=data_type): for paragraph in article["paragraphs"]: context = paragraph["context"].replace("``", '" ').replace("''", '" ') context_words = self.word_tokenizer.tokenize(context) if ( self.context_max_length is not None and data_type == "train" and len(context_words) > self.context_max_length ): continue for qa in paragraph["qas"]: question = qa["question"].strip().replace("\n", "") id_ = qa["id"] answer_texts, answer_indices = [], [] if qa.get("is_impossible", None): answers = qa["plausible_answers"] answerable = 0 else: answers = qa["answers"] answerable = 1 for answer in answers: answer_start = answer["answer_start"] answer_end = answer_start + len(answer["text"]) answer_texts.append(answer["text"]) answer_indices.append((answer_start, answer_end)) feature_row = { "context": self._clean_text(context), "question": question, } features.append(feature_row) if len(answer_indices) > 0: answer_start, answer_end = self._find_one_most_common(answer_indices) text_spans = self._convert_to_spans(context, context_words) word_idxs = self._get_word_span_idxs(text_spans, answer_start, answer_end) word_answer_start = word_idxs[0] word_answer_end = word_idxs[-1] # To check rebuild answer: char_answer_text - word_answer_text char_answer_text = context[answer_start:answer_end] word_answer_text = context[ text_spans[word_answer_start][0] : text_spans[word_answer_end][1] ] if not self._is_rebuild(char_answer_text, word_answer_text): logger.warning(f"word_tokenized_error: {char_answer_text} ### {word_answer_text}") tokenized_error_count += 1 else: # Unanswerable answers = [""] text_spans = [] answer_start, answer_end = 0, 0 word_answer_start, word_answer_end = 0, 0 label_row = { "id": id_, "answer_start": word_answer_start, "answer_end": word_answer_end, "answerable": answerable, } labels.append(label_row) helper.set_example(id_, { "context": context, "text_span": text_spans, "question": question, "answers": answer_texts, }) logger.info(f"tokenized_error_count: {tokenized_error_count} ") return utils.make_batch(features, labels), helper.to_dict() @overrides def read_one_example(self, inputs): """ inputs keys: question, context """ context_text = inputs["context"] tokenized_context = self.word_tokenizer.tokenize(context_text) question_text = inputs["question"].strip().replace("\n", "") features = {} features["context"] = self._clean_text(context_text) features["question"] = self._clean_text(question_text) helper = { "text_span": self._convert_to_spans(context_text, tokenized_context), "tokenized_context": tokenized_context, "token_key": "tokenized_context" # for 1-example inference latency key } return features, helper def _clean_text(self, text): # https://github.com/allenai/document-qa/blob/2f9fa6878b60ed8a8a31bcf03f802cde292fe48b/docqa/data_processing/text_utils.py#L124 # be consistent with quotes, and replace \u2014 and \u2212 which I have seen being mapped to UNK # by glove word vecs return ( text.replace("''", '"') .replace("``", '"') .replace("\u2212", "-") .replace("\u2014", "\u2013") ) def _find_one_most_common(self, answers): answer_counter = Counter(answers) value = answer_counter.most_common(1)[0][0] return value[0], value[1] def _convert_to_spans(self, raw_text, tokenized_text): """ Convert a tokenized version of `raw_text` into a series character spans referencing the `raw_text` """ double_quote_re = re.compile("\"|``|''") curr_idx = 0 spans = [] for token in tokenized_text: # Tokenizer might transform double quotes, for this case search over several # possible encodings if double_quote_re.match(token): span = double_quote_re.search(raw_text[curr_idx:]) temp = curr_idx + span.start() token_length = span.end() - span.start() else: temp = raw_text.find(token, curr_idx) token_length = len(token) if temp < curr_idx: raise ValueError(f"{raw_text} \n{tokenized_text} \n{token}") curr_idx = temp spans.append((curr_idx, curr_idx + token_length)) curr_idx += token_length return spans def _get_word_span_idxs(self, spans, start, end): idxs = [] for word_ix, (s, e) in enumerate(spans): if e > start: if s < end: idxs.append(word_ix) else: break return idxs def _is_rebuild(self, char_answer_text, word_answer_text): norm_char_answer_text = normalize_answer(char_answer_text) norm_word_answer_text = normalize_answer(word_answer_text) if norm_char_answer_text != norm_word_answer_text: return False else: return True ================================================ FILE: claf/data/reader/wikisql.py ================================================ import json import logging from pathlib import Path import uuid from overrides import overrides from tqdm import tqdm from claf.data.dataset import WikiSQLDataset from claf.data.dto import Helper from claf.data.reader.base import DataReader from claf.data import utils from claf.decorator import register from claf.metric.wikisql_lib.dbengine import DBEngine from claf.metric.wikisql_lib.query import Query logger = logging.getLogger(__name__) @register("reader:wikisql") class WikiSQLReader(DataReader): """ WikiSQL DataReader (http://arxiv.org/abs/1709.00103) * Args: file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word) """ def __init__(self, file_paths, tokenizers, context_max_length=None, is_test=None): super(WikiSQLReader, self).__init__(file_paths, WikiSQLDataset) self.is_test = is_test self.text_columns = ["column", "question"] if "word" not in tokenizers: raise ValueError("WordTokenizer is required. define English WordTokenizer") self.word_tokenizer = tokenizers["word"] self.dbengine = None @overrides def _read(self, file_path, data_type=None): file_path = self.data_handler.read(file_path, return_path=True) file_path = Path(file_path) data_dir = file_path.parent file_name = file_path.stem db_path = data_dir / f"{file_name}.db" table_path = data_dir / f"{file_name}.tables.jsonl" self.dbengine = DBEngine(db_path) helper = Helper(**{ "file_path": file_path, "db_path": db_path, }) features, labels = [], [] sql_datas, table_data = self.load_data(file_path, table_path, data_type=data_type) for sql_data in tqdm(sql_datas, desc=data_type): question = sql_data["question"] table_id = sql_data["table_id"] column_headers = table_data[table_id]["header"] feature_row = {"column": column_headers, "question": question} data_uid = str(uuid.uuid1()) conditions_value_position = self.get_coditions_value_position( sql_data["question"], [x[2] for x in sql_data["sql"]["conds"]] ) sql_query = Query.from_dict(sql_data["sql"], ordered=True) execution_result = self.dbengine.execute_query(table_id, sql_query, lower=True) label_row = { "id": data_uid, "table_id": table_id, "tokenized_question": self.word_tokenizer.tokenize(question), "aggregator_idx": sql_data["sql"]["agg"], "select_column_idx": sql_data["sql"]["sel"], "conditions_num": len(sql_data["sql"]["conds"]), "conditions_column_idx": [x[0] for x in sql_data["sql"]["conds"]], "conditions_operator_idx": [x[1] for x in sql_data["sql"]["conds"]], "conditions_value_string": [str(x[2]) for x in sql_data["sql"]["conds"]], "conditions_value_position": conditions_value_position, "sql_query": sql_query, "execution_result": execution_result, } features.append(feature_row) labels.append(label_row) helper.set_example(data_uid, { "question": question, "sql_query": sql_query, "execution_result": execution_result, }) if self.is_test and len(labels) == 10: break return utils.make_batch(features, labels), helper.to_dict() @overrides def read_one_example(self, inputs): """ inputs keys: question, column, db_path, table_id """ question_text = inputs["question"] helper = {"tokenized_question": self.word_tokenizer.tokenize(question_text)} return inputs, helper def load_data(self, sql_path, table_path, data_type=None): sql_data = [] table_data = {} logger.info(f"Loading data from {sql_path}") with open(sql_path) as inf: for line in tqdm(inf, desc=f"sql_{data_type}"): sql = json.loads(line.strip()) sql_data.append(sql) logger.info(f"Loading data from {table_path}") with open(table_path) as inf: for line in tqdm(inf, desc=f"table_{data_type}"): tab = json.loads(line.strip()) table_data[tab["id"]] = tab for sql in sql_data: assert sql["table_id"] in table_data return sql_data, table_data def get_coditions_value_position(self, question, values): tokenized_question = self.word_tokenizer.tokenize(question.lower()) tokenized_values = [self.word_tokenizer.tokenize(str(value).lower()) for value in values] START_TOKEN, END_TOKEN = "", "" token_to_index = {START_TOKEN: 0} for token in tokenized_question: token_to_index[token] = len(token_to_index) token_to_index[END_TOKEN] = len(token_to_index) position_tokens = [] for value in tokenized_values: position_token = [token_to_index[START_TOKEN]] for token in value: if token in token_to_index: position_token.append(token_to_index[token]) else: for i in range(len(tokenized_question)): q_token = tokenized_question[i] if token in q_token: position_token.append(token_to_index[q_token]) position_token.append(token_to_index[END_TOKEN]) assert len(position_token) != 2 position_tokens.append(position_token) return position_tokens ================================================ FILE: claf/data/utils.py ================================================ from collections import defaultdict import numpy as np import torch from claf.data.dto.batch import Batch def make_batch(features, labels): return Batch(**{"features": features, "labels": labels}) def make_bert_input( sequence_a, sequence_b, bert_tokenizer, max_seq_length=128, data_type="train", cls_token="[CLS]", sep_token="[SEP]", input_type="bert", ): sequence_a_tokens = bert_tokenizer.tokenize(sequence_a) bert_input = [cls_token] + sequence_a_tokens + [sep_token] if sequence_b: if input_type == "roberta": bert_input += [sep_token] sequence_b_tokens = bert_tokenizer.tokenize(sequence_b) bert_input += sequence_b_tokens + [sep_token] if len(bert_input) > max_seq_length: if data_type == "train": return None # for skip else: return bert_input[:max_seq_length-1] + [sep_token] return bert_input def make_bert_token_types(bert_inputs, SEP_token="[SEP]"): """ Bert Inputs segment_ids ex) [CLS] hi [SEP] he ##llo [SEP] => 0 0 0 1 1 1 * Args: bert_inputs: feature dictionary consisting of - text: text from data_reader - token_name: text converted to corresponding token_type * Kwargs: SEP_token: SEP special token for BERT """ feature_keys = list(bert_inputs[0].keys()) # TODO: hard-code if "text" in feature_keys: feature_keys.remove("text") feature_key = feature_keys[0] token_types = [] for bert_input in bert_inputs: token_type = make_bert_token_type(bert_input["text"], SEP_token=SEP_token) token_types.append({feature_key: token_type}) return token_types def make_bert_token_type(bert_input_text, SEP_token="[SEP]"): SEP_index = bert_input_text.index(SEP_token) + 1 token_type = [0] * SEP_index token_type += [1] * (len(bert_input_text) - SEP_index) assert len(token_type) == len(bert_input_text) return token_type def padding_tokens(tokens, max_len=None, token_name=None, pad_value=0): """ Padding tokens according to token's dimension """ def _pad_tokens(seqs, maxlen, pad_id=0): lens = [len(seq) for seq in seqs] if pad_id == 0: padded_seqs = torch.zeros(len(seqs), maxlen).long() else: padded_seqs = torch.ones(len(seqs), maxlen).long() * pad_id for i, seq in enumerate(seqs): if type(seq[0]) == dict: pass else: seq = [int(s) for s in seq] end = lens[i] padded_seqs[i, :end] = torch.LongTensor(seq) return padded_seqs def _pad_char_tokens(seqs, seq_maxlen, char_minlen=10, char_maxlen=None, pad_value=0): if char_maxlen is None: char_maxlen = max([len(chars) for seq in seqs for chars in seq]) if char_maxlen < char_minlen: char_maxlen = char_minlen padded_chars = torch.zeros(len(seqs), seq_maxlen, char_maxlen).long() for i in range(len(seqs)): char_tokens = _pad_with_value(seqs[i], seq_maxlen, pad_value=[[pad_value]]) padded_chars[i] = _pad_tokens(char_tokens, char_maxlen, pad_id=pad_value) return padded_chars def _pad_with_value(data, size, pad_value=[0]): if type(pad_value) != list: raise ValueError("pad_value data type is list.") return data + pad_value * (size - len(data)) token_dim = get_token_dim(tokens) if token_dim > 1 and max_len is None: max_len = max(len(token) for token in tokens) if token_dim == 2: # word return _pad_tokens(tokens, max_len, pad_id=pad_value) elif token_dim == 3: # char if token_name == "elmo": return _pad_char_tokens( tokens, max_len, char_maxlen=50, pad_value=261, ) # 260: padding_character, +1 for mask elif token_name == "char": return _pad_char_tokens(tokens, max_len, char_minlen=10, pad_value=pad_value) else: return _pad_char_tokens(tokens, max_len, char_minlen=1, pad_value=pad_value) else: return tokens def get_sequence_a(example): if "sequence" in example: return example["sequence"] elif "sequence_a" in example: return example["sequence_a"] else: raise ValueError("'sequence' or 'sequence_a' key is required.") def get_token_dim(tokens, dim=0): if type(tokens) == torch.Tensor: dim = tokens.dim() if tokens.size(-1) > 1: dim += 1 return dim if type(tokens) == np.ndarray: dim = tokens.ndim if tokens.shape[-1] > 1: dim += 1 return dim if type(tokens) == list or type(tokens) == tuple: dim = get_token_dim(tokens[0], dim + 1) return dim def get_token_type(tokens): token = tokens[0] while isinstance(token, np.ndarray) and isinstance(token, list): token = token[0] return type(token) def is_lazy(tokens): if type(tokens) == list: tokens = tokens[0] if callable(tokens): return True else: return False def transpose(list_of_dict, skip_keys=[]): if type(skip_keys) != list: raise ValueError(f"skip_keys type must be list. not {type(skip_keys)}") dict_of_list = defaultdict(lambda: []) for dic in list_of_dict: for key, value in dic.items(): if key in skip_keys: continue dict_of_list[key].append(value) return dict_of_list def sanity_check_iob(naive_tokens, tag_texts): """ Check if the IOB tags are valid. * Args: naive_tokens: tokens split by .split() tag_texts: list of tags in IOB format """ def prefix(tag): if tag == "O": return tag return tag.split("-")[0] def body(tag): if tag == "O": return None return tag.split("-")[1] # same number check assert len(naive_tokens) == len(tag_texts), \ f"""Number of tokens and tags doest not match. original tokens: {naive_tokens} tags: {tag_texts}""" # IOB format check prev_tag = None for tag_text in tag_texts: curr_tag = tag_text if prev_tag is None: # first tag assert prefix(curr_tag) in ["B", "O"], \ f"""Wrong tag: first tag starts with I. tag: {curr_tag}""""" else: # following tags if prefix(prev_tag) in ["B", "I"]: assert ( (prefix(curr_tag) == "I" and body(curr_tag) == body(prev_tag)) or (prefix(curr_tag) == "B") or (prefix(curr_tag) == "O") ), f"""Wrong tag: following tag mismatch. previous tag: {prev_tag} current tag: {curr_tag}""" elif prefix(prev_tag) in ["O"]: assert prefix(curr_tag) in ["B", "O"], \ f"""Wrong tag: following tag mismatch. previous tag: {prev_tag} current tag: {curr_tag}""" else: raise RuntimeError(f"Encountered unknown tag: {prev_tag}.") prev_tag = curr_tag def get_is_head_of_word(naive_tokens, sequence_tokens): """ Return a list of flags whether the token is head(prefix) of naively split tokens ex) naive_tokens: ["hello.", "how", "are", "you?"] sequence_tokens: ["hello", ".", "how", "are", "you", "?"] => [1, 0, 1, 1, 1, 0] * Args: naive_tokens: a list of tokens, naively split by whitespace sequence_tokens: a list of tokens, split by 'word_tokenizer' * Returns: is_head_of_word: a list with its length the same as that of 'sequence_tokens'. has 1 if the tokenized word at the position is head(prefix) of a `naive_token` and 0 if otherwise. """ is_head_of_word = [] for naive_token in naive_tokens: consumed_chars = 0 consumed_words = 0 for sequence_token in sequence_tokens: if naive_token[consumed_chars:].startswith(sequence_token): is_head_of_word.append(0 if consumed_chars else 1) consumed_chars += len(sequence_token) consumed_words += 1 else: break sequence_tokens = sequence_tokens[consumed_words:] return is_head_of_word ================================================ FILE: claf/decorator/__init__.py ================================================ from claf.decorator.arguments import arguments_required from claf.decorator.register import register __all__ = ["arguments_required", "register"] ================================================ FILE: claf/decorator/arguments.py ================================================ class arguments_required: """ Decorator Class check required arguments for predict function (eg. @arguments_required(["db_path", "table_id"])) """ def __init__(self, required_fields): self.required_fields = required_fields def __call__(self, fn): def wrapper(*args, **kwargs): arguments = args[2] for item in self.required_fields: if arguments.get(item, None) is None: raise ValueError(f"--{item} is required argument.") return fn(*args, **kwargs) return wrapper ================================================ FILE: claf/decorator/register.py ================================================ from claf.config.registry import Registry class register: """ Decorator Class register subclass with decorator. (eg. @register("model:bidaf"), @register("reader:squad") ) """ def __init__(self, name): self.name = name def __call__(self, obj): registry = Registry() registry.add(self.name, obj) return obj ================================================ FILE: claf/factory/__init__.py ================================================ from claf.factory.data_reader import DataReaderFactory from claf.factory.data_loader import DataLoaderFactory from claf.factory.model import ModelFactory from claf.factory.optimizer import OptimizerFactory from claf.factory.tokens import TokenMakersFactory __all__ = [ "DataReaderFactory", "DataLoaderFactory", "ModelFactory", "OptimizerFactory", "TokenMakersFactory", ] ================================================ FILE: claf/factory/base.py ================================================ class Factory: """ Factory Base Class Factory method pattern In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor. """ def __init__(self): pass def create(self): """ interface """ raise NotImplementedError ================================================ FILE: claf/factory/data_loader.py ================================================ from overrides import overrides from torch.utils.data import DataLoader from .base import Factory def make_data_loader(dataset, batch_size=32, shuffle=True, cuda_device_id=None): is_cpu = cuda_device_id is None return DataLoader( dataset, batch_size=batch_size, shuffle=shuffle, collate_fn=dataset.collate_fn(cuda_device_id=cuda_device_id), num_workers=0, pin_memory=is_cpu, # only CPU memory can be pinned ) class DataLoaderFactory(Factory): """ DataLoader Factory Class * Args: config: data_loader config from argument (config.data_loader) """ def __init__(self): pass @overrides def create(self, config, datasets): """ create train, valid and test iterator """ cuda_device_id = None if config.cuda_devices: cuda_device_id = config.cuda_devices[0] dataset_key = next(iter(datasets)) dataset = datasets[dataset_key] if getattr(dataset, "name", None) is None: raise ValueError("unknown dataset.") train_loader = None if "train" in datasets: train_loader = make_data_loader( datasets["train"], batch_size=config.batch_size, shuffle=True, cuda_device_id=cuda_device_id, ) valid_loader = None if "valid" in datasets: valid_loader = make_data_loader( datasets["valid"], batch_size=config.batch_size, shuffle=False, cuda_device_id=cuda_device_id, ) test_loader = None if "test" in datasets: test_loader = make_data_loader( datasets["test"], batch_size=config.batch_size, shuffle=False, cuda_device_id=cuda_device_id, ) return train_loader, valid_loader, test_loader ================================================ FILE: claf/factory/data_reader.py ================================================ from overrides import overrides from claf.config.registry import Registry from .base import Factory class DataReaderFactory(Factory): """ DataReader Factory Class Create Concrete reader according to config.dataset Get reader from reader registries (eg. @register("reader:{reader_name}")) * Args: config: data_reader config from argument (config.data_reader) """ def __init__(self): self.registry = Registry() @overrides def create(self, config): dataset_name = config.dataset file_paths = {} if getattr(config, "train_file_path", None): file_paths["train"] = config.train_file_path if getattr(config, "valid_file_path", None): file_paths["valid"] = config.valid_file_path reader_config = {"file_paths": file_paths} if "params" in config and type(config.params) == dict: reader_config.update(config.params) if "tokenizers" in config: reader_config["tokenizers"] = config.tokenizers dataset_config = getattr(config, config.dataset, None) if dataset_config is not None: dataset_config = vars(dataset_config) reader_config.update(dataset_config) reader = self.registry.get(f"reader:{dataset_name.lower()}") return reader(**reader_config) ================================================ FILE: claf/factory/model.py ================================================ from overrides import overrides from claf.config.registry import Registry from claf.model.base import ModelWithTokenEmbedder, ModelWithoutTokenEmbedder from claf.model.reading_comprehension.mixin import ReadingComprehension from claf.tokens import token_embedder from .base import Factory class ModelFactory(Factory): """ Model Factory Class Create Concrete model according to config.model_name Get model from model registries (eg. @register("model:{model_name}")) * Args: config: model config from argument (config.model) """ def __init__(self): self.registry = Registry() @overrides def create(self, config, token_makers, **params): name = config.name model_config = {} if getattr(config, config.name, None): model_config = vars(getattr(config, config.name)) model = self.registry.get(f"model:{name}") if issubclass(model, ModelWithTokenEmbedder): token_embedder = self.create_token_embedder(model, token_makers) model_config["token_embedder"] = token_embedder elif issubclass(model, ModelWithoutTokenEmbedder): model_config["token_makers"] = token_makers else: raise ValueError( "Model must have inheritance. (ModelWithTokenEmbedder or ModelWithoutTokenEmbedder)" ) return model(**model_config, **params) def create_token_embedder(self, model, token_makers): # 1. Specific case # ... # 2. Base case if issubclass(model, ReadingComprehension): return token_embedder.RCTokenEmbedder(token_makers) else: return token_embedder.BasicTokenEmbedder(token_makers) ================================================ FILE: claf/factory/optimizer.py ================================================ from overrides import overrides import torch from claf.config.namespace import NestedNamespace from claf.learn.optimization.learning_rate_scheduler import get_lr_schedulers from claf.learn.optimization.learning_rate_scheduler import ( LearningRateWithoutMetricsWrapper, LearningRateWithMetricsWrapper, ) from claf.learn.optimization.optimizer import get_optimizer_by_name from claf.model.sequence_classification import BertForSeqCls, RobertaForSeqCls from .base import Factory class OptimizerFactory(Factory): """ Optimizer Factory Class include optimizer, learning_rate_scheduler and exponential_moving_average * Args: config: optimizer config from argument (config.optimizer) """ def __init__(self): pass @overrides def create(self, config, model): if not issubclass(type(model), torch.nn.Module): raise ValueError("optimizer model is must be subclass of torch.nn.Module.") # Optimizer op_type = config.op_type optimizer_params = {"lr": config.learning_rate} op_config = getattr(config, op_type, None) if op_config is not None: op_config = vars(op_config) optimizer_params.update(op_config) model_parameters = self.get_model_parameters(model, optimizer_params) optimizer = get_optimizer_by_name(op_type)(model_parameters, **optimizer_params) op_dict = {"optimizer": optimizer} # LearningRate Scheduler lr_scheduler = self.make_lr_scheduler(config, optimizer) if lr_scheduler is not None: op_dict["learning_rate_scheduler"] = lr_scheduler # exponential_moving_average ema_value = getattr(config, "exponential_moving_average", None) if ema_value and ema_value > 0: op_dict["exponential_moving_average"] = ema_value return op_dict def get_model_parameters(self, model, optimizer_params): if getattr(model, "use_pytorch_transformers", False): weight_decay = optimizer_params.get("weight_decay", 0) model_parameters = self._group_parameters_for_transformers(model, weight_decay=weight_decay) else: model_parameters = [param for param in model.parameters() if param.requires_grad] return model_parameters def _group_parameters_for_transformers(self, model, weight_decay=0): # Prepare optimizer param_optimizer = list(model.named_parameters()) # hack to remove pooler, which is not used # thus it produce None grad that break apex if not isinstance(model, BertForSeqCls) or not isinstance(model, RobertaForSeqCls): param_optimizer = [n for n in param_optimizer if "pooler" not in n[0]] no_decay = ["bias", "LayerNorm.weight"] optimizer_grouped_parameters = [ { "params": [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)], "weight_decay": weight_decay, }, { "params": [p for n, p in param_optimizer if any(nd in n for nd in no_decay)], "weight_decay": 0.0, }, ] return optimizer_grouped_parameters def make_lr_scheduler(self, config, optimizer): lr_scheduler_type = getattr(config, "lr_scheduler_type", None) if lr_scheduler_type is None: return None lr_scheduler_config = getattr(config, lr_scheduler_type, {}) if type(lr_scheduler_config) == NestedNamespace: lr_scheduler_config = vars(lr_scheduler_config) if "warmup" in lr_scheduler_type: lr_scheduler_config["num_training_steps"] = config.num_train_steps self.set_warmup_steps(lr_scheduler_config) lr_scheduler_config["optimizer"] = optimizer lr_scheduler = get_lr_schedulers()[lr_scheduler_type](**lr_scheduler_config) if lr_scheduler_type == "reduce_on_plateau": lr_scheduler = LearningRateWithMetricsWrapper(lr_scheduler) else: lr_scheduler = LearningRateWithoutMetricsWrapper(lr_scheduler) return lr_scheduler def set_warmup_steps(self, lr_scheduler_config): warmup_proportion = lr_scheduler_config.get("warmup_proportion", None) warmup_steps = lr_scheduler_config.get("warmup_steps", None) total_steps = lr_scheduler_config["num_training_steps"] if warmup_steps and warmup_proportion: raise ValueError("Check 'warmup_steps' and 'warmup_proportion'.") elif not warmup_steps and warmup_proportion: lr_scheduler_config["num_warmup_steps"] = int(total_steps * warmup_proportion) + 1 del lr_scheduler_config["warmup_proportion"] elif warmup_steps and not warmup_proportion: # v2.11.0 change (argument name: warmup_steps -> num_warmup_steps) lr_scheduler_config["num_warmup_steps"] = warmup_steps del lr_scheduler_config["warmup_steps"] else: raise ValueError("Check 'warmup_steps' and 'warmup_proportion'.") ================================================ FILE: claf/factory/tokens.py ================================================ from overrides import overrides from claf.config.registry import Registry from claf.config.utils import convert_config2dict from claf.tokens import tokenizer from .base import Factory def make_tokenizer(tokenizer_cls, tokenizer_config, parent_tokenizers={}): if tokenizer_config is None or "name" not in tokenizer_config: return None package_name = tokenizer_config["name"] package_config = tokenizer_config.get(package_name, {}) tokenizer_config["config"] = package_config if package_name in tokenizer_config: del tokenizer_config[package_name] tokenizer_config.update(parent_tokenizers) return tokenizer_cls(**tokenizer_config) def make_all_tokenizers(all_tokenizer_config): """ Tokenizer is resource used all token together """ sent_tokenizer = make_tokenizer( tokenizer.SentTokenizer, all_tokenizer_config.get("sent", {"name": "punkt"}) ) word_tokenizer = make_tokenizer( tokenizer.WordTokenizer, all_tokenizer_config.get("word", None), parent_tokenizers={"sent_tokenizer": sent_tokenizer}, ) subword_tokenizer = make_tokenizer( tokenizer.SubwordTokenizer, all_tokenizer_config.get("subword", None), parent_tokenizers={"word_tokenizer": word_tokenizer}, ) char_tokenizer = make_tokenizer( tokenizer.CharTokenizer, all_tokenizer_config.get("char", None), parent_tokenizers={"word_tokenizer": word_tokenizer}, ) bpe_tokenizer = make_tokenizer( tokenizer.BPETokenizer, all_tokenizer_config.get("bpe", None), ) return { "bpe": bpe_tokenizer, "char": char_tokenizer, "subword": subword_tokenizer, "word": word_tokenizer, "sent": sent_tokenizer, } class TokenMakersFactory(Factory): """ TokenMakers Factory Class * Args: config: token config from argument (config.token) """ LANGS = ["eng", "kor"] def __init__(self): self.registry = Registry() @overrides def create(self, config): if getattr(config, "tokenizer", None): tokenizers = make_all_tokenizers(convert_config2dict(config.tokenizer)) else: tokenizers = {} token_names, token_types = config.names, config.types if len(token_names) != len(token_types): raise ValueError("token_names and token_types must be same length.") token_makers = {"tokenizers": tokenizers} for token_name, token_type in sorted(zip(token_names, token_types)): token_config = getattr(config, token_name, {}) if token_config != {}: token_config = convert_config2dict(token_config) # Token (tokenizer, indexer, embedding, vocab) token_config = { "tokenizers": tokenizers, "indexer_config": token_config.get("indexer", {}), "embedding_config": token_config.get("embedding", {}), "vocab_config": token_config.get("vocab", {}), } token_makers[token_name] = self.registry.get(f"token:{token_type}")(**token_config) return token_makers ================================================ FILE: claf/learn/__init__.py ================================================ ================================================ FILE: claf/learn/experiment.py ================================================ import atexit import logging from pathlib import Path import torch from claf import nsml from claf.factory import ( DataReaderFactory, DataLoaderFactory, TokenMakersFactory, ModelFactory, OptimizerFactory, ) from claf import utils as common_utils from claf.config.args import NestedNamespace from claf.config.utils import convert_config2dict, pretty_json_dumps, set_global_seed from claf.tokens.text_handler import TextHandler from claf.learn.mode import Mode from claf.learn.trainer import Trainer from claf.learn import utils logger = logging.getLogger(__name__) class Experiment: """ Experiment settings with config. * Args: mode: Mode (ex. TRAIN, EVAL, INFER_EVAL, PREDICT) config: (NestedNamespace) Argument config according to mode """ def __init__(self, mode, config): common_utils.set_logging_config(mode, config) self.argument = ( config ) # self.config (experiment overall config) / config (argument according to mode) self.config = config self.mode = mode self.common_setting(mode, config) if mode != Mode.TRAIN: # evaluate and predict self.load_setting() # Set evaluation config if mode.endswith(Mode.EVAL): self.config.data_reader.train_file_path = "" self.config.data_reader.valid_file_path = self.argument.data_file_path self.config.cuda_devices = self.argument.cuda_devices self.config.iterator.cuda_devices = self.argument.cuda_devices if getattr(self.argument, "inference_latency", None): self.config.max_latency = self.argument.inference_latency self.predict_settings = None def common_setting(self, mode, config): """ Common Setting - experiment config, use_gpu and cuda_device_ids """ self.config_dict = convert_config2dict(config) cuda_devices = self._get_cuda_devices() self.config.cuda_devices = cuda_devices self.config.slack_url = getattr(self.config, "slack_url", False) def _get_cuda_devices(self): if getattr(self.config, "use_gpu", None) is None: self.config.use_gpu = torch.cuda.is_available() or nsml.IS_ON_NSML if self.config.use_gpu: if nsml.IS_ON_NSML: return list(range(self.config.gpu_num)) else: return self.config.cuda_devices else: return None def load_setting(self): """ Load Setting - need to load checkpoint case (ex. evaluate and predict) """ cuda_devices = self.argument.cuda_devices checkpoint_path = self.argument.checkpoint_path prev_cuda_device_id = getattr(self.argument, "prev_cuda_device_id", None) self.model_checkpoint = self._read_checkpoint( cuda_devices, checkpoint_path, prev_cuda_device_id=prev_cuda_device_id ) self._set_saved_config(cuda_devices) def _read_checkpoint(self, cuda_devices, checkpoint_path, prev_cuda_device_id=None): if cuda_devices == "cpu": return torch.load(checkpoint_path, map_location="cpu") # use CPU if torch.cuda.is_available(): checkpoint = torch.load( checkpoint_path, map_location={ f"cuda:{prev_cuda_device_id}": f"cuda:{cuda_devices[0]}" }, # different cuda_device id case (save/load) ) else: checkpoint = torch.load(checkpoint_path, map_location="cpu") # use CPU return checkpoint def _set_saved_config(self, cuda_devices): saved_config_dict = self.model_checkpoint["config"] self.config_dict = saved_config_dict logger.info("Load saved_config ...") logger.info(pretty_json_dumps(saved_config_dict)) saved_config = NestedNamespace() saved_config.load_from_json(saved_config_dict) is_use_gpu = self.config.use_gpu self.config = saved_config self.config.use_gpu = is_use_gpu self.config.cuda_devices = cuda_devices def __call__(self): """ Run Trainer """ set_global_seed(self.config.seed_num) # For Reproducible if self.mode == Mode.TRAIN: # exit trigger slack notification if self.config.slack_url: atexit.register(utils.send_message_to_slack) train_loader, valid_loader, optimizer = self.set_train_mode() assert train_loader is not None assert optimizer is not None if valid_loader is None: self.trainer.train(train_loader, optimizer) else: self.trainer.train_and_evaluate(train_loader, valid_loader, optimizer) self._summary_experiments() elif self.mode == Mode.EVAL: valid_loader = self.set_eval_mode() assert valid_loader is not None return self.trainer.evaluate(valid_loader) elif self.mode == Mode.INFER_EVAL: raw_examples, raw_to_tensor_fn = self.set_eval_inference_latency_mode() assert raw_examples is not None assert raw_to_tensor_fn is not None return self.trainer.evaluate_inference_latency(raw_examples, raw_to_tensor_fn, max_latency=self.config.max_latency) elif self.mode.endswith(Mode.PREDICT): raw_features, raw_to_tensor_fn, arguments = self.set_predict_mode() assert raw_features is not None assert raw_to_tensor_fn is not None return self.trainer.predict( raw_features, raw_to_tensor_fn, arguments, interactive=arguments.get("interactive", False), ) else: raise ValueError(f"unknown mode: {self.mode}") def set_train_mode(self): """ Training Mode - Pipeline 1. read raw_data (DataReader) 2. build vocabs (DataReader, Token) 3. indexing tokens (DataReader, Token) 4. convert to DataSet (DataReader) 5. create DataLoader (DataLoader) 6. define model and optimizer 7. run! """ logger.info("Config. \n" + pretty_json_dumps(self.config_dict) + "\n") data_reader, token_makers = self._create_data_and_token_makers() datas, helpers = data_reader.read() # Token & Vocab text_handler = TextHandler(token_makers, lazy_indexing=True) if text_handler.is_all_vocab_use_pretrained(): token_counters = token_makers else: texts = data_reader.filter_texts(datas) token_counters = text_handler.make_token_counters(texts, config=self.config) vocabs = text_handler.build_vocabs(token_counters) text_handler.index(datas, data_reader.text_columns) # iterator vocab = vocabs[next(iter(vocabs))] datasets = data_reader.convert_to_dataset(datas, vocab, helpers=helpers) # with name self.config.iterator.cuda_devices = self.config.cuda_devices train_loader, valid_loader, test_loader = self._create_by_factory( DataLoaderFactory, self.config.iterator, param={"datasets": datasets} ) # calculate 'num_train_steps' num_train_steps = self._get_num_train_steps(train_loader) self.config.optimizer.num_train_steps = num_train_steps checkpoint_dir = Path(self.config.trainer.log_dir) / "checkpoint" checkpoints = None if checkpoint_dir.exists(): checkpoints = self._load_exist_checkpoints(checkpoint_dir) # contain model and optimizer if checkpoints is None: model = self._create_model(token_makers, helpers=helpers) op_dict = self._create_by_factory( OptimizerFactory, self.config.optimizer, param={"model": model} ) else: model = self._create_model(token_makers, checkpoint=checkpoints) op_dict = self._create_by_factory( OptimizerFactory, self.config.optimizer, param={"model": model} ) utils.load_optimizer_checkpoint(op_dict["optimizer"], checkpoints) self.set_trainer(model, op_dict=op_dict) return train_loader, valid_loader, op_dict["optimizer"] def _create_data_and_token_makers(self): token_makers = self._create_by_factory(TokenMakersFactory, self.config.token) tokenizers = token_makers["tokenizers"] del token_makers["tokenizers"] self.config.data_reader.tokenizers = tokenizers data_reader = self._create_by_factory(DataReaderFactory, self.config.data_reader) return data_reader, token_makers def _create_by_factory(self, factory_cls, item_config, param={}): factory_obj = factory_cls() return factory_obj.create(item_config, **param) def _get_num_train_steps(self, train_loader): train_set_size = len(train_loader.dataset) batch_size = self.config.iterator.batch_size gradient_accumulation_steps = getattr(self.config.optimizer, "gradient_accumulation_steps", 1) num_epochs = self.config.trainer.num_epochs one_epoch_steps = int(train_set_size / batch_size / gradient_accumulation_steps) if one_epoch_steps == 0: one_epoch_steps = 1 num_train_steps = one_epoch_steps * num_epochs return num_train_steps def _load_exist_checkpoints(self, checkpoint_dir): # pragma: no cover checkpoints = utils.get_sorted_path(checkpoint_dir, both_exist=True) train_counts = list(checkpoints.keys()) if not train_counts: return None seperator = "-" * 50 message = f"{seperator}\n !! Find exist checkpoints {train_counts}.\n If you want to recover, input train_count in list.\n If you don't want to recover, input 0.\n{seperator}" selected_train_count = common_utils.get_user_input(message) if selected_train_count == 0: return None model_path = checkpoints[selected_train_count]["model"] model_checkpoint = self._read_checkpoint(self.config.cuda_devices, model_path) optimizer_path = checkpoints[selected_train_count]["optimizer"] optimizer_checkpoint = self._read_checkpoint("cpu", optimizer_path) checkpoints = {} checkpoints.update(model_checkpoint) checkpoints.update(optimizer_checkpoint) return checkpoints def _create_model(self, token_makers, checkpoint=None, helpers=None): if checkpoint is None: assert helpers is not None first_key = next(iter(helpers)) helper = helpers[first_key] # get first helper model_init_params = helper.get("model", {}) predict_helper = helper.get("predict_helper", {}) else: model_init_params = checkpoint.get("init_params", {}) predict_helper = checkpoint.get("predict_helper", {}) model_params = {"token_makers": token_makers} model_params.update(model_init_params) model = self._create_by_factory( ModelFactory, self.config.model, param=model_params ) # Save params model.init_params = model_init_params model.predict_helper = predict_helper if checkpoint is not None: model = utils.load_model_checkpoint(model, checkpoint) model = self._set_gpu_env(model) return model def _set_gpu_env(self, model): if self.config.use_gpu: cuda_devices = self._get_cuda_devices() num_gpu = len(cuda_devices) use_multi_gpu = num_gpu > 1 if use_multi_gpu: model = torch.nn.DataParallel(model, device_ids=cuda_devices) model.cuda() else: num_gpu = 0 num_gpu_state = str(num_gpu) if num_gpu > 1: num_gpu_state += " (Multi-GPU)" # TODO: distributed training and 16-bits training (FP16) logger.info(f"use_gpu: {self.config.use_gpu} num_gpu: {num_gpu_state}, distributed training: False, 16-bits training: False") return model def set_trainer(self, model, op_dict={}, save_params={}): trainer_config = vars(self.config.trainer) trainer_config["config"] = self.config_dict trainer_config["model"] = model trainer_config["learning_rate_scheduler"] = op_dict.get("learning_rate_scheduler", None) trainer_config["exponential_moving_average"] = op_dict.get( "exponential_moving_average", None ) self.trainer = Trainer(**trainer_config) # Set NSML if nsml.IS_ON_NSML: utils.bind_nsml(model, optimizer=op_dict.get("optimizer", None)) if getattr(self.config.nsml, "pause", None): nsml.paused(scope=locals()) def _summary_experiments(self): hr_text = "-" * 50 summary_logs = f"\n\n\nExperiment Summary. {nsml.SESSION_NAME}\n{hr_text}\n" summary_logs += f"Config.\n{pretty_json_dumps(self.config_dict)}\n{hr_text}\n" summary_logs += ( f"Training Logs.\n{pretty_json_dumps(self.trainer.training_logs)}\n{hr_text}\n" ) summary_logs += f"Metric Logs.\n{pretty_json_dumps(self.trainer.metric_logs)}" logger.info(summary_logs) if self.config.slack_url: # pragma: no cover simple_summary_title = f"Session Name: {nsml.SESSION_NAME} " if getattr(self.config, "base_config", None): simple_summary_title += f"({self.config.base_config})" simple_summary_logs = f" - Dataset: {self.config.data_reader.dataset} \n" simple_summary_logs += f" - Model: {self.config.model.name}" best_metrics = {"epoch": self.trainer.metric_logs["best_epoch"]} best_metrics.update(self.trainer.metric_logs["best"]) simple_summary_logs += f" - Best metrics.\n {pretty_json_dumps(best_metrics)} " utils.send_message_to_slack(self.config.slack_url, title=simple_summary_title, message=simple_summary_logs) def set_eval_mode(self): """ Evaluate Mode - Pipeline 1. read raw_data (DataReader) 2. load vocabs from checkpoint (DataReader, Token) 3. indexing tokens (DataReader, Token) 4. convert to DataSet (DataReader) 5. create DataLoader (DataLoader) 6. define and load model 7. run! """ data_reader, token_makers = self._create_data_and_token_makers() # DataReader datas, helpers = data_reader.read() # Token & Vocab vocabs = utils.load_vocabs(self.model_checkpoint) for token_name, token_maker in token_makers.items(): token_maker.set_vocab(vocabs[token_name]) text_handler = TextHandler(token_makers, lazy_indexing=False) text_handler.index(datas, data_reader.text_columns) # iterator vocab = vocabs[next(iter(vocabs))] datasets = data_reader.convert_to_dataset(datas, vocab, helpers=helpers) # with name self.config.iterator.cuda_devices = self.config.cuda_devices _, valid_loader, _ = self._create_by_factory( DataLoaderFactory, self.config.iterator, param={"datasets": datasets} ) # Model model = self._create_model(token_makers, checkpoint=self.model_checkpoint) self.set_trainer(model) return valid_loader def set_eval_inference_latency_mode(self): """ Evaluate Inference Latency Mode - Pipeline 1. read raw_data (DataReader) 2. load vocabs from checkpoint (DataReader, Token) 3. define raw_to_tensor_fn (DataReader, Token) 4. define and load model 5. run! """ data_reader, token_makers = self._create_data_and_token_makers() # Token & Vocab vocabs = utils.load_vocabs(self.model_checkpoint) for token_name, token_maker in token_makers.items(): token_maker.set_vocab(vocabs[token_name]) text_handler = TextHandler(token_makers, lazy_indexing=False) _, helpers = data_reader.read() raw_examples = helpers["valid"]["examples"] cuda_device = self.config.cuda_devices[0] if self.config.use_gpu else None raw_to_tensor_fn = text_handler.raw_to_tensor_fn(data_reader, cuda_device=cuda_device) # Model model = self._create_model(token_makers, checkpoint=self.model_checkpoint) self.set_trainer(model) return raw_examples, raw_to_tensor_fn def predict(self, raw_features): if self.predict_settings is None: raise ValueError( "To use 'predict()', you must call 'set_predict_mode()' first, with preload=True parameter" ) raw_to_tensor_fn = self.predict_settings["raw_to_tensor_fn"] arguments = self.predict_settings["arguments"] arguments.update(raw_features) assert raw_features is not None assert raw_to_tensor_fn is not None return self.trainer.predict( raw_features, raw_to_tensor_fn, arguments, interactive=arguments.get("interactive", False), ) def set_predict_mode(self, preload=False): """ Predict Mode - Pipeline 1. read raw_data (Argument) 2. load vocabs from checkpoint (DataReader, Token) 3. define raw_to_tensor_fn (DataReader, Token) 4. define and load model 5. run! """ data_reader, token_makers = self._create_data_and_token_makers() # Token & Vocab vocabs = utils.load_vocabs(self.model_checkpoint) for token_name, token_maker in token_makers.items(): token_maker.set_vocab(vocabs[token_name]) text_handler = TextHandler(token_makers, lazy_indexing=False) # Set predict config if self.argument.interactive: raw_features = {feature_name: "" for feature_name in data_reader.text_columns} else: raw_features = {} for feature_name in data_reader.text_columns: feature = getattr(self.argument, feature_name, None) # if feature is None: # raise ValueError(f"--{feature_name} argument is required!") raw_features[feature_name] = feature cuda_device = self.config.cuda_devices[0] if self.config.use_gpu else None raw_to_tensor_fn = text_handler.raw_to_tensor_fn( data_reader, cuda_device=cuda_device, helper=self.model_checkpoint.get("predict_helper", {}) ) # Model model = self._create_model(token_makers, checkpoint=self.model_checkpoint) self.set_trainer(model) arguments = vars(self.argument) if preload: self.predict_settings = {"raw_to_tensor_fn": raw_to_tensor_fn, "arguments": arguments} else: return raw_features, raw_to_tensor_fn, arguments ================================================ FILE: claf/learn/mode.py ================================================ class Mode: """ Experiment Flag class """ TRAIN = "train" EVAL = "eval" INFER_EVAL = "infer_eval" PREDICT = "predict" MACHINE = "machine" ================================================ FILE: claf/learn/optimization/__init__.py ================================================ ================================================ FILE: claf/learn/optimization/exponential_moving_avarage.py ================================================ class EMA: """ Exponential Moving Average the moving averages of all weights of the model are maintained with the exponential decay rate of {ema}. * Args: model: for model's parameters mu: decay rate """ def __init__(self, model, mu): self.mu = mu self.shadow = {} for name, param in model.named_parameters(): if param.requires_grad: self.register(name, param.data) def register(self, name, val): self.shadow[name] = val.clone() def __call__(self, name, x): assert name in self.shadow new_average = self.mu * x + (1.0 - self.mu) * self.shadow[name] self.shadow[name] = new_average.clone() return new_average ================================================ FILE: claf/learn/optimization/learning_rate_scheduler.py ================================================ """ https://github.com/allenai/allennlp/blob/master/allennlp/training/learning_rate_schedulers.py """ from overrides import overrides from transformers import ( get_constant_schedule_with_warmup, get_linear_schedule_with_warmup, get_cosine_schedule_with_warmup, get_cosine_with_hard_restarts_schedule_with_warmup, ) import torch def get_lr_schedulers(): return { "step": torch.optim.lr_scheduler.StepLR, "multi_step": torch.optim.lr_scheduler.MultiStepLR, "exponential": torch.optim.lr_scheduler.ExponentialLR, "reduce_on_plateau": torch.optim.lr_scheduler.ReduceLROnPlateau, "cosine": torch.optim.lr_scheduler.CosineAnnealingLR, "noam": NoamLR, "warmup_constant": get_constant_schedule_with_warmup, "warmup_linear": get_linear_schedule_with_warmup, "warmup_consine": get_cosine_schedule_with_warmup, "warmup_consine_with_hard_restart": get_cosine_with_hard_restarts_schedule_with_warmup, } class LearningRateScheduler: def __init__(self, lr_scheduler): self.lr_scheduler = lr_scheduler def step(self, metric, epoch=None): raise NotImplementedError def step_batch(self, batch_num_total): if batch_num_total is not None: if hasattr(self.lr_scheduler, "step_batch"): self.lr_scheduler.step_batch(batch_num_total) return class LearningRateWithoutMetricsWrapper(LearningRateScheduler): """ A wrapper around learning rate schedulers that do not require metrics """ def __init__( self, lr_scheduler: torch.optim.lr_scheduler._LRScheduler ) -> None: # pylint: disable=protected-access super().__init__(lr_scheduler) self.lr_scheduler = lr_scheduler @overrides def step(self, metric, epoch=None): self.lr_scheduler.step(epoch) class LearningRateWithMetricsWrapper(LearningRateScheduler): """ A wrapper around learning rate schedulers that require metrics, At the moment there is only a single instance of this lrs. It is the ReduceLROnPlateau """ def __init__(self, lr_scheduler: torch.optim.lr_scheduler.ReduceLROnPlateau) -> None: super().__init__(lr_scheduler) self.lr_scheduler = lr_scheduler @overrides def step(self, metric, epoch=None): if metric is None: raise ValueError( "The reduce_on_plateau learning rate scheduler requires " "a validation metric to compute the schedule and therefore " "must be used with a validation dataset." ) self.lr_scheduler.step(metric, epoch) class NoamLR(torch.optim.lr_scheduler._LRScheduler): # pylint: disable=protected-access """ Implements the Noam Learning rate schedule. This corresponds to increasing the learning rate linearly for the first ``warmup_steps`` training steps, and decreasing it thereafter proportionally to the inverse square root of the step number, scaled by the inverse square root of the dimensionality of the model. Time will tell if this is just madness or it's actually important. Parameters ---------- model_size : ``int``, required. The hidden size parameter which dominates the number of parameters in your model. warmup_steps: ``int``, required. The number of steps to linearly increase the learning rate. factor : ``float``, optional (default = 1.0). The overall scale factor for the learning rate decay. """ def __init__( self, optimizer: torch.optim.Optimizer, model_size: int, warmup_steps: int, factor: float = 1.0, last_epoch: int = -1, ) -> None: self.warmup_steps = warmup_steps self.factor = factor self.model_size = model_size super().__init__(optimizer, last_epoch=last_epoch) def step(self, epoch=None): pass def step_batch(self, epoch=None): if epoch is None: epoch = self.last_epoch + 1 self.last_epoch = epoch for param_group, learning_rate in zip(self.optimizer.param_groups, self.get_lr()): param_group["lr"] = learning_rate def get_lr(self): step = max(self.last_epoch, 1) scale = self.factor * ( self.model_size ** (-0.5) * min(step ** (-0.5), step * self.warmup_steps ** (-1.5)) ) return [scale for _ in range(len(self.base_lrs))] ================================================ FILE: claf/learn/optimization/optimizer.py ================================================ from transformers import AdamW import torch def get_optimizer_by_name(name): optimizers = { "adam": torch.optim.Adam, "adamw": AdamW, "sparse_adam": torch.optim.SparseAdam, "adagrad": torch.optim.Adagrad, "adadelta": torch.optim.Adadelta, "sgd": torch.optim.SGD, "rmsprop": torch.optim.RMSprop, "adamax": torch.optim.Adamax, "averaged_sgd": torch.optim.ASGD, } if name in optimizers: return optimizers[name] else: raise ValueError(f"'{name}' is not registered. \noptimizer list: {list(optimizers.keys())}") ================================================ FILE: claf/learn/tensorboard.py ================================================ import os from tensorboardX import SummaryWriter from claf import nsml class TensorBoard: """ TensorBoard Wrapper for Pytorch """ def __init__(self, log_dir): if not os.path.exists(log_dir): os.makedirs(log_dir) self.writer = SummaryWriter(log_dir=log_dir) def scalar_summaries(self, step, summary): if nsml.IS_ON_NSML: if type(summary) != dict: raise ValueError(f"summary type is dict. not {type(summary)}") kwargs = {"summary": True, "scope": locals(), "step": step} kwargs.update(summary) nsml.report(**kwargs) else: for tag, value in summary.items(): self.scalar_summary(step, tag, value) def scalar_summary(self, step, tag, value): """Log a scalar variable.""" if nsml.IS_ON_NSML: nsml.report(**{"summary": True, "scope": locals(), "step": step, tag: value}) else: self.writer.add_scalar(tag, value, step) def image_summary(self, tag, images, step): """Log a list of images.""" raise NotImplementedError() def embedding_summary(self, features, metadata=None, label_img=None): raise NotImplementedError() def histogram_summary(self, tag, values, step, bins=1000): """Log a histogram of the tensor of values.""" raise NotImplementedError() def graph_summary(self, model, input_to_model=None): raise NotImplementedError() ================================================ FILE: claf/learn/trainer.py ================================================ # -*- coding: utf-8 -*- import json import logging import os import time import random import torch from torch.nn.utils import clip_grad_norm_ from tqdm import tqdm from claf import nsml from claf.config.utils import pretty_json_dumps from claf.learn.optimization.exponential_moving_avarage import EMA from claf.learn.tensorboard import TensorBoard from claf.learn import utils logger = logging.getLogger(__name__) class Trainer: """ Trainer Run experiment - train - train_and_evaluate - evaluate - evaluate_inference_latency - predict * Args: config: experiment overall config model: Model based on torch.nn.Module * Kwargs: log_dir: path to directory for save model and other options grad_max_norm: Clips gradient norm of an iterable of parameters. learning_rate_scheduler: PyTorch's Learning Rate Scheduler. (https://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html) exponential_moving_average: the moving averages of all weights of the model are maintained with the exponential decay rate of {ema}. num_epochs: the number of maximun epochs (Default is 20) early_stopping_threshold: the number of early stopping threshold (Default is 10) max_eval_examples: print evaluation examples metric_key: metric score's control point verbose_step_count: print verbose step count (Default is 100) eval_and_save_step_count: evaluate valid_dataset then save every n step_count (Default is 'epoch') """ def __init__( self, model, config={}, log_dir="logs/experiment", grad_max_norm=None, gradient_accumulation_steps=1, learning_rate_scheduler=None, exponential_moving_average=None, num_epochs=20, early_stopping_threshold=10, max_eval_examples=5, metric_key=None, verbose_step_count=100, eval_and_save_step_count="epoch", save_checkpoint=True, ): assert metric_key is not None # CUDA self.use_multi_gpu = type(model) == torch.nn.DataParallel if getattr(model, "train_counter", None): self.train_counter = model.train_counter else: self.train_counter = utils.TrainCounter(display_unit=eval_and_save_step_count) self.model = model model_config = config.get("model", {}) self.model_name = model_config.get("name", "model") self.set_model_base_properties(config, log_dir) # Logs os.makedirs(log_dir, exist_ok=True) self.tensorboard = TensorBoard(log_dir) self.metric_logs = {"best_epoch": 0, "best_global_step": 0, "best": None, "best_score": 0} self.training_logs = {"early_stopping_count": 0} # optimization options self.grad_max_norm = grad_max_norm if gradient_accumulation_steps is None: gradient_accumulation_steps = 1 self.gradient_accumulation_steps = gradient_accumulation_steps self.learning_rate_scheduler = learning_rate_scheduler self.exponential_moving_average = exponential_moving_average if exponential_moving_average: self.exponential_moving_average = EMA(model, self.exponential_moving_average) # property self.num_epochs = num_epochs self.early_stopping = False self.early_stopping_threshold = early_stopping_threshold self.max_eval_examples = max_eval_examples self.metric_key = metric_key self.verbose_step_count = verbose_step_count self.eval_and_save_step_count = eval_and_save_step_count self.save_checkpoint = save_checkpoint self.log_dir = log_dir def set_model_base_properties(self, config, log_dir): model = self.model if self.use_multi_gpu: model = self.model.module model.config = config model.log_dir = log_dir model.train_counter = self.train_counter assert model.is_ready() == True def train_and_evaluate(self, train_loader, valid_loader, optimizer): """ Train and Evaluate """ start_time = time.time() for epoch in range(1, self.num_epochs + 1): self.train_counter.epoch = epoch # Training with metrics train_metrics = self._run_epoch( train_loader, valid_loader=valid_loader, is_training=True, optimizer=optimizer, verbose_step_count=self.verbose_step_count, eval_and_save_step_count=self.eval_and_save_step_count, ) valid_metrics = None if self.eval_and_save_step_count == "epoch": with torch.no_grad(): valid_metrics = self._run_epoch(valid_loader, is_training=False) self._check_valid_results(valid_metrics, report=False) self.save(optimizer) self._report_metrics(train_metrics=train_metrics, valid_metrics=valid_metrics) self._estimate_remainig_time(start_time) if self.early_stopping: break self._report_trainings(start_time, train_loader=train_loader, valid_loader=valid_loader) def train(self, data_loader, optimizer): """ Train """ start_time = time.time() for epoch in range(1, self.num_epochs + 1): self.train_counter.epoch = epoch metrics = self._run_epoch( data_loader, is_training=True, optimizer=optimizer, verbose_step_count=self.verbose_step_count, ) self._report_metrics(train_metrics=metrics) self._estimate_remainig_time(start_time) self.save(optimizer) self._report_trainings(start_time, train_loader=data_loader) def evaluate(self, data_loader): """ Evaluate """ print("evaluate:", type(data_loader), data_loader) eval_metrics = self._run_epoch(data_loader, is_training=False, disable_prograss_bar=False) self._report_metrics(tensorboard=False, valid_metrics=eval_metrics) def evaluate_inference_latency(self, raw_examples, raw_to_tensor_fn, token_key=None, max_latency=1000): """ Evaluate with focusing inferece latency (Note: must use sorted synthetic data) * inference_latency: raw_data -> pre-processing -> model -> predict_value (elapsed_time) (elapsed_time) """ logger.info("\n# Evaluate Inference Latency Mode.") self.model.eval() total_raw_to_tensor_time = 0 tensor_to_predicts = [] raw_example_items = tqdm(raw_examples.items()) for _, raw_example in raw_example_items: # raw_data -> tensor raw_to_tensor_start_time = time.time() feature, helper = raw_to_tensor_fn(raw_example) raw_to_tensor_elapsted_time = time.time() - raw_to_tensor_start_time raw_to_tensor_elapsted_time *= 1000 # unit: sec -> ms total_raw_to_tensor_time += raw_to_tensor_elapsted_time # tensor to predict tensor_to_predict_start_time = time.time() output_dict = self.model(feature) tensor_to_predict_elapsed_time = time.time() - tensor_to_predict_start_time if "token_key" not in helper: raise ValueError( "helper must have 'token_key' data for 1-example inference latency." ) tensor_to_predict_elapsed_time *= 1000 # unit: sec -> ms tensor_to_predict = { "elapsed_time": tensor_to_predict_elapsed_time, "token_count": len(helper[helper["token_key"]]), } tensor_to_predicts.append(tensor_to_predict) if tensor_to_predict_elapsed_time > max_latency: raw_example_items.close() break total_tensor_to_predict = sum( [tensor_to_predict["elapsed_time"] for tensor_to_predict in tensor_to_predicts] ) max_token_count_per_times = {} max_times = list(range(0, max_latency+1, 100)) for t2p in sorted(tensor_to_predicts, key=lambda x: x["token_count"]): elapsed_time = t2p["elapsed_time"] token_count = t2p["token_count"] for max_time in max_times: if elapsed_time < max_time: max_token_count_per_times[max_time] = token_count result = { "average_raw_to_tensor": total_raw_to_tensor_time / len(raw_examples), "average_tensor_to_predict": total_tensor_to_predict / len(raw_examples), "average_end_to_end": (total_raw_to_tensor_time + total_tensor_to_predict) / len(raw_examples), "tensor_to_predicts": tensor_to_predicts, "max_token_count_per_time": max_token_count_per_times } env = "gpu" if torch.cuda.is_available() else "cpu" file_name = f"{self.model_name}-{env}.json" with open(file_name, "w") as f: json.dump(result, f, indent=4) logger.info(f"saved inference_latency results. {file_name}") def _is_early_stopping(self, metrics): score = metrics[self.metric_key] if score > self.metric_logs["best_score"]: self.training_logs["early_stopping_count"] = 0 else: self.training_logs["early_stopping_count"] += 1 if self.training_logs["early_stopping_count"] >= self.early_stopping_threshold: self.training_logs["early_stopping"] = True return True else: return False def _report_metrics(self, tensorboard=True, train_metrics=None, valid_metrics=None): total_metrics = {} def update_metrics(metrics, category=""): if metrics is not None: for k, v in metrics.items(): total_metrics[f"{category}/{k}"] = v update_metrics(train_metrics, "train") update_metrics(valid_metrics, "valid") # TensorBoard if tensorboard: self.tensorboard.scalar_summaries(self.train_counter.get_display(), total_metrics) # Console metric_console = "" if train_metrics: metric_console += ( f"\n# Epoch: [{self.train_counter.epoch}/{self.num_epochs}]: Metrics \n" ) metric_console += json.dumps(total_metrics, indent=4) logger.info(metric_console) if valid_metrics: self._update_metric_logs(total_metrics) def _update_metric_logs(self, total_metrics): for k, v in total_metrics.items(): if self.metric_logs.get(k, None) is None: self.metric_logs[k] = [v] else: self.metric_logs[k].append(v) valid_score = total_metrics.get(f"valid/{self.metric_key}", None) if valid_score and valid_score > self.metric_logs["best_score"]: logger.info(f" * Best validation score so far. ({self.metric_key}) : {valid_score}") self.metric_logs["best_score"] = valid_score self.metric_logs["best"] = total_metrics self.metric_logs["best_epoch"] = self.train_counter.epoch self.metric_logs["best_global_step"] = self.train_counter.global_step else: logger.info( f" * Current best validation score. ({self.metric_key}) : {self.metric_logs['best_score']}" ) def _estimate_remainig_time(self, start_time): elapsed_time = time.time() - start_time estimated_time_remaining = elapsed_time * ( (self.num_epochs - self.train_counter.epoch) / float(self.train_counter.epoch) - 1 ) formatted_time = time.strftime("%H:%M:%S", time.gmtime(estimated_time_remaining)) logger.info(f"Estimated training time remaining: {formatted_time} ") def _report_trainings(self, start_time, train_loader=None, valid_loader=None): elapsed_time = time.time() - start_time self.training_logs["elapsed_time"] = (time.strftime("%H:%M:%S", time.gmtime(elapsed_time)),) if train_loader is not None: self.training_logs["train_dataset"] = json.loads(str(train_loader.dataset)) if valid_loader is not None: self.training_logs["valid_dataset"] = json.loads(str(valid_loader.dataset)) def _run_epoch( self, data_loader, valid_loader=None, is_training=True, optimizer=None, disable_prograss_bar=True, verbose_step_count=100, eval_and_save_step_count=None, ): """ Run Epoch 1. forward inputs to model 2. (training) backpropagation 3. update predictions 4. make metrics """ if is_training: logger.info("# Train Mode.") self.model.train() else: logger.info("# Evaluate Mode.") self.model.eval() # set dataset (train/valid) self._set_dataset_to_model(data_loader.dataset) metrics = {} predictions = {} epoch_loss = 0 epoch_start_time = time.time() step_start_time = time.time() eval_example_count = 0 for step, batch in enumerate(tqdm(data_loader, disable=disable_prograss_bar)): inputs = batch.to_dict() # for DataParallel output_dict = self.model(**inputs) loss = output_dict["loss"] if self.use_multi_gpu: loss = loss.mean() if self.gradient_accumulation_steps > 1: loss = loss / self.gradient_accumulation_steps epoch_loss += loss.item() if is_training: # Training Verbose if self.train_counter.global_step == 0: logger.info(f" Start - Batch Loss: {loss.item():.5f}") if ( self.train_counter.global_step != 0 and self.train_counter.global_step % verbose_step_count == 0 ): step_elapsed_time = time.time() - step_start_time logger.info( f" Step: {self.train_counter.global_step} Batch Loss: {loss.item():.5f} {step_elapsed_time:.5f} sec" ) self.tensorboard.scalar_summary( self.train_counter.global_step, "train/batch_loss", loss.item() ) step_start_time = time.time() loss.backward() if self.grad_max_norm: clip_grad_norm_(self._get_model_parameters(), self.grad_max_norm) if (step + 1) % self.gradient_accumulation_steps == 0: # Backpropagation if self.learning_rate_scheduler: self.learning_rate_scheduler.step_batch(self.train_counter.global_step) optimizer.step() optimizer.zero_grad() self.train_counter.global_step += 1 if self.exponential_moving_average: for name, param in self.model.named_parameters(): if param.requires_grad: param.data = self.exponential_moving_average(name, param.data) # Evaluate then Save checkpoint if ( valid_loader and type(eval_and_save_step_count) == int and self.train_counter.global_step % eval_and_save_step_count == 0 ): with torch.no_grad(): valid_metrics = self._run_epoch(valid_loader, is_training=False) self._check_valid_results(valid_metrics, report=True) self.save(optimizer) if is_training: # roll-back to train mode self.model.train() self._set_dataset_to_model(data_loader.dataset) else: if eval_example_count < self.max_eval_examples: total_step_count = int(len(data_loader) / data_loader.batch_size) random_num = random.randint(0, total_step_count) if random_num <= self.max_eval_examples: eval_example_predictions = {} self._update_predictions(eval_example_predictions, output_dict) random_index = random.randint(0, data_loader.batch_size) self._print_examples(random_index, inputs, eval_example_predictions) eval_example_count += 1 self._update_predictions(predictions, output_dict) epoch_loss /= len(data_loader) epoch_elapsed_time = time.time() - epoch_start_time logger.info("Epoch duration: " + time.strftime("%H:%M:%S", time.gmtime(epoch_elapsed_time))) # Updat metrics metrics["loss"] = epoch_loss metrics["epoch_time"] = epoch_elapsed_time metrics.update(self._make_metrics(predictions)) # model metric return metrics def _set_dataset_to_model(self, dataset): if self.use_multi_gpu: self.model.module.dataset = dataset else: self.model.dataset = dataset def _get_model_parameters(self): if self.use_multi_gpu: return self.model.module.parameters() else: return self.model.parameters() def _check_valid_results(self, metrics, report=False): if self.learning_rate_scheduler: # The LRScheduler API is agnostic to whether your schedule requires a validation metric - # if it doesn't, the validation metric passed here is ignored. this_epoch_val_metric = metrics[self.metric_key] self.learning_rate_scheduler.step(this_epoch_val_metric, self.train_counter.global_step) if self._is_early_stopping(metrics): self.early_stopping = True logger.info(" --- Early Stopping. --- ") if report: self._report_metrics(valid_metrics=metrics) def _make_metrics(self, predictions): model = self.model if self.use_multi_gpu: model = model.module model.train_counter = self.train_counter return model.make_metrics(predictions) def _update_predictions(self, predictions, output_dict): if self.use_multi_gpu: predictions.update(self.model.module.make_predictions(output_dict)) else: predictions.update(self.model.make_predictions(output_dict)) def _print_examples(self, index, inputs, predictions): try: if self.use_multi_gpu: self.model.module.print_examples(index, inputs, predictions) else: self.model.print_examples(index, inputs, predictions) except IndexError: pass def predict(self, raw_feature, raw_to_tensor_fn, arguments, interactive=False): """ Inference / Predict """ self.model.eval() with torch.no_grad(): if interactive: # pragma: no cover while True: for k in raw_feature: raw_feature[k] = utils.get_user_input(k) tensor_feature, helper = raw_to_tensor_fn(raw_feature) output_dict = self.model(tensor_feature) arguments.update(raw_feature) predict = self.model.predict(output_dict, arguments, helper) print(f"Predict: {pretty_json_dumps(predict)} \n") else: tensor_feature, helper = raw_to_tensor_fn(raw_feature) output_dict = self.model(tensor_feature) return self.model.predict(output_dict, arguments, helper) def save(self, optimizer): if not self.save_checkpoint: return # set all config to model model = self.model if self.use_multi_gpu: model = self.model.module model.train_counter = self.train_counter model.metrics = self.metric_logs if nsml.IS_ON_NSML: nsml.save(self.train_counter.get_display()) else: utils.save_checkpoint(self.log_dir, model, optimizer) ================================================ FILE: claf/learn/utils.py ================================================ from collections import OrderedDict import json import logging from pathlib import Path import os import re import torch from torch.nn import DataParallel import requests from claf import nsml from claf.tokens.vocabulary import Vocab logger = logging.getLogger(__name__) """ Train Counter """ class TrainCounter: global_step = 0 epoch = 0 def __init__(self, display_unit="epoch"): if type(display_unit) == int: display_unit = f"every_{display_unit}_global_step" self.display_unit = display_unit def get_display(self): if self.display_unit == "epoch": return self.epoch else: return self.global_step """ Save and Load checkpoint """ def load_model_checkpoint(model, checkpoint): model.load_state_dict(checkpoint["weights"]) model.config = checkpoint["config"] model.metrics = checkpoint["metrics"] model.init_params = checkpoint["init_params"] model.predict_helper = checkpoint["predict_helper"] model.train_counter = checkpoint["train_counter"] model.vocabs = load_vocabs(checkpoint) logger.info(f"Load model checkpoints...!") return model def load_optimizer_checkpoint(optimizer, checkpoint): optimizer.load_state_dict(checkpoint["optimizer"]) logger.info(f"Load optimizer checkpoints...!") return optimizer def load_vocabs(model_checkpoint): vocabs = {} token_config = model_checkpoint["config"]["token"] for token_name in token_config["names"]: token = token_config[token_name] vocab_config = token.get("vocab", {}) texts = model_checkpoint["vocab_texts"][token_name] vocabs[token_name] = Vocab(token_name, **vocab_config).from_texts(texts) return vocabs def save_checkpoint(path, model, optimizer, max_to_keep=10): path = Path(path) checkpoint_dir = path / "checkpoint" checkpoint_dir.mkdir(exist_ok=True) # Remove old checkpoints sorted_path = get_sorted_path(checkpoint_dir) if len(sorted_path) > max_to_keep: remove_train_counts = list(sorted_path.keys())[: -(max_to_keep - 1)] for train_count in remove_train_counts: optimizer_path = sorted_path[train_count].get("optimizer", None) if optimizer_path: os.remove(optimizer_path) model_path = sorted_path[train_count].get("model", None) if model_path: os.remove(model_path) train_counter = model.train_counter optimizer_path = checkpoint_dir / f"optimizer_{train_counter.get_display()}.pkl" torch.save({"optimizer": optimizer.state_dict()}, optimizer_path) model_path = checkpoint_dir / f"model_{train_counter.get_display()}.pkl" torch.save( { "config": model.config, "init_params": model.init_params, "predict_helper": model.predict_helper, "metrics": model.metrics, "train_counter": model.train_counter, "vocab_texts": {k: v.to_text() for k, v in model.vocabs.items()}, "weights": model.state_dict(), }, model_path, ) # Write Vocab as text file (Only once) vocab_dir = path / "vocab" vocab_dir.mkdir(exist_ok=True) for token_name, vocab in model.vocabs.items(): vocab_path = vocab_dir / f"{token_name}.txt" if not vocab_path.exists(): vocab.dump(vocab_path) logger.info(f"Save {train_counter.global_step} global_step checkpoints...!") def get_sorted_path(checkpoint_dir, both_exist=False): paths = [] for root, dirs, files in os.walk(checkpoint_dir): for f_name in files: if "model" in f_name or "optimizer" in f_name: paths.append(Path(root) / f_name) path_with_train_count = {} for path in paths: train_count = re.findall("\d+", path.name)[0] train_count = int(train_count) if train_count not in path_with_train_count: path_with_train_count[train_count] = {} if "model" in path.name: path_with_train_count[train_count]["model"] = path if "optimizer" in path.name: path_with_train_count[train_count]["optimizer"] = path if both_exist: remove_keys = [] for key, checkpoint in path_with_train_count.items(): if not ("model" in checkpoint and "optimizer" in checkpoint): remove_keys.append(key) for key in remove_keys: del path_with_train_count[key] return OrderedDict(sorted(path_with_train_count.items())) """ NSML """ def bind_nsml(model, **kwargs): # pragma: no cover if type(model) == DataParallel: model = model.module CHECKPOINT_FNAME = "checkpoint.bin" def infer(raw_data, **kwargs): print("raw_data:", raw_data) def load(dir_path, *args): checkpoint_path = os.path.join(dir_path, CHECKPOINT_FNAME) checkpoint = torch.load(checkpoint_path) model.load_state_dict(checkpoint["weights"]) model.config = checkpoint["config"] model.metrics = checkpoint["metrics"] model.init_params = checkpoint["init_params"], model.predict_helper = checkpoint["predict_helper"], model.train_counter = checkpoint["train_counter"] model.vocabs = load_vocabs(checkpoint) if "optimizer" in kwargs: kwargs["optimizer"].load_state_dict(checkpoint["optimizer"]) logger.info(f"Load checkpoints...! {checkpoint_path}") def save(dir_path, *args): # save the model with 'checkpoint' dictionary. checkpoint_path = os.path.join(dir_path, CHECKPOINT_FNAME) checkpoint = { "config": model.config, "init_params": model.init_params, "predict_helper": model.predict_helper, "metrics": model.metrics, "train_counter": model.train_counter, "vocab_texts": {k: v.to_text() for k, v in model.vocabs.items()}, "weights": model.state_dict(), } if "optimizer" in kwargs: checkpoint["optimizer"] = kwargs["optimizer"].state_dict() torch.save(checkpoint, checkpoint_path) train_counter = model.train_counter logger.info(f"Save {train_counter.global_step} global_step checkpoints...! {checkpoint_path}") # function in function is just used to divide the namespace. nsml.bind(save, load, infer) """ Notification """ def get_session_name(): session_name = "local" if nsml.IS_ON_NSML: session_name = nsml.SESSION_NAME return session_name def send_message_to_slack(webhook_url, title=None, message=None): # pragma: no cover if message is None: data = {"text": f"{get_session_name()} session is exited."} else: data = {"attachments": [{"title": title, "text": message, "color": "#438C56"}]} try: if webhook_url == "": print(data["text"]) else: requests.post(webhook_url, data=json.dumps(data)) except Exception as e: print(str(e)) ================================================ FILE: claf/machine/__init__.py ================================================ from claf.machine.open_qa import OpenQA from claf.machine.nlu import NLU # fmt: off __all__ = [ "OpenQA", "NLU", ] # fmt: on ================================================ FILE: claf/machine/base.py ================================================ from argparse import Namespace import json from claf.config.namespace import NestedNamespace from claf.config.registry import Registry from claf.learn.experiment import Experiment from claf.learn.mode import Mode from claf.machine.module import Module class Machine: """ Machine: Combine modules then make a NLP Machine * Args: config: machine_config """ def __init__(self, config): self.config = config self.registry = Registry() def load(self): raise NotImplementedError("") @classmethod def load_from_config(cls, config_path): with open(config_path, "r", encoding="utf-8") as in_file: machine_config = NestedNamespace() machine_config.load_from_json(json.load(in_file)) machine_name = machine_config.name config = getattr(machine_config, machine_name, {}) return cls(config) def __call__(self, text): raise NotImplementedError("") def make_module(self, config): """ Make component or experiment for claf Machine's module * Args: - config: module's config (claf.config.namespace.NestedNamespace) """ module_type = config.type if module_type == Module.COMPONENT: name = config.name module_config = getattr(config, name, {}) if isinstance(module_config, Namespace): module_config = vars(module_config) if getattr(config, "params", None): module_config.update(config.params) return self.registry.get(f"component:{name}")(**module_config) elif module_type == Module.EXPERIMENT: experiment_config = Namespace() experiment_config.checkpoint_path = config.checkpoint_path experiment_config.cuda_devices = getattr(config, "cuda_devices", None) experiment_config.interactive = False experiment = Experiment(Mode.PREDICT, experiment_config) experiment.set_predict_mode(preload=True) return experiment else: raise ValueError( f"module_type is available only [component|experiment]. not '{module_type}'" ) ================================================ FILE: claf/machine/components/__init__.py ================================================ from claf.machine.components.retrieval.tfidf import TFIDF # fmt: off __all__ = [ "TFIDF", # Retrieval ] # fmt: on ================================================ FILE: claf/machine/components/retrieval/__init__.py ================================================ ================================================ FILE: claf/machine/components/retrieval/tfidf.py ================================================ from pathlib import Path from gensim.corpora import Dictionary from gensim.models import TfidfModel from gensim.similarities import MatrixSimilarity, SparseMatrixSimilarity from tqdm import tqdm from claf.decorator import register @register("component:tfidf") class TFIDF: """ TF-IDF document retrieval model - Term Frequency - Inverse Document Frequency - log(tf + 1) * log((N - Nt + 0.5) / (Nt + 0.5)) * Kwargs: k: the number of top k results """ VOCAB_FNAME = "vocab.txt" TFIDF_FNAME = "tfidf.model" INDEX_FNAME = "similarities.index" def __init__(self, texts, word_tokenizer, k=1): super(TFIDF, self).__init__() self.k = k self.texts = texts self.word_tokenizer = word_tokenizer def init(self): corpus = [ self.word_tokenizer.tokenize(text) for text in tqdm(self.texts, desc="make corpus (Tokenize)") ] self.vocab = Dictionary(corpus) self.init_model() def init_model(self): corpus = [] for text in tqdm(self.texts, desc="make corpus (BoW)"): corpus.append(self.parse(text)) self.model = TfidfModel(corpus) self.index = SparseMatrixSimilarity(self.model[corpus], num_features=len(self.vocab)) def get_closest(self, query): query_tfidf = self.text_to_tfidf(query) self.index.num_best = self.k results = self.index[query_tfidf] return [ (text_index, self.texts[text_index], score) # return (index, text, score) for (text_index, score) in results ] def parse(self, query, ngram=1): query_tokens = self.word_tokenizer.tokenize(query) return self.vocab.doc2bow(query_tokens) def text_to_tfidf(self, query): """ Create a tfidf-weighted word vector from query. tfidf = log(tf + 1) * log((N - Nt + 0.5) / (Nt + 0.5)) """ query_bow = self.parse(query) return self.model[query_bow] def save(self, dir_path): dir_path = Path(dir_path) dir_path.mkdir(parents=True, exist_ok=True) vocab_path = str(dir_path / self.VOCAB_FNAME) model_path = str(dir_path / self.TFIDF_FNAME) index_path = str(dir_path / self.INDEX_FNAME) self.vocab.save(vocab_path) self.model.save(model_path) self.index.save(index_path) def load(self, dir_path): dir_path = Path(dir_path) vocab_path = str(dir_path / self.VOCAB_FNAME) model_path = str(dir_path / self.TFIDF_FNAME) index_path = str(dir_path / self.INDEX_FNAME) self.vocab = Dictionary.load(vocab_path) self.model = TfidfModel.load(model_path) self.index = SparseMatrixSimilarity.load(index_path) ================================================ FILE: claf/machine/ensemble_topk.py ================================================ from functools import reduce # Valid in Python 2.6+, required in Python 3 import logging import json import operator from overrides import overrides from tqdm import tqdm from claf.data.data_handler import CachePath, DataHandler from claf.decorator import register from claf.machine.base import Machine from claf.metric.korquad_v1_official import evaluate, metric_max_over_ground_truths, f1_score, normalize_answer logger = logging.getLogger(__name__) @register("machine:mrc_ensemble") class MRCEnsemble(Machine): """ Machine Reading Comprehension Ensemble * Args: config: machine_config """ def __init__(self, config): super(MRCEnsemble, self).__init__(config) self.data_handler = DataHandler(CachePath.MACHINE / "mrc_ensemble") self.load() @overrides def load(self): mrc_config = self.config.reading_comprehension # Model 1 - BERT-Kor self.rc_experiment1 = self.make_module(mrc_config.model_1) print("BERT-Kor ready ..! \n") # # Model 2 - BERT-Multilingual # self.rc_experiment2 = self.make_module(mrc_config.model_2) # print("BERT-Multilingual ready ..! \n") # # Model 3 - DocQA # self.rc_experiment3 = self.make_module(mrc_config.model_3) # print("DocQA ready ..! \n") # # Model 4 - DrQA # self.rc_experiment4 = self.make_module(mrc_config.model_4) # print("DrQA ready ..! \n") print("All ready ..! \n") def evaluate(self, file_path, output_path): # KorQuAD dataset... # def get_answer_after_clustering(predictions): # categories = {} # for l1 in predictions: # l1_text = l1["text"] # l1_text_normalized = normalize_answer(l1_text) # categories[l1_text] = { # "items": [], # "score": 0 # } # for l2 in predictions: # l2_text = l2["text"] # l2_text_normalized = normalize_answer(l2_text) # if l1_text_normalized in l2_text_normalized: # categories[l1_text]["items"].append(l2) # categories[l1_text]["score"] += l2["score"] # # # count items then score * 1.n # # for k, v in categories.items(): # # ratio = 1 + (len(v["items"]) / 10) # # v["score"] *= ratio # highest_category = [categories[c] for c in sorted(categories, key=lambda x: categories[x]["score"], reverse=True)][0] # answer_text = sorted(highest_category["items"], key=lambda x: x["score"], reverse=True)[0]["text"] # return answer_text # def get_answer_after_clustering_marginal(predictions): # categories = {} # for l1 in predictions: # l1_text = l1["text"] # l1_text_normalized = normalize_answer(l1_text) # categories[l1_text] = { # "items": [], # "score": 0 # } # for l2 in predictions: # l2_text = l2["text"] # l2_text_normalized = normalize_answer(l2_text) # if l1_text_normalized in l2_text_normalized: # categories[l1_text]["items"].append(l2) # categories[l1_text]["score"] *= l2["score"] # else: # categories[l1_text]["score"] *= 0.01 # Default value # # count items then score * 1.n # for k, v in categories.items(): # ratio = 1 + (len(v["items"]) / 10) # v["score"] *= ratio # highest_category = [categories[c] for c in sorted(categories, key=lambda x: categories[x]["score"], reverse=True)][0] # answer_text = sorted(highest_category["items"], key=lambda x: x["score"], reverse=True)[0]["text"] # return answer_text # def post_processing(text): # # detach josa # # josas = ['은', '는', '이', '가', '을', '를', '과', '와', '이다', '다', '으로', '로', '의', '에'] # josas = ["는", "를", "이다", "으로", "에", "이라고", "라고", "와의", "인데"] # for josa in josas: # if text.endswith(josa): # text = text[:-len(josa)] # break # # temperature # if text.endswith("°"): # text += "C" # # etc # special_cases = ["(", ",", "였", "."] # for s in special_cases: # if text.endswith(s): # text = text[:-len(s)] # return text def _clean_text(text): # https://github.com/allenai/document-qa/blob/2f9fa6878b60ed8a8a31bcf03f802cde292fe48b/docqa/data_processing/text_utils.py#L124 # be consistent with quotes, and replace \u2014 and \u2212 which I have seen being mapped to UNK # by glove word vecs return ( text.replace("''", '"') .replace("``", '"') .replace("\u2212", "-") .replace("\u2014", "\u2013") ) predictions = {} topk_predictions = {} print("Read input_data...") data = self.data_handler.read(file_path) squad = json.loads(data) if "data" in squad: squad = squad["data"] wrong_count = 0 print("Start predict 1-examples...") for article in tqdm(squad): for paragraph in article["paragraphs"]: context = paragraph["context"] for qa in paragraph["qas"]: question = qa["question"] id_ = qa["id"] # Marginal probabilities... # prediction = self.get_predict_with_marginal(context, question) prediction = self.get_predict(context, question) # print("prediction count:", len(prediction)) topk_predictions[id_] = prediction predictions[id_] = prediction[0]["text"] # answer_texts = [q["text"] for q in qa["answers"]] # # 1. Highest value # sorted_prediction = sorted(prediction, key=lambda x: x["score"], reverse=True) # prediction_text = sorted_prediction[0]["text"] # 2. Cluster by text # prediction_text = get_answer_after_clustering_marginal(prediction) # prediction_text = post_processing(prediction_text) # predictions[id_] = prediction_text # if prediction_text not in answer_texts: # pred_f1_score = metric_max_over_ground_truths(f1_score, prediction_text, answer_texts) # if pred_f1_score <= 0.5: # sorted_prediction = sorted(prediction, key=lambda x: x["score"], reverse=True) # print("predict:", json.dumps(sorted_prediction[:5], indent=4, ensure_ascii=False)) # print("predict_text:", prediction_text) # print("answers:", qa["answers"], "f1:", pred_f1_score) # print("-"*50) # wrong_count += 1 # is_answer = False # for pred in prediction: # if pred["text"] in answer_texts: # predictions[id_] = pred["text"] # is_answer = True # break # if not is_answer: # prediction_text = sorted(prediction, key=lambda x: x["score"], reverse=True)[0]["text"] # predictions[id_] = prediction_text # print("predict:", prediction) # print("predict_text:", prediction_text) # print("answers:", qa["answers"]) # print("-"*50) # wrong_count += 1 print("total_count:", len(predictions), "wrong_count:", wrong_count) print("Completed...!") with open(output_path, "w") as out_file: out_file.write(json.dumps(topk_predictions, indent=4) + "\n") # Evaluate with open(file_path) as dataset_file: dataset_json = json.load(dataset_file) dataset = dataset_json if "data" in dataset: dataset = dataset["data"] # with open(output_path) as prediction_file: # predictions = json.load(prediction_file) results = evaluate(dataset, predictions) print(json.dumps(results)) def get_predict(self, context, question): raw_feature = {"context": context, "question": question} # print(raw_feature) # Approach 1. Max Prob models = [ (self.rc_experiment1, 0.94), # (self.rc_experiment2, 0.90) # (self.rc_experiment3, 0.85), # (self.rc_experiment4, 0.84), ] # models = [self.rc_experiment3, self.rc_experiment4] model = models[0][0] return sorted(model.predict(raw_feature), key=lambda x: x["score"], reverse=True) ================================================ FILE: claf/machine/knowlege_base/__init__.py ================================================ ================================================ FILE: claf/machine/knowlege_base/docs.py ================================================ import json import logging import os from tqdm import tqdm logger = logging.getLogger(__name__) def read_wiki_articles(dir_path): """ WikiExtractor's output like below: (https://github.com/attardi/wikiextractor) wiki_path/ - AA - wiki_00 - wiki_01 ... - AB ... """ dir_paths = get_subdir_paths(dir_path) all_file_path = [] for path in dir_paths: all_file_path += get_file_paths(path) articles = [] for path in tqdm(all_file_path, desc="Read Wiki Articles"): articles += read_wiki_article(path) return articles def get_subdir_paths(dir_path): dir_paths = [] for path, subdirs, __ in os.walk(dir_path): for dir_name in subdirs: dir_paths.append(os.path.join(path, dir_name)) return dir_paths def get_file_paths(dir_path): file_paths = [] for path, _, files in os.walk(dir_path): for file_name in files: file_paths.append(os.path.join(path, file_name)) return file_paths def read_wiki_article(file_path): """ Wiki articles format (WikiExtractor) => {"id": "", "revid": "", "url":"", "title": "", "text": "..."} """ articles = [] with open(file_path, "r", encoding="utf-8") as in_file: for line in in_file.readlines(): article = json.loads(line) articles.append(article) return [WikiArticle(**article) for article in articles] class WikiArticle: # pragma: no cover def __init__(self, id=None, url=None, title=None, text=None): self._id = id self._url = url self._title = title self._text = text @property def id(self): return self._id @id.setter def id(self, id): self._id = id @property def url(self): return self._url @url.setter def url(self, url): self._url = url @property def title(self): return self._title @title.setter def title(self, title): self._title = title @property def text(self): return self._text @text.setter def text(self, text): self._text = text ================================================ FILE: claf/machine/module.py ================================================ class Module: """ Machine Flag class """ KNOWLEDGE_BASE = "knowledge_base" COMPONENT = "component" EXPERIMENT = "experiment" ================================================ FILE: claf/machine/nlu.py ================================================ import logging from overrides import overrides from claf.data.data_handler import CachePath, DataHandler from claf.decorator import register from claf.machine.base import Machine logger = logging.getLogger(__name__) @register("machine:nlu") class NLU(Machine): """ Natural Language Understanding Machine * Args: config: machine_config """ def __init__(self, config): super(NLU, self).__init__(config) self.data_handler = DataHandler(CachePath.MACHINE / "nlu") self.load() @overrides def load(self): # NLU # - Intent Classification Experiment # - Slot Filling Experiment nlu_config = self.config.nlu self.ic_experiment = self.make_module(nlu_config.intent) self.sf_experiment = self.make_module(nlu_config.slots) print("Ready ..! \n") @overrides def __call__(self, utterance): nlu_result = dict() intent_info = self.intent_classification(utterance) nlu_result.update({"intent": intent_info["class_text"]}) slots_info = self.slot_filling(utterance) nlu_result.update({"slots": slots_info["tag_dict"]}) return nlu_result def intent_classification(self, utterance): raw_feature = {"sequence": utterance} return self.ic_experiment.predict(raw_feature) def slot_filling(self, utterance): raw_feature = {"sequence": utterance} return self.sf_experiment.predict(raw_feature) ================================================ FILE: claf/machine/open_qa.py ================================================ import logging import os from overrides import overrides from claf.config.utils import convert_config2dict from claf.data.data_handler import CachePath, DataHandler from claf.decorator import register from claf.factory.tokens import make_all_tokenizers from claf.machine.base import Machine from claf.machine.knowlege_base.docs import read_wiki_articles logger = logging.getLogger(__name__) @register("machine:open_qa") class OpenQA(Machine): """ Open-Domain Question Answer Machine (DrQA) DrQA is a system for reading comprehension applied to open-domain question answering. * Args: config: machine_config """ def __init__(self, config): super(OpenQA, self).__init__(config) self.data_handler = DataHandler(CachePath.MACHINE / "open_qa") self.load() @overrides def load(self): # Tokenizers tokenizers_config = convert_config2dict(self.config.tokenizers) tokenizers = make_all_tokenizers(tokenizers_config) # Knowledge Base # - Wiki knowledge_base_config = self.config.knowledge_base self.docs, doc_name = self._load_knowledge_base(knowledge_base_config) # Reasoning # - Document Retrieval # - Reading Comprehension Experiment reasoning_config = self.config.reasoning self.document_retrieval = self._load_document_retrieval( reasoning_config.document_retrieval, tokenizers["word"], basename=doc_name ) self.rc_experiment = self.make_module(reasoning_config.reading_comprehension) print("Ready ..! \n") def _load_knowledge_base(self, config): docs = read_wiki_articles(config.wiki) # TODO: fix read whole wiki doc_name = f"{os.path.basename(config.wiki)}-{len(docs)}-articles" return docs, doc_name def _load_document_retrieval(self, config, word_tokenizer, basename="docs"): dir_path = f"doc-{config.type}-{config.name}-{word_tokenizer.cache_name}" doc_retrieval_path = os.path.join(dir_path, basename) config.params = { "texts": [doc.title for doc in self.docs], "word_tokenizer": word_tokenizer, } document_retrieval = self.make_module(config) doc_retrieval_path = self.data_handler.convert_cache_path(doc_retrieval_path) if doc_retrieval_path.exists(): document_retrieval.load(doc_retrieval_path) else: print("Start Document Retrieval Indexing ...") document_retrieval.init() document_retrieval.save(doc_retrieval_path) # Save Cache print("Completed!") return document_retrieval @overrides def __call__(self, question): result_docs = self.search_documents(question) print("-" * 50) print("Doc Scores:") for doc in result_docs: print(f" - {doc[1]} : {doc[2]}") print("-" * 50) passages = [] for result_doc in result_docs: doc_index = result_doc[0] doc = self.docs[doc_index] passages.append(doc.text) answers = [] for passage in passages: answer_text = self.machine_reading(passage, question) answers.append(answer_text) ranked_answers = sorted(answers, key=lambda x: x["score"], reverse=True) return ranked_answers def search_documents(self, question): return self.document_retrieval.get_closest(question) def machine_reading(self, context, question): raw_feature = {"context": context, "question": question} return self.rc_experiment.predict(raw_feature) ================================================ FILE: claf/metric/__init__.py ================================================ ================================================ FILE: claf/metric/classification.py ================================================ def recall(pycm_obj): return {key: pycm_obj.TPR[key] if pycm_obj.TPR[key] != "None" else 0. for key in pycm_obj.TPR} def precision(pycm_obj): return {key: pycm_obj.PPV[key] if pycm_obj.PPV[key] != "None" else 0. for key in pycm_obj.PPV} def f1(pycm_obj): return {key: pycm_obj.F1[key] if pycm_obj.F1[key] != "None" else 0. for key in pycm_obj.F1} def macro_recall(pycm_obj): return sum(recall(pycm_obj).values()) / len(pycm_obj.classes) def macro_precision(pycm_obj): return sum(precision(pycm_obj).values()) / len(pycm_obj.classes) def macro_f1(pycm_obj): return sum(f1(pycm_obj).values()) / len(pycm_obj.classes) ================================================ FILE: claf/metric/glue.py ================================================ import numpy as np from scipy.stats import pearsonr, spearmanr from sklearn.metrics import matthews_corrcoef, f1_score def simple_accuracy(preds, labels): preds = np.array(preds) labels = np.array(labels) return (preds == labels).mean() def f1(preds, labels): return { "f1": f1_score(y_true=labels, y_pred=preds) } def matthews_corr(preds, labels): return { "matthews_corr": matthews_corrcoef(labels, preds), } def pearson_and_spearman(preds, labels): pearson_corr = pearsonr(preds, labels)[0] spearman_corr = spearmanr(preds, labels)[0] if pearson_corr == "": pearson_corr = 0 if spearman_corr == "": spearman_corr = 0 return { "pearson": pearson_corr, "spearmanr": spearman_corr, "pearson_spearman_corr": (pearson_corr + spearman_corr) / 2, } ================================================ FILE: claf/metric/korquad_v1_official.py ================================================ from __future__ import print_function from collections import Counter import string import re import argparse import json import sys '''KorQuAD v1.0에 대한 공식 평가 스크립트 ''' '''본 스크립트는 SQuAD v1.1 평가 스크립트 https://rajpurkar.github.io/SQuAD-explorer/ 를 바탕으로 작성됨.''' def normalize_answer(s): def remove_(text): ''' 불필요한 기호 제거 ''' text = re.sub("'", " ", text) text = re.sub('"', " ", text) text = re.sub('《', " ", text) text = re.sub('》', " ", text) text = re.sub('<', " ", text) text = re.sub('>', " ", text) text = re.sub('〈', " ", text) text = re.sub('〉', " ", text) text = re.sub("\(", " ", text) text = re.sub("\)", " ", text) text = re.sub("‘", " ", text) text = re.sub("’", " ", text) return text def white_space_fix(text): return ' '.join(text.split()) def remove_punc(text): exclude = set(string.punctuation) return ''.join(ch for ch in text if ch not in exclude) def lower(text): return text.lower() return white_space_fix(remove_punc(lower(remove_(s)))) def f1_score(prediction, ground_truth): prediction_tokens = normalize_answer(prediction).split() ground_truth_tokens = normalize_answer(ground_truth).split() #F1 by character prediction_Char = [] for tok in prediction_tokens: now = [a for a in tok] prediction_Char.extend(now) ground_truth_Char = [] for tok in ground_truth_tokens: now = [a for a in tok] ground_truth_Char.extend(now) common = Counter(prediction_Char) & Counter(ground_truth_Char) num_same = sum(common.values()) if num_same == 0: return 0 precision = 1.0 * num_same / len(prediction_Char) recall = 1.0 * num_same / len(ground_truth_Char) f1 = (2 * precision * recall) / (precision + recall) return f1 def exact_match_score(prediction, ground_truth): return (normalize_answer(prediction) == normalize_answer(ground_truth)) def metric_max_over_ground_truths(metric_fn, prediction, ground_truths): scores_for_ground_truths = [] for ground_truth in ground_truths: score = metric_fn(prediction, ground_truth) scores_for_ground_truths.append(score) return max(scores_for_ground_truths) def evaluate(dataset, predictions): f1 = exact_match = total = 0 for article in dataset: for paragraph in article['paragraphs']: for qa in paragraph['qas']: total += 1 if qa['id'] not in predictions: message = 'Unanswered question ' + qa['id'] + \ ' will receive score 0.' print(message, file=sys.stderr) continue ground_truths = list(map(lambda x: x['text'], qa['answers'])) prediction = predictions[qa['id']] exact_match += metric_max_over_ground_truths( exact_match_score, prediction, ground_truths) f1 += metric_max_over_ground_truths( f1_score, prediction, ground_truths) exact_match = 100.0 * exact_match / total f1 = 100.0 * f1 / total return {'em': exact_match, 'f1': f1} if __name__ == '__main__': expected_version = 'KorQuAD_v1.0' parser = argparse.ArgumentParser( description='Evaluation for KorQuAD ' + expected_version) parser.add_argument('dataset_file', help='Dataset file') parser.add_argument('prediction_file', help='Prediction File') args = parser.parse_args() with open(args.dataset_file) as dataset_file: dataset_json = json.load(dataset_file) read_version = "_".join(dataset_json['version'].split("_")[:-1]) if (read_version != expected_version): print('Evaluation expects ' + expected_version + ', but got dataset with ' + read_version, file=sys.stderr) dataset = dataset_json['data'] with open(args.prediction_file) as prediction_file: predictions = json.load(prediction_file) print(json.dumps(evaluate(dataset, predictions))) ================================================ FILE: claf/metric/regression.py ================================================ import numpy as np def mse(outputs, labels): if type(outputs) == list: outputs = np.array(outputs) if type(labels) == list: labels = np.array(labels) # read prediction and compute result if outputs.ndim != 1: outputs = outputs.reshape(-1) if labels.ndim != 1: labels = labels.reshape(-1) return np.square(labels.astype(np.float32) - outputs).sum() ================================================ FILE: claf/metric/squad_v1_official.py ================================================ """ Official evaluation script for v1.1 of the SQuAD dataset. """ from __future__ import print_function from collections import Counter import string import re import argparse import json import sys def normalize_answer(s): # pragma: no cover """Lower text and remove punctuation, articles and extra whitespace.""" def remove_articles(text): return re.sub(r"\b(a|an|the)\b", " ", text) def white_space_fix(text): return " ".join(text.split()) def remove_punc(text): exclude = set(string.punctuation) return "".join(ch for ch in text if ch not in exclude) def lower(text): return text.lower() return white_space_fix(remove_articles(remove_punc(lower(s)))) def f1_score(prediction, ground_truth): # pragma: no cover prediction_tokens = normalize_answer(prediction).split() ground_truth_tokens = normalize_answer(ground_truth).split() common = Counter(prediction_tokens) & Counter(ground_truth_tokens) num_same = sum(common.values()) if num_same == 0: return 0 precision = 1.0 * num_same / len(prediction_tokens) recall = 1.0 * num_same / len(ground_truth_tokens) f1 = (2 * precision * recall) / (precision + recall) return f1 def exact_match_score(prediction, ground_truth): # pragma: no cover return normalize_answer(prediction) == normalize_answer(ground_truth) def metric_max_over_ground_truths(metric_fn, prediction, ground_truths): # pragma: no cover scores_for_ground_truths = [] for ground_truth in ground_truths: score = metric_fn(prediction, ground_truth) scores_for_ground_truths.append(score) return max(scores_for_ground_truths) def evaluate(dataset, predictions): f1 = exact_match = total = 0 for article in dataset: for paragraph in article["paragraphs"]: for qa in paragraph["qas"]: total += 1 if qa["id"] not in predictions: message = "Unanswered question " + qa["id"] + " will receive score 0." print(message, file=sys.stderr) continue ground_truths = list(map(lambda x: x["text"], qa["answers"])) prediction = predictions[qa["id"]] exact_match += metric_max_over_ground_truths( exact_match_score, prediction, ground_truths ) f1 += metric_max_over_ground_truths(f1_score, prediction, ground_truths) exact_match = 100.0 * exact_match / total f1 = 100.0 * f1 / total return {"em": exact_match, "f1": f1} if __name__ == "__main__": # pragma: no cover expected_version = "1.1" parser = argparse.ArgumentParser(description="Evaluation for SQuAD " + expected_version) parser.add_argument("dataset_file", help="Dataset file") parser.add_argument("prediction_file", help="Prediction File") args = parser.parse_args() with open(args.dataset_file) as dataset_file: dataset_json = json.load(dataset_file) if dataset_json["version"] != expected_version: print( "Evaluation expects v-" + expected_version + ", but got dataset with v-" + dataset_json["version"], file=sys.stderr, ) dataset = dataset_json["data"] with open(args.prediction_file) as prediction_file: predictions = json.load(prediction_file) print(json.dumps(evaluate(dataset, predictions))) ================================================ FILE: claf/metric/squad_v2_official.py ================================================ """Official evaluation script for SQuAD version 2.0. In addition to basic functionality, we also compute additional statistics and plot precision-recall curves if an additional na_prob.json file is provided. This file is expected to map question ID's to the model's predicted probability that a question is unanswerable. """ import argparse import collections import json import numpy as np import os import re import string import sys OPTS = None def parse_args(): # pragma: no cover parser = argparse.ArgumentParser("Official evaluation script for SQuAD version 2.0.") parser.add_argument("data_file", metavar="data.json", help="Input data JSON file.") parser.add_argument("pred_file", metavar="pred.json", help="Model predictions.") parser.add_argument( "--out-file", "-o", metavar="eval.json", help="Write accuracy metrics to file (default is stdout).", ) parser.add_argument( "--na-prob-file", "-n", metavar="na_prob.json", help="Model estimates of probability of no answer.", ) parser.add_argument( "--na-prob-thresh", "-t", type=float, default=1.0, help='Predict "" if no-answer probability exceeds this (default = 1.0).', ) parser.add_argument( "--out-image-dir", "-p", metavar="out_images", default=None, help="Save precision-recall curves to directory.", ) parser.add_argument("--verbose", "-v", action="store_true") if len(sys.argv) == 1: parser.print_help() sys.exit(1) return parser.parse_args() def make_qid_to_has_ans(dataset): # pragma: no cover qid_to_has_ans = {} for article in dataset: for p in article["paragraphs"]: for qa in p["qas"]: qid_to_has_ans[qa["id"]] = bool(qa["answers"]) return qid_to_has_ans def normalize_answer(s): # pragma: no cover """Lower text and remove punctuation, articles and extra whitespace.""" def remove_articles(text): regex = re.compile(r"\b(a|an|the)\b", re.UNICODE) return re.sub(regex, " ", text) def white_space_fix(text): return " ".join(text.split()) def remove_punc(text): exclude = set(string.punctuation) return "".join(ch for ch in text if ch not in exclude) def lower(text): return text.lower() return white_space_fix(remove_articles(remove_punc(lower(s)))) def get_tokens(s): # pragma: no cover if not s: return [] return normalize_answer(s).split() def compute_exact(a_gold, a_pred): # pragma: no cover return int(normalize_answer(a_gold) == normalize_answer(a_pred)) def compute_f1(a_gold, a_pred): # pragma: no cover gold_toks = get_tokens(a_gold) pred_toks = get_tokens(a_pred) common = collections.Counter(gold_toks) & collections.Counter(pred_toks) num_same = sum(common.values()) if len(gold_toks) == 0 or len(pred_toks) == 0: # If either is no-answer, then F1 is 1 if they agree, 0 otherwise return int(gold_toks == pred_toks) if num_same == 0: return 0 precision = 1.0 * num_same / len(pred_toks) recall = 1.0 * num_same / len(gold_toks) f1 = (2 * precision * recall) / (precision + recall) return f1 def get_raw_scores(dataset, preds): # pragma: no cover exact_scores = {} f1_scores = {} for article in dataset: for p in article["paragraphs"]: for qa in p["qas"]: qid = qa["id"] gold_answers = [a["text"] for a in qa["answers"] if normalize_answer(a["text"])] if not gold_answers: # For unanswerable questions, only correct answer is empty # string gold_answers = [""] if qid not in preds: # print('Missing prediction for %s' % qid) continue a_pred = preds[qid] # Take max over all gold answers exact_scores[qid] = max(compute_exact(a, a_pred) for a in gold_answers) f1_scores[qid] = max(compute_f1(a, a_pred) for a in gold_answers) return exact_scores, f1_scores def apply_no_ans_threshold(scores, na_probs, qid_to_has_ans, na_prob_thresh): # pragma: no cover new_scores = {} for qid, s in scores.items(): pred_na = na_probs[qid] > na_prob_thresh if pred_na: new_scores[qid] = float(not qid_to_has_ans[qid]) else: new_scores[qid] = s return new_scores def make_eval_dict(exact_scores, f1_scores, qid_list=None): # pragma: no cover if not qid_list: total = len(exact_scores) return collections.OrderedDict( [ ("exact", 100.0 * sum(exact_scores.values()) / total), ("f1", 100.0 * sum(f1_scores.values()) / total), ("total", total), ] ) else: total = len(qid_list) return collections.OrderedDict( [ ("exact", 100.0 * sum(exact_scores[k] for k in qid_list) / total), ("f1", 100.0 * sum(f1_scores[k] for k in qid_list) / total), ("total", total), ] ) def merge_eval(main_eval, new_eval, prefix): # pragma: no cover for k in new_eval: main_eval["%s_%s" % (prefix, k)] = new_eval[k] def plot_pr_curve(precisions, recalls, out_image, title): # pragma: no cover plt.step(recalls, precisions, color="b", alpha=0.2, where="post") plt.fill_between(recalls, precisions, step="post", alpha=0.2, color="b") plt.xlabel("Recall") plt.ylabel("Precision") plt.xlim([0.0, 1.05]) plt.ylim([0.0, 1.05]) plt.title(title) plt.savefig(out_image) plt.clf() def make_precision_recall_eval( scores, na_probs, num_true_pos, qid_to_has_ans, out_image=None, title=None ): # pragma: no cover qid_list = sorted(na_probs, key=lambda k: na_probs[k]) true_pos = 0.0 cur_p = 1.0 cur_r = 0.0 precisions = [1.0] recalls = [0.0] avg_prec = 0.0 for i, qid in enumerate(qid_list): if qid_to_has_ans[qid]: true_pos += scores[qid] cur_p = true_pos / float(i + 1) cur_r = true_pos / float(num_true_pos) if i == len(qid_list) - 1 or na_probs[qid] != na_probs[qid_list[i + 1]]: # i.e., if we can put a threshold after this point avg_prec += cur_p * (cur_r - recalls[-1]) precisions.append(cur_p) recalls.append(cur_r) if out_image: plot_pr_curve(precisions, recalls, out_image, title) return {"ap": 100.0 * avg_prec} def run_precision_recall_analysis( main_eval, exact_raw, f1_raw, na_probs, qid_to_has_ans, out_image_dir ): # pragma: no cover if out_image_dir and not os.path.exists(out_image_dir): os.makedirs(out_image_dir) num_true_pos = sum(1 for v in qid_to_has_ans.values() if v) if num_true_pos == 0: return pr_exact = make_precision_recall_eval( exact_raw, na_probs, num_true_pos, qid_to_has_ans, out_image=os.path.join(out_image_dir, "pr_exact.png"), title="Precision-Recall curve for Exact Match score", ) pr_f1 = make_precision_recall_eval( f1_raw, na_probs, num_true_pos, qid_to_has_ans, out_image=os.path.join(out_image_dir, "pr_f1.png"), title="Precision-Recall curve for F1 score", ) oracle_scores = {k: float(v) for k, v in qid_to_has_ans.items()} pr_oracle = make_precision_recall_eval( oracle_scores, na_probs, num_true_pos, qid_to_has_ans, out_image=os.path.join(out_image_dir, "pr_oracle.png"), title="Oracle Precision-Recall curve (binary task of HasAns vs. NoAns)", ) merge_eval(main_eval, pr_exact, "pr_exact") merge_eval(main_eval, pr_f1, "pr_f1") merge_eval(main_eval, pr_oracle, "pr_oracle") def histogram_na_prob(na_probs, qid_list, image_dir, name): # pragma: no cover if not qid_list: return x = [na_probs[k] for k in qid_list] weights = np.ones_like(x) / float(len(x)) plt.hist(x, weights=weights, bins=20, range=(0.0, 1.0)) plt.xlabel("Model probability of no-answer") plt.ylabel("Proportion of dataset") plt.title("Histogram of no-answer probability: %s" % name) plt.savefig(os.path.join(image_dir, "na_prob_hist_%s.png" % name)) plt.clf() def find_best_thresh(preds, scores, na_probs, qid_to_has_ans): # pragma: no cover num_no_ans = sum(1 for k in qid_to_has_ans if not qid_to_has_ans[k]) cur_score = num_no_ans best_score = cur_score best_thresh = 0.0 qid_list = sorted(na_probs, key=lambda k: na_probs[k]) for i, qid in enumerate(qid_list): if qid not in scores: continue if qid_to_has_ans[qid]: diff = scores[qid] else: if preds[qid]: diff = -1 else: diff = 0 cur_score += diff if cur_score > best_score: best_score = cur_score best_thresh = na_probs[qid] return 100.0 * best_score / len(scores), best_thresh def find_all_best_thresh( main_eval, preds, exact_raw, f1_raw, na_probs, qid_to_has_ans ): # pragma: no cover best_exact, exact_thresh = find_best_thresh(preds, exact_raw, na_probs, qid_to_has_ans) best_f1, f1_thresh = find_best_thresh(preds, f1_raw, na_probs, qid_to_has_ans) main_eval["best_exact"] = best_exact main_eval["best_exact_thresh"] = exact_thresh main_eval["best_f1"] = best_f1 main_eval["best_f1_thresh"] = f1_thresh def evaluate(dataset, na_probs, preds, na_prob_thresh=1.0): qid_to_has_ans = make_qid_to_has_ans(dataset) # maps qid to True/False has_ans_qids = [k for k, v in qid_to_has_ans.items() if v] no_ans_qids = [k for k, v in qid_to_has_ans.items() if not v] exact_raw, f1_raw = get_raw_scores(dataset, preds) exact_thresh = apply_no_ans_threshold(exact_raw, na_probs, qid_to_has_ans, na_prob_thresh) f1_thresh = apply_no_ans_threshold(f1_raw, na_probs, qid_to_has_ans, na_prob_thresh) out_eval = make_eval_dict(exact_thresh, f1_thresh) if has_ans_qids: has_ans_eval = make_eval_dict(exact_thresh, f1_thresh, qid_list=has_ans_qids) merge_eval(out_eval, has_ans_eval, "HasAns") if no_ans_qids: no_ans_eval = make_eval_dict(exact_thresh, f1_thresh, qid_list=no_ans_qids) merge_eval(out_eval, no_ans_eval, "NoAns") find_all_best_thresh(out_eval, preds, exact_raw, f1_raw, na_probs, qid_to_has_ans) return out_eval def main(): # pragma: no cover with open(OPTS.data_file) as f: dataset_json = json.load(f) dataset = dataset_json["data"] with open(OPTS.pred_file) as f: preds = json.load(f) if OPTS.na_prob_file: with open(OPTS.na_prob_file) as f: na_probs = json.load(f) else: na_probs = {k: 0.0 for k in preds} qid_to_has_ans = make_qid_to_has_ans(dataset) # maps qid to True/False has_ans_qids = [k for k, v in qid_to_has_ans.items() if v] no_ans_qids = [k for k, v in qid_to_has_ans.items() if not v] exact_raw, f1_raw = get_raw_scores(dataset, preds) exact_thresh = apply_no_ans_threshold(exact_raw, na_probs, qid_to_has_ans, OPTS.na_prob_thresh) f1_thresh = apply_no_ans_threshold(f1_raw, na_probs, qid_to_has_ans, OPTS.na_prob_thresh) out_eval = make_eval_dict(exact_thresh, f1_thresh) if has_ans_qids: has_ans_eval = make_eval_dict(exact_thresh, f1_thresh, qid_list=has_ans_qids) merge_eval(out_eval, has_ans_eval, "HasAns") if no_ans_qids: no_ans_eval = make_eval_dict(exact_thresh, f1_thresh, qid_list=no_ans_qids) merge_eval(out_eval, no_ans_eval, "NoAns") if OPTS.na_prob_file: find_all_best_thresh(out_eval, preds, exact_raw, f1_raw, na_probs, qid_to_has_ans) if OPTS.na_prob_file and OPTS.out_image_dir: run_precision_recall_analysis( out_eval, exact_raw, f1_raw, na_probs, qid_to_has_ans, OPTS.out_image_dir ) histogram_na_prob(na_probs, has_ans_qids, OPTS.out_image_dir, "hasAns") histogram_na_prob(na_probs, no_ans_qids, OPTS.out_image_dir, "noAns") if OPTS.out_file: with open(OPTS.out_file, "w") as f: json.dump(out_eval, f) else: print(json.dumps(out_eval, indent=2)) if __name__ == "__main__": # pragma: no cover OPTS = parse_args() if OPTS.out_image_dir: import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt main() ================================================ FILE: claf/metric/wikisql_lib/__init__.py ================================================ ================================================ FILE: claf/metric/wikisql_lib/dbengine.py ================================================ import records import re from babel.numbers import parse_decimal, NumberFormatError from claf.metric.wikisql_lib.query import Query schema_re = re.compile(r'\((.+)\)') num_re = re.compile(r'[-+]?\d*\.\d+|\d+') class DBEngine: # pragma: no cover def __init__(self, fdb): self.db = records.Database('sqlite:///{}'.format(fdb)) self.conn = self.db.get_connection() def execute_query(self, table_id, query, *args, **kwargs): return self.execute(table_id, query.sel_index, query.agg_index, query.conditions, *args, **kwargs) def execute(self, table_id, select_index, aggregation_index, conditions, lower=True): if not table_id.startswith('table'): table_id = 'table_{}'.format(table_id.replace('-', '_')) table_info = self.conn.query('SELECT sql from sqlite_master WHERE tbl_name = :name', name=table_id).all()[0].sql schema_str = schema_re.findall(table_info)[0] schema = {} for tup in schema_str.split(', '): c, t = tup.split() schema[c] = t select = 'col{}'.format(select_index) agg = Query.agg_ops[aggregation_index] if agg: select = '{}({})'.format(agg, select) where_clause = [] where_map = {} for col_index, op, val in conditions: if lower and isinstance(val, str): val = val.lower() if schema['col{}'.format(col_index)] == 'real' and not isinstance(val, (int, float)): try: val = float(parse_decimal(val)) except NumberFormatError as e: val = float(num_re.findall(val)[0]) where_clause.append('col{} {} :col{}'.format(col_index, Query.cond_ops[op], col_index)) where_map['col{}'.format(col_index)] = val where_str = '' if where_clause: where_str = 'WHERE ' + ' AND '.join(where_clause) query = 'SELECT {} AS result FROM {} {}'.format(select, table_id, where_str) out = self.conn.query(query, **where_map) return [o.result for o in out] ================================================ FILE: claf/metric/wikisql_lib/query.py ================================================ from collections import defaultdict from copy import deepcopy import re re_whitespace = re.compile(r"\s+", flags=re.UNICODE) def detokenize(tokens): # pragma: no cover ret = "" for g, a in zip(tokens["gloss"], tokens["after"]): ret += g + a return ret.strip() class Query: # pragma: no cover agg_ops = ["", "MAX", "MIN", "COUNT", "SUM", "AVG"] cond_ops = ["=", ">", "<", "OP"] syms = [ "SELECT", "WHERE", "AND", "COL", "TABLE", "CAPTION", "PAGE", "SECTION", "OP", "COND", "QUESTION", "AGG", "AGGOPS", "CONDOPS", ] def __init__(self, sel_index, agg_index, conditions=tuple(), ordered=False): self.sel_index = sel_index self.agg_index = agg_index self.conditions = list(conditions) self.ordered = ordered def __eq__(self, other): if isinstance(other, self.__class__): indices = self.sel_index == other.sel_index and self.agg_index == other.agg_index if other.ordered: conds = [(col, op, str(cond).lower()) for col, op, cond in self.conditions] == [ (col, op, str(cond).lower()) for col, op, cond in other.conditions ] else: conds = set( [(col, op, str(cond).lower()) for col, op, cond in self.conditions] ) == set([(col, op, str(cond).lower()) for col, op, cond in other.conditions]) return indices and conds return NotImplemented def __ne__(self, other): if isinstance(other, self.__class__): return not self.__eq__(other) return NotImplemented def __hash__(self): return hash(tuple(sorted(self.__dict__.items()))) def __repr__(self): rep = "SELECT {agg} {sel} FROM table".format( agg=self.agg_ops[self.agg_index], sel="col{}".format(self.sel_index) ) if self.conditions: rep += " WHERE " + " AND ".join( [ "{} {} {}".format("col{}".format(i), self.cond_ops[o], v) for i, o, v in self.conditions ] ) return rep def to_dict(self): return {"sel": self.sel_index, "agg": self.agg_index, "conds": self.conditions} def lower(self): conds = [] for col, op, cond in self.conditions: conds.append([col, op, cond.lower()]) return self.__class__(self.sel_index, self.agg_index, conds) @classmethod def from_dict(cls, d, ordered=False): return cls(sel_index=d["sel"], agg_index=d["agg"], conditions=d["conds"], ordered=ordered) @classmethod def from_tokenized_dict(cls, d): conds = [] for col, op, val in d["conds"]: conds.append([col, op, detokenize(val)]) return cls(d["sel"], d["agg"], conds) @classmethod def from_generated_dict(cls, d): conds = [] for col, op, val in d["conds"]: end = len(val["words"]) conds.append([col, op, detokenize(val)]) return cls(d["sel"], d["agg"], conds) @classmethod def from_sequence(cls, sequence, table, lowercase=True): sequence = deepcopy(sequence) if "symend" in sequence["words"]: end = sequence["words"].index("symend") for k, v in sequence.items(): sequence[k] = v[:end] terms = [ {"gloss": g, "word": w, "after": a} for g, w, a in zip(sequence["gloss"], sequence["words"], sequence["after"]) ] headers = [detokenize(h) for h in table["header"]] # lowercase everything and truncate sequence if lowercase: headers = [h.lower() for h in headers] for i, t in enumerate(terms): for k, v in t.items(): t[k] = v.lower() headers_no_whitespcae = [re.sub(re_whitespace, "", h) for h in headers] # get select if "symselect" != terms.pop(0)["word"]: raise Exception("Missing symselect operator") # get aggregation if "symagg" != terms.pop(0)["word"]: raise Exception("Missing symagg operator") agg_op = terms.pop(0)["word"] if agg_op == "symcol": agg_op = "" else: if "symcol" != terms.pop(0)["word"]: raise Exception("Missing aggregation column") try: agg_op = cls.agg_ops.index(agg_op.upper()) except Exception as e: raise Exception("Invalid agg op {}".format(agg_op)) def find_column(name): return headers_no_whitespcae.index(re.sub(re_whitespace, "", name)) def flatten(tokens): ret = {"words": [], "after": [], "gloss": []} for t in tokens: ret["words"].append(t["word"]) ret["after"].append(t["after"]) ret["gloss"].append(t["gloss"]) return ret where_index = [i for i, t in enumerate(terms) if t["word"] == "symwhere"] where_index = where_index[0] if where_index else len(terms) flat = flatten(terms[:where_index]) try: agg_col = find_column(detokenize(flat)) except Exception as e: raise Exception("Cannot find aggregation column {}".format(flat["words"])) where_terms = terms[where_index + 1 :] # get conditions conditions = [] while where_terms: t = where_terms.pop(0) flat = flatten(where_terms) if t["word"] != "symcol": raise Exception("Missing conditional column {}".format(flat["words"])) try: op_index = flat["words"].index("symop") col_tokens = flatten(where_terms[:op_index]) except Exception as e: raise Exception("Missing conditional operator {}".format(flat["words"])) cond_op = where_terms[op_index + 1]["word"] try: cond_op = cls.cond_ops.index(cond_op.upper()) except Exception as e: raise Exception("Invalid cond op {}".format(cond_op)) try: cond_col = find_column(detokenize(col_tokens)) except Exception as e: raise Exception("Cannot find conditional column {}".format(col_tokens["words"])) try: val_index = flat["words"].index("symcond") except Exception as e: raise Exception("Cannot find conditional value {}".format(flat["words"])) where_terms = where_terms[val_index + 1 :] flat = flatten(where_terms) val_end_index = ( flat["words"].index("symand") if "symand" in flat["words"] else len(where_terms) ) cond_val = detokenize(flatten(where_terms[:val_end_index])) conditions.append([cond_col, cond_op, cond_val]) where_terms = where_terms[val_end_index + 1 :] q = cls(agg_col, agg_op, conditions) return q @classmethod def from_partial_sequence(cls, agg_col, agg_op, sequence, table, lowercase=True): sequence = deepcopy(sequence) if "symend" in sequence["words"]: end = sequence["words"].index("symend") for k, v in sequence.items(): sequence[k] = v[:end] terms = [ {"gloss": g, "word": w, "after": a} for g, w, a in zip(sequence["gloss"], sequence["words"], sequence["after"]) ] headers = [detokenize(h) for h in table["header"]] # lowercase everything and truncate sequence if lowercase: headers = [h.lower() for h in headers] for i, t in enumerate(terms): for k, v in t.items(): t[k] = v.lower() headers_no_whitespcae = [re.sub(re_whitespace, "", h) for h in headers] def find_column(name): return headers_no_whitespcae.index(re.sub(re_whitespace, "", name)) def flatten(tokens): ret = {"words": [], "after": [], "gloss": []} for t in tokens: ret["words"].append(t["word"]) ret["after"].append(t["after"]) ret["gloss"].append(t["gloss"]) return ret where_index = [i for i, t in enumerate(terms) if t["word"] == "symwhere"] where_index = where_index[0] if where_index else len(terms) where_terms = terms[where_index + 1 :] # get conditions conditions = [] while where_terms: t = where_terms.pop(0) flat = flatten(where_terms) if t["word"] != "symcol": raise Exception("Missing conditional column {}".format(flat["words"])) try: op_index = flat["words"].index("symop") col_tokens = flatten(where_terms[:op_index]) except Exception as e: raise Exception("Missing conditional operator {}".format(flat["words"])) cond_op = where_terms[op_index + 1]["word"] try: cond_op = cls.cond_ops.index(cond_op.upper()) except Exception as e: raise Exception("Invalid cond op {}".format(cond_op)) try: cond_col = find_column(detokenize(col_tokens)) except Exception as e: raise Exception("Cannot find conditional column {}".format(col_tokens["words"])) try: val_index = flat["words"].index("symcond") except Exception as e: raise Exception("Cannot find conditional value {}".format(flat["words"])) where_terms = where_terms[val_index + 1 :] flat = flatten(where_terms) val_end_index = ( flat["words"].index("symand") if "symand" in flat["words"] else len(where_terms) ) cond_val = detokenize(flatten(where_terms[:val_end_index])) conditions.append([cond_col, cond_op, cond_val]) where_terms = where_terms[val_end_index + 1 :] q = cls(agg_col, agg_op, conditions) return q ================================================ FILE: claf/metric/wikisql_official.py ================================================ """ Official evaluation script for WikiSQL dataset. """ import json from argparse import ArgumentParser from tqdm import tqdm from claf.metric.wikisql_lib.dbengine import DBEngine from claf.metric.wikisql_lib.query import Query def count_lines(fname): # pragma: no cover with open(fname) as f: return sum(1 for line in f) def evaluate(labels, predictions, db_path, ordered=True): # pragma: no cover """ labels and predictions: dictionary {data_uid: sql_data, ...} """ engine = DBEngine(db_path) exact_match, grades = [], [] for idx, data_uid in enumerate(predictions): eg = labels[data_uid] ep = predictions[data_uid] qg = eg["sql_query"] gold = eg["execution_result"] pred = ep.get("error", None) qp = None if not ep.get("error", None): try: qp = Query.from_dict(ep["query"], ordered=ordered) pred = engine.execute_query(ep["table_id"], qp, lower=True) except Exception as e: pred = repr(e) correct = pred == gold match = qp == qg grades.append(correct) exact_match.append(match) return { "ex_accuracy": sum(grades) / len(grades) * 100.0, "lf_accuracy": sum(exact_match) / len(exact_match) * 100.0, } if __name__ == "__main__": # pragma: no cover parser = ArgumentParser() parser.add_argument("source_file", help="source file for the prediction") parser.add_argument("db_file", help="source database for the prediction") parser.add_argument("pred_file", help="predictions by the model") parser.add_argument( "--ordered", action="store_true", help="whether the exact match should consider the order of conditions", ) args = parser.parse_args() engine = DBEngine(args.db_file) exact_match = [] with open(args.source_file) as fs, open(args.pred_file) as fp: grades = [] for ls, lp in tqdm(zip(fs, fp), total=count_lines(args.source_file)): eg = json.loads(ls) ep = json.loads(lp) qg = Query.from_dict(eg["sql"], ordered=args.ordered) gold = engine.execute_query(eg["table_id"], qg, lower=True) pred = ep.get("error", None) qp = None if not ep.get("error", None): try: qp = Query.from_dict(ep["query"], ordered=args.ordered) pred = engine.execute_query(eg["table_id"], qp, lower=True) except Exception as e: pred = repr(e) correct = pred == gold match = qp == qg grades.append(correct) exact_match.append(match) print( json.dumps( { "ex_accuracy": sum(grades) / len(grades), "lf_accuracy": sum(exact_match) / len(exact_match), }, indent=2, ) ) ================================================ FILE: claf/model/__init__.py ================================================ from claf.model.multi_task import * from claf.model.reading_comprehension import * from claf.model.regression import * from claf.model.semantic_parsing import * from claf.model.sequence_classification import * from claf.model.token_classification import * ================================================ FILE: claf/model/base.py ================================================ import json from pathlib import Path import torch.nn as nn class ModelBase(nn.Module): """ Model Base Class Args: token_embedder: (claf.tokens.token_embedder.base) TokenEmbedder """ def __init__(self): super(ModelBase, self).__init__() def forward(self, inputs): raise NotImplementedError def make_metrics(self, predictions): raise NotImplementedError def make_predictions(self, features): """ for Metrics """ raise NotImplementedError def predict(self, features): """ Inference """ raise NotImplementedError def print_examples(self, params): """ Print evaluation examples """ raise NotImplementedError def write_predictions(self, predictions, file_path=None, is_dict=True): data_type = "train" if self.training else "valid" pred_dir = Path(self._log_dir) / "predictions" pred_dir.mkdir(exist_ok=True) if file_path is None: file_path = f"predictions-{data_type}-{self._train_counter.get_display()}.json" pred_path = pred_dir / file_path with open(pred_path, "w") as out_file: if is_dict: out_file.write(json.dumps(predictions, indent=4)) else: out_file.write(predictions) def is_ready(self): properties = [ self._config, self._log_dir, # self._dataset, It's set at _run_epoch() # self._metrics, It's set at save() self._train_counter, self._vocabs ] return all([p is not None for p in properties]) @property def config(self): return self._config @config.setter def config(self, config): self._config = config @property def log_dir(self): return self._log_dir @log_dir.setter def log_dir(self, log_dir): self._log_dir = log_dir @property def dataset(self): return self._dataset @dataset.setter def dataset(self, dataset): self._dataset = dataset @property def metrics(self): return self._metrics @metrics.setter def metrics(self, metrics): self._metrics = metrics @property def train_counter(self): return self._train_counter @train_counter.setter def train_counter(self, train_counter): self._train_counter = train_counter @property def vocabs(self): return self._vocabs @vocabs.setter def vocabs(self, vocabs): self._vocabs = vocabs class ModelWithTokenEmbedder(ModelBase): def __init__(self, token_embedder): super(ModelWithTokenEmbedder, self).__init__() self.token_embedder = token_embedder if token_embedder is not None: self._vocabs = token_embedder.vocabs class ModelWithoutTokenEmbedder(ModelBase): def __init__(self, token_makers): super(ModelWithoutTokenEmbedder, self).__init__() self.token_makers = token_makers self._vocabs = { token_name: token_maker.vocab for token_name, token_maker in token_makers.items() } ================================================ FILE: claf/model/cls_utils.py ================================================ import csv from collections import defaultdict from seqeval.metrics.sequence_labeling import get_entities # pycm def write_confusion_matrix_to_csv(file_path, pycm_obj): with open(file_path + ".csv", "w") as f: indicator = "target/predict" fieldnames = [indicator] + pycm_obj.classes + ["FN"] writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() data = dict(pycm_obj.matrix) FN = dict(pycm_obj.FN) for row_idx in fieldnames[1:-1]: # remove indicator and FN row = {indicator: row_idx} row.update( { col_idx: data[row_idx][col_idx] for col_idx in data[row_idx] if col_idx in fieldnames } ) row.update({"FN": FN[row_idx]}) writer.writerow(row) row = {indicator: "FP"} row.update(dict(pycm_obj.FP)) writer.writerow(row) # seqeval def get_tag_dict(sequence, tag_texts): words = sequence.split() entities = get_entities(tag_texts) slots = defaultdict(list) for slot, start_idx, end_idx in entities: slots[slot].append(" ".join(words[start_idx : end_idx + 1])) return dict(slots) ================================================ FILE: claf/model/multi_task/__init__.py ================================================ from claf.model.multi_task.bert import BertForMultiTask # fmt: off __all__ = [ "BertForMultiTask" ] # fmt: on ================================================ FILE: claf/model/multi_task/bert.py ================================================ from overrides import overrides import torch.nn as nn from transformers import BertModel from claf.data.data_handler import CachePath from claf.decorator import register from claf.model.base import ModelWithoutTokenEmbedder from claf.model.multi_task.category import TaskCategory from claf.model.multi_task.mixin import MultiTask from claf.model.reading_comprehension.mixin import ReadingComprehension @register("model:bert_for_multi") class BertForMultiTask(MultiTask, ModelWithoutTokenEmbedder): """ Implementation of Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_classes: number of classified classes * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__(self, token_makers, tasks, pretrained_model_name=None, dropouts=None): super(BertForMultiTask, self).__init__(token_makers) self.use_transformers = True # for optimizer's model parameters self.tasks = tasks assert len(tasks) == len(dropouts) self.curr_task_category = None self.curr_dataset = None self.shared_layers = BertModel.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self._init_task_layers(tasks, dropouts) self._init_criterions(tasks) def _init_criterions(self, tasks): self.criterions = {} for task_index, task in enumerate(tasks): task_category = task["category"] criterion = None if task_category == TaskCategory.SEQUENCE_CLASSIFICATION or task_category == TaskCategory.READING_COMPREHENSION: criterion = nn.CrossEntropyLoss() elif task_category == TaskCategory.TOKEN_CLASSIFICATION: ignore_tag_idx = task.get("ignore_tag_idx", 0) criterion = nn.CrossEntropyLoss(ignore_index=ignore_tag_idx) elif task_category == TaskCategory.REGRESSION: criterion = nn.MSELoss() else: raise ValueError("Check task_category.") self.criterions[task_index] = criterion def _init_task_layers(self, tasks, dropouts): self.task_specific_layers = nn.ModuleList() for task, dropout in zip(tasks, dropouts): task_category = task["category"] if task_category == TaskCategory.SEQUENCE_CLASSIFICATION \ or task_category == TaskCategory.REGRESSION: task_layer = nn.Sequential( nn.Dropout(dropout), nn.Linear(self.shared_layers.config.hidden_size, task["num_label"]) ) elif task_category == TaskCategory.READING_COMPREHENSION: task_layer = nn.Linear( self.shared_layers.config.hidden_size, self.shared_layers.config.num_labels, ) elif task_category == TaskCategory.TOKEN_CLASSIFICATION: raise NotImplementedError() else: raise ValueError("Check task_category.") self.task_specific_layers.append(task_layer) @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [3, 4, 1, 0, 0, 0, ...], ..., ] }, "token_type": { "feature": [ [0, 0, 0, 0, 0, 0, ...], ..., ], } } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ task_index = features["task_index"] self.curr_task_category = self.tasks[task_index]["category"] self.curr_dataset = self._dataset.task_datasets[task_index] bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] attention_mask = (bert_inputs > 0).long() shared_outputs = self.shared_layers( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) output_dict = self._task_forward(task_index, shared_outputs) if labels: loss = self._task_calculate_loss(task_index, output_dict, labels) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict def _task_forward(self, task_index, shared_outputs): sequence_output = shared_outputs[0] pooled_output = shared_outputs[1] task_specific_layer = self.task_specific_layers[task_index] task_category = self.curr_task_category if task_category == TaskCategory.SEQUENCE_CLASSIFICATION \ or task_category == TaskCategory.REGRESSION: logits = task_specific_layer(pooled_output) output_dict = { "sequence_embed": pooled_output, "logits": logits, } elif task_category == TaskCategory.READING_COMPREHENSION: logits = task_specific_layer(sequence_output) start_logits, end_logits = logits.split(1, dim=-1) span_start_logits = start_logits.squeeze(-1) span_end_logits = end_logits.squeeze(-1) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": ReadingComprehension().get_best_span( span_start_logits, span_end_logits, answer_maxlen=30, ), } elif task_category == TaskCategory.TOKEN_CLASSIFICATION: raise NotImplementedError() else: raise ValueError(f"Check {self.curr_task_category}.") output_dict["task_index"] = task_index return output_dict def _task_calculate_loss(self, task_index, output_dict, labels): # Loss num_label = self.tasks[task_index]["num_label"] criterion = self.criterions[task_index.item()] task_category = self.curr_task_category if task_category == TaskCategory.SEQUENCE_CLASSIFICATION \ or task_category == TaskCategory.REGRESSION: label_key = None if task_category == TaskCategory.SEQUENCE_CLASSIFICATION: label_key = "class_idx" elif task_category == TaskCategory.REGRESSION: label_key = "score" label_value = labels[label_key] data_idx = labels["data_idx"] output_dict[label_key] = label_value output_dict["data_idx"] = data_idx logits = output_dict["logits"] logits = logits.view(-1, num_label) if num_label == 1: label_value = label_value.view(-1, 1) loss = criterion(logits, label_value) elif task_category == TaskCategory.READING_COMPREHENSION: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # If we are on multi-GPU, split add a dimension if len(answer_start_idx.size()) > 1: answer_start_idx = answer_start_idx.squeeze(-1) if len(answer_end_idx.size()) > 1: answer_end_idx = answer_end_idx.squeeze(-1) # sometimes the start/end positions are outside our model inputs, we ignore these terms ignored_index = output_dict["start_logits"].size(1) answer_start_idx.clamp_(0, ignored_index) answer_end_idx.clamp_(0, ignored_index) # Loss criterion = nn.CrossEntropyLoss(ignore_index=ignored_index) loss = criterion(output_dict["start_logits"], answer_start_idx) loss += criterion(output_dict["end_logits"], answer_end_idx) loss /= 2 # (start + end) elif task_category == TaskCategory.TOKEN_CLASSIFICATION: raise NotImplementedError() else: raise ValueError(f"Check {self.curr_task_category}.") return loss @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Class, Predicted Class) """ task_index = inputs["features"]["task_index"] task_dataset = self._dataset.task_datasets[task_index] task_category = self.tasks[task_index]["category"] data_idx = inputs["labels"]["data_idx"][index].item() data_id = task_dataset.get_id(data_idx) helper = task_dataset.helper if task_category == TaskCategory.SEQUENCE_CLASSIFICATION \ or task_category == TaskCategory.REGRESSION: sequence_a = helper["examples"][data_id]["sequence_a"] sequence_a_tokens = helper["examples"][data_id]["sequence_a_tokens"] sequence_b = helper["examples"][data_id]["sequence_b"] sequence_b_tokens = helper["examples"][data_id]["sequence_b_tokens"] print() print("Task(Dataset) name:", self.tasks[task_index]["name"]) print() print("- Sequence a:", sequence_a) print("- Sequence a Tokens:", sequence_a_tokens) if sequence_b: print("- Sequence b:", sequence_b) print("- Sequence b Tokens:", sequence_b_tokens) if task_category == TaskCategory.SEQUENCE_CLASSIFICATION: target_class_text = helper["examples"][data_id]["class_text"] pred_class_idx = predictions[data_id]["class_idx"] pred_class_text = task_dataset.get_class_text_with_idx(pred_class_idx) print("- Target:") print(" Class:", target_class_text) print("- Predict:") print(" Class:", pred_class_text) elif task_category == TaskCategory.REGRESSION: target_score = helper["examples"][data_id]["score"] pred_score = predictions[data_id]["score"] print("- Target:") print(" Score:", target_score) print("- Predict:") print(" Score:", pred_score) elif task_category == TaskCategory.READING_COMPREHENSION: context = helper["examples"][data_id]["context"] question = helper["examples"][data_id]["question"] answers = helper["examples"][data_id]["answers"] predict_text = predictions[data_idx]["predict_text"] print() print("- Context:", context) print("- Question:", question) print("- Answers:", answers) print("- Predict:", predict_text) print() ================================================ FILE: claf/model/multi_task/category.py ================================================ class TaskCategory: """ TaskCategory Flag class """ SEQUENCE_CLASSIFICATION = "sequence_classification" REGRESSION = "regression" READING_COMPREHENSION = "reading_comprehension" TOKEN_CLASSIFICATION = "token_classification" ================================================ FILE: claf/model/multi_task/mixin.py ================================================ import logging from claf.model.multi_task.category import TaskCategory from claf.model.sequence_classification.mixin import SequenceClassification from claf.model.reading_comprehension.mixin import SQuADv1ForBert from claf.model.regression.mixin import Regression from claf.model.token_classification.mixin import TokenClassification logger = logging.getLogger(__name__) class MultiTask: """ MultiTask Mixin Class """ def make_predictions(self, output_dict): task_index = output_dict["task_index"].item() mixin_obj = self._make_task_mixin_obj(task_index) predictions = mixin_obj.make_predictions(output_dict) for k, v in predictions.items(): predictions[k]["task_index"] = task_index return predictions def predict(self, output_dict, arguments, helper): task_index = output_dict["task_index"].item() mixin_obj = self._make_task_mixin_obj(task_index) return mixin_obj.predict(output_dict, arguments, helper) def make_metrics(self, predictions): task_predictions = self._split_predictions_by_task_index(predictions) # Must match task_predictions data_sizes and dataset's assert [len(task_preds) for task_preds in task_predictions] == [len(dataset) for dataset in self._dataset.task_datasets] all_metrics = {"average": 0} for task_index, predictions in enumerate(task_predictions): mixin_obj = self._make_task_mixin_obj(task_index) mixin_obj.write_predictions(predictions) task_metrics = mixin_obj.make_metrics(predictions) for k, v in task_metrics.items(): task_name = self.tasks[task_index]["name"].replace("_bert", "") # hard_code all_metrics[f"{task_name}/{k}"] = v task_metric_key = self.tasks[task_index]["metric_key"] if k == task_metric_key: if v > 1: # SQuAD case v /= 100 all_metrics["average"] += v all_metrics["average"] /= len(task_predictions) return all_metrics def _split_predictions_by_task_index(self, predictions): """ split predictions by task_index -> each task make_metrics then add task_index as prefix """ task_predictions = [{} for _ in range(len(self.tasks))] # init predictions for k, v in predictions.items(): task_index = v["task_index"] task_predictions[task_index][k] = v return task_predictions def _make_task_mixin_obj(self, task_index): mixin_obj = None task_category = self.tasks[task_index]["category"] if task_category == TaskCategory.SEQUENCE_CLASSIFICATION: mixin_obj = SequenceClassification() elif task_category == TaskCategory.READING_COMPREHENSION: mixin_obj = SQuADv1ForBert() elif task_category == TaskCategory.REGRESSION: mixin_obj = Regression() elif task_category == TaskCategory.TOKEN_CLASSIFICATION: mixin_obj = TokenClassification() else: raise ValueError("task category error.") self._set_model_properties(mixin_obj, task_index=task_index) return mixin_obj def _set_model_properties(self, mixin_obj, task_index=None): mixin_obj._config = self.config mixin_obj._log_dir = self.log_dir if task_index is None: mixin_obj._dataset = self.curr_dataset else: mixin_obj._dataset = self._dataset.task_datasets[task_index] mixin_obj._train_counter = self.train_counter mixin_obj.training = self.training mixin_obj._vocabs = self.vocabs # Helper's model_parameters task = self.tasks[task_index] for k, v in task["model_params"].items(): setattr(mixin_obj, k, v) ================================================ FILE: claf/model/reading_comprehension/__init__.py ================================================ from claf.model.reading_comprehension.bert import BertForQA from claf.model.reading_comprehension.bidaf import BiDAF from claf.model.reading_comprehension.bidaf_no_answer import BiDAF_No_Answer from claf.model.reading_comprehension.docqa import DocQA from claf.model.reading_comprehension.docqa_no_answer import DocQA_No_Answer from claf.model.reading_comprehension.drqa import DrQA from claf.model.reading_comprehension.qanet import QANet from claf.model.reading_comprehension.roberta import RoBertaForQA # fmt: off __all__ = [ "BertForQA", "BiDAF", "QANet", "DocQA", "DrQA", "RoBertaForQA", # SQuAD v1 "BiDAF_No_Answer", "DocQA_No_Answer", # SQuAD v2 ] # fmt: on ================================================ FILE: claf/model/reading_comprehension/bert.py ================================================ from overrides import overrides import torch.nn as nn from transformers import BertForQuestionAnswering from claf.data.data_handler import CachePath from claf.decorator import register from claf.model.base import ModelWithoutTokenEmbedder from claf.model.reading_comprehension.mixin import SQuADv1ForBert @register("model:bert_for_qa") class BertForQA(SQuADv1ForBert, ModelWithoutTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] pretrained_model_name: the name of a pre-trained model answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} """ def __init__(self, token_makers, lang_code="en", pretrained_model_name=None, answer_maxlen=30): super(BertForQA, self).__init__(token_makers) self.lang_code = lang_code self.use_transformers = True # for optimizer's model parameters self.answer_maxlen = answer_maxlen self.model = BertForQuestionAnswering.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] attention_mask = (bert_inputs > 0).long() span_start_logits, span_end_logits = self.model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # If we are on multi-GPU, split add a dimension if len(answer_start_idx.size()) > 1: answer_start_idx = answer_start_idx.squeeze(-1) if len(answer_end_idx.size()) > 1: answer_end_idx = answer_end_idx.squeeze(-1) # sometimes the start/end positions are outside our model inputs, we ignore these terms ignored_index = span_start_logits.size(1) answer_start_idx.clamp_(0, ignored_index) answer_end_idx.clamp_(0, ignored_index) # Loss criterion = nn.CrossEntropyLoss(ignore_index=ignored_index) loss = criterion(span_start_logits, answer_start_idx) loss += criterion(span_end_logits, answer_end_idx) loss /= 2 # (start + end) output_dict["loss"] = loss return output_dict ================================================ FILE: claf/model/reading_comprehension/bidaf.py ================================================ from overrides import overrides import torch import torch.nn as nn from claf.decorator import register from claf.model.base import ModelWithTokenEmbedder from claf.model.reading_comprehension.mixin import SQuADv1 import claf.modules.functional as f import claf.modules.attention as attention import claf.modules.layer as layer @register("model:bidaf") class BiDAF(SQuADv1, ModelWithTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in BiDAF: Bidirectional Attention Flow for Machine Comprehension (https://arxiv.org/abs/1611.01603) - Embedding (Word + Char -> Contextual) - Attention Flow - Modeling (RNN) - Output * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension contextual_rnn_num_layer: the number of recurrent layers (contextual) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=None, model_dim=100, contextual_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, ): super(BiDAF, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_highway = layer.Highway(context_embed_dim) self.context_contextual_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) self.query_highway = layer.Highway(query_embed_dim) self.query_contextual_rnn = nn.LSTM( input_size=query_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) else: highway = layer.Highway(query_embed_dim) self.context_highway = highway self.query_highway = highway contextual_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) self.context_contextual_rnn = contextual_rnn self.query_contextual_rnn = contextual_rnn self.attention = attention.BiAttention(model_dim) self.modeling_rnn = nn.LSTM( input_size=8 * model_dim, hidden_size=model_dim, num_layers=modeling_rnn_num_layer, bidirectional=True, dropout=dropout, batch_first=True, ) self.output_end_rnn = nn.LSTM( input_size=14 * model_dim, hidden_size=model_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_start_linear = nn.Linear(10 * model_dim, 1) self.span_end_linear = nn.Linear(10 * model_dim, 1) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding Layer (Char + Word -> Contextual) query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() query_mask = f.get_mask_from_tokens(question).float() B, C_L = context_embed.size(0), context_embed.size(1) context_embed = self.context_highway(context_embed) query_embed = self.query_highway(query_embed) context_encoded = f.forward_rnn_with_pack( self.context_contextual_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_encoded = f.forward_rnn_with_pack( self.query_contextual_rnn, query_embed, query_seq_config ) query_encoded = self.dropout(query_encoded) # Attention Flow Layer attention_context_query = self.attention( context_encoded, context_mask, query_encoded, query_mask ) # Modeling Layer modeled_context = f.forward_rnn_with_pack( self.modeling_rnn, attention_context_query, context_seq_config ) modeled_context = self.dropout(modeled_context) M_D = modeled_context.size(-1) # Output Layer span_start_input = self.dropout( torch.cat([attention_context_query, modeled_context], dim=-1) ) # (B, C_L, 10d) span_start_logits = self.span_start_linear(span_start_input).squeeze(-1) # (B, C_L) span_start_probs = f.masked_softmax(span_start_logits, context_mask) span_start_representation = f.weighted_sum( attention=span_start_probs, matrix=modeled_context ) tiled_span_start_representation = span_start_representation.unsqueeze(1).expand(B, C_L, M_D) span_end_representation = torch.cat( [ attention_context_query, modeled_context, tiled_span_start_representation, modeled_context * tiled_span_start_representation, ], dim=-1, ) encoded_span_end = f.forward_rnn_with_pack( self.output_end_rnn, span_end_representation, context_seq_config ) encoded_span_end = self.dropout(encoded_span_end) span_end_input = self.dropout( torch.cat([attention_context_query, encoded_span_end], dim=-1) ) span_end_logits = self.span_end_linear(span_end_input).squeeze(-1) # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict ================================================ FILE: claf/model/reading_comprehension/bidaf_no_answer.py ================================================ from overrides import overrides import torch import torch.nn as nn from claf.decorator import register from claf.model.base import ModelWithTokenEmbedder from claf.model.reading_comprehension.mixin import SQuADv2 import claf.modules.functional as f import claf.modules.attention as attention import claf.modules.layer as layer @register("model:bidaf_no_answer") class BiDAF_No_Answer(SQuADv2, ModelWithTokenEmbedder): """ Question Answering Model. `Span Detector`, `No Answer` Bidirectional Attention Flow for Machine Comprehension + Bias (No_Answer) - Embedding (Word + Char -> Contextual) - Attention Flow - Modeling (RNN) - Output * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=None, model_dim=100, contextual_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, ): super(BiDAF_No_Answer, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_highway = layer.Highway(context_embed_dim) self.context_contextual_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) self.query_highway = layer.Highway(query_embed_dim) self.query_contextual_rnn = nn.LSTM( input_size=query_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) else: highway = layer.Highway(query_embed_dim) self.context_highway = highway self.query_highway = highway contextual_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) self.context_contextual_rnn = contextual_rnn self.query_contextual_rnn = contextual_rnn self.attention = attention.BiAttention(model_dim) self.modeling_rnn = nn.LSTM( input_size=8 * model_dim, hidden_size=model_dim, num_layers=modeling_rnn_num_layer, bidirectional=True, dropout=dropout, batch_first=True, ) self.output_end_rnn = nn.LSTM( input_size=14 * model_dim, hidden_size=model_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_start_linear = nn.Linear(10 * model_dim, 1) self.span_end_linear = nn.Linear(10 * model_dim, 1) self.bias = nn.Parameter(torch.randn(1, 1)) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding Layer (Char + Word -> Contextual) query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() query_mask = f.get_mask_from_tokens(question).float() B, C_L = context_embed.size(0), context_embed.size(1) context_embed = self.context_highway(context_embed) query_embed = self.query_highway(query_embed) context_encoded = f.forward_rnn_with_pack( self.context_contextual_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_encoded = f.forward_rnn_with_pack( self.query_contextual_rnn, query_embed, query_seq_config ) query_encoded = self.dropout(query_encoded) # Attention Flow Layer attention_context_query = self.attention( context_encoded, context_mask, query_encoded, query_mask ) # Modeling Layer modeled_context = f.forward_rnn_with_pack( self.modeling_rnn, attention_context_query, context_seq_config ) modeled_context = self.dropout(modeled_context) M_D = modeled_context.size(-1) # Output Layer span_start_input = self.dropout( torch.cat([attention_context_query, modeled_context], dim=-1) ) # (B, C_L, 10d) span_start_logits = self.span_start_linear(span_start_input).squeeze(-1) # (B, C_L) span_start_probs = f.masked_softmax(span_start_logits, context_mask) span_start_representation = f.weighted_sum( attention=span_start_probs, matrix=modeled_context ) tiled_span_start_representation = span_start_representation.unsqueeze(1).expand(B, C_L, M_D) span_end_representation = torch.cat( [ attention_context_query, modeled_context, tiled_span_start_representation, modeled_context * tiled_span_start_representation, ], dim=-1, ) encoded_span_end = f.forward_rnn_with_pack( self.output_end_rnn, span_end_representation, context_seq_config ) encoded_span_end = self.dropout(encoded_span_end) span_end_input = self.dropout( torch.cat([attention_context_query, encoded_span_end], dim=-1) ) span_end_logits = self.span_end_linear(span_end_input).squeeze(-1) # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) # No_Answer Bias bias = self.bias.expand(B, 1) span_start_logits = torch.cat([span_start_logits, bias], dim=-1) span_end_logits = torch.cat([span_end_logits, bias], dim=-1) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits[:, :-1], span_end_logits[:, :-1], answer_maxlen=self.answer_maxlen, # except no_answer bias ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] answerable = labels["answerable"] # No_Asnwer Case C_L = context_mask.size(1) answer_start_idx = answer_start_idx.masked_fill(answerable.eq(0), C_L) answer_end_idx = answer_end_idx.masked_fill(answerable.eq(0), C_L) output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict ================================================ FILE: claf/model/reading_comprehension/docqa.py ================================================ from overrides import overrides import torch import torch.nn as nn import torch.nn.functional as F from claf.decorator import register from claf.model.base import ModelWithTokenEmbedder from claf.model.reading_comprehension.mixin import SQuADv1 from claf.modules import attention, initializer from claf.modules import functional as f @register("model:docqa") class DocQA(SQuADv1, ModelWithTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in Simple and Effective Multi-Paragraph Reading Comprehension (https://arxiv.org/abs/1710.10723) - Embedding (Word + Char -> Contextual) - Attention - Residual self-attention - Output * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} rnn_dim: the number of RNN cell dimension linear_dim: the number of attention linear dimension preprocess_rnn_num_layer: the number of recurrent layers (preprocess) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=17, rnn_dim=100, linear_dim=200, preprocess_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, weight_init=True, ): super(DocQA, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_preprocess_rnn = nn.GRU( input_size=context_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) self.query_preprocess_rnn = nn.GRU( input_size=query_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) else: preprocess_rnn = nn.GRU( input_size=context_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) self.context_preprocess_rnn = preprocess_rnn self.query_preprocess_rnn = preprocess_rnn self.bi_attention = attention.DocQAAttention(rnn_dim, linear_dim) self.attn_linear = nn.Linear(rnn_dim * 8, linear_dim) self.modeling_rnn = nn.GRU( input_size=linear_dim, hidden_size=rnn_dim, num_layers=modeling_rnn_num_layer, bidirectional=True, batch_first=True, ) self.self_attention = SelfAttention(rnn_dim, linear_dim, weight_init=weight_init) self.span_start_rnn = nn.GRU( input_size=linear_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_start_linear = nn.Linear(rnn_dim * 2, 1) self.span_end_rnn = nn.GRU( input_size=linear_dim + rnn_dim * 2, hidden_size=rnn_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_end_linear = nn.Linear(rnn_dim * 2, 1) self.activation_fn = F.relu self.criterion = nn.CrossEntropyLoss() if weight_init: modules = [ self.context_preprocess_rnn, self.query_preprocess_rnn, self.modeling_rnn, self.attn_linear, self.span_start_rnn, self.span_start_linear, self.span_end_rnn, self.span_end_linear, ] initializer.weight(modules) @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() # B X 1 X C_L query_mask = f.get_mask_from_tokens(question).float() # B X 1 X Q_L # Pre-process context_embed = self.dropout(context_embed) context_encoded = f.forward_rnn_with_pack( self.context_preprocess_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_embed = self.dropout(query_embed) query_encoded = f.forward_rnn_with_pack( self.query_preprocess_rnn, query_embed, query_seq_config ) query_encoded = self.dropout(query_encoded) # Attention -> Projection context_attnded = self.bi_attention( context_encoded, context_mask, query_encoded, query_mask ) context_attnded = self.activation_fn(self.attn_linear(context_attnded)) # B X C_L X dim*2 # Residual Self-Attention context_attnded = self.dropout(context_attnded) context_encoded = f.forward_rnn_with_pack( self.modeling_rnn, context_attnded, context_seq_config ) context_encoded = self.dropout(context_encoded) context_self_attnded = self.self_attention(context_encoded, context_mask) # B X C_L X dim*2 context_final = self.dropout(context_attnded + context_self_attnded) # B X C_L X dim*2 # Prediction span_start_input = f.forward_rnn_with_pack( self.span_start_rnn, context_final, context_seq_config ) # B X C_L X dim*2 span_start_input = self.dropout(span_start_input) span_start_logits = self.span_start_linear(span_start_input).squeeze(-1) # B X C_L span_end_input = torch.cat([span_start_input, context_final], dim=-1) # B X C_L X dim*4 span_end_input = f.forward_rnn_with_pack( self.span_end_rnn, span_end_input, context_seq_config ) # B X C_L X dim*2 span_end_input = self.dropout(span_end_input) span_end_logits = self.span_end_linear(span_end_input).squeeze(-1) # B X C_L # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict class SelfAttention(nn.Module): """ Same bi-attention mechanism, only now between the passage and itself. """ def __init__(self, rnn_dim, linear_dim, dropout=0.2, weight_init=True): super(SelfAttention, self).__init__() self.self_attention = attention.DocQAAttention( rnn_dim, linear_dim, self_attn=True, weight_init=weight_init ) self.self_attn_Linear = nn.Linear(rnn_dim * 6, linear_dim) self.dropout = nn.Dropout(p=dropout) self.activation_fn = F.relu if weight_init: initializer.weight(self.self_attn_Linear) def forward(self, context, context_mask): context_self_attnded = self.self_attention(context, context_mask, context, context_mask) return self.activation_fn(self.self_attn_Linear(context_self_attnded)) ================================================ FILE: claf/model/reading_comprehension/docqa_no_answer.py ================================================ from overrides import overrides import torch import torch.nn as nn import torch.nn.functional as F from claf.decorator import register from claf.model.base import ModelWithTokenEmbedder from claf.model.reading_comprehension.mixin import SQuADv2 from claf.modules import attention, initializer from claf.modules import functional as f @register("model:docqa_no_answer") class DocQA_No_Answer(SQuADv2, ModelWithTokenEmbedder): """ Question Answering Model. `Span Detector`, `No Answer` Implementation of model presented in Simple and Effective Multi-Paragraph Reading Comprehension + No_Asnwer (https://arxiv.org/abs/1710.10723) - Embedding (Word + Char -> Contextual) - Attention - Residual self-attention - Output * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} rnn_dim: the number of RNN cell dimension linear_dim: the number of attention linear dimension preprocess_rnn_num_layer: the number of recurrent layers (preprocess) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=17, rnn_dim=100, linear_dim=200, preprocess_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, weight_init=True, ): super(DocQA_No_Answer, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_preprocess_rnn = nn.GRU( input_size=context_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) self.query_preprocess_rnn = nn.GRU( input_size=query_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) else: preprocess_rnn = nn.GRU( input_size=context_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) self.context_preprocess_rnn = preprocess_rnn self.query_preprocess_rnn = preprocess_rnn self.bi_attention = attention.DocQAAttention(rnn_dim, linear_dim) self.attn_linear = nn.Linear(rnn_dim * 8, linear_dim) self.modeling_rnn = nn.GRU( input_size=linear_dim, hidden_size=rnn_dim, num_layers=modeling_rnn_num_layer, bidirectional=True, batch_first=True, ) self.self_attention = SelfAttention(rnn_dim, linear_dim, weight_init=weight_init) self.span_start_rnn = nn.GRU( input_size=linear_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_start_linear = nn.Linear(rnn_dim * 2, 1) self.span_end_rnn = nn.GRU( input_size=linear_dim + rnn_dim * 2, hidden_size=rnn_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_end_linear = nn.Linear(rnn_dim * 2, 1) self.no_answer_op = NoAnswer(context_embed_dim, 80) self.activation_fn = F.relu self.criterion = nn.CrossEntropyLoss() if weight_init: modules = [ self.context_preprocess_rnn, self.query_preprocess_rnn, self.modeling_rnn, self.attn_linear, self.span_start_rnn, self.span_start_linear, self.span_end_rnn, self.span_end_linear, ] initializer.weight(modules) @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() # B X C_L query_mask = f.get_mask_from_tokens(question).float() # B X Q_L # Pre-process context_embed = self.dropout(context_embed) context_encoded = f.forward_rnn_with_pack( self.context_preprocess_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_embed = self.dropout(query_embed) query_encoded = f.forward_rnn_with_pack( self.query_preprocess_rnn, query_embed, query_seq_config ) query_encoded = self.dropout(query_encoded) # Attention -> Projection context_attnded = self.bi_attention( context_encoded, context_mask, query_encoded, query_mask ) context_attnded = self.activation_fn(self.attn_linear(context_attnded)) # B X C_L X dim*2 # Residual Self-Attention context_attnded = self.dropout(context_attnded) context_encoded = f.forward_rnn_with_pack( self.modeling_rnn, context_attnded, context_seq_config ) context_encoded = self.dropout(context_encoded) context_self_attnded = self.self_attention(context_encoded, context_mask) # B X C_L X dim*2 context_final = self.dropout(context_attnded + context_self_attnded) # B X C_L X dim*2 # Prediction span_start_input = f.forward_rnn_with_pack( self.span_start_rnn, context_final, context_seq_config ) # B X C_L X dim*2 span_start_input = self.dropout(span_start_input) span_start_logits = self.span_start_linear(span_start_input).squeeze(-1) # B X C_L span_end_input = torch.cat([span_start_input, context_final], dim=-1) # B X C_L X dim*4 span_end_input = f.forward_rnn_with_pack( self.span_end_rnn, span_end_input, context_seq_config ) # B X C_L X dim*2 span_end_input = self.dropout(span_end_input) span_end_logits = self.span_end_linear(span_end_input).squeeze(-1) # B X C_L # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) # No_Asnwer Option bias = self.no_answer_op(context_embed, span_start_logits, span_end_logits) span_start_logits = torch.cat([span_start_logits, bias], dim=-1) span_end_logits = torch.cat([span_end_logits, bias], dim=-1) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits[:, :-1], span_end_logits[:, :-1], answer_maxlen=self.answer_maxlen, # except no_answer bias ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] answerable = labels["answerable"] # No_Asnwer Case C_L = context_mask.size(1) answer_start_idx = answer_start_idx.masked_fill(answerable.eq(0), C_L) answer_end_idx = answer_end_idx.masked_fill(answerable.eq(0), C_L) output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict class SelfAttention(nn.Module): """ Same bi-attention mechanism, only now between the passage and itself. """ def __init__(self, rnn_dim, linear_dim, dropout=0.2, weight_init=True): super(SelfAttention, self).__init__() self.self_attention = attention.DocQAAttention( rnn_dim, linear_dim, self_attn=True, weight_init=weight_init ) self.self_attn_Linear = nn.Linear(rnn_dim * 6, linear_dim) self.dropout = nn.Dropout(p=dropout) self.activation_fn = F.relu if weight_init: initializer.weight(self.self_attn_Linear) def forward(self, context, context_mask): context_self_attnded = self.self_attention(context, context_mask, context, context_mask) context_self_attnded = self.activation_fn(self.self_attn_Linear(context_self_attnded)) return context_self_attnded class NoAnswer(nn.Module): """ No-Answer Option * Args: embed_dim: the number of passage embedding dimension bias_hidden_dim: bias use two layer mlp, the number of hidden_size """ def __init__(self, embed_dim, bias_hidden_dim): super(NoAnswer, self).__init__() self.self_attn = nn.Linear(embed_dim, 1) self.bias_mlp = nn.Sequential( nn.Linear(embed_dim * 3, bias_hidden_dim), nn.ReLU(), nn.Linear(bias_hidden_dim, 1) ) def forward(self, context_embed, span_start_logits, span_end_logits): p_1_h = F.softmax(span_start_logits, -1).unsqueeze(1) # B,1,T p_2_h = F.softmax(span_end_logits, -1).unsqueeze(1) # B,1,T p_3_h = self.self_attn(context_embed).transpose(1, 2) # B,1,T v_1 = torch.matmul(p_1_h, context_embed) # B,1,D v_2 = torch.matmul(p_2_h, context_embed) # B,1,D v_3 = torch.matmul(p_3_h, context_embed) # B,1,D return self.bias_mlp(torch.cat([v_1, v_2, v_3], -1)).squeeze(-1) ================================================ FILE: claf/model/reading_comprehension/drqa.py ================================================ from overrides import overrides import torch.nn as nn from claf.decorator import register from claf.model.base import ModelWithTokenEmbedder from claf.model.reading_comprehension.mixin import SQuADv1 import claf.modules.functional as f import claf.modules.attention as attention @register("model:drqa") class DrQA(SQuADv1, ModelWithTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in Reading Wikipedia to Answer Open-Domain Questions (https://arxiv.org/abs/1704.00051) - Embedding + features - Align question embedding * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=None, model_dim=128, dropout=0.3, ): super(DrQA, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim self.paragraph_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, num_layers=3, dropout=dropout, bidirectional=True, batch_first=True, ) self.query_rnn = nn.LSTM( input_size=query_embed_dim, hidden_size=model_dim, num_layers=3, dropout=dropout, bidirectional=True, batch_first=True, ) self.query_att = attention.LinearSeqAttn(model_dim * 2) self.start_attn = attention.BilinearSeqAttn(model_dim * 2, model_dim * 2) self.end_attn = attention.BilinearSeqAttn(model_dim * 2, model_dim * 2) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] # aka paragraph question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() query_mask = f.get_mask_from_tokens(question).float() context_embed = self.dropout(context_embed) query_embed = self.dropout(query_embed) # RNN (LSTM) context_encoded = f.forward_rnn_with_pack( self.paragraph_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_encoded = f.forward_rnn_with_pack( self.query_rnn, query_embed, query_seq_config ) # (B, Q_L, H*2) query_encoded = self.dropout(query_encoded) query_attention = self.query_att(query_encoded, query_mask) # (B, Q_L) query_att_sum = f.weighted_sum(query_attention, query_encoded) # (B, H*2) span_start_logits = self.start_attn(context_encoded, query_att_sum, context_mask) span_end_logits = self.end_attn(context_encoded, query_att_sum, context_mask) # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) return output_dict ================================================ FILE: claf/model/reading_comprehension/mixin.py ================================================ from collections import OrderedDict import numpy as np import torch import torch.nn.functional as F from claf.decorator import arguments_required from claf.metric import korquad_v1_official, squad_v1_official, squad_v2_official from claf.model.base import ModelBase class ReadingComprehension: """ Reading Comprehension Mixin Class * Args: token_embedder: 'RCTokenEmbedder', Used to embed the 'context' and 'question'. """ def get_best_span(self, span_start_logits, span_end_logits, answer_maxlen=None): """ Take argmax of constrained score_s * score_e. * Args: span_start_logits: independent start logits span_end_logits: independent end logits * Kwargs: answer_maxlen: max span length to consider (default is None -> All) """ B = span_start_logits.size(0) best_word_span = span_start_logits.new_zeros((B, 2), dtype=torch.long) score_starts = F.softmax(span_start_logits, dim=-1) score_ends = F.softmax(span_end_logits, dim=-1) max_len = answer_maxlen or score_starts.size(1) for i in range(score_starts.size(0)): # Outer product of scores to get full p_s * p_e matrix scores = torch.ger(score_starts[i], score_ends[i]) # Zero out negative length and over-length span scores scores.triu_().tril_(max_len - 1) # Take argmax or top n scores = scores.detach().cpu().numpy() scores_flat = scores.flatten() idx_sort = [np.argmax(scores_flat)] s_idx, e_idx = np.unravel_index(idx_sort, scores.shape) best_word_span[i, 0] = int(s_idx[0]) best_word_span[i, 1] = int(e_idx[0]) return best_word_span def _make_span_metrics(self, predictions): """ span accuracy metrics """ start_accuracy, end_accuracy, span_accuracy = 0, 0, 0 for index, preds in predictions.items(): _, _, (answer_start, answer_end) = self._dataset.get_ground_truths(index) start_acc = 1 if preds["pred_span_start"] == answer_start else 0 end_acc = 1 if preds["pred_span_end"] == answer_end else 0 span_acc = 1 if start_acc == 1 and end_acc == 1 else 0 start_accuracy += start_acc end_accuracy += end_acc span_accuracy += span_acc start_accuracy = 100.0 * start_accuracy / len(self._dataset) end_accuracy = 100.0 * end_accuracy / len(self._dataset) span_accuracy = 100.0 * span_accuracy / len(self._dataset) return {"start_acc": start_accuracy, "end_acc": end_accuracy, "span_acc": span_accuracy} def make_predictions(self, output_dict): """ Make predictions with model's output_dict * Args: output_dict: model's output dictionary consisting of - data_idx: question id - best_span: calculate the span_start_logits and span_end_logits to what is the best span - start_logits: span start logits - end_logits: span end logits * Returns: predictions: prediction dictionary consisting of - key: 'id' (question id) - value: consisting of dictionary predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob """ data_indices = output_dict["data_idx"] best_word_span = output_dict["best_span"] return OrderedDict( [ ( index.item(), { "predict_text": self._dataset.get_text_with_index( index.item(), best_span[0], best_span[1] ), "pred_span_start": best_span[0], "pred_span_end": best_span[1], "start_logits": start_logits, "end_logits": end_logits, }, ) for index, best_span, start_logits, end_logits in zip( list(data_indices.data), list(best_word_span.data), list(output_dict["start_logits"].data), list(output_dict["end_logits"].data), ) ] ) @arguments_required(["context", "question"]) def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - data_idx: question id - best_span: calculate the span_start_logits and span_end_logits to what is the best span arguments: arguments dictionary consisting of user_input helper: dictionary for helping get answer * Returns: span: predict best_span """ span_start, span_end = list(output_dict["best_span"][0].data) word_start = span_start.item() word_end = span_end.item() text_span = helper["text_span"] char_start = text_span[word_start][0] char_end = text_span[word_end][1] context_text = arguments["context"] answer_text = context_text[char_start:char_end] start_logit = output_dict["start_logits"][0] end_logit = output_dict["end_logits"][0] score = start_logit[span_start] + end_logit[span_end] score = score.item() return {"text": answer_text, "score": score} def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (question id) - value: consisting of dictionary predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob * Returns: print(Context, Question, Answers and Predict) """ data_index = inputs["labels"]["data_idx"][index].item() qid = self._dataset.get_qid(data_index) if "#" in qid: # bert case (qid#index) qid = qid.split("#")[0] helper = self._dataset.helper context = helper["examples"][qid]["context"] question = helper["examples"][qid]["question"] answers = helper["examples"][qid]["answers"] predict_text = predictions[data_index]["predict_text"] print() print("- Context:", context) print("- Question:", question) print("- Answers:", answers) print("- Predict:", predict_text) print() def write_predictions(self, predictions, file_path=None, is_dict=True): pass # TODO: start and end logits (TypeError: Object of type 'Tensor' is not JSON serializable) # try: # super(ReadingComprehension, self).write_predictions( # predictions, file_path=file_path, is_dict=is_dict # ) # except AttributeError: # # TODO: Need to Fix # model_base = ModelBase() # model_base._log_dir = self._log_dir # model_base._train_counter = self._train_counter # model_base.training = self.training # model_base.write_predictions(predictions, file_path=file_path, is_dict=is_dict) class SQuADv1(ReadingComprehension): """ Reading Comprehension Mixin Class with SQuAD v1.1 evaluation * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. """ def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (question id) - value: (predict_text, pred_span_start, pred_span_end) * Returns: metrics: metric dictionary consisting of - 'em': exact_match (SQuAD v1.1 official evaluation) - 'f1': f1 (SQuAD v1.1 official evaluation) - 'start_acc': span_start accuracy - 'end_acc': span_end accuracy - 'span_acc': span accuracy (start and end) """ preds = {} for index, prediction in predictions.items(): _, _, (answer_start, answer_end) = self._dataset.get_ground_truths(index) qid = self._dataset.get_qid(index) preds[qid] = prediction["predict_text"] self.write_predictions(preds) squad_offical_metrics = self._make_metrics_with_official(preds) metrics = self._make_span_metrics(predictions) metrics.update(squad_offical_metrics) return metrics def _make_metrics_with_official(self, preds): """ SQuAD v1.1 official evaluation """ dataset = self._dataset.raw_dataset if self.lang_code.startswith("ko"): scores = korquad_v1_official.evaluate(dataset, preds) else: scores = squad_v1_official.evaluate(dataset, preds) return scores class SQuADv1ForBert(SQuADv1): """ Reading Comprehension Mixin Class with SQuAD v1.1 evaluation * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. """ def make_metrics(self, predictions): """ BERT predictions need to get nbest result """ best_predictions = {} for index, prediction in predictions.items(): qid = self._dataset.get_qid(index) predict_text = prediction["predict_text"] start_logit = prediction["start_logits"][prediction["pred_span_start"]] end_logit = prediction["end_logits"][prediction["pred_span_end"]] predict_score = start_logit.item() + end_logit.item() if qid not in best_predictions: best_predictions[qid] = [] best_predictions[qid].append((predict_text, predict_score)) for qid, predictions in best_predictions.items(): sorted_predictions = sorted(predictions, key=lambda x: x[1], reverse=True) best_predictions[qid] = sorted_predictions[0][0] self.write_predictions(best_predictions) return self._make_metrics_with_official(best_predictions) def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - data_idx: question id - best_span: calculate the span_start_logits and span_end_logits to what is the best span arguments: arguments dictionary consisting of user_input helper: dictionary for helping get answer * Returns: span: predict best_span """ context_text = arguments["context"] bert_tokens = helper["bert_token"] predictions = [ (best_span, start_logits, end_logits) for best_span, start_logits, end_logits in zip( list(output_dict["best_span"].data), list(output_dict["start_logits"].data), list(output_dict["end_logits"].data), ) ] best_predictions = [] for index, prediction in enumerate(predictions): bert_token = bert_tokens[index] best_span, start_logits, end_logits = prediction pred_start, pred_end = best_span predict_text = "" if ( pred_start < len(bert_token) and pred_end < len(bert_token) and bert_token[pred_start].text_span is not None and bert_token[pred_end].text_span is not None ): char_start = bert_token[pred_start].text_span[0] char_end = bert_token[pred_end].text_span[1] predict_text = context_text[char_start:char_end] start_logit = start_logits[pred_start] end_logit = end_logits[pred_end] predict_score = start_logit.item() + end_logit.item() best_predictions.append((predict_text, predict_score)) sorted_predictions = sorted(best_predictions, key=lambda x: x[1], reverse=True) return {"text": sorted_predictions[0][0], "score": sorted_predictions[0][1]} class SQuADv2(ReadingComprehension): """ Reading Comprehension Mixin Class with SQuAD v2.0 evaluation * Args: token_embedder: 'RCTokenEmbedder', Used to embed the 'context' and 'question'. """ def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (question id) - value: consisting of dictionary predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob * Returns: metrics: metric dictionary consisting of - 'start_acc': span_start accuracy - 'end_acc': span_end accuracy - 'span_acc': span accuracy (start and end) - 'em': exact_match (SQuAD v2.0 official evaluation) - 'f1': f1 (SQuAD v2.0 official evaluation) - 'HasAns_exact': has answer exact_match - 'HasAns_f1': has answer f1 - 'NoAns_exact': no answer exact_match - 'NoAns_f1': no answer f1 - 'best_exact': best exact_match score with best_exact_thresh - 'best_exact_thresh': best exact_match answerable threshold - 'best_f1': best f1 score with best_f1_thresh - 'best_f1_thresh': best f1 answerable threshold """ preds, na_probs = {}, {} for index, prediction in predictions.items(): _, _, (answer_start, answer_end) = self._dataset.get_ground_truths(index) # Metrics (SQuAD official metric) predict_text = prediction["predict_text"] if predict_text == "": predict_text = "" qid = self._dataset.get_qid(index) preds[qid] = predict_text span_start_probs = F.softmax(prediction["start_logits"], dim=-1) span_end_probs = F.softmax(prediction["end_logits"], dim=-1) start_no_prob = span_start_probs[-1].item() end_no_prob = span_end_probs[-1].item() no_answer_prob = start_no_prob * end_no_prob na_probs[qid] = no_answer_prob self.write_predictions(preds) model_type = "train" if self.training else "valid" self.write_predictions( na_probs, file_path=f"na_probs-{model_type}-{self._train_counter.get_display()}.json" ) squad_offical_metrics = self._make_metrics_with_official(preds, na_probs) metrics = self._make_span_metrics(predictions) metrics.update(squad_offical_metrics) return metrics def _make_metrics_with_official(self, preds, na_probs, na_prob_thresh=1.0): """ SQuAD 2.0 official evaluation """ dataset = self._dataset.raw_dataset squad_scores = squad_v2_official.evaluate(dataset, na_probs, preds) squad_scores["em"] = squad_scores["exact"] remove_keys = ["total", "exact", "HasAns_total", "NoAns_total"] for key in remove_keys: if key in squad_scores: del squad_scores[key] return squad_scores ================================================ FILE: claf/model/reading_comprehension/qanet.py ================================================ import torch import torch.nn as nn from overrides import overrides from claf.decorator import register from claf.model.base import ModelWithTokenEmbedder from claf.model.reading_comprehension.mixin import SQuADv1 import claf.modules.functional as f import claf.modules.attention as attention import claf.modules.encoder as encoder import claf.modules.conv as conv import claf.modules.layer as layer @register("model:qanet") class QANet(SQuADv1, ModelWithTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in QANet:Combining Local Convolution with Global Self-Attention for Reading Comprehension (https://arxiv.org/abs/1804.09541) - Input Embedding Layer - Embedding Encoder Layer - Context-Query Attention Layer - Model Encoder Layer - Output Layer * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension * Encoder Block Parameters (embedding, modeling) kernel_size: convolution kernel size in encoder block num_head: the number of multi-head attention's head num_conv_block: the number of convolution block in encoder block [Layernorm -> Conv (residual)] num_encoder_block: the number of the encoder block [position_encoding -> [n repeat conv block] -> Layernorm -> Self-attention (residual) -> Layernorm -> Feedforward (residual)] dropout: the dropout probability layer_dropout: the layer dropout probability (cf. Deep Networks with Stochastic Depth(https://arxiv.org/abs/1603.09382) ) """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=None, model_dim=128, kernel_size_in_embedding=7, num_head_in_embedding=8, num_conv_block_in_embedding=4, num_embedding_encoder_block=1, kernel_size_in_modeling=5, num_head_in_modeling=8, num_conv_block_in_modeling=2, num_modeling_encoder_block=7, dropout=0.1, layer_dropout=0.9, ): super(QANet, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_highway = layer.Highway(context_embed_dim) self.query_highway = layer.Highway(query_embed_dim) self.context_embed_pointwise_conv = conv.PointwiseConv(context_embed_dim, model_dim) self.query_embed_pointwise_conv = conv.PointwiseConv(query_embed_dim, model_dim) else: highway = layer.Highway(context_embed_dim) self.context_highway = highway self.query_highway = highway embed_pointwise_conv = conv.PointwiseConv(context_embed_dim, model_dim) self.context_embed_pointwise_conv = embed_pointwise_conv self.query_embed_pointwise_conv = embed_pointwise_conv self.embed_encoder_blocks = nn.ModuleList( [ EncoderBlock( model_dim=model_dim, kernel_size=kernel_size_in_embedding, num_head=num_head_in_embedding, num_conv_block=num_conv_block_in_modeling, dropout=dropout, layer_dropout=layer_dropout, ) for _ in range(num_embedding_encoder_block) ] ) self.co_attention = attention.CoAttention(model_dim) self.pointwise_conv = conv.PointwiseConv(model_dim * 4, model_dim) self.model_encoder_blocks = nn.ModuleList( [ EncoderBlock( model_dim=model_dim, kernel_size=kernel_size_in_modeling, num_head=num_head_in_modeling, num_conv_block=num_conv_block_in_modeling, dropout=dropout, layer_dropout=layer_dropout, ) for _ in range(num_modeling_encoder_block) ] ) self.span_start_linear = nn.Linear(model_dim * 2, 1, bias=False) self.span_end_linear = nn.Linear(model_dim * 2, 1, bias=False) self.dropout = nn.Dropout(p=dropout) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # 1. Input Embedding Layer query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() query_mask = f.get_mask_from_tokens(question).float() context_embed = self.context_highway(context_embed) context_embed = self.dropout(context_embed) context_embed = self.context_embed_pointwise_conv(context_embed) query_embed = self.query_highway(query_embed) query_embed = self.dropout(query_embed) query_embed = self.query_embed_pointwise_conv(query_embed) # 2. Embedding Encoder Layer for encoder_block in self.embed_encoder_blocks: context = encoder_block(context_embed) context_embed = context query = encoder_block(query_embed) query_embed = query # 3. Context-Query Attention Layer context_query_attention = self.co_attention(context, query, context_mask, query_mask) # Projection (memory issue) context_query_attention = self.pointwise_conv(context_query_attention) context_query_attention = self.dropout(context_query_attention) # 4. Model Encoder Layer model_encoder_block_inputs = context_query_attention # Stacked Model Encoder Block stacked_model_encoder_blocks = [] for i in range(3): for _, model_encoder_block in enumerate(self.model_encoder_blocks): output = model_encoder_block(model_encoder_block_inputs, context_mask) model_encoder_block_inputs = output stacked_model_encoder_blocks.append(output) # 5. Output Layer span_start_inputs = torch.cat( [stacked_model_encoder_blocks[0], stacked_model_encoder_blocks[1]], dim=-1 ) span_start_inputs = self.dropout(span_start_inputs) span_start_logits = self.span_start_linear(span_start_inputs).squeeze(-1) span_end_inputs = torch.cat( [stacked_model_encoder_blocks[0], stacked_model_encoder_blocks[2]], dim=-1 ) span_end_inputs = self.dropout(span_end_inputs) span_end_logits = self.span_end_linear(span_end_inputs).squeeze(-1) # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span(span_start_logits, span_end_logits), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict class EncoderBlock(nn.Module): """ Encoder Block []: residual position_encoding -> [convolution-layer] x # -> [self-attention-layer] -> [feed-forward-layer] - convolution-layer: depthwise separable convolutions - self-attention-layer: multi-head attention - feed-forward-layer: pointwise convolution * Args: model_dim: the number of model dimension num_heads: the number of head in multi-head attention kernel_size: convolution kernel size num_conv_block: the number of convolution block dropout: the dropout probability layer_dropout: the layer dropout probability (cf. Deep Networks with Stochastic Depth(https://arxiv.org/abs/1603.09382) ) """ def __init__( self, model_dim=128, num_head=8, kernel_size=5, num_conv_block=4, dropout=0.1, layer_dropout=0.9, ): super(EncoderBlock, self).__init__() self.position_encoding = encoder.PositionalEncoding(model_dim) self.dropout = nn.Dropout(dropout) self.num_conv_block = num_conv_block self.conv_blocks = nn.ModuleList( [conv.DepSepConv(model_dim, model_dim, kernel_size) for _ in range(num_conv_block)] ) self.self_attention = attention.MultiHeadAttention( num_head=num_head, model_dim=model_dim, dropout=dropout ) self.feedforward_layer = layer.PositionwiseFeedForward( model_dim, model_dim * 4, dropout=dropout ) # survival probability for stochastic depth if layer_dropout < 1.0: L = (num_conv_block) + 2 - 1 layer_dropout_prob = round(1 - (1 / L) * (1 - layer_dropout), 3) self.residuals = nn.ModuleList( layer.ResidualConnection( model_dim, layer_dropout=layer_dropout_prob, layernorm=True ) for l in range(num_conv_block + 2) ) else: self.residuals = nn.ModuleList( layer.ResidualConnection(model_dim, layernorm=True) for l in range(num_conv_block + 2) ) def forward(self, x, mask=None): # Positional Encoding x = self.position_encoding(x) # Convolution Block (LayerNorm -> Conv) for i, conv_block in enumerate(self.conv_blocks): x = self.residuals[i](x, sub_layer_fn=conv_block) x = self.dropout(x) # LayerNorm -> Self-attention self_attention = lambda x: self.self_attention(q=x, k=x, v=x, mask=mask) x = self.residuals[self.num_conv_block](x, sub_layer_fn=self_attention) x = self.dropout(x) # LayerNorm -> Feedforward layer x = self.residuals[self.num_conv_block + 1](x, sub_layer_fn=self.feedforward_layer) x = self.dropout(x) return x ================================================ FILE: claf/model/reading_comprehension/roberta.py ================================================ from overrides import overrides from transformers import RobertaModel import torch.nn as nn from claf.data.data_handler import CachePath from claf.decorator import register from claf.model.base import ModelWithoutTokenEmbedder from claf.model.reading_comprehension.mixin import SQuADv1ForBert @register("model:roberta_for_qa") class RoBertaForQA(SQuADv1ForBert, ModelWithoutTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] pretrained_model_name: the name of a pre-trained model answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} """ def __init__(self, token_makers, lang_code="en", pretrained_model_name=None, answer_maxlen=30): super(RoBertaForQA, self).__init__(token_makers) self.lang_code = lang_code self.use_transformers = True # for optimizer's model parameters self.answer_maxlen = answer_maxlen self.model = RobertaModel.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.qa_outputs = nn.Linear(self.model.config.hidden_size, self.model.config.num_labels) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ bert_inputs = features["bert_input"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self.model( bert_inputs, token_type_ids=None, attention_mask=attention_mask ) sequence_output = outputs[0] logits = self.qa_outputs(sequence_output) span_start_logits, span_end_logits = logits.split(1, dim=-1) span_start_logits = span_start_logits.squeeze(-1) span_end_logits = span_end_logits.squeeze(-1) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # If we are on multi-GPU, split add a dimension if len(answer_start_idx.size()) > 1: answer_start_idx = answer_start_idx.squeeze(-1) if len(answer_end_idx.size()) > 1: answer_end_idx = answer_end_idx.squeeze(-1) # sometimes the start/end positions are outside our model inputs, we ignore these terms ignored_index = span_start_logits.size(1) answer_start_idx.clamp_(0, ignored_index) answer_end_idx.clamp_(0, ignored_index) # Loss criterion = nn.CrossEntropyLoss(ignore_index=ignored_index) loss = criterion(span_start_logits, answer_start_idx) loss += criterion(span_end_logits, answer_end_idx) loss /= 2 # (start + end) output_dict["loss"] = loss return output_dict ================================================ FILE: claf/model/regression/__init__.py ================================================ from claf.model.regression.bert import BertForRegression from claf.model.regression.roberta import RobertaForRegression # fmt: off __all__ = [ "BertForRegression", "RobertaForRegression" ] # fmt: on ================================================ FILE: claf/model/regression/bert.py ================================================ from overrides import overrides import torch.nn as nn from transformers import BertForSequenceClassification from claf.data.data_handler import CachePath from claf.decorator import register from claf.model.base import ModelWithoutTokenEmbedder from claf.model.regression.mixin import Regression @register("model:bert_for_reg") class BertForRegression(Regression, ModelWithoutTokenEmbedder): """ Implementation of Single Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_makers: used to convert the sequence to feature * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__(self, token_makers, pretrained_model_name=None, dropout=0.2): super(BertForRegression, self).__init__(token_makers) self.use_transformers = True # for optimizer's model parameters NUM_CLASSES = 1 self.model = BertForSequenceClassification.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT), num_labels=NUM_CLASSES, ) self.criterion = nn.MSELoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [3, 4, 1, 0, 0, 0, ...], ..., ] }, "token_type": { "feature": [ [0, 0, 0, 0, 0, 0, ...], ..., ], } } * Kwargs: label: label dictionary like below. { "score": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no labels. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - logits: model's score - data_idx: data idx - score: target score - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self._model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) pooled_output = outputs[1] logits = self.classifier(pooled_output) output_dict = {"sequence_embed": pooled_output, "logits": logits} if labels: data_idx = labels["data_idx"] score = labels["score"] output_dict["data_idx"] = data_idx output_dict["score"] = score # Loss loss = self.criterion(logits.view(-1, 1), score.view(-1, 1).float()) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence_a = helper["examples"][data_id]["sequence_a"] sequence_a_tokens = helper["examples"][data_id]["sequence_a_tokens"] sequence_b = helper["examples"][data_id]["sequence_b"] sequence_b_tokens = helper["examples"][data_id]["sequence_b_tokens"] target_score = helper["examples"][data_id]["score"] pred_score = predictions[data_id]["score"] print() print("- Sequence a:", sequence_a) print("- Sequence a Tokens:", sequence_a_tokens) if sequence_b: print("- Sequence b:", sequence_b) print("- Sequence b Tokens:", sequence_b_tokens) print("- Target:") print(" Score:", target_score) print("- Predict:") print(" Score:", pred_score) print() ================================================ FILE: claf/model/regression/mixin.py ================================================ import logging from claf.metric.glue import pearson_and_spearman from claf.metric.regression import mse from claf.model.base import ModelBase logger = logging.getLogger(__name__) class Regression: """ Regression Mixin Class """ def make_predictions(self, output_dict): """ Make predictions with model's output_dict * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - class_logits: representing unnormalized log probabilities of the class - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized * Returns: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - score """ data_indices = output_dict["data_idx"] pred_logits = output_dict["logits"] predictions = { self._dataset.get_id(data_idx.item()): {"score": pred_score.item()} for data_idx, pred_score in zip(list(data_indices.data), list(pred_logits.data)) } return predictions def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - logits: model's score arguments: arguments dictionary consisting of user_input helper: dictionary to get the classification result, consisting of - * Returns: output dict (dict) consisting of - score: model's score """ score = output_dict["logits"] return { "score": score, } def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: metrics: metric dictionary consisting of - 'mse': Mean Squard Error - 'pearson': Pearson correlation coefficient - 'spearmanr': Spearman correlation coefficient - 'pearson_spearman_corr': (pearson_corr + spearman_corr) / 2, """ pred_scores = [] target_scores = [] preds = {} for data_id, pred in predictions.items(): target = self._dataset.get_ground_truth(data_id) preds[data_id] = pred["score"] pred_scores.append(pred["score"]) target_scores.append(target["score"]) self.write_predictions(preds) metrics = {"mse": mse(pred_scores, target_scores) / len(target_scores)} pearson_spearman_metrics = pearson_and_spearman(pred_scores, target_scores) metrics.update(pearson_spearman_metrics) return metrics def write_predictions(self, predictions, ): try: super(Regression, self).write_predictions(predictions) except AttributeError: # TODO: Need to Fix model_base = ModelBase() model_base._log_dir = self._log_dir model_base._train_counter = self._train_counter model_base.training = self.training model_base.write_predictions(predictions) def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence = helper["examples"][data_id]["sequence"] target_score = helper["examples"][data_id]["score"] pred_score = predictions[data_id]["score"] print() print("- Sequence:", sequence) print("- Target:") print(" Score:", target_score) print("- Predict:") print(" Score:", pred_score) print() ================================================ FILE: claf/model/regression/roberta.py ================================================ from overrides import overrides from transformers import RobertaForSequenceClassification import torch.nn as nn from claf.data.data_handler import CachePath from claf.decorator import register from claf.model.base import ModelWithoutTokenEmbedder from claf.model.regression.mixin import Regression @register("model:roberta_for_reg") class RobertaForRegression(Regression, ModelWithoutTokenEmbedder): """ Implementation of Sentence Regression model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_makers: used to convert the sequence to feature * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__(self, token_makers, pretrained_model_name=None, dropout=0.2): super(RobertaForRegression, self).__init__(token_makers) self.use_transformers = True # for optimizer's model parameters NUM_CLASSES = 1 self.model = RobertaForSequenceClassification.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT), num_labels=NUM_CLASSES, ) self.criterion = nn.MSELoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [3, 4, 1, 0, 0, 0, ...], ..., ] }, } * Kwargs: label: label dictionary like below. { "score": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no labels. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - logits: model's score - data_idx: data idx - score: target score - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self.model( bert_inputs, token_type_ids=None, attention_mask=attention_mask ) logits = outputs[0] output_dict = {"logits": logits} if labels: data_idx = labels["data_idx"] score = labels["score"] output_dict["data_idx"] = data_idx output_dict["score"] = score # Loss loss = self.criterion(logits.view(-1, 1), score.view(-1, 1).float()) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence_a = helper["examples"][data_id]["sequence_a"] sequence_a_tokens = helper["examples"][data_id]["sequence_a_tokens"] sequence_b = helper["examples"][data_id]["sequence_b"] sequence_b_tokens = helper["examples"][data_id]["sequence_b_tokens"] target_score = helper["examples"][data_id]["score"] pred_score = predictions[data_id]["score"] print() print("- Sequence a:", sequence_a) print("- Sequence a Tokens:", sequence_a_tokens) if sequence_b: print("- Sequence b:", sequence_b) print("- Sequence b Tokens:", sequence_b_tokens) print("- Target:") print(" Score:", target_score) print("- Predict:") print(" Score:", pred_score) print() ================================================ FILE: claf/model/semantic_parsing/__init__.py ================================================ from claf.model.semantic_parsing.sqlnet import SQLNet # fmt: off __all__ = [ "SQLNet" ] # fmt: on ================================================ FILE: claf/model/semantic_parsing/mixin.py ================================================ import torch from claf.decorator import arguments_required from claf.metric import wikisql_official from claf.metric.wikisql_lib.dbengine import DBEngine from claf.metric.wikisql_lib.query import Query class WikiSQL: """ WikiSQL Mixin Class with official evaluation * Args: token_embedder: 'TokenEmbedder' """ AGG_OPS = ["None", "MAX", "MIN", "COUNT", "SUM", "AVG"] COND_OPS = ["EQL", "GT", "LT"] def make_metrics(self, predictions): """ aggregator, select_column, conditions accuracy """ agg_accuracy, sel_accuracy, conds_accuracy = 0, 0, 0 for index, pred in predictions.items(): target = self._dataset.get_ground_truth(index) # Aggregator, Select_Column, Conditions agg_acc = 1 if pred["query"]["agg"] == target["agg_idx"] else 0 sel_acc = 1 if pred["query"]["sel"] == target["sel_idx"] else 0 pred_conds = pred["query"]["conds"] string_set_pred_conds = set(["#".join(map(str, cond)).lower() for cond in pred_conds]) target_conds = [ [target["conds_col"][i], target["conds_op"][i], target["conds_val_str"][i]] for i in range(target["conds_num"]) ] string_set_target_conds = set( ["#".join(map(str, cond)).lower() for cond in target_conds] ) conds_acc = ( 1 if string_set_pred_conds == string_set_target_conds else 0 ) # not matter in order agg_accuracy += agg_acc sel_accuracy += sel_acc conds_accuracy += conds_acc total_count = len(self._dataset) agg_accuracy = 100.0 * agg_accuracy / total_count sel_accuracy = 100.0 * sel_accuracy / total_count conds_accuracy = 100.0 * conds_accuracy / total_count metrics = { "agg_accuracy": agg_accuracy, "sel_accuracy": sel_accuracy, "conds_accuracy": conds_accuracy, } self.write_predictions(predictions) wikisql_official_metrics = self._make_metrics_with_official(predictions) metrics.update(wikisql_official_metrics) return metrics def _make_metrics_with_official(self, preds): """ WikiSQL official evaluation lf_accuracy: Logical-form accuracy - Directly compare the synthesized SQL query with the ground truth to check whether they match each other. ex_accuracy: Execution accuracy - Execute both the synthesized query and the ground truth query and compare whether the results match to each other. """ labels = self._dataset.labels db_path = self._dataset.helper["db_path"] return wikisql_official.evaluate(labels, preds, db_path) def make_predictions(self, output_dict): predictions = {} sql_quries = self.generate_queries(output_dict) for i in range(len(sql_quries)): query = sql_quries[i] prediction = {} prediction.update(query) data_id = self._dataset.get_id(output_dict["data_id"][i]) predictions[data_id] = prediction return predictions def generate_queries(self, output_dict): preds_agg = torch.argmax(output_dict["agg_logits"], dim=-1) preds_sel = torch.argmax(output_dict["sel_logits"], dim=-1) conds_logits = output_dict["conds_logits"] conds_num_logits, conds_column_logits, conds_op_logits, conds_value_logits = conds_logits preds_conds_num = torch.argmax(conds_num_logits, dim=-1) preds_conds_op = torch.argmax(conds_op_logits, dim=-1) sql_quries = [] B = output_dict["agg_logits"].size(0) for i in range(B): if "table_id" in output_dict: table_id = output_dict["table_id"] else: table_id = self._dataset.get_table_id(output_dict["data_id"][i]) query = { "table_id": table_id, "query": {"agg": preds_agg[i].item(), "sel": preds_sel[i].item()}, } pred_conds_num = preds_conds_num[i].item() conds_pred = [] if pred_conds_num == 0: pass else: _, pred_conds_column_idx = torch.topk(conds_column_logits[i], pred_conds_num) if preds_conds_op.dim() == 1: # for one-example (TODO: fix hard-code) pred_conds_op = preds_conds_op conds_value_logits = conds_value_logits.squeeze(3) conds_value_logits = conds_value_logits.squeeze(0) else: pred_conds_op = preds_conds_op[i] if "tokenized_question" in output_dict: tokenized_question = output_dict["tokenized_question"] else: tokenized_question = self._dataset.get_tokenized_question( output_dict["data_id"][i] ) conds_pred = [ [ pred_conds_column_idx[j].item(), pred_conds_op[j].item(), self.decode_pointer(tokenized_question, conds_value_logits[i][j]), ] for j in range(pred_conds_num) ] query["query"]["conds"] = conds_pred sql_quries.append(query) return sql_quries def decode_pointer(self, tokenized_question, cond_value_logits): question_text = " ".join(tokenized_question) tokenized_question = [""] + tokenized_question + [""] conds_value = [] for value_logit in cond_value_logits: pred_value_pos = torch.argmax(value_logit[: len(tokenized_question)]).item() pred_value_token = tokenized_question[pred_value_pos] if pred_value_token == "": break conds_value.append(pred_value_token) conds_value = self.merge_tokens(conds_value, question_text) return conds_value def merge_tokens(self, tok_list, raw_tok_str): lower_tok_str = raw_tok_str.lower() alphabet = set("abcdefghijklmnopqrstuvwxyz0123456789$(") special = { "-LRB-": "(", "-RRB-": ")", "-LSB-": "[", "-RSB-": "]", "``": '"', "''": '"', "--": "\u2013", } ret = "" double_quote_appear = 0 for raw_tok in tok_list: if not raw_tok: continue tok = special.get(raw_tok, raw_tok) lower_tok = tok.lower() if tok == '"': double_quote_appear = 1 - double_quote_appear if len(ret) == 0: pass elif len(ret) > 0 and ret + " " + lower_tok in lower_tok_str: ret = ret + " " elif len(ret) > 0 and ret + lower_tok in lower_tok_str: pass elif lower_tok == '"': if double_quote_appear: ret = ret + " " elif lower_tok[0] not in alphabet: pass elif (ret[-1] not in ["(", "/", "\u2013", "#", "$", "&"]) and ( ret[-1] != '"' or not double_quote_appear ): ret = ret + " " ret = ret + tok return ret.strip() @arguments_required(["db_path", "table_id"]) def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of arguments: arguments dictionary consisting of user_input helper: dictionary for helping get answer * Returns: query: Generated SQL Query execute_result: Execute result by generated query """ output_dict["table_id"] = arguments["table_id"] output_dict["tokenized_question"] = helper["tokenized_question"] prediction = self.generate_queries(output_dict)[0] pred_query = Query.from_dict(prediction["query"], ordered=True) dbengine = DBEngine(arguments["db_path"]) try: pred_execute_result = dbengine.execute_query( prediction["table_id"], pred_query, lower=True ) except IndexError as e: pred_execute_result = str(e) return {"query": str(pred_query), "execute_result": pred_execute_result} def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (question id) - value: consisting of dictionary table_id, query (agg, sel, conds) * Returns: print(Context, Question, Answers and Predict) """ data_index = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_index) helper = self._dataset.helper question = helper["examples"][data_id]["question"] label = self._dataset.get_ground_truth(data_id) dbengine = DBEngine(helper["db_path"]) prediction = predictions[data_id] pred_query = Query.from_dict(prediction["query"], ordered=True) pred_execute_result = dbengine.execute_query(prediction["table_id"], pred_query, lower=True) print("- Question:", question) print("- Answers:") print(" SQL Query: ", label["sql_query"]) print(" Execute Results:", label["execution_result"]) print("- Predict:") print(" SQL Query: ", pred_query) print(" Execute Results:", pred_execute_result) print("-" * 30) ================================================ FILE: claf/model/semantic_parsing/sqlnet.py ================================================ from overrides import overrides import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from claf.decorator import register from claf.model.base import ModelWithTokenEmbedder from claf.model.semantic_parsing import utils from claf.model.semantic_parsing.mixin import WikiSQL import claf.modules.functional as f import claf.modules.attention as attention @register("model:sqlnet") class SQLNet(WikiSQL, ModelWithTokenEmbedder): """ Nature Language to SQL Query Model. `Semantic Parsing`, `NL2SQL` Implementation of model presented in SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning (https://arxiv.org/abs/1711.04436) * Args: token_embedder: 'WikiSQLTokenEmbedder', Used to embed the 'column' and 'question'. * Kwargs: column_attention: highlight that column attention is a special instance of the generic attention mechanism to compute the attention map on a question conditioned on the column names. model_dim: the number of model dimension rnn_num_layer: the number of recurrent layers (all of rnn) column_maxlen: an upper-bound N on the number of columns to choose token_maxlen: conds value slot - pointer network an upper-bound N on the number of token conds_column_loss_alpha: balance the positive data versus negative data """ def __init__( self, token_embedder, column_attention=None, model_dim=100, rnn_num_layer=2, dropout=0.3, column_maxlen=4, token_maxlen=200, conds_column_loss_alpha=3, ): super(SQLNet, self).__init__(token_embedder) embed_dim = token_embedder.get_embed_dim() # NOTE: need to fix self.token_maxlen = token_maxlen self.column_maxlen = column_maxlen self.conds_column_loss_alpha = conds_column_loss_alpha # Predict aggregator self.agg_predictor = AggPredictor( embed_dim, model_dim, rnn_num_layer, dropout, len(self.AGG_OPS) ) # Predict selected column self.sel_predictor = SelPredictor( embed_dim, model_dim, rnn_num_layer, dropout, column_attention=column_attention ) # #Predict number of conditions self.conds_predictor = CondsPredictor( embed_dim, model_dim, rnn_num_layer, dropout, len(self.COND_OPS), column_maxlen, token_maxlen, column_attention=column_attention, ) self.cross_entropy = nn.CrossEntropyLoss() self.bce_logit = nn.BCEWithLogitsLoss() @overrides def forward(self, features, labels=None): column = features["column"] question = features["question"] column_embed = self.token_embedder(column) question_embed = self.token_embedder(question) B, C_L = column_embed.size(0), column_embed.size(1) column_indexed = column[next(iter(column))] column_name_mask = column_indexed.gt(0).float() # NOTE: hard-code column_lengths = utils.get_column_lengths(column_embed, column_name_mask) column_mask = column_lengths.view(B, C_L).gt(0).float() # NOTE: hard-code question_mask = f.get_mask_from_tokens(question).float() agg_logits = self.agg_predictor(question_embed, question_mask) sel_logits = self.sel_predictor( question_embed, question_mask, column_embed, column_name_mask, column_mask ) conds_col_idx, conds_val_pos = None, None if labels: data_idx = labels["data_idx"] ground_truths = self._dataset.get_ground_truths(data_idx) conds_col_idx = [ground_truth["conds_col"] for ground_truth in ground_truths] conds_val_pos = [ground_truth["conds_val_pos"] for ground_truth in ground_truths] conds_logits = self.conds_predictor( question_embed, question_mask, column_embed, column_name_mask, column_mask, conds_col_idx, conds_val_pos, ) # Convert GPU to CPU agg_logits = agg_logits.cpu() sel_logits = sel_logits.cpu() conds_logits = [logits.cpu() for logits in conds_logits] output_dict = { "agg_logits": agg_logits, "sel_logits": sel_logits, "conds_logits": conds_logits, } if labels: data_idx = labels["data_idx"] output_dict["data_id"] = data_idx ground_truths = self._dataset.get_ground_truths(data_idx) # Aggregator, Select Column target_agg_idx = torch.LongTensor( [ground_truth["agg_idx"] for ground_truth in ground_truths] ) target_sel_idx = torch.LongTensor( [ground_truth["sel_idx"] for ground_truth in ground_truths] ) loss = 0 loss += self.cross_entropy(agg_logits, target_agg_idx) loss += self.cross_entropy(sel_logits, target_sel_idx) conds_num_logits, conds_column_logits, conds_op_logits, conds_value_logits = ( conds_logits ) # Conditions # 1. The number of conditions target_conds_num = torch.LongTensor( [ground_truth["conds_num"] for ground_truth in ground_truths] ) target_conds_column = [ground_truth["conds_col"] for ground_truth in ground_truths] loss += self.cross_entropy(conds_num_logits, target_conds_num) # 2. Columns of conditions B = conds_column_logits.size(0) target_conds_columns = np.zeros(list(conds_column_logits.size()), dtype=np.float32) for i in range(B): target_conds_column_idx = target_conds_column[i] if len(target_conds_column_idx) == 0: continue target_conds_columns[i][target_conds_column_idx] = 1 target_conds_columns = torch.from_numpy(target_conds_columns) conds_column_probs = torch.sigmoid(conds_column_logits) bce_loss = -torch.mean( self.conds_column_loss_alpha * (target_conds_columns * torch.log(conds_column_probs + 1e-10)) + (1 - target_conds_columns) * torch.log(1 - conds_column_probs + 1e-10) ) loss += bce_loss # 3. Operator of conditions conds_op_loss = 0 for i in range(B): target_conds_op = ground_truths[i]["conds_op"] if len(target_conds_op) == 0: continue target_conds_op = torch.from_numpy(np.array(target_conds_op)) logits_conds_op = conds_op_logits[i, : len(target_conds_op)] target_op_count = len(target_conds_op) conds_op_loss += ( self.cross_entropy(logits_conds_op, target_conds_op) / target_op_count ) loss += conds_op_loss # 4. Value of conditions conds_val_pos = [ground_truth["conds_val_pos"] for ground_truth in ground_truths] conds_value_loss = 0 for i in range(B): for j in range(len(conds_val_pos[i])): cond_val_pos = conds_val_pos[i][j] if len(cond_val_pos) == 1: continue target_cond_val_pos = torch.from_numpy( np.array(cond_val_pos[1:]) ) # index 0: START_TOKEN logits_cond_val_pos = conds_value_logits[i, j, : len(cond_val_pos) - 1] conds_value_loss += self.cross_entropy( logits_cond_val_pos, target_cond_val_pos ) / len(conds_val_pos[i]) loss += conds_value_loss / B output_dict["loss"] = loss.unsqueeze(0) return output_dict class AggPredictor(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, agg_count): super(AggPredictor, self).__init__() self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.seq_attn = attention.LinearSeqAttn(model_dim) self.mlp = nn.Sequential( nn.Linear(model_dim, model_dim), nn.Tanh(), nn.Linear(model_dim, agg_count) ) def forward(self, question_embed, question_mask): encoded_question, _ = self.question_rnn(question_embed) attn_matrix = self.seq_attn(encoded_question, question_mask) attn_question = f.weighted_sum(attn_matrix, encoded_question) logits = self.mlp(attn_question) return logits class SelPredictor(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, column_attention=None): super(SelPredictor, self).__init__() self.column_attention = column_attention self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) if column_attention: self.linear_attn = nn.Linear(model_dim, model_dim) else: self.seq_attn = attention.LinearSeqAttn(model_dim) self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.linear_question = nn.Linear(model_dim, model_dim) self.linear_column = nn.Linear(model_dim, model_dim) self.mlp = nn.Sequential(nn.Tanh(), nn.Linear(model_dim, 1)) def forward(self, question_embed, question_mask, column_embed, column_name_mask, column_mask): B, C_L, N_L, embed_D = list(column_embed.size()) encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) encoded_question, _ = self.question_rnn(question_embed) if self.column_attention: attn_matrix = torch.bmm( encoded_column, self.linear_attn(encoded_question).transpose(1, 2) ) attn_matrix = f.add_masked_value(attn_matrix, question_mask.unsqueeze(1), value=-1e7) attn_matrix = F.softmax(attn_matrix, dim=-1) attn_question = (encoded_question.unsqueeze(1) * attn_matrix.unsqueeze(3)).sum(2) else: attn_matrix = self.seq_attn(encoded_question, question_mask) attn_question = f.weighted_sum(attn_matrix, encoded_question) attn_question = attn_question.unsqueeze(1) logits = self.mlp( self.linear_question(attn_question) + self.linear_column(encoded_column) ).squeeze() logits = f.add_masked_value(logits, column_mask, value=-1e7) return logits class CondsPredictor(nn.Module): def __init__( self, embed_dim, model_dim, rnn_num_layer, dropout, conds_op_count, column_maxlen, token_maxlen, column_attention=None, ): super(CondsPredictor, self).__init__() self.num_predictor = CondsNumPredictor( embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen ) self.column_predictor = CondsColPredictor( embed_dim, model_dim, rnn_num_layer, dropout, column_attention=column_attention ) self.op_predictor = CondsOpPredictor( embed_dim, model_dim, rnn_num_layer, dropout, conds_op_count, column_maxlen, column_attention=column_attention, ) self.value_pointer = CondsValuePointer( embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen, token_maxlen ) def forward( self, question_embed, question_mask, column_embed, column_name_mask, column_mask, col_idx, conds_val_pos, ): num_logits = self.num_predictor( question_embed, question_mask, column_embed, column_name_mask, column_mask ) column_logits = self.column_predictor( question_embed, question_mask, column_embed, column_name_mask, column_mask ) if col_idx is None: col_idx = [] preds_num = torch.argmax(num_logits, dim=-1) for i in range(column_logits.size(0)): _, pred_conds_column_idx = torch.topk(column_logits[i], preds_num[i]) col_idx.append(pred_conds_column_idx.tolist()) op_logits = self.op_predictor( question_embed, question_mask, column_embed, column_name_mask, col_idx ) value_logits = self.value_pointer( question_embed, question_mask, column_embed, column_name_mask, col_idx, conds_val_pos ) return (num_logits, column_logits, op_logits, value_logits) class CondsNumPredictor(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen): super(CondsNumPredictor, self).__init__() self.model_dim = model_dim self.column_maxlen = column_maxlen self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.column_seq_attn = attention.LinearSeqAttn(model_dim) self.column_to_hidden_state = nn.Linear(model_dim, 2 * model_dim) self.column_to_cell_state = nn.Linear(model_dim, 2 * model_dim) self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.question_seq_attn = attention.LinearSeqAttn(model_dim) self.mlp = nn.Sequential( nn.Linear(model_dim, model_dim), nn.Tanh(), nn.Linear(model_dim, column_maxlen + 1) ) def forward(self, question_embed, question_mask, column_embed, column_name_mask, column_mask): B, C_L, N_L, embed_D = list(column_embed.size()) encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) attn_column = self.column_seq_attn(encoded_column, column_mask) out_column = f.weighted_sum(attn_column, encoded_column) question_rnn_hidden_state = ( self.column_to_hidden_state(out_column) .view(B, self.column_maxlen, self.model_dim // 2) .transpose(0, 1) .contiguous() ) question_rnn_cell_state = ( self.column_to_cell_state(out_column) .view(B, self.column_maxlen, self.model_dim // 2) .transpose(0, 1) .contiguous() ) encoded_question, _ = self.question_rnn( question_embed, (question_rnn_hidden_state, question_rnn_cell_state) ) attn_question = self.question_seq_attn(encoded_question, question_mask) out_question = f.weighted_sum(attn_question, encoded_question) return self.mlp(out_question) class CondsColPredictor(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, column_attention=None): super(CondsColPredictor, self).__init__() self.column_attention = column_attention self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) if column_attention: self.linear_attn = nn.Linear(model_dim, model_dim) else: self.seq_attn = attention.LinearSeqAttn(model_dim) self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.linear_question = nn.Linear(model_dim, model_dim) self.linear_column = nn.Linear(model_dim, model_dim) self.mlp = nn.Sequential(nn.ReLU(), nn.Linear(model_dim, 1)) def forward(self, question_embed, question_mask, column_embed, column_name_mask, column_mask): B, C_L, N_L, embed_D = list(column_embed.size()) # Column Encoder encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) encoded_question, _ = self.question_rnn(question_embed) if self.column_attention: attn_matrix = torch.bmm( encoded_column, self.linear_attn(encoded_question).transpose(1, 2) ) attn_matrix = f.add_masked_value(attn_matrix, question_mask.unsqueeze(1), value=-1e7) attn_matrix = F.softmax(attn_matrix, dim=-1) attn_question = (encoded_question.unsqueeze(1) * attn_matrix.unsqueeze(3)).sum(2) else: attn_matrix = self.seq_attn(encoded_question, question_mask) attn_question = f.weighted_sum(attn_matrix, encoded_question) attn_question = attn_question.unsqueeze(1) logits = self.mlp( self.linear_question(attn_question) + self.linear_column(encoded_column) ).squeeze() logits = f.add_masked_value(logits, column_mask, value=-1e7) return logits class CondsOpPredictor(nn.Module): def __init__( self, embed_dim, model_dim, rnn_num_layer, dropout, op_count, column_maxlen, column_attention=None, ): super(CondsOpPredictor, self).__init__() self.column_attention = column_attention self.column_maxlen = column_maxlen self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) if column_attention: self.linear_attn = nn.Linear(model_dim, model_dim) else: self.seq_attn = attention.LinearSeqAttn(model_dim) self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.linear_question = nn.Linear(model_dim, model_dim) self.linear_column = nn.Linear(model_dim, model_dim) self.mlp = nn.Sequential( nn.Linear(model_dim, model_dim), nn.Tanh(), nn.Linear(model_dim, op_count) ) def forward(self, question_embed, question_mask, column_embed, column_name_mask, col_idx): B, C_L, N_L, embed_D = list(column_embed.size()) # Column Encoder encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) encoded_used_column = utils.filter_used_column( encoded_column, col_idx, padding_count=self.column_maxlen ) encoded_question, _ = self.question_rnn(question_embed) if self.column_attention: attn_matrix = torch.matmul( self.linear_attn(encoded_question).unsqueeze(1), encoded_used_column.unsqueeze(3) ).squeeze() attn_matrix = f.add_masked_value(attn_matrix, question_mask.unsqueeze(1), value=-1e7) attn_matrix = F.softmax(attn_matrix, dim=-1) attn_question = (encoded_question.unsqueeze(1) * attn_matrix.unsqueeze(3)).sum(2) else: attn_matrix = self.seq_attn(encoded_question, question_mask) attn_question = f.weighted_sum(attn_matrix, encoded_question) attn_question = attn_question.unsqueeze(1) return self.mlp( self.linear_question(attn_question) + self.linear_column(encoded_used_column) ).squeeze() class CondsValuePointer(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen, token_maxlen): super(CondsValuePointer, self).__init__() self.model_dim = model_dim self.column_maxlen = column_maxlen self.token_maxlen = token_maxlen self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.seq_attn = attention.LinearSeqAttn(model_dim) self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.decoder = nn.LSTM( input_size=self.token_maxlen, hidden_size=model_dim, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, ) self.linear_column = nn.Linear(model_dim, model_dim) self.linear_conds = nn.Linear(model_dim, model_dim) self.linear_question = nn.Linear(model_dim, model_dim) self.mlp = nn.Sequential(nn.ReLU(), nn.Linear(model_dim, 1)) def forward( self, question_embed, question_mask, column_embed, column_name_mask, col_idx, conds_val_pos ): B, C_L, N_L, embed_D = list(column_embed.size()) question_embed, question_mask = self.concat_start_and_end_zero_padding( question_embed, question_mask ) # Column Encoder encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) encoded_used_column = utils.filter_used_column( encoded_column, col_idx, padding_count=self.column_maxlen ) encoded_question, _ = self.question_rnn(question_embed) encoded_used_column = encoded_used_column.unsqueeze(2).unsqueeze(2) encoded_question = encoded_question.unsqueeze(1).unsqueeze(1) if conds_val_pos is None: # inference MAX_DECODER_STEP = 50 decoder_input = torch.zeros(4 * B, 1, self.token_maxlen) decoder_input[:, 0, 0] = 2 # Set Token if torch.cuda.is_available(): decoder_input = decoder_input.cuda() decoder_hidden = None logits = [] for _ in range(MAX_DECODER_STEP): step_logit, decoder_hidden = self.decode_then_output( encoded_used_column, encoded_question, question_mask, decoder_input, decoder_hidden=decoder_hidden, ) step_logit = step_logit.unsqueeze(1) logits.append(step_logit) # To ont-hot _, decoder_idxs = step_logit.view(B * self.column_maxlen, -1).max(1) decoder_input = torch.zeros(B * self.column_maxlen, self.token_maxlen).scatter_( 1, decoder_idxs.cpu().unsqueeze(1), 1 ) if torch.cuda.is_available(): decoder_input = decoder_input.cuda() logits = torch.stack(logits, 2) else: decoder_input, _ = utils.convert_position_to_decoder_input( conds_val_pos, token_maxlen=self.token_maxlen ) logits, _ = self.decode_then_output( encoded_used_column, encoded_question, question_mask, decoder_input ) return logits def concat_start_and_end_zero_padding(self, question_embed, mask): B, Q_L, embed_D = list(question_embed.size()) zero_padding = torch.zeros(B, 1, embed_D) mask_with_start_end = torch.zeros(B, Q_L + 2) if torch.cuda.is_available(): zero_padding = zero_padding.cuda(torch.cuda.current_device()) mask_with_start_end = mask_with_start_end.cuda(torch.cuda.current_device()) question_embed_with_start_end = torch.cat( [zero_padding, question_embed, zero_padding], dim=1 ) # add and mask_with_start_end[:, 0] = 1 # mask_with_start_end[:, 1 : Q_L + 1] = mask question_lengths = torch.sum(mask, dim=-1).byte() for i in range(B): mask_with_start_end[i, question_lengths[i].item() + 1] = 1 # return question_embed_with_start_end, mask_with_start_end def decode_then_output( self, encoded_used_column, encoded_question, question_mask, decoder_input, decoder_hidden=None, ): B = encoded_used_column.size(0) decoder_output, decoder_hidden = self.decoder( decoder_input.view(B * self.column_maxlen, -1, self.token_maxlen), decoder_hidden ) decoder_output = decoder_output.contiguous().view(B, self.column_maxlen, -1, self.model_dim) decoder_output = decoder_output.unsqueeze(3) logits = self.mlp( self.linear_column(encoded_used_column) + self.linear_conds(decoder_output) + self.linear_question(encoded_question) ).squeeze() logits = f.add_masked_value(logits, question_mask.unsqueeze(1).unsqueeze(1), value=-1e7) return logits, decoder_hidden ================================================ FILE: claf/model/semantic_parsing/utils.py ================================================ import numpy as np import torch def encode_column(column_embed, column_name_mask, rnn_module): B, C_L, N_L, embed_D = list(column_embed.size()) column_lengths = get_column_lengths(column_embed, column_name_mask) column_last_index = column_lengths - column_lengths.gt(0).long() # NOTE: hard-code column_reshape = [-1] + [N_L, embed_D] column_embed = column_embed.view(*column_reshape) encoded_column, _ = rnn_module(column_embed) encoded_D = encoded_column.size(-1) encoded_output_column = torch.cat( [ torch.index_select(encoded_column[i], 0, column_last_index[i]) for i in range(column_last_index.size(0)) ], dim=0, ) encoded_output_column = encoded_output_column.view([B, C_L, encoded_D]) return encoded_output_column def get_column_lengths(column_embed, column_name_mask): _, _, N_L, embed_D = list(column_embed.size()) column_reshape = [-1] + [N_L, embed_D] return torch.sum(column_name_mask.view(*column_reshape[:-1]), dim=-1).long() def filter_used_column(encoded_columns, col_idx, padding_count=4): B, C_L, D = list(encoded_columns.size()) zero_padding = torch.zeros(D) if torch.cuda.is_available(): zero_padding = zero_padding.cuda(torch.cuda.current_device()) encoded_used_columns = [] for i in range(B): encoded_used_column = torch.stack( [encoded_columns[i][j] for j in col_idx[i]] + [zero_padding] * (padding_count - len(col_idx[i])) ) encoded_used_columns.append(encoded_used_column) return torch.stack(encoded_used_columns) def convert_position_to_decoder_input(conds_val_pos, token_maxlen=200): B = len(conds_val_pos) max_len = ( max([max([len(tok) for tok in tok_seq] + [0]) for tok_seq in conds_val_pos]) - 1 ) # The max seq len in the batch. if max_len < 1: max_len = 1 ret_array = np.zeros((B, 4, max_len, token_maxlen), dtype=np.float32) ret_len = np.zeros((B, 4)) for b, tok_seq in enumerate(conds_val_pos): idx = 0 for idx, one_tok_seq in enumerate(tok_seq): out_one_tok_seq = one_tok_seq[:-1] ret_len[b, idx] = len(out_one_tok_seq) for t, tok_id in enumerate(out_one_tok_seq): ret_array[b, idx, t, tok_id] = 1 if idx < 3: ret_array[b, idx + 1 :, 0, 1] = 1 ret_len[b, idx + 1 :] = 1 ret_inp = torch.from_numpy(ret_array) if torch.cuda.is_available(): ret_inp = ret_inp.cuda(torch.cuda.current_device()) return ret_inp, ret_len # [B, IDX, max_len, token_maxlen] ================================================ FILE: claf/model/sequence_classification/__init__.py ================================================ from claf.model.sequence_classification.bert import BertForSeqCls from claf.model.sequence_classification.roberta import RobertaForSeqCls from claf.model.sequence_classification.structured_self_attention import StructuredSelfAttention # fmt: off __all__ = [ "BertForSeqCls", "RobertaForSeqCls", "StructuredSelfAttention" ] # fmt: on ================================================ FILE: claf/model/sequence_classification/bert.py ================================================ from overrides import overrides import torch.nn as nn from transformers import BertForSequenceClassification from claf.data.data_handler import CachePath from claf.decorator import register from claf.model.base import ModelWithoutTokenEmbedder from claf.model.sequence_classification.mixin import SequenceClassification @register("model:bert_for_seq_cls") class BertForSeqCls(SequenceClassification, ModelWithoutTokenEmbedder): """ Implementation of Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_classes: number of classified classes * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__(self, token_makers, num_classes, pretrained_model_name=None, dropout=0.2): super(BertForSeqCls, self).__init__(token_makers) self.use_transformers = True # for optimizer's model parameters self.num_classes = num_classes self.model = BertForSequenceClassification.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT), num_labels=num_classes, ) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [3, 4, 1, 0, 0, 0, ...], ..., ] }, "token_type": { "feature": [ [0, 0, 0, 0, 0, 0, ...], ..., ], } } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - logits: representing unnormalized log probabilities of the class. - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self.model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) logits = outputs[0] output_dict = {"logits": logits} if labels: class_idx = labels["class_idx"] data_idx = labels["data_idx"] output_dict["class_idx"] = class_idx output_dict["data_idx"] = data_idx # Loss loss = self.criterion( logits.view(-1, self.num_classes), class_idx.view(-1) ) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence_a = helper["examples"][data_id]["sequence_a"] sequence_a_tokens = helper["examples"][data_id]["sequence_a_tokens"] sequence_b = helper["examples"][data_id]["sequence_b"] sequence_b_tokens = helper["examples"][data_id]["sequence_b_tokens"] target_class_text = helper["examples"][data_id]["class_text"] pred_class_idx = predictions[data_id]["class_idx"] pred_class_text = self._dataset.get_class_text_with_idx(pred_class_idx) print() print("- Sequence a:", sequence_a) print("- Sequence a Tokens:", sequence_a_tokens) if sequence_b: print("- Sequence b:", sequence_b) print("- Sequence b Tokens:", sequence_b_tokens) print("- Target:") print(" Class:", target_class_text) print("- Predict:") print(" Class:", pred_class_text) print() ================================================ FILE: claf/model/sequence_classification/mixin.py ================================================ from pathlib import Path import logging import torch import pycm from pycm.pycm_obj import pycmVectorError from claf.model import cls_utils from claf.model.base import ModelBase from claf.metric.classification import macro_f1, macro_precision, macro_recall from claf.metric.glue import simple_accuracy, f1, matthews_corr logger = logging.getLogger(__name__) class SequenceClassification: """ Sequence Classification Mixin Class """ def make_predictions(self, output_dict): """ Make predictions with model's output_dict * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities of the class - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized * Returns: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx """ data_indices = output_dict["data_idx"] pred_logits = output_dict["logits"] pred_class_idxs = torch.argmax(pred_logits, dim=-1) predictions = { self._dataset.get_id(data_idx.item()): {"class_idx": pred_class_idx.item()} for data_idx, pred_class_idx in zip(list(data_indices.data), list(pred_class_idxs.data)) } return predictions def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities of the class. arguments: arguments dictionary consisting of user_input helper: dictionary to get the classification result, consisting of - class_idx2text: dictionary converting class_idx to class_text * Returns: output dict (dict) consisting of - logits: representing unnormalized log probabilities of the class - class_idx: predicted class idx - class_text: predicted class text """ logits = output_dict["logits"] class_idx = logits.argmax(dim=-1) return { "logits": logits, "class_idx": class_idx, "class_text": helper["class_idx2text"][class_idx.item()], } def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: metrics: metric dictionary consisting of - 'macro_f1': class prediction macro(unweighted mean) f1 - 'macro_precision': class prediction macro(unweighted mean) precision - 'macro_recall': class prediction macro(unweighted mean) recall - 'accuracy': class prediction accuracy """ pred_idx = [] pred_classes = [] target_idx = [] target_classes = [] target_count = len(self._dataset.class_idx2text) for data_id, pred in predictions.items(): target = self._dataset.get_ground_truth(data_id) pred_idx.append(pred["class_idx"]) pred_classes.append(self._dataset.class_idx2text[pred["class_idx"]]) target_idx.append(target["class_idx"]) target_classes.append(target["class_text"]) metrics = { "accuracy": simple_accuracy(pred_idx, target_idx), } if target_count == 2: # binary class f1_metric = f1(pred_idx, target_idx) metrics.update(f1_metric) matthews_corr_metric = matthews_corr(pred_idx, target_idx) metrics.update(matthews_corr_metric) return metrics def write_predictions(self, predictions, file_path=None, is_dict=True, pycm_obj=None): """ Override write_predictions() in ModelBase to log confusion matrix """ try: super(SequenceClassification, self).write_predictions( predictions, file_path=file_path, is_dict=is_dict ) except AttributeError: # TODO: Need to Fix model_base = ModelBase() model_base._log_dir = self._log_dir model_base._train_counter = self._train_counter model_base.training = self.training model_base.write_predictions(predictions, file_path=file_path, is_dict=is_dict) data_type = "train" if self.training else "valid" if pycm_obj is not None: stats_file_path = f"predictions-{data_type}-{self._train_counter.get_display()}-stats" pycm_obj.save_csv(str(Path(self._log_dir) / "predictions" / stats_file_path)) confusion_matrix_file_path = ( f"predictions-{data_type}-{self._train_counter.get_display()}-confusion_matrix" ) cls_utils.write_confusion_matrix_to_csv( str(Path(self._log_dir) / "predictions" / confusion_matrix_file_path), pycm_obj ) def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence = helper["examples"][data_id]["sequence"] target_class_text = helper["examples"][data_id]["class_text"] pred_class_idx = predictions[data_id]["class_idx"] pred_class_text = self._dataset.get_class_text_with_idx(pred_class_idx) print() print("- Sequence:", sequence) print("- Target:") print(" Class:", target_class_text) print("- Predict:") print(" Class:", pred_class_text) print() ================================================ FILE: claf/model/sequence_classification/roberta.py ================================================ from overrides import overrides from transformers import RobertaForSequenceClassification import torch.nn as nn from claf.data.data_handler import CachePath from claf.decorator import register from claf.model.base import ModelWithoutTokenEmbedder from claf.model.sequence_classification.mixin import SequenceClassification @register("model:roberta_for_seq_cls") class RobertaForSeqCls(SequenceClassification, ModelWithoutTokenEmbedder): """ Implementation of Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_classes: number of classified classes * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__(self, token_makers, num_classes, pretrained_model_name=None, dropout=0.2): super(RobertaForSeqCls, self).__init__(token_makers) self.use_pytorch_transformers = True # for optimizer's model parameters self.num_classes = num_classes self.model = RobertaForSequenceClassification.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT), num_labels=num_classes, ) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [3, 4, 1, 0, 0, 0, ...], ..., ] }, } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - logits: representing unnormalized log probabilities of the class. - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self.model( bert_inputs, token_type_ids=None, attention_mask=attention_mask ) logits = outputs[0] output_dict = {"logits": logits} if labels: class_idx = labels["class_idx"] data_idx = labels["data_idx"] output_dict["class_idx"] = class_idx output_dict["data_idx"] = data_idx # Loss loss = self.criterion( logits.view(-1, self.num_classes), class_idx.view(-1) ) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence_a = helper["examples"][data_id]["sequence_a"] sequence_a_tokens = helper["examples"][data_id]["sequence_a_tokens"] sequence_b = helper["examples"][data_id]["sequence_b"] sequence_b_tokens = helper["examples"][data_id]["sequence_b_tokens"] target_class_text = helper["examples"][data_id]["class_text"] pred_class_idx = predictions[data_id]["class_idx"] pred_class_text = self._dataset.get_class_text_with_idx(pred_class_idx) print() print("- Sequence a:", sequence_a) print("- Sequence a Tokens:", sequence_a_tokens) if sequence_b: print("- Sequence b:", sequence_b) print("- Sequence b Tokens:", sequence_b_tokens) print("- Target:") print(" Class:", target_class_text) print("- Predict:") print(" Class:", pred_class_text) print() ================================================ FILE: claf/model/sequence_classification/structured_self_attention.py ================================================ from overrides import overrides import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from claf.decorator import register from claf.model.base import ModelWithTokenEmbedder from claf.model.sequence_classification.mixin import SequenceClassification from claf.modules import functional as f @register("model:structured_self_attention") class StructuredSelfAttention(SequenceClassification, ModelWithTokenEmbedder): """ Implementation of model presented in A Structured Self-attentive Sentence Embedding (https://arxiv.org/abs/1703.03130) * Args: token_embedder: used to embed the sequence num_classes: number of classified classes * Kwargs: encoding_rnn_hidden_dim: hidden dimension of rnn (unidirectional) encoding_rnn_num_layer: the number of rnn layers encoding_rnn_dropout: rnn dropout probability attention_dim: attention dimension # d_a in the paper num_attention_heads: number of attention heads # r in the paper sequence_embed_dim: dimension of sequence embedding dropout: classification layer dropout penalization_coefficient: penalty coefficient for frobenius norm """ def __init__( self, token_embedder, num_classes, encoding_rnn_hidden_dim=300, encoding_rnn_num_layer=2, encoding_rnn_dropout=0., attention_dim=350, num_attention_heads=30, sequence_embed_dim=2000, dropout=0.5, penalization_coefficient=1., ): super(StructuredSelfAttention, self).__init__(token_embedder) rnn_input_dim = token_embedder.get_embed_dim() self.num_classes = num_classes self.encoding_rnn_hidden_dim = encoding_rnn_hidden_dim * 2 # bidirectional self.attention_dim = attention_dim self.num_attention_heads = num_attention_heads self.project_dim = sequence_embed_dim self.dropout = dropout self.penalization_coefficient = penalization_coefficient self.encoder = nn.LSTM( input_size=rnn_input_dim, hidden_size=encoding_rnn_hidden_dim, num_layers=encoding_rnn_num_layer, dropout=encoding_rnn_dropout, bidirectional=True, batch_first=True, ) self.A = nn.Sequential( nn.Linear(self.encoding_rnn_hidden_dim, attention_dim, bias=False), nn.Tanh(), nn.Linear(attention_dim, num_attention_heads, bias=False), ) self.fully_connected = nn.Sequential( nn.Linear(self.encoding_rnn_hidden_dim * num_attention_heads, sequence_embed_dim), nn.ReLU(), nn.Dropout(dropout), ) self.classifier = nn.Linear(sequence_embed_dim, num_classes) self.criterion = nn.CrossEntropyLoss() @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"sequence": [0, 3, 4, 1]} * Kwargs: label: label dictionary like below. {"class_idx": 2, "data_idx": 0} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities of the class. - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ sequence = features["sequence"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward sequence_config = f.get_sorted_seq_config(sequence) token_embed = self.token_embedder(sequence) token_encodings = f.forward_rnn_with_pack( self.encoder, token_embed, sequence_config ) # [B, L, encoding_rnn_hidden_dim] attention = self.A(token_encodings).transpose(1, 2) # [B, num_attention_heads, L] sequence_mask = f.get_mask_from_tokens(sequence).float() # [B, L] sequence_mask = sequence_mask.unsqueeze(1).expand_as(attention) attention = F.softmax(f.add_masked_value(attention, sequence_mask) + 1e-13, dim=2) attended_encodings = torch.bmm( attention, token_encodings ) # [B, num_attention_heads, sequence_embed_dim] sequence_embed = self.fully_connected( attended_encodings.view(attended_encodings.size(0), -1) ) # [B, sequence_embed_dim] logits = self.classifier(sequence_embed) # [B, num_classes] output_dict = {"sequence_embed": sequence_embed, "logits": logits} if labels: class_idx = labels["class_idx"] data_idx = labels["data_idx"] output_dict["class_idx"] = class_idx output_dict["data_idx"] = data_idx # Loss loss = self.criterion(logits, class_idx) loss += self.penalty(attention) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict def penalty(self, attention): aa = torch.bmm( attention, attention.transpose(1, 2) ) # [B, num_attention_heads, num_attention_heads] penalization_term = ((aa - aa.new_tensor(np.eye(aa.size(1)))) ** 2).sum() ** 0.5 return penalization_term * self.penalization_coefficient ================================================ FILE: claf/model/token_classification/__init__.py ================================================ from claf.model.token_classification.bert import BertForTokCls # fmt: off __all__ = [ "BertForTokCls", ] # fmt: on ================================================ FILE: claf/model/token_classification/bert.py ================================================ from overrides import overrides import torch.nn as nn from transformers import BertForTokenClassification from claf.data.data_handler import CachePath from claf.decorator import register from claf.model.base import ModelWithoutTokenEmbedder from claf.model.token_classification.mixin import TokenClassification from claf.model import cls_utils @register("model:bert_for_tok_cls") class BertForTokCls(TokenClassification, ModelWithoutTokenEmbedder): """ Implementation of Single Sentence Tagging model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_tags: number of classified tags ignore_tag_idx: index of the tag to ignore when calculating loss (tag pad value) * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__( self, token_makers, num_tags, ignore_tag_idx, pretrained_model_name=None, dropout=0.2 ): super(BertForTokCls, self).__init__(token_makers) self.use_transformers = True # for optimizer's model parameters self.ignore_tag_idx = ignore_tag_idx self.num_tags = num_tags self.model = BertForTokenClassification.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT), num_labels=num_tags, ) self.criterion = nn.CrossEntropyLoss(ignore_index=ignore_tag_idx) @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [100, 576, 21, 45, 7, 91, 101, 0, 0, ...], ..., ] } "token_type": { "feature": [ [0, 0, 0, 0, 0, 0, 0, 0, 0, ...], ..., ] }, "tagged_sub_token_idxs": { [ [1, 3, 4, 0, 0, 0, 0, 0, 0, ...], ..., ] } } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - tag_logits: representing unnormalized log probabilities of the tags. - tag_idxs: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] tagged_sub_token_idxs = features["tagged_sub_token_idxs"]["feature"] num_tokens = features["num_tokens"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self.model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) logits = outputs[0] # [B, L, num_tags] # gather the logits of the tagged token positions. gather_token_pos_idxs = tagged_sub_token_idxs.unsqueeze(-1).repeat(1, 1, self.num_tags) token_tag_logits = logits.gather(1, gather_token_pos_idxs) # [B, num_tokens, num_tags] sliced_token_tag_logits = [token_tag_logits[idx, :n, :] for idx, n in enumerate(num_tokens)] output_dict = {"tag_logits": sliced_token_tag_logits} if labels: tag_idxs = labels["tag_idxs"] data_idx = labels["data_idx"] output_dict["tag_idxs"] = tag_idxs output_dict["data_idx"] = data_idx # Loss loss = self.criterion(token_tag_logits.view(-1, self.num_tags), tag_idxs.view(-1)) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Tags, Target Slots, Predicted Tags, Predicted Slots) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence = helper["examples"][data_id]["sequence"] target_tag_texts = helper["examples"][data_id]["tag_texts"] pred_tag_idxs = predictions[data_id]["tag_idxs"] pred_tag_texts = self._dataset.get_tag_texts_with_idxs(pred_tag_idxs) sequence_tokens = helper["examples"][data_id]["sequence_sub_tokens"] print() print("- Sequence:", sequence) print("- Sequence Tokens:", sequence_tokens) print("- Target:") print(" Tags:", target_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, target_tag_texts)) print("- Predict:") print(" Tags:", pred_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, pred_tag_texts)) print() ================================================ FILE: claf/model/token_classification/mixin.py ================================================ from pathlib import Path import logging import numpy as np import torch import pycm from pycm.pycm_obj import pycmVectorError from claf.decorator import arguments_required import claf.utils as common_utils from claf.model import cls_utils from claf.metric.classification import macro_f1, macro_precision, macro_recall from seqeval.metrics import accuracy_score as conlleval_accuracy from seqeval.metrics import f1_score as conlleval_f1 logger = logging.getLogger(__name__) class TokenClassification: """ Token Classification Mixin Class """ def make_predictions(self, output_dict): """ Make predictions with model's output_dict * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - tag_logits: representing unnormalized log probabilities of the tag - tag_idxs: target tag idxs - data_idx: data idx - loss: a scalar loss to be optimized * Returns: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - tag_idxs """ data_indices = output_dict["data_idx"] pred_tag_logits = output_dict["tag_logits"] pred_tag_idxs = [ torch.argmax(pred_tag_logit, dim=-1).tolist() for pred_tag_logit in pred_tag_logits ] predictions = { self._dataset.get_id(data_idx.item()): {"tag_idxs": pred_tag_idx} for data_idx, pred_tag_idx in zip(list(data_indices.data), pred_tag_idxs) } return predictions @arguments_required(["sequence"]) def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - tag_logits: representing unnormalized log probabilities of the tags. arguments: arguments dictionary consisting of user_input helper: dictionary to get the classification result, consisting of - tag_idx2text: dictionary converting tag_idx to tag_text * Returns: output dict (dict) consisting of - tag_logits: representing unnormalized log probabilities of the tags - tag_idxs: predicted tag idxs - tag_texts: predicted tag texts - tag_slots: predicted tag slots """ sequence = arguments["sequence"] tag_logits = output_dict["tag_logits"][0] tag_idxs = [tag_logit.argmax(dim=-1) for tag_logit in tag_logits] tag_texts = [helper["tag_idx2text"][tag_idx.item()] for tag_idx in tag_idxs] return { "tag_logits": tag_logits, "tag_idxs": tag_idxs, "tag_texts": tag_texts, "tag_dict": cls_utils.get_tag_dict(sequence, tag_texts), } def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - tag_idxs * Returns: metrics: metric dictionary consisting of - 'accuracy': sequence level accuracy - 'tag_accuracy': tag level accuracy - 'macro_f1': tag prediction macro(unweighted mean) f1 - 'macro_precision': tag prediction macro(unweighted mean) precision - 'macro_recall': tag prediction macro(unweighted mean) recall """ pred_tag_idxs_list = [] target_tag_idxs_list = [] accurate_sequence = [] for data_idx, pred in predictions.items(): target = self._dataset.get_ground_truth(data_idx) pred_tag_idxs_list.append(pred["tag_idxs"]) target_tag_idxs_list.append(target["tag_idxs"]) accurate_sequence.append( 1 if (np.asarray(target["tag_idxs"]) == np.asarray(pred["tag_idxs"])).all() else 0 ) pred_tags = [ [self._dataset.tag_idx2text[tag_idx] for tag_idx in tag_idxs] for tag_idxs in pred_tag_idxs_list ] target_tags = [ [self._dataset.tag_idx2text[tag_idx] for tag_idx in tag_idxs] for tag_idxs in target_tag_idxs_list ] flat_pred_tags = list(common_utils.flatten(pred_tags)) flat_target_tags = list(common_utils.flatten(target_tags)) # confusion matrix try: pycm_obj = pycm.ConfusionMatrix(actual_vector=flat_target_tags, predict_vector=flat_pred_tags) except pycmVectorError as e: if str(e) == "Number of the classes is lower than 2": logger.warning("Number of tags in the batch is 1. Sanity check is highly recommended.") return { "accuracy": 1., "tag_accuracy": 1., "macro_f1": 1., "macro_precision": 1., "macro_recall": 1., "conlleval_accuracy": 1., "conlleval_f1": 1., } raise self.write_predictions( {"target": flat_target_tags, "predict": flat_pred_tags}, pycm_obj=pycm_obj ) sequence_accuracy = sum(accurate_sequence) / len(accurate_sequence) metrics = { "accuracy": sequence_accuracy, "tag_accuracy": pycm_obj.Overall_ACC, "macro_f1": macro_f1(pycm_obj), "macro_precision": macro_precision(pycm_obj), "macro_recall": macro_recall(pycm_obj), "conlleval_accuracy": conlleval_accuracy(target_tags, pred_tags), "conlleval_f1": conlleval_f1(target_tags, pred_tags), } return metrics def write_predictions(self, predictions, file_path=None, is_dict=True, pycm_obj=None): """ Override write_predictions() in ModelBase to log confusion matrix """ super(TokenClassification, self).write_predictions( predictions, file_path=file_path, is_dict=is_dict ) data_type = "train" if self.training else "valid" if pycm_obj is not None: stats_file_path = f"predictions-{data_type}-{self._train_counter.get_display()}-stats" pycm_obj.save_csv(str(Path(self._log_dir) / "predictions" / stats_file_path)) confusion_matrix_file_path = ( f"predictions-{data_type}-{self._train_counter.get_display()}-confusion_matrix" ) cls_utils.write_confusion_matrix_to_csv( str(Path(self._log_dir) / "predictions" / confusion_matrix_file_path), pycm_obj ) def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Target Tags, Target Slots, Predicted Tags, Predicted Slots) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence = helper["examples"][data_id]["sequence"] target_tag_texts = helper["examples"][data_id]["tag_texts"] pred_tag_idxs = predictions[data_id]["tag_idxs"] pred_tag_texts = self._dataset.get_tag_texts_with_idxs(pred_tag_idxs) print() print("- Sequence:", sequence) print("- Target:") print(" Tags:", target_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, target_tag_texts)) print("- Predict:") print(" Tags:", pred_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, pred_tag_texts)) print() ================================================ FILE: claf/modules/__init__.py ================================================ ================================================ FILE: claf/modules/activation.py ================================================ import torch.nn as nn def get_activation_fn(name): """ PyTorch built-in activation functions """ activation_functions = { "linear": lambda: lambda x: x, "relu": nn.ReLU, "relu6": nn.ReLU6, "elu": nn.ELU, "prelu": nn.PReLU, "leaky_relu": nn.LeakyReLU, "threshold": nn.Threshold, "hardtanh": nn.Hardtanh, "sigmoid": nn.Sigmoid, "tanh": nn.Tanh, "log_sigmoid": nn.LogSigmoid, "softplus": nn.Softplus, "softshrink": nn.Softshrink, "softsign": nn.Softsign, "tanhshrink": nn.Tanhshrink, } if name not in activation_functions: raise ValueError( f"'{name}' is not included in activation_functions. use below one. \n {activation_functions.keys()}" ) return activation_functions[name] ================================================ FILE: claf/modules/attention/__init__.py ================================================ from .bi_attention import BiAttention from .co_attention import CoAttention from .docqa_attention import DocQAAttention from .multi_head_attention import MultiHeadAttention from .seq_attention import SeqAttnMatch, LinearSeqAttn, BilinearSeqAttn __all__ = [ "BiAttention", "CoAttention", "MultiHeadAttention", "DocQAAttention", "SeqAttnMatch", "LinearSeqAttn", "BilinearSeqAttn", ] ================================================ FILE: claf/modules/attention/bi_attention.py ================================================ import torch import torch.nn as nn import claf.modules.functional as f class BiAttention(nn.Module): """ Attention Flow Layer in BiDAF (https://arxiv.org/pdf/1611.01603.pdf) The Similarity matrix Context-to-query Attention (C2Q) Query-to-context Attention (Q2C) * Args: model_dim: The number of module dimension """ def __init__(self, model_dim): super(BiAttention, self).__init__() self.model_dim = model_dim self.W = nn.Linear(6 * model_dim, 1, bias=False) def forward(self, context, context_mask, query, query_mask): c, c_mask, q, q_mask = context, context_mask, query, query_mask S = self._make_similiarity_matrix(c, q) # (B, C_L, Q_L) masked_S = f.add_masked_value(S, query_mask.unsqueeze(1), value=-1e7) c2q = self._context2query(S, q, q_mask) q2c = self._query2context(masked_S.max(dim=-1)[0], c, c_mask) # [h; u˜; h◦u˜; h◦h˜] ~ (B, C_L, 8d) G = torch.cat((c, c2q, c * c2q, c * q2c), dim=-1) return G def _make_similiarity_matrix(self, c, q): # B: batch_size, C_L: context_maxlen, Q_L: query_maxlen B, C_L, Q_L = c.size(0), c.size(1), q.size(1) matrix_shape = (B, C_L, Q_L, self.model_dim * 2) c_aug = c.unsqueeze(2).expand(matrix_shape) # (B, C_L, Q_L, 2d) q_aug = q.unsqueeze(1).expand(matrix_shape) # (B, C_L, Q_L, 2d) c_q = torch.mul(c_aug, q_aug) # element-wise multiplication concated_vector = torch.cat((c_aug, q_aug, c_q), dim=3) # [h; u; h◦u] return self.W(concated_vector).view(c.size(0), C_L, Q_L) def _context2query(self, S, q, q_mask): attention = f.last_dim_masked_softmax(S, q_mask) # (B, C_L, Q_L) c2q = f.weighted_sum(attention=attention, matrix=q) # (B, C_L, 2d) return c2q def _query2context(self, S, c, c_mask): attention = f.masked_softmax(S, c_mask) # (B, C_L) q2c = f.weighted_sum(attention=attention, matrix=c) return q2c.unsqueeze(1).expand(c.size()) # (B, C_L, 2d) ================================================ FILE: claf/modules/attention/co_attention.py ================================================ import torch import torch.nn as nn import torch.nn.functional as F import claf.modules.functional as f class CoAttention(nn.Module): """ CoAttention encoder in Dynamic Coattention Networks For Question Answering (https://arxiv.org/abs/1611.01604) check the Figure 2 in paper * Args: embed_dim: the number of input embedding dimension """ def __init__(self, embed_dim): super(CoAttention, self).__init__() self.W_0 = nn.Linear(embed_dim * 3, 1, bias=False) def forward(self, context_embed, question_embed, context_mask=None, question_mask=None): C, Q = context_embed, question_embed B, C_L, Q_L, D = C.size(0), C.size(1), Q.size(1), Q.size(2) similarity_matrix_shape = torch.zeros(B, C_L, Q_L, D) # (B, C_L, Q_L, D) C_ = C.unsqueeze(2).expand_as(similarity_matrix_shape) Q_ = Q.unsqueeze(1).expand_as(similarity_matrix_shape) C_Q = torch.mul(C_, Q_) S = self.W_0(torch.cat([C_, Q_, C_Q], 3)).squeeze(3) # (B, C_L, Q_L) S_question = S if question_mask is not None: S_question = f.add_masked_value(S_question, question_mask.unsqueeze(1), value=-1e7) S_q = F.softmax(S_question, 2) # (B, C_L, Q_L) S_context = S.transpose(1, 2) if context_mask is not None: S_context = f.add_masked_value(S_context, context_mask.unsqueeze(1), value=-1e7) S_c = F.softmax(S_context, 2) # (B, Q_L, C_L) A = torch.bmm(S_q, Q) # context2query (B, C_L, D) B = torch.bmm(S_q, S_c).bmm(C) # query2context (B, Q_L, D) out = torch.cat([C, A, C * A, C * B], dim=-1) return out ================================================ FILE: claf/modules/attention/docqa_attention.py ================================================ import torch import torch.nn as nn import torch.nn.functional as F from claf.modules import initializer import claf.modules.functional as f class DocQAAttention(nn.Module): """ Bi-Attention Layer + (Self-Attention) in DocumentQA (https://arxiv.org/abs/1710.10723) * Args: rnn_dim: the number of GRU cell hidden size linear_dim: the number of linear hidden size * Kwargs: self_attn: (bool) self-attention weight_init: (bool) weight initialization """ def __init__(self, rnn_dim, linear_dim, self_attn=False, weight_init=True): super(DocQAAttention, self).__init__() self.self_attn = self_attn self.input_w = nn.Linear(2 * rnn_dim, 1, bias=False) self.key_w = nn.Linear(2 * rnn_dim, 1, bias=False) self.dot_w = nn.Parameter(torch.randn(1, 1, rnn_dim * 2)) torch.nn.init.xavier_uniform_(self.dot_w) self.bias = nn.Parameter(torch.FloatTensor([[1]])) self.diag_mask = nn.Parameter(torch.eye(5000)) # NOTE: (hard-code) max_sequence_length if weight_init: initializer.weight(self.input_w) initializer.weight(self.key_w) def forward(self, x, x_mask, key, key_mask): S = self._trilinear(x, key) if self.self_attn: seq_length = x.size(1) diag_mask = self.diag_mask.narrow(0, 0, seq_length).narrow(1, 0, seq_length) joint_mask = 1 - self._compute_attention_mask(x_mask, key_mask) mask = torch.clamp(diag_mask + joint_mask, 0, 1) masked_S = S + mask * (-1e7) x2key = self._x2key(masked_S, key, key_mask) return torch.cat((x, x2key, x * x2key), dim=-1) else: joint_mask = 1 - self._compute_attention_mask(x_mask, key_mask) masked_S = S + joint_mask * (-1e7) x2key = self._x2key(masked_S, key, key_mask) masked_S = f.add_masked_value(S, key_mask.unsqueeze(1), value=-1e7) key2x = self._key2x(masked_S.max(dim=-1)[0], x, x_mask) return torch.cat((x, x2key, x * x2key, x * key2x), dim=-1) def _compute_attention_mask(self, x_mask, key_mask): x_mask = x_mask.unsqueeze(2) key_mask = key_mask.unsqueeze(1) joint_mask = torch.mul(x_mask, key_mask) return joint_mask def _trilinear(self, x, key): B, X_L, K_L = x.size(0), x.size(1), key.size(1) matrix_shape = (B, X_L, K_L) x_logits = self.input_w(x).expand(matrix_shape) key_logits = self.key_w(key).transpose(1, 2).expand(matrix_shape) x_dots = torch.mul(x, self.dot_w) x_key = torch.matmul(x_dots, key.transpose(1, 2)) return x_logits + key_logits + x_key def _x2key(self, S, key, key_mask): if self.self_attn: bias = torch.exp(self.bias) S = torch.exp(S) attention = S / (S.sum(dim=-1, keepdim=True).expand(S.size()) + bias.expand(S.size())) else: attention = F.softmax(S, dim=-1) # (B, C_L, Q_L) x2key = f.weighted_sum(attention=attention, matrix=key) # (B, C_L, 2d) return x2key def _key2x(self, S, x, x_mask): attention = f.masked_softmax(S, x_mask) # (B, C_L) key2x = f.weighted_sum(attention=attention, matrix=x) return key2x.unsqueeze(1).expand(x.size()) # (B, C_L, 2d) ================================================ FILE: claf/modules/attention/multi_head_attention.py ================================================ import math import torch import torch.nn as nn import torch.nn.functional as F import claf.modules.functional as f class MultiHeadAttention(nn.Module): """ Transformer's Multi-Head Attention in "Attention is All You Need" (https://arxiv.org/abs/1706.03762) * Kwargs: num_head: the number of Head model_dim: the number of model dimension linear_key_dim: the number of linear key dimemsion linear_value_dim: the number of linear value dimension """ def __init__( self, num_head=8, model_dim=100, dropout=0.1, linear_key_dim=None, linear_value_dim=None ): super(MultiHeadAttention, self).__init__() if linear_key_dim is None: linear_key_dim = model_dim if linear_value_dim is None: linear_value_dim = model_dim assert linear_key_dim % num_head == 0 assert linear_value_dim % num_head == 0 self.model_dim = model_dim self.num_head = num_head self.projection = nn.ModuleList( [ nn.Linear(model_dim, linear_key_dim, bias=False), # query nn.Linear(model_dim, linear_key_dim, bias=False), # key nn.Linear(model_dim, linear_value_dim, bias=False), # value ] ) self.out_linear = nn.Linear(linear_value_dim, model_dim) if dropout > 0: self.dropout = nn.Dropout(dropout) else: self.dropout = lambda x: x def forward(self, q, k, v, mask=None): q, k, v = self._linear_projection(q, k, v) qs, ks, vs = self._split_heads(q, k, v) outputs = self._scaled_dot_product(qs, ks, vs, mask=mask) output = self._concat_heads(outputs) return self.out_linear(output) def _linear_projection(self, query, key, value): q = self.projection[0](query) k = self.projection[1](key) v = self.projection[2](value) return q, k, v def _split_heads(self, query, key, value): B = query.size(0) qs, ks, vs = [ x.view(B, -1, self.num_head, x.size(-1) // self.num_head).transpose(1, 2) for x in [query, key, value] ] return qs, ks, vs def _scaled_dot_product(self, query, key, value, mask=None): K_D = query.size(-1) scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(K_D) if mask is not None: mask = mask.unsqueeze(1).unsqueeze(1) # [B, #H, C_L, D] scores = f.add_masked_value(scores, mask, value=-1e7) attn = F.softmax(scores, dim=-1) attn = self.dropout(attn) return torch.matmul(attn, value) def _concat_heads(self, outputs): B = outputs.size(0) num_head, dim = outputs.size()[-2:] return outputs.transpose(1, 2).contiguous().view(B, -1, self.num_head * dim) ================================================ FILE: claf/modules/attention/seq_attention.py ================================================ #!/usr/bin/env python3 # Copyright 2017-present, Facebook, Inc. # All rights reserved. # # This source code is licensed under the license found in the # LICENSE file in the root directory of this source tree. """ original code from: https://github.com/facebookresearch/DrQA/blob/master/drqa/reader/layers.py """ import torch.nn as nn import torch.nn.functional as F class SeqAttnMatch(nn.Module): """ Given sequences X and Y, match sequence Y to each element in X. * o_i = sum(alpha_j * y_j) for i in X * alpha_j = softmax(y_j * x_i) """ def __init__(self, embed_dim, identity=False): super(SeqAttnMatch, self).__init__() if not identity: self.linear = nn.Linear(embed_dim, embed_dim) else: self.linear = None def forward(self, x, y, y_mask): if self.linear: x_proj = self.linear(x.view(-1, x.size(2))).view(x.size()) x_proj = F.relu(x_proj) y_proj = self.linear(y.view(-1, y.size(2))).view(y.size()) y_proj = F.relu(y_proj) else: x_proj = x y_proj = y scores = x_proj.bmm(y_proj.transpose(2, 1)) y_mask = y_mask.unsqueeze(1).expand(scores.size()) scores = scores.masked_fill((y_mask == 0), -1e30) alpha_flat = F.softmax(scores.view(-1, y.size(1)), -1) alpha = alpha_flat.view(-1, x.size(1), y.size(1)) matched_seq = alpha.bmm(y) return matched_seq class LinearSeqAttn(nn.Module): """ Self attention over a sequence: * o_i = softmax(Wx_i) for x_i in X. """ def __init__(self, input_size): super(LinearSeqAttn, self).__init__() self.linear = nn.Linear(input_size, 1) def forward(self, x, x_mask): x_flat = x.contiguous().view(-1, x.size(-1)) scores = self.linear(x_flat).view(x.size(0), x.size(1)) scores.data.masked_fill_((x_mask == 0), -1e30) alpha = F.softmax(scores, dim=-1) return alpha class BilinearSeqAttn(nn.Module): """ A bilinear attention layer over a sequence X w.r.t y: * o_i = softmax(x_i'Wy) for x_i in X. Optionally don't normalize output weights. """ def __init__(self, x_size, y_size, identity=False, normalize=True): super(BilinearSeqAttn, self).__init__() self.normalize = normalize if not identity: self.linear = nn.Linear(y_size, x_size) else: self.linear = None def forward(self, x, y, x_mask): Wy = self.linear(y) if self.linear is not None else y xWy = x.bmm(Wy.unsqueeze(2)).squeeze(2) xWy.data.masked_fill_((x_mask == 0), -1e30) if self.normalize: if self.training: alpha = F.log_softmax(xWy, dim=-1) else: alpha = F.softmax(xWy, dim=-1) else: alpha = xWy.exp() return alpha ================================================ FILE: claf/modules/conv/__init__.py ================================================ from .depthwise_separable_conv import DepSepConv from .pointwise_conv import PointwiseConv __all__ = ["DepSepConv", "PointwiseConv"] ================================================ FILE: claf/modules/conv/depthwise_separable_conv.py ================================================ import torch.nn as nn import torch.nn.functional as F from .pointwise_conv import PointwiseConv class DepSepConv(nn.Module): """ Depthwise Separable Convolutions in Xception: Deep Learning with Depthwise Separable Convolutions (https://arxiv.org/abs/1610.02357) depthwise -> pointwise (1x1 conv) * Args: input_size: the number of input tensor's dimension num_filters: the number of convolution filter kernel_size: the number of convolution kernel size """ def __init__(self, input_size=None, num_filters=None, kernel_size=None): super(DepSepConv, self).__init__() self.depthwise = nn.Conv1d( in_channels=input_size, out_channels=input_size, kernel_size=kernel_size, groups=input_size, padding=kernel_size // 2, ) nn.init.kaiming_normal_(self.depthwise.weight) self.pointwise = PointwiseConv(input_size=input_size, num_filters=num_filters) self.activation_fn = F.relu def forward(self, x): x = self.depthwise(x.transpose(1, 2)) x = self.pointwise(x.transpose(1, 2)) x = self.activation_fn(x) return x ================================================ FILE: claf/modules/conv/pointwise_conv.py ================================================ import torch import torch.nn as nn class PointwiseConv(nn.Module): """ Pointwise Convolution (1x1 Conv) Convolution 1 Dimension (Faster version) (cf. https://github.com/huggingface/pytorch-openai-transformer-lm/blob/\ eafc28abdfadfa0732f03a0fc65805c5bfb2ffe7/model_pytorch.py#L45) * Args: input_size: the number of input tensor's dimension num_filters: the number of convolution filter """ # nf: num_filters, rf: kernel_size, nx: in_channels def __init__(self, input_size, num_filters): super(PointwiseConv, self).__init__() self.kernel_size = 1 self.num_filters = num_filters weight = torch.empty(input_size, num_filters) nn.init.normal_(weight, std=0.02) self.weight = nn.Parameter(weight) self.bias = nn.Parameter(torch.zeros(num_filters)) def forward(self, x): size_out = x.size()[:-1] + (self.num_filters,) x = torch.addmm(self.bias, x.contiguous().view(-1, x.size(-1)), self.weight) x = x.view(*size_out) return x ================================================ FILE: claf/modules/encoder/__init__.py ================================================ from .positional import PositionalEncoding from .lstm_cell_with_projection import LstmCellWithProjection, _EncoderBase __all__ = ["PositionalEncoding", "LstmCellWithProjection", "_EncoderBase"] ================================================ FILE: claf/modules/encoder/lstm_cell_with_projection.py ================================================ """ This code is from allenai/allennlp (https://github.com/allenai/allennlp/blob/master/allennlp/modules/lstm_cell_with_projection.py) """ import itertools from typing import Callable, List, Tuple, Union, Optional import torch from torch.nn.utils.rnn import pack_padded_sequence, PackedSequence class LstmCellWithProjection(torch.nn.Module): # pragma: no cover """ An LSTM with Recurrent Dropout and a projected and clipped hidden state and memory. Note: this implementation is slower than the native Pytorch LSTM because it cannot make use of CUDNN optimizations for stacked RNNs due to and variational dropout and the custom nature of the cell state. Parameters ---------- input_size : ``int``, required. The dimension of the inputs to the LSTM. hidden_size : ``int``, required. The dimension of the outputs of the LSTM. cell_size : ``int``, required. The dimension of the memory cell used for the LSTM. go_forward: ``bool``, optional (default = True) The direction in which the LSTM is applied to the sequence. Forwards by default, or backwards if False. recurrent_dropout_probability: ``float``, optional (default = 0.0) The dropout probability to be used in a dropout scheme as stated in `A Theoretically Grounded Application of Dropout in Recurrent Neural Networks `_ . Implementation wise, this simply applies a fixed dropout mask per sequence to the recurrent connection of the LSTM. state_projection_clip_value: ``float``, optional, (default = None) The magnitude with which to clip the hidden_state after projecting it. memory_cell_clip_value: ``float``, optional, (default = None) The magnitude with which to clip the memory cell. Returns ------- output_accumulator : ``torch.FloatTensor`` The outputs of the LSTM for each timestep. A tensor of shape (batch_size, max_timesteps, hidden_size) where for a given batch element, all outputs past the sequence length for that batch are zero tensors. final_state: ``Tuple[torch.FloatTensor, torch.FloatTensor]`` The final (state, memory) states of the LSTM, with shape (1, batch_size, hidden_size) and (1, batch_size, cell_size) respectively. The first dimension is 1 in order to match the Pytorch API for returning stacked LSTM states. """ def __init__( self, input_size: int, hidden_size: int, cell_size: int, go_forward: bool = True, recurrent_dropout_probability: float = 0.0, memory_cell_clip_value: Optional[float] = None, state_projection_clip_value: Optional[float] = None, ) -> None: super(LstmCellWithProjection, self).__init__() # Required to be wrapped with a :class:`PytorchSeq2SeqWrapper`. self.input_size = input_size self.hidden_size = hidden_size self.cell_size = cell_size self.go_forward = go_forward self.state_projection_clip_value = state_projection_clip_value self.memory_cell_clip_value = memory_cell_clip_value self.recurrent_dropout_probability = recurrent_dropout_probability # We do the projections for all the gates all at once. self.input_linearity = torch.nn.Linear(input_size, 4 * cell_size, bias=False) self.state_linearity = torch.nn.Linear(hidden_size, 4 * cell_size, bias=True) # Additional projection matrix for making the hidden state smaller. self.state_projection = torch.nn.Linear(cell_size, hidden_size, bias=False) self.reset_parameters() def reset_parameters(self): # Use sensible default initializations for parameters. block_orthogonal(self.input_linearity.weight.data, [self.cell_size, self.input_size]) block_orthogonal(self.state_linearity.weight.data, [self.cell_size, self.hidden_size]) self.state_linearity.bias.data.fill_(0.0) # Initialize forget gate biases to 1.0 as per An Empirical # Exploration of Recurrent Network Architectures, (Jozefowicz, 2015). self.state_linearity.bias.data[self.cell_size : 2 * self.cell_size].fill_(1.0) def forward( self, # pylint: disable=arguments-differ inputs: torch.FloatTensor, batch_lengths: List[int], initial_state: Optional[Tuple[torch.Tensor, torch.Tensor]] = None, ): """ Parameters ---------- inputs : ``torch.FloatTensor``, required. A tensor of shape (batch_size, num_timesteps, input_size) to apply the LSTM over. batch_lengths : ``List[int]``, required. A list of length batch_size containing the lengths of the sequences in batch. initial_state : ``Tuple[torch.Tensor, torch.Tensor]``, optional, (default = None) A tuple (state, memory) representing the initial hidden state and memory of the LSTM. The ``state`` has shape (1, batch_size, hidden_size) and the ``memory`` has shape (1, batch_size, cell_size). Returns ------- output_accumulator : ``torch.FloatTensor`` The outputs of the LSTM for each timestep. A tensor of shape (batch_size, max_timesteps, hidden_size) where for a given batch element, all outputs past the sequence length for that batch are zero tensors. final_state : ``Tuple[``torch.FloatTensor, torch.FloatTensor]`` A tuple (state, memory) representing the initial hidden state and memory of the LSTM. The ``state`` has shape (1, batch_size, hidden_size) and the ``memory`` has shape (1, batch_size, cell_size). """ batch_size = inputs.size()[0] total_timesteps = inputs.size()[1] output_accumulator = inputs.new_zeros(batch_size, total_timesteps, self.hidden_size) if initial_state is None: full_batch_previous_memory = inputs.new_zeros(batch_size, self.cell_size) full_batch_previous_state = inputs.new_zeros(batch_size, self.hidden_size) else: full_batch_previous_state = initial_state[0].squeeze(0) full_batch_previous_memory = initial_state[1].squeeze(0) current_length_index = batch_size - 1 if self.go_forward else 0 if self.recurrent_dropout_probability > 0.0 and self.training: dropout_mask = get_dropout_mask( self.recurrent_dropout_probability, full_batch_previous_state ) else: dropout_mask = None for timestep in range(total_timesteps): # The index depends on which end we start. index = timestep if self.go_forward else total_timesteps - timestep - 1 # What we are doing here is finding the index into the batch dimension # which we need to use for this timestep, because the sequences have # variable length, so once the index is greater than the length of this # particular batch sequence, we no longer need to do the computation for # this sequence. The key thing to recognise here is that the batch inputs # must be _ordered_ by length from longest (first in batch) to shortest # (last) so initially, we are going forwards with every sequence and as we # pass the index at which the shortest elements of the batch finish, # we stop picking them up for the computation. if self.go_forward: while batch_lengths[current_length_index] <= index: current_length_index -= 1 # If we're going backwards, we are _picking up_ more indices. else: # First conditional: Are we already at the maximum number of elements in the batch? # Second conditional: Does the next shortest sequence beyond the current batch # index require computation use this timestep? while ( current_length_index < (len(batch_lengths) - 1) and batch_lengths[current_length_index + 1] > index ): current_length_index += 1 # Actually get the slices of the batch which we # need for the computation at this timestep. # shape (batch_size, cell_size) previous_memory = full_batch_previous_memory[0 : current_length_index + 1].clone() # Shape (batch_size, hidden_size) previous_state = full_batch_previous_state[0 : current_length_index + 1].clone() # Shape (batch_size, input_size) timestep_input = inputs[0 : current_length_index + 1, index] # Do the projections for all the gates all at once. # Both have shape (batch_size, 4 * cell_size) projected_input = self.input_linearity(timestep_input) projected_state = self.state_linearity(previous_state) # Main LSTM equations using relevant chunks of the big linear # projections of the hidden state and inputs. input_gate = torch.sigmoid( projected_input[:, (0 * self.cell_size) : (1 * self.cell_size)] + projected_state[:, (0 * self.cell_size) : (1 * self.cell_size)] ) forget_gate = torch.sigmoid( projected_input[:, (1 * self.cell_size) : (2 * self.cell_size)] + projected_state[:, (1 * self.cell_size) : (2 * self.cell_size)] ) memory_init = torch.tanh( projected_input[:, (2 * self.cell_size) : (3 * self.cell_size)] + projected_state[:, (2 * self.cell_size) : (3 * self.cell_size)] ) output_gate = torch.sigmoid( projected_input[:, (3 * self.cell_size) : (4 * self.cell_size)] + projected_state[:, (3 * self.cell_size) : (4 * self.cell_size)] ) memory = input_gate * memory_init + forget_gate * previous_memory # Here is the non-standard part of this LSTM cell; first, we clip the # memory cell, then we project the output of the timestep to a smaller size # and again clip it. if self.memory_cell_clip_value: # pylint: disable=invalid-unary-operand-type memory = torch.clamp( memory, -self.memory_cell_clip_value, self.memory_cell_clip_value ) # shape (current_length_index, cell_size) pre_projection_timestep_output = output_gate * torch.tanh(memory) # shape (current_length_index, hidden_size) timestep_output = self.state_projection(pre_projection_timestep_output) if self.state_projection_clip_value: # pylint: disable=invalid-unary-operand-type timestep_output = torch.clamp( timestep_output, -self.state_projection_clip_value, self.state_projection_clip_value, ) # Only do dropout if the dropout prob is > 0.0 and we are in training mode. if dropout_mask is not None: timestep_output = timestep_output * dropout_mask[0 : current_length_index + 1] # We've been doing computation with less than the full batch, so here we create a new # variable for the the whole batch at this timestep and insert the result for the # relevant elements of the batch into it. full_batch_previous_memory = full_batch_previous_memory.clone() full_batch_previous_state = full_batch_previous_state.clone() full_batch_previous_memory[0 : current_length_index + 1] = memory full_batch_previous_state[0 : current_length_index + 1] = timestep_output output_accumulator[0 : current_length_index + 1, index] = timestep_output # Mimic the pytorch API by returning state in the following shape: # (num_layers * num_directions, batch_size, ...). As this # LSTM cell cannot be stacked, the first dimension here is just 1. final_state = ( full_batch_previous_state.unsqueeze(0), full_batch_previous_memory.unsqueeze(0), ) return output_accumulator, final_state def get_dropout_mask( dropout_probability: float, tensor_for_masking: torch.Tensor ): # pragma: no cover """ Computes and returns an element-wise dropout mask for a given tensor, where each element in the mask is dropped out with probability dropout_probability. Note that the mask is NOT applied to the tensor - the tensor is passed to retain the correct CUDA tensor type for the mask. Parameters ---------- dropout_probability : float, required. Probability of dropping a dimension of the input. tensor_for_masking : torch.Tensor, required. Returns ------- A torch.FloatTensor consisting of the binary mask scaled by 1/ (1 - dropout_probability). This scaling ensures expected values and variances of the output of applying this mask and the original tensor are the same. """ binary_mask = tensor_for_masking.new_tensor( torch.rand(tensor_for_masking.size()) > dropout_probability ) # Scale mask by 1/keep_prob to preserve output statistics. dropout_mask = binary_mask.float().div(1.0 - dropout_probability) return dropout_mask def block_orthogonal( tensor: torch.Tensor, split_sizes: List[int], gain: float = 1.0 ) -> None: # pragma: no cover """ An initializer which allows initializing model parameters in "blocks". This is helpful in the case of recurrent models which use multiple gates applied to linear projections, which can be computed efficiently if they are concatenated together. However, they are separate parameters which should be initialized independently. Parameters ---------- tensor : ``torch.Tensor``, required. A tensor to initialize. split_sizes : List[int], required. A list of length ``tensor.ndim()`` specifying the size of the blocks along that particular dimension. E.g. ``[10, 20]`` would result in the tensor being split into chunks of size 10 along the first dimension and 20 along the second. gain : float, optional (default = 1.0) The gain (scaling) applied to the orthogonal initialization. """ data = tensor.data sizes = list(tensor.size()) if any([a % b != 0 for a, b in zip(sizes, split_sizes)]): raise ValueError( "tensor dimensions must be divisible by their respective " "split_sizes. Found size: {} and split_sizes: {}".format(sizes, split_sizes) ) indexes = [list(range(0, max_size, split)) for max_size, split in zip(sizes, split_sizes)] # Iterate over all possible blocks within the tensor. for block_start_indices in itertools.product(*indexes): # A list of tuples containing the index to start at for this block # and the appropriate step size (i.e split_size[i] for dimension i). index_and_step_tuples = zip(block_start_indices, split_sizes) # This is a tuple of slices corresponding to: # tensor[index: index + step_size, ...]. This is # required because we could have an arbitrary number # of dimensions. The actual slices we need are the # start_index: start_index + step for each dimension in the tensor. block_slice = tuple( [slice(start_index, start_index + step) for start_index, step in index_and_step_tuples] ) data[block_slice] = torch.nn.init.orthogonal_(tensor[block_slice].contiguous(), gain=gain) def sort_batch_by_length(tensor: torch.Tensor, sequence_lengths: torch.Tensor): # pragma: no cover """ Sort a batch first tensor by some specified lengths. Parameters ---------- tensor : torch.FloatTensor, required. A batch first Pytorch tensor. sequence_lengths : torch.LongTensor, required. A tensor representing the lengths of some dimension of the tensor which we want to sort by. Returns ------- sorted_tensor : torch.FloatTensor The original tensor sorted along the batch dimension with respect to sequence_lengths. sorted_sequence_lengths : torch.LongTensor The original sequence_lengths sorted by decreasing size. restoration_indices : torch.LongTensor Indices into the sorted_tensor such that ``sorted_tensor.index_select(0, restoration_indices) == original_tensor`` permuation_index : torch.LongTensor The indices used to sort the tensor. This is useful if you want to sort many tensors using the same ordering. """ if not isinstance(tensor, torch.Tensor) or not isinstance(sequence_lengths, torch.Tensor): raise ValueError("Both the tensor and sequence lengths must be torch.Tensors.") sorted_sequence_lengths, permutation_index = sequence_lengths.sort(0, descending=True) sorted_tensor = tensor.index_select(0, permutation_index) index_range = sequence_lengths.new_tensor(torch.arange(0, len(sequence_lengths))) # This is the equivalent of zipping with index, sorting by the original # sequence lengths and returning the now sorted indices. _, reverse_mapping = permutation_index.sort(0, descending=False) restoration_indices = index_range.index_select(0, reverse_mapping) return sorted_tensor, sorted_sequence_lengths, restoration_indices, permutation_index # We have two types here for the state, because storing the state in something # which is Iterable (like a tuple, below), is helpful for internal manipulation # - however, the states are consumed as either Tensors or a Tuple of Tensors, so # returning them in this format is unhelpful. RnnState = Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]] # pylint: disable=invalid-name RnnStateStorage = Tuple[torch.Tensor, ...] # pylint: disable=invalid-name class _EncoderBase(torch.nn.Module): # pragma: no cover # pylint: disable=abstract-method """ This abstract class serves as a base for the 3 ``Encoder`` abstractions in AllenNLP. - :class:`~allennlp.modules.seq2seq_encoders.Seq2SeqEncoders` - :class:`~allennlp.modules.seq2vec_encoders.Seq2VecEncoders` Additionally, this class provides functionality for sorting sequences by length so they can be consumed by Pytorch RNN classes, which require their inputs to be sorted by length. Finally, it also provides optional statefulness to all of it's subclasses by allowing the caching and retrieving of the hidden states of RNNs. """ def __init__(self, stateful: bool = False) -> None: super(_EncoderBase, self).__init__() self.stateful = stateful self._states: Optional[RnnStateStorage] = None def sort_and_run_forward( self, module: Callable[ [PackedSequence, Optional[RnnState]], Tuple[Union[PackedSequence, torch.Tensor], RnnState], ], inputs: torch.Tensor, mask: torch.Tensor, hidden_state: Optional[RnnState] = None, ): """ This function exists because Pytorch RNNs require that their inputs be sorted before being passed as input. As all of our Seq2xxxEncoders use this functionality, it is provided in a base class. This method can be called on any module which takes as input a ``PackedSequence`` and some ``hidden_state``, which can either be a tuple of tensors or a tensor. As all of our Seq2xxxEncoders have different return types, we return `sorted` outputs from the module, which is called directly. Additionally, we return the indices into the batch dimension required to restore the tensor to it's correct, unsorted order and the number of valid batch elements (i.e the number of elements in the batch which are not completely masked). This un-sorting and re-padding of the module outputs is left to the subclasses because their outputs have different types and handling them smoothly here is difficult. Parameters ---------- module : ``Callable[[PackedSequence, Optional[RnnState]], Tuple[Union[PackedSequence, torch.Tensor], RnnState]]``, required. A function to run on the inputs. In most cases, this is a ``torch.nn.Module``. inputs : ``torch.Tensor``, required. A tensor of shape ``(batch_size, sequence_length, embedding_size)`` representing the inputs to the Encoder. mask : ``torch.Tensor``, required. A tensor of shape ``(batch_size, sequence_length)``, representing masked and non-masked elements of the sequence for each element in the batch. hidden_state : ``Optional[RnnState]``, (default = None). A single tensor of shape (num_layers, batch_size, hidden_size) representing the state of an RNN with or a tuple of tensors of shapes (num_layers, batch_size, hidden_size) and (num_layers, batch_size, memory_size), representing the hidden state and memory state of an LSTM-like RNN. Returns ------- module_output : ``Union[torch.Tensor, PackedSequence]``. A Tensor or PackedSequence representing the output of the Pytorch Module. The batch size dimension will be equal to ``num_valid``, as sequences of zero length are clipped off before the module is called, as Pytorch cannot handle zero length sequences. final_states : ``Optional[RnnState]`` A Tensor representing the hidden state of the Pytorch Module. This can either be a single tensor of shape (num_layers, num_valid, hidden_size), for instance in the case of a GRU, or a tuple of tensors, such as those required for an LSTM. restoration_indices : ``torch.LongTensor`` A tensor of shape ``(batch_size,)``, describing the re-indexing required to transform the outputs back to their original batch order. """ # In some circumstances you may have sequences of zero length. ``pack_padded_sequence`` # requires all sequence lengths to be > 0, so remove sequences of zero length before # calling self._module, then fill with zeros. # First count how many sequences are empty. batch_size = mask.size(0) num_valid = torch.sum(mask[:, 0]).int().item() sequence_lengths = mask.long().sum(-1) sorted_inputs, sorted_sequence_lengths, restoration_indices, sorting_indices = sort_batch_by_length( inputs, sequence_lengths ) # Now create a PackedSequence with only the non-empty, sorted sequences. packed_sequence_input = pack_padded_sequence( sorted_inputs[:num_valid, :, :], sorted_sequence_lengths[:num_valid].data.tolist(), batch_first=True, ) # Prepare the initial states. if not self.stateful: if hidden_state is None: initial_states = hidden_state elif isinstance(hidden_state, tuple): initial_states = [ state.index_select(1, sorting_indices)[:, :num_valid, :].contiguous() for state in hidden_state ] else: initial_states = hidden_state.index_select(1, sorting_indices)[ :, :num_valid, : ].contiguous() else: initial_states = self._get_initial_states(batch_size, num_valid, sorting_indices) # Actually call the module on the sorted PackedSequence. module_output, final_states = module(packed_sequence_input, initial_states) return module_output, final_states, restoration_indices def _get_initial_states( self, batch_size: int, num_valid: int, sorting_indices: torch.LongTensor ) -> Optional[RnnState]: """ Returns an initial state for use in an RNN. Additionally, this method handles the batch size changing across calls by mutating the state to append initial states for new elements in the batch. Finally, it also handles sorting the states with respect to the sequence lengths of elements in the batch and removing rows which are completely padded. Importantly, this `mutates` the state if the current batch size is larger than when it was previously called. Parameters ---------- batch_size : ``int``, required. The batch size can change size across calls to stateful RNNs, so we need to know if we need to expand or shrink the states before returning them. Expanded states will be set to zero. num_valid : ``int``, required. The batch may contain completely padded sequences which get removed before the sequence is passed through the encoder. We also need to clip these off of the state too. sorting_indices ``torch.LongTensor``, required. Pytorch RNNs take sequences sorted by length. When we return the states to be used for a given call to ``module.forward``, we need the states to match up to the sorted sequences, so before returning them, we sort the states using the same indices used to sort the sequences. Returns ------- This method has a complex return type because it has to deal with the first time it is called, when it has no state, and the fact that types of RNN have heterogeneous states. If it is the first time the module has been called, it returns ``None``, regardless of the type of the ``Module``. Otherwise, for LSTMs, it returns a tuple of ``torch.Tensors`` with shape ``(num_layers, num_valid, state_size)`` and ``(num_layers, num_valid, memory_size)`` respectively, or for GRUs, it returns a single ``torch.Tensor`` of shape ``(num_layers, num_valid, state_size)``. """ # We don't know the state sizes the first time calling forward, # so we let the module define what it's initial hidden state looks like. if self._states is None: return None # Otherwise, we have some previous states. if batch_size > self._states[0].size(1): # This batch is larger than the all previous states. # If so, resize the states. num_states_to_concat = batch_size - self._states[0].size(1) resized_states = [] # state has shape (num_layers, batch_size, hidden_size) for state in self._states: # This _must_ be inside the loop because some # RNNs have states with different last dimension sizes. zeros = state.new_zeros(state.size(0), num_states_to_concat, state.size(2)) resized_states.append(torch.cat([state, zeros], 1)) self._states = tuple(resized_states) correctly_shaped_states = self._states elif batch_size < self._states[0].size(1): # This batch is smaller than the previous one. correctly_shaped_states = tuple(state[:, :batch_size, :] for state in self._states) else: correctly_shaped_states = self._states # At this point, our states are of shape (num_layers, batch_size, hidden_size). # However, the encoder uses sorted sequences and additionally removes elements # of the batch which are fully padded. We need the states to match up to these # sorted and filtered sequences, so we do that in the next two blocks before # returning the state/s. if len(self._states) == 1: # GRUs only have a single state. This `unpacks` it from the # tuple and returns the tensor directly. correctly_shaped_state = correctly_shaped_states[0] sorted_state = correctly_shaped_state.index_select(1, sorting_indices) return sorted_state[:, :num_valid, :] else: # LSTMs have a state tuple of (state, memory). sorted_states = [ state.index_select(1, sorting_indices) for state in correctly_shaped_states ] return tuple(state[:, :num_valid, :] for state in sorted_states) def _update_states( self, final_states: RnnStateStorage, restoration_indices: torch.LongTensor ) -> None: """ After the RNN has run forward, the states need to be updated. This method just sets the state to the updated new state, performing several pieces of book-keeping along the way - namely, unsorting the states and ensuring that the states of completely padded sequences are not updated. Finally, it also detaches the state variable from the computational graph, such that the graph can be garbage collected after each batch iteration. Parameters ---------- final_states : ``RnnStateStorage``, required. The hidden states returned as output from the RNN. restoration_indices : ``torch.LongTensor``, required. The indices that invert the sorting used in ``sort_and_run_forward`` to order the states with respect to the lengths of the sequences in the batch. """ # TODO(Mark): seems weird to sort here, but append zeros in the subclasses. # which way around is best? new_unsorted_states = [state.index_select(1, restoration_indices) for state in final_states] if self._states is None: # We don't already have states, so just set the # ones we receive to be the current state. self._states = tuple(state.data for state in new_unsorted_states) else: # Now we've sorted the states back so that they correspond to the original # indices, we need to figure out what states we need to update, because if we # didn't use a state for a particular row, we want to preserve its state. # Thankfully, the rows which are all zero in the state correspond exactly # to those which aren't used, so we create masks of shape (new_batch_size,), # denoting which states were used in the RNN computation. current_state_batch_size = self._states[0].size(1) new_state_batch_size = final_states[0].size(1) # Masks for the unused states of shape (1, new_batch_size, 1) used_new_rows_mask = [ (state[0, :, :].sum(-1) != 0.0).float().view(1, new_state_batch_size, 1) for state in new_unsorted_states ] new_states = [] if current_state_batch_size > new_state_batch_size: # The new state is smaller than the old one, # so just update the indices which we used. for old_state, new_state, used_mask in zip( self._states, new_unsorted_states, used_new_rows_mask ): # zero out all rows in the previous state # which _were_ used in the current state. masked_old_state = old_state[:, :new_state_batch_size, :] * (1 - used_mask) # The old state is larger, so update the relevant parts of it. old_state[:, :new_state_batch_size, :] = new_state + masked_old_state new_states.append(old_state.detach()) else: # The states are the same size, so we just have to # deal with the possibility that some rows weren't used. new_states = [] for old_state, new_state, used_mask in zip( self._states, new_unsorted_states, used_new_rows_mask ): # zero out all rows which _were_ used in the current state. masked_old_state = old_state * (1 - used_mask) # The old state is larger, so update the relevant parts of it. new_state += masked_old_state new_states.append(new_state.detach()) # It looks like there should be another case handled here - when # the current_state_batch_size < new_state_batch_size. However, # this never happens, because the states themeselves are mutated # by appending zeros when calling _get_inital_states, meaning that # the new states are either of equal size, or smaller, in the case # that there are some unused elements (zero-length) for the RNN computation. self._states = tuple(new_states) def reset_states(self): self._states = None ================================================ FILE: claf/modules/encoder/positional.py ================================================ import math import numpy as np import torch import torch.nn as nn class PositionalEncoding(nn.Module): """ Positional Encoding in "Attention is All You Need" (https://arxiv.org/abs/1706.03762) The use of relative position is possible because sin(x+y) and cos(x+y) can be expressed in terms of y, sin(x) and cos(x). (cf. https://github.com/tensorflow/tensor2tensor/blob/42c3f377f441e5a0f431127d63e71414ead291c4/\ tensor2tensor/layers/common_attention.py#L388) * Args: embed_dim: the number of embedding dimension * Kwargs: max_len: the number of maximum sequence length """ def __init__(self, embed_dim, max_length=2000): super(PositionalEncoding, self).__init__() signal_sinusoid = self._get_timing_signal(max_length, embed_dim) self.register_buffer("position_encoding", signal_sinusoid) def _get_timing_signal(self, length, channels, min_timescale=1.0, max_timescale=1.0e4): position = np.arange(length) num_timescales = channels // 2 log_timescale_increment = math.log( float(max_timescale) / float(min_timescale) / (float(num_timescales) - 1) ) inv_timescales = min_timescale * np.exp( np.arange(num_timescales).astype(np.float) * -log_timescale_increment ) scaled_time = np.expand_dims(position, 1) * np.expand_dims(inv_timescales, 0) signal = np.concatenate([np.sin(scaled_time), np.cos(scaled_time)], axis=1) signal = np.pad(signal, [[0, 0], [0, channels % 2]], "constant", constant_values=[0.0, 0.0]) signal = signal.reshape([1, length, channels]) return torch.from_numpy(signal).type(torch.FloatTensor) def forward(self, x): x = x + self.position_encoding[:, : x.size(1)] return x ================================================ FILE: claf/modules/functional.py ================================================ """ some functional codes from allennlp: https://github.com/allenai/allennlp - add_masked_value : replace_masked_values (allennlp) - get_mask_from_tokens : get_mask_from_tokens (allennlp) - last_dim_masked_softmax : last_dim_masked_softmax (allennlp) - masked_softmax : masked_softmax (allennlp) - weighted_sum : weighted_sum (allennlp) """ import torch import torch.nn.functional as F from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence def add_masked_value(tensor, mask, value=-1e7): mask = mask.float() one_minus_mask = 1.0 - mask values_to_add = value * one_minus_mask return tensor * mask + values_to_add def get_mask_from_tokens(tokens): tensor_dims = [(tensor.dim(), tensor) for tensor in tokens.values()] tensor_dims.sort(key=lambda x: x[0]) smallest_dim = tensor_dims[0][0] if smallest_dim == 2: token_tensor = tensor_dims[0][1] return (token_tensor != 0).long() elif smallest_dim == 3: character_tensor = tensor_dims[0][1] return ((character_tensor > 0).long().sum(dim=-1) > 0).long() else: raise ValueError("Expected a tensor with dimension 2 or 3, found {}".format(smallest_dim)) def last_dim_masked_softmax(x, mask): x_shape = x.size() reshaped_x = x.view(-1, x.size()[-1]) while mask.dim() < x.dim(): mask = mask.unsqueeze(1) mask = mask.expand_as(x).contiguous().float() mask = mask.view(-1, mask.size()[-1]) reshaped_result = masked_softmax(reshaped_x, mask) return reshaped_result.view(*x_shape) def masked_softmax(x, mask): if mask is None: raise ValueError("mask can't be None.") output = F.softmax(x * mask, dim=-1) output = output * mask output = output / (output.sum(dim=1, keepdim=True) + 1e-13) return output def weighted_sum(attention, matrix): # pragma: no cover if attention.dim() == 2 and matrix.dim() == 3: return attention.unsqueeze(1).bmm(matrix).squeeze(1) elif attention.dim() == 3 and matrix.dim() == 3: return attention.bmm(matrix) else: raise ValueError( f"attention dim {attention.dim()} and matrix dim {matrix.dim()} operation not support. (2, 3) and (3, 3) are available dimemsion." ) def masked_zero(tensor, mask): """ Tensor masking operation """ while mask.dim() < tensor.dim(): mask = mask.unsqueeze(-1) if isinstance(tensor, torch.FloatTensor): mask = mask.float() elif isinstance(tensor, torch.ByteTensor): mask = mask.byte() elif isinstance(tensor, torch.LongTensor): mask = mask.long() return tensor * mask def masked_log_softmax(vector, mask): # pragma: no cover if mask is not None: vector = vector + mask.float().log() return torch.nn.functional.log_softmax(vector, dim=1) def get_sorted_seq_config(features, pad_index=0): tensor_dims = [(tensor.dim(), tensor) for tensor in features.values()] tensor_dims.sort(key=lambda x: x[0]) smallest_dim = tensor_dims[0][0] if smallest_dim == 2: token_tensor = tensor_dims[0][1] else: raise ValueError("features smallest_dim must be `2` ([B, S_L]) ") seq_lengths = torch.sum(token_tensor > pad_index, dim=-1) seq_lengths, perm_idx = seq_lengths.sort(0, descending=True) _, unperm_idx = perm_idx.sort(0) return {"seq_lengths": seq_lengths, "perm_idx": perm_idx, "unperm_idx": unperm_idx} def forward_rnn_with_pack(rnn_module, tensor, seq_config): sorted_tensor = tensor[seq_config["perm_idx"]] packed_input = pack_padded_sequence(sorted_tensor, seq_config["seq_lengths"], batch_first=True) packed_output, _ = rnn_module(packed_input) output, _ = pad_packed_sequence(packed_output, batch_first=True) output = output[seq_config["unperm_idx"]] # restore origin order return output ================================================ FILE: claf/modules/initializer.py ================================================ import logging import torch import torch.nn as nn logger = logging.getLogger(__name__) def weight(module): """ weight initialization (according to module type) * Args: module: torch.nn.Module """ if type(module) == list: for m in module: weight(m) if isinstance(module, nn.Conv2d): logger.info("initializing Conv Layer") torch.nn.init.uniform_(module.weight) elif isinstance(module, nn.Linear): torch.nn.init.xavier_uniform_(module.weight) logger.info("Initializing Linear Layer") elif isinstance(module, nn.GRU): torch.nn.init.normal_(module.weight_hh_l0, std=0.05) logger.info("Initializing GRU Layer") ================================================ FILE: claf/modules/layer/__init__.py ================================================ from .highway import Highway from .positionwise import PositionwiseFeedForward from .residual import ResidualConnection from .scalar_mix import ScalarMix __all__ = ["Highway", "PositionwiseFeedForward", "ResidualConnection", "ScalarMix"] ================================================ FILE: claf/modules/layer/highway.py ================================================ import torch import torch.nn as nn from claf.modules.activation import get_activation_fn class Highway(nn.Module): """ Highway Networks (https://arxiv.org/abs/1505.00387) https://github.com/allenai/allennlp/blob/master/allennlp/modules/highway.py * Args: input_size: The number of expected features in the input `x` num_layers: The number of Highway layers. activation: Activation Function (ReLU is default) """ def __init__(self, input_size, num_layers=2, activation="relu"): super(Highway, self).__init__() self.activation_fn = activation if type(activation) == str: self.activation_fn = get_activation_fn(activation)() self._layers = torch.nn.ModuleList( [nn.Linear(input_size, input_size * 2) for _ in range(num_layers)] ) for layer in self._layers: layer.bias[input_size:].data.fill_( 1 ) # should bias the highway layer to just carry its input forward. def forward(self, x): current_input = x for layer in self._layers: projected_input = layer(current_input) linear_part = current_input nonlinear_part, gate = projected_input.chunk(2, dim=-1) nonlinear_part = self.activation_fn(nonlinear_part) gate = torch.sigmoid(gate) current_input = gate * linear_part + (1 - gate) * nonlinear_part return current_input ================================================ FILE: claf/modules/layer/normalization.py ================================================ import torch import torch.nn as nn class LayerNorm(nn.Module): """ Layer Normalization (https://arxiv.org/abs/1607.06450) """ def __init__(self, normalized_shape, eps=1e-5): super(LayerNorm, self).__init__() self.gamma = nn.Parameter(torch.ones(normalized_shape)) self.beta = nn.Parameter(torch.zeros(normalized_shape)) self.eps = eps def forward(self, x): mean = x.mean(-1, keepdim=True) std = x.std(-1, keepdim=True) return self.gamma * (x - mean) / (std + self.eps) + self.beta ================================================ FILE: claf/modules/layer/positionwise.py ================================================ import torch.nn as nn import torch.nn.functional as F from claf.modules.conv import PointwiseConv class PositionwiseFeedForward(nn.Module): """ Pointwise Feed-Forward Layer * Args: input_size: the number of input size hidden_size: the number of hidden size * Kwargs: dropout: the probability of dropout """ def __init__(self, input_size, hidden_size, dropout=0.1): super(PositionwiseFeedForward, self).__init__() self.pointwise_conv1 = PointwiseConv(input_size=input_size, num_filters=hidden_size) self.pointwise_conv2 = PointwiseConv(input_size=hidden_size, num_filters=input_size) self.activation_fn = F.relu self.dropout = nn.Dropout(p=dropout) def forward(self, x): x = self.pointwise_conv1(x) x = self.activation_fn(x) x = self.pointwise_conv2(x) x = self.dropout(x) return x ================================================ FILE: claf/modules/layer/residual.py ================================================ import torch import torch.nn as nn from claf.modules.layer.normalization import LayerNorm class ResidualConnection(nn.Module): """ ResidualConnection in Deep Residual Learning for Image Recognition (https://arxiv.org/abs/1512.03385) => f(x) + x * Args: dim: the number of dimension * Kwargs: layer_dropout: layer dropout probability (stochastic depth) dropout: dropout probability """ def __init__(self, dim, layer_dropout=None, layernorm=False): super(ResidualConnection, self).__init__() self.survival = None if layer_dropout < 1: self.survival = torch.FloatTensor([layer_dropout]) if layernorm: self.norm = LayerNorm(dim) else: self.norm = lambda x: x def forward(self, x, sub_layer_fn): # implementation of stochastic depth if self.training and self.survival is not None: survival_prob = torch.bernoulli(self.survival).item() if survival_prob == 1: return x + sub_layer_fn(self.norm(x)) else: return x else: return x + sub_layer_fn(self.norm(x)) ================================================ FILE: claf/modules/layer/scalar_mix.py ================================================ """ This code is from allenai/allennlp (https://github.com/allenai/allennlp/blob/master/allennlp/modules/scalar_mix.py) """ from typing import List import torch from torch.nn import ParameterList, Parameter class ScalarMix(torch.nn.Module): # pragma: no cover """ Computes a parameterised scalar mixture of N tensors, ``mixture = gamma * sum(s_k * tensor_k)`` where ``s = softmax(w)``, with ``w`` and ``gamma`` scalar parameters. In addition, if ``do_layer_norm=True`` then apply layer normalization to each tensor before weighting. """ def __init__( self, mixture_size: int, do_layer_norm: bool = False, initial_scalar_parameters: List[float] = None, trainable: bool = True, ) -> None: super(ScalarMix, self).__init__() self.mixture_size = mixture_size self.do_layer_norm = do_layer_norm if initial_scalar_parameters is None: initial_scalar_parameters = [0.0] * mixture_size elif len(initial_scalar_parameters) != mixture_size: raise ValueError( "Length of initial_scalar_parameters {} differs " "from mixture_size {}".format(initial_scalar_parameters, mixture_size) ) self.scalar_parameters = ParameterList( [ Parameter( torch.FloatTensor([initial_scalar_parameters[i]]), requires_grad=trainable ) for i in range(mixture_size) ] ) self.gamma = Parameter(torch.FloatTensor([1.0]), requires_grad=trainable) def forward( self, tensors: List[torch.Tensor], # pylint: disable=arguments-differ mask: torch.Tensor = None, ) -> torch.Tensor: """ Compute a weighted average of the ``tensors``. The input tensors an be any shape with at least two dimensions, but must all be the same shape. When ``do_layer_norm=True``, the ``mask`` is required input. If the ``tensors`` are dimensioned ``(dim_0, ..., dim_{n-1}, dim_n)``, then the ``mask`` is dimensioned ``(dim_0, ..., dim_{n-1})``, as in the typical case with ``tensors`` of shape ``(batch_size, timesteps, dim)`` and ``mask`` of shape ``(batch_size, timesteps)``. When ``do_layer_norm=False`` the ``mask`` is ignored. """ if len(tensors) != self.mixture_size: raise ValueError( "{} tensors were passed, but the module was initialized to " "mix {} tensors.".format(len(tensors), self.mixture_size) ) def _do_layer_norm(tensor, broadcast_mask, num_elements_not_masked): tensor_masked = tensor * broadcast_mask mean = torch.sum(tensor_masked) / num_elements_not_masked variance = ( torch.sum(((tensor_masked - mean) * broadcast_mask) ** 2) / num_elements_not_masked ) return (tensor - mean) / torch.sqrt(variance + 1E-12) normed_weights = torch.nn.functional.softmax( torch.cat([parameter for parameter in self.scalar_parameters]), dim=0 ) normed_weights = torch.split(normed_weights, split_size_or_sections=1) if not self.do_layer_norm: pieces = [] for weight, tensor in zip(normed_weights, tensors): pieces.append(weight * tensor) return self.gamma * sum(pieces) else: mask_float = mask.float() broadcast_mask = mask_float.unsqueeze(-1) input_dim = tensors[0].size(-1) num_elements_not_masked = torch.sum(mask_float) * input_dim pieces = [] for weight, tensor in zip(normed_weights, tensors): pieces.append( weight * _do_layer_norm(tensor, broadcast_mask, num_elements_not_masked) ) return self.gamma * sum(pieces) ================================================ FILE: claf/nsml.py ================================================ """ NSML is NAVER SMART MACHINE LEARNING PLATFORM for internal (NAVER Corp)""" IS_ON_NSML = False DATASET_PATH = None SESSION_NAME = "" try: from nsml import * except ImportError: pass ================================================ FILE: claf/tokens/__init__.py ================================================ from claf.decorator import register from claf.tokens import indexer, embedding from claf.tokens.linguistic import POSTag, NER from claf.tokens.token_maker import TokenMaker from claf.tokens.tokenizer import PassText def basic_embedding_fn(embedding_config, module): def wrapper(vocab): embedding_config["vocab"] = vocab return module(**embedding_config) return wrapper @register(f"token:{TokenMaker.FEATURE_TYPE}") class FeatureTokenMaker(TokenMaker): """ Feature Token Do not use Embedding function. Just pass indexed_feature example. hello -> ['hello', 'world'] -> [3, 5] -> tensor consisting of - tokenizer: Tokenizer (need to define unit) - indexer: WordIndexer - embedding: None - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): tokenizer = PassText() do_tokenize = indexer_config.get("do_tokenize", False) if do_tokenize: text_unit = indexer_config.get("unit", None) if text_unit is None: raise ValueError("When use 'do_tokenize', 'unit' is required. ") del indexer_config["unit"] tokenizer = tokenizers[text_unit] super(FeatureTokenMaker, self).__init__( TokenMaker.FEATURE_TYPE, tokenizer=tokenizer, indexer=indexer.WordIndexer(tokenizer, **indexer_config), embedding_fn=None, vocab_config=vocab_config, ) @register(f"token:{TokenMaker.BERT_TYPE}") class BertTokenMaker(TokenMaker): """ BERT Token Pre-training of Deep Bidirectional Transformers for Language Understanding example. hello -> ['[CLS]', 'he', '##llo', [SEP]] -> [1, 4, 7, 2] -> BERT -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: ELMoEmbedding (Language Modeling BiLSTM) - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): tokenizer = tokenizers["subword"] super(BertTokenMaker, self).__init__( TokenMaker.BERT_TYPE, tokenizer=tokenizer, indexer=indexer.BertIndexer(tokenizer, **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.BertEmbedding), vocab_config=vocab_config, ) @register(f"token:{TokenMaker.CHAR_TYPE}") class CharTokenMaker(TokenMaker): """ Character Token Character-level Convolutional Networks for Text Classification (https://arxiv.org/abs/1509.01626) example. hello -> ['h', 'e', 'l', 'l', 'o'] -> [2, 3, 4, 4, 5] -> CharCNN -> tensor consisting of - tokenizer: CharTokenizer - indexer: CharIndexer - embedding: CharEmbedding (CharCNN) - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(CharTokenMaker, self).__init__( TokenMaker.CHAR_TYPE, tokenizer=tokenizers["char"], indexer=indexer.CharIndexer(tokenizers["char"], **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.CharEmbedding), vocab_config=vocab_config, ) @register(f"token:{TokenMaker.COVE_TYPE}") class CoveTokenMaker(TokenMaker): """ CoVe Token Learned in Translation: Contextualized Word Vectors (McCann et. al. 2017) (https://github.com/salesforce/cove) example. hello -> ['hello'] -> [2] -> CoVe -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: CoveEmbedding (Machine Translation LSTM) - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(CoveTokenMaker, self).__init__( TokenMaker.CHAR_TYPE, tokenizer=tokenizers["word"], indexer=indexer.WordIndexer(tokenizers["word"], **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.CoveEmbedding), vocab_config=vocab_config, ) @register(f"token:{TokenMaker.ELMO_TYPE}") class ElmoTokenMaker(TokenMaker): """ ELMo Token Embedding from Language Modeling Deep contextualized word representations (https://github.com/allenai/allennlp/blob/master/allennlp/modules/elmo.py) example. hello -> ['h', 'e', 'l', 'l', 'o'] -> [2, 3, 4, 4, 5] -> ELMo -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: ELMoEmbedding (Language Modeling BiLSTM) - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(ElmoTokenMaker, self).__init__( TokenMaker.WORD_TYPE, tokenizer=tokenizers["word"], indexer=indexer.ELMoIndexer(tokenizers["word"], **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.ELMoEmbedding), vocab_config="elmo", ) @register(f"token:{TokenMaker.EXACT_MATCH_TYPE}") class ExactMatchTokenMaker(TokenMaker): """ Exact Match Token (Sparse Feature) Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form. example. c: i do, q: i -> ['i', 'do'] -> [1, 0] -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: SparseFeature - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(ExactMatchTokenMaker, self).__init__( TokenMaker.EXACT_MATCH_TYPE, tokenizer=tokenizers["word"], indexer=indexer.ExactMatchIndexer(tokenizers["word"], **indexer_config), embedding_fn=self._embedding_fn(embedding_config, indexer_config), vocab_config=vocab_config, ) def _embedding_fn(self, embedding_config, indexer_config): def wrapper(vocab): embed_type = embedding_config.get("type", "sparse") if "type" in embedding_config: del embedding_config["type"] binary_classes = ["False", "True"] feature_count = 1 # origin embedding_config["classes"] = [binary_classes] if indexer_config.get("lower", False): feature_count += 1 embedding_config["classes"].append(binary_classes) if indexer_config.get("lemma", False): feature_count += 1 embedding_config["classes"].append(binary_classes) return embedding.SparseFeature( vocab, embed_type, feature_count, params=embedding_config ) return wrapper @register(f"token:{TokenMaker.WORD_TYPE}") class WordTokenMaker(TokenMaker): """ Word Token (default) i do -> ['i', 'do'] -> [1, 2] -> Embedding Matrix -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: WordEmbedding - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(WordTokenMaker, self).__init__( TokenMaker.WORD_TYPE, tokenizer=tokenizers["word"], indexer=indexer.WordIndexer(tokenizers["word"], **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.WordEmbedding), vocab_config=vocab_config, ) @register(f"token:{TokenMaker.FREQUENT_WORD_TYPE}") class FrequentWordTokenMaker(TokenMaker): """ Frequent-Tuning Word Token word token + pre-trained word embeddings fixed and only fine-tune the N most frequent example. i do -> ['i', 'do'] -> [1, 2] -> Embedding Matrix -> tensor finetuning only 'do' consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: FrequentTuningWordEmbedding - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(FrequentWordTokenMaker, self).__init__( TokenMaker.FREQUENT_WORD_TYPE, tokenizer=tokenizers["word"], indexer=indexer.WordIndexer(tokenizers["word"], **indexer_config), embedding_fn=basic_embedding_fn( embedding_config, embedding.FrequentTuningWordEmbedding ), vocab_config=vocab_config, ) @register(f"token:{TokenMaker.LINGUISTIC_TYPE}") class LinguisticTokenMaker(TokenMaker): """ Exact Match Token (Sparse Feature) Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form. example. c: i do, q: i -> ['i', 'do'] -> [1, 0] -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: SparseFeature - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(LinguisticTokenMaker, self).__init__( TokenMaker.LINGUISTIC_TYPE, tokenizer=tokenizers["word"], indexer=indexer.LinguisticIndexer(tokenizers["word"], **indexer_config), embedding_fn=self._embedding_fn(embedding_config, indexer_config), vocab_config=vocab_config, ) def _embedding_fn(self, embedding_config, indexer_config): def wrapper(vocab): embed_type = embedding_config.get("type", "sparse") if "type" in embedding_config: del embedding_config["type"] feature_count = 0 embedding_config["classes"] = [] if indexer_config.get("pos_tag", False): feature_count += 1 embedding_config["classes"].append(POSTag.classes) if indexer_config.get("ner", False): feature_count += 1 embedding_config["classes"].append(NER.classes) return embedding.SparseFeature( vocab, embed_type, feature_count, params=embedding_config ) return wrapper ================================================ FILE: claf/tokens/cove.py ================================================ """ This code is from salesforce/cove (https://github.com/salesforce/cove/blob/master/cove/encoder.py) """ import torch from torch import nn from claf.data.data_handler import CachePath, DataHandler class MTLSTM(nn.Module): def __init__( self, word_embedding, pretrained_path=None, requires_grad=False, residual_embeddings=False ): """Initialize an MTLSTM. Arguments: n_vocab (bool): If not None, initialize MTLSTM with an embedding matrix with n_vocab vectors vectors (Float Tensor): If not None, initiapize embedding matrix with specified vectors residual_embedding (bool): If True, concatenate the input embeddings with MTLSTM outputs during forward """ super(MTLSTM, self).__init__() self.word_embedding = word_embedding self.rnn = nn.LSTM(300, 300, num_layers=2, bidirectional=True, batch_first=True) data_handler = DataHandler(cache_path=CachePath.PRETRAINED_VECTOR) cove_weight_path = data_handler.read(pretrained_path, return_path=True) if torch.cuda.is_available(): checkpoint = torch.load(cove_weight_path) else: checkpoint = torch.load(cove_weight_path, map_location="cpu") self.rnn.load_state_dict(checkpoint) self.residual_embeddings = residual_embeddings self.requires_grad = requires_grad def forward(self, inputs): """A pretrained MT-LSTM (McCann et. al. 2017). This LSTM was trained with 300d 840B GloVe on the WMT 2017 machine translation dataset. Arguments: inputs (Tensor): If MTLSTM handles embedding, a Long Tensor of size (batch_size, timesteps). Otherwise, a Float Tensor of size (batch_size, timesteps, features). lengths (Long Tensor): (batch_size, lengths) lenghts of each sequence for handling padding hidden (Float Tensor): initial hidden state of the LSTM """ embedded_inputs = self.word_embedding(inputs) encoded_inputs, _ = self.rnn(embedded_inputs) if not self.requires_grad: encoded_inputs.detach() outputs = encoded_inputs if self.residual_embeddings: outputs = torch.cat([embedded_inputs, encoded_inputs], 2) return outputs ================================================ FILE: claf/tokens/elmo.py ================================================ """ This code is from allenai/allennlp (https://github.com/allenai/allennlp/blob/master/allennlp/modules/elmo.py) """ import json import logging from typing import Union, List, Dict, Any, Optional, Tuple import warnings import numpy from overrides import overrides import torch from torch.nn.utils.rnn import PackedSequence, pad_packed_sequence from torch.nn.modules import Dropout with warnings.catch_warnings(): # pragma: no cover warnings.filterwarnings("ignore", category=FutureWarning) import h5py from claf.modules.layer import Highway, ScalarMix from claf.modules.encoder import _EncoderBase, LstmCellWithProjection logger = logging.getLogger(__name__) # pylint: disable=invalid-name # pylint: disable=attribute-defined-outside-init class Elmo(torch.nn.Module): # pragma: no cover """ Compute ELMo representations using a pre-trained bidirectional language model. See "Deep contextualized word representations", Peters et al. for details. This module takes character id input and computes ``num_output_representations`` different layers of ELMo representations. Typically ``num_output_representations`` is 1 or 2. For example, in the case of the SRL model in the above paper, ``num_output_representations=1`` where ELMo was included at the input token representation layer. In the case of the SQuAD model, ``num_output_representations=2`` as ELMo was also included at the GRU output layer. In the implementation below, we learn separate scalar weights for each output layer, but only run the biLM once on each input sequence for efficiency. Parameters ---------- options_file : ``str``, required. ELMo JSON options file weight_file : ``str``, required. ELMo hdf5 weight file num_output_representations: ``int``, required. The number of ELMo representation layers to output. requires_grad: ``bool``, optional If True, compute gradient of ELMo parameters for fine tuning. do_layer_norm : ``bool``, optional, (default=False). Should we apply layer normalization (passed to ``ScalarMix``)? dropout : ``float``, optional, (default = 0.5). The dropout to be applied to the ELMo representations. vocab_to_cache : ``List[str]``, optional, (default = 0.5). A list of words to pre-compute and cache character convolutions for. If you use this option, Elmo expects that you pass word indices of shape (batch_size, timesteps) to forward, instead of character indices. If you use this option and pass a word which wasn't pre-cached, this will break. module : ``torch.nn.Module``, optional, (default = None). If provided, then use this module instead of the pre-trained ELMo biLM. If using this option, then pass ``None`` for both ``options_file`` and ``weight_file``. The module must provide a public attribute ``num_layers`` with the number of internal layers and its ``forward`` method must return a ``dict`` with ``activations`` and ``mask`` keys (see `_ElmoBilm`` for an example). Note that ``requires_grad`` is also ignored with this option. """ def __init__( self, options_file: str, weight_file: str, num_output_representations: int, requires_grad: bool = False, do_layer_norm: bool = False, dropout: float = 0.5, vocab_to_cache: List[str] = None, module: torch.nn.Module = None, ) -> None: super(Elmo, self).__init__() logging.info("Initializing ELMo") if module is not None: if options_file is not None or weight_file is not None: raise ValueError("Don't provide options_file or weight_file with module") self._elmo_lstm = module else: self._elmo_lstm = _ElmoBiLm( options_file, weight_file, requires_grad=requires_grad, vocab_to_cache=vocab_to_cache, ) self._has_cached_vocab = vocab_to_cache is not None self._dropout = Dropout(p=dropout) self._scalar_mixes: Any = [] for k in range(num_output_representations): scalar_mix = ScalarMix(self._elmo_lstm.num_layers, do_layer_norm=do_layer_norm) self.add_module("scalar_mix_{}".format(k), scalar_mix) self._scalar_mixes.append(scalar_mix) def get_output_dim(self): return self._elmo_lstm.get_output_dim() def forward( self, inputs: torch.Tensor, word_inputs: torch.Tensor = None, # pylint: disable=arguments-differ ) -> Dict[str, Union[torch.Tensor, List[torch.Tensor]]]: """ Parameters ---------- inputs: ``torch.Tensor``, required. Shape ``(batch_size, timesteps, 50)`` of character ids representing the current batch. word_inputs : ``torch.Tensor``, required. If you passed a cached vocab, you can in addition pass a tensor of shape ``(batch_size, timesteps)``, which represent word ids which have been pre-cached. Returns ------- Dict with keys: ``'elmo_representations'``: ``List[torch.Tensor]`` A ``num_output_representations`` list of ELMo representations for the input sequence. Each representation is shape ``(batch_size, timesteps, embedding_dim)`` ``'mask'``: ``torch.Tensor`` Shape ``(batch_size, timesteps)`` long tensor with sequence mask. """ # reshape the input if needed original_shape = inputs.size() if len(original_shape) > 3: timesteps, num_characters = original_shape[-2:] reshaped_inputs = inputs.view(-1, timesteps, num_characters) else: reshaped_inputs = inputs if word_inputs is not None: original_word_size = word_inputs.size() if self._has_cached_vocab and len(original_word_size) > 2: reshaped_word_inputs = word_inputs.view(-1, original_word_size[-1]) logger.warning( "Word inputs were passed to ELMo but it does not have a cached vocab." ) reshaped_word_inputs = None else: reshaped_word_inputs = word_inputs else: reshaped_word_inputs = word_inputs # run the biLM bilm_output = self._elmo_lstm(reshaped_inputs, reshaped_word_inputs) layer_activations = bilm_output["activations"] mask_with_bos_eos = bilm_output["mask"] # compute the elmo representations representations = [] for i in range(len(self._scalar_mixes)): scalar_mix = getattr(self, "scalar_mix_{}".format(i)) representation_with_bos_eos = scalar_mix(layer_activations, mask_with_bos_eos) representation_without_bos_eos, mask_without_bos_eos = remove_sentence_boundaries( representation_with_bos_eos, mask_with_bos_eos ) representations.append(self._dropout(representation_without_bos_eos)) # reshape if necessary if word_inputs is not None and len(original_word_size) > 2: mask = mask_without_bos_eos.view(original_word_size) elmo_representations = [ representation.view(original_word_size + (-1,)) for representation in representations ] elif len(original_shape) > 3: mask = mask_without_bos_eos.view(original_shape[:-1]) elmo_representations = [ representation.view(original_shape[:-1] + (-1,)) for representation in representations ] else: mask = mask_without_bos_eos elmo_representations = representations return {"elmo_representations": elmo_representations, "mask": mask} @classmethod def from_params(cls, params) -> "Elmo": # Add files to archive params.add_file_to_archive("options_file") params.add_file_to_archive("weight_file") options_file = params.pop("options_file") weight_file = params.pop("weight_file") requires_grad = params.pop("requires_grad", False) num_output_representations = params.pop("num_output_representations") do_layer_norm = params.pop_bool("do_layer_norm", False) dropout = params.pop_float("dropout", 0.5) params.assert_empty(cls.__name__) return cls( options_file=options_file, weight_file=weight_file, num_output_representations=num_output_representations, requires_grad=requires_grad, do_layer_norm=do_layer_norm, dropout=dropout, ) def remove_sentence_boundaries( tensor: torch.Tensor, mask: torch.Tensor ) -> Tuple[torch.Tensor, torch.Tensor]: # pragma: no cover """ Remove begin/end of sentence embeddings from the batch of sentences. Given a batch of sentences with size ``(batch_size, timesteps, dim)`` this returns a tensor of shape ``(batch_size, timesteps - 2, dim)`` after removing the beginning and end sentence markers. The sentences are assumed to be padded on the right, with the beginning of each sentence assumed to occur at index 0 (i.e., ``mask[:, 0]`` is assumed to be 1). Returns both the new tensor and updated mask. This function is the inverse of ``add_sentence_boundary_token_ids``. Parameters ---------- tensor : ``torch.Tensor`` A tensor of shape ``(batch_size, timesteps, dim)`` mask : ``torch.Tensor`` A tensor of shape ``(batch_size, timesteps)`` Returns ------- tensor_without_boundary_tokens : ``torch.Tensor`` The tensor after removing the boundary tokens of shape ``(batch_size, timesteps - 2, dim)`` new_mask : ``torch.Tensor`` The new mask for the tensor of shape ``(batch_size, timesteps - 2)``. """ # TODO: matthewp, profile this transfer sequence_lengths = mask.sum(dim=1).detach().cpu().numpy() tensor_shape = list(tensor.data.shape) new_shape = list(tensor_shape) new_shape[1] = tensor_shape[1] - 2 tensor_without_boundary_tokens = tensor.new_zeros(*new_shape) new_mask = tensor.new_zeros((new_shape[0], new_shape[1]), dtype=torch.long) for i, j in enumerate(sequence_lengths): if j > 2: tensor_without_boundary_tokens[i, : (j - 2), :] = tensor[i, 1 : (j - 1), :] new_mask[i, : (j - 2)] = 1 return tensor_without_boundary_tokens, new_mask class _ElmoBiLm(torch.nn.Module): # pragma: no cover """ Run a pre-trained bidirectional language model, outputing the activations at each layer for weighting together into an ELMo representation (with ``allennlp.modules.seq2seq_encoders.Elmo``). This is a lower level class, useful for advanced uses, but most users should use ``allennlp.modules.seq2seq_encoders.Elmo`` directly. Parameters ---------- options_file : ``str`` ELMo JSON options file weight_file : ``str`` ELMo hdf5 weight file requires_grad: ``bool``, optional If True, compute gradient of ELMo parameters for fine tuning. vocab_to_cache : ``List[str]``, optional, (default = 0.5). A list of words to pre-compute and cache character convolutions for. If you use this option, _ElmoBiLm expects that you pass word indices of shape (batch_size, timesteps) to forward, instead of character indices. If you use this option and pass a word which wasn't pre-cached, this will break. """ def __init__( self, options_file: str, weight_file: str, requires_grad: bool = False, vocab_to_cache: List[str] = None, ) -> None: super(_ElmoBiLm, self).__init__() self._token_embedder = _ElmoCharacterEncoder( options_file, weight_file, requires_grad=requires_grad ) self._requires_grad = requires_grad if requires_grad and vocab_to_cache: logging.warning( "You are fine tuning ELMo and caching char CNN word vectors. " "This behaviour is not guaranteed to be well defined, particularly. " "if not all of your inputs will occur in the vocabulary cache." ) # This is an embedding, used to look up cached # word vectors built from character level cnn embeddings. self._word_embedding = None self._bos_embedding: torch.Tensor = None self._eos_embedding: torch.Tensor = None with open(options_file, "r") as fin: options = json.load(fin) if not options["lstm"].get("use_skip_connections"): raise ValueError("We only support pretrained biLMs with residual connections") self._elmo_lstm = ElmoLstm( input_size=options["lstm"]["projection_dim"], hidden_size=options["lstm"]["projection_dim"], cell_size=options["lstm"]["dim"], num_layers=options["lstm"]["n_layers"], memory_cell_clip_value=options["lstm"]["cell_clip"], state_projection_clip_value=options["lstm"]["proj_clip"], requires_grad=requires_grad, ) self._elmo_lstm.load_weights(weight_file) # Number of representation layers including context independent layer self.num_layers = options["lstm"]["n_layers"] + 1 def get_output_dim(self): return 2 * self._token_embedder.get_output_dim() def forward( self, inputs: torch.Tensor, word_inputs: torch.Tensor = None, # pylint: disable=arguments-differ ) -> Dict[str, Union[torch.Tensor, List[torch.Tensor]]]: """ Parameters ---------- inputs: ``torch.Tensor``, required. Shape ``(batch_size, timesteps, 50)`` of character ids representing the current batch. word_inputs : ``torch.Tensor``, required. If you passed a cached vocab, you can in addition pass a tensor of shape ``(batch_size, timesteps)``, which represent word ids which have been pre-cached. Returns ------- Dict with keys: ``'activations'``: ``List[torch.Tensor]`` A list of activations at each layer of the network, each of shape ``(batch_size, timesteps + 2, embedding_dim)`` ``'mask'``: ``torch.Tensor`` Shape ``(batch_size, timesteps + 2)`` long tensor with sequence mask. Note that the output tensors all include additional special begin and end of sequence markers. """ if self._word_embedding is not None and word_inputs is not None: try: mask_without_bos_eos = (word_inputs > 0).long() # The character cnn part is cached - just look it up. embedded_inputs = self._word_embedding(word_inputs) # type: ignore # shape (batch_size, timesteps + 2, embedding_dim) type_representation, mask = add_sentence_boundary_token_ids( embedded_inputs, mask_without_bos_eos, self._bos_embedding, self._eos_embedding ) except RuntimeError: # Back off to running the character convolutions, # as we might not have the words in the cache. token_embedding = self._token_embedder(inputs) mask = token_embedding["mask"] type_representation = token_embedding["token_embedding"] else: token_embedding = self._token_embedder(inputs) mask = token_embedding["mask"] type_representation = token_embedding["token_embedding"] lstm_outputs = self._elmo_lstm(type_representation, mask) # Prepare the output. The first layer is duplicated. # Because of minor differences in how masking is applied depending # on whether the char cnn layers are cached, we'll be defensive and # multiply by the mask here. It's not strictly necessary, as the # mask passed on is correct, but the values in the padded areas # of the char cnn representations can change. output_tensors = [ torch.cat([type_representation, type_representation], dim=-1) * mask.float().unsqueeze(-1) ] for layer_activations in torch.chunk(lstm_outputs, lstm_outputs.size(0), dim=0): output_tensors.append(layer_activations.squeeze(0)) return {"activations": output_tensors, "mask": mask} def add_sentence_boundary_token_ids( tensor: torch.Tensor, mask: torch.Tensor, sentence_begin_token: Any, sentence_end_token: Any ) -> Tuple[torch.Tensor, torch.Tensor]: # pragma: no cover """ Add begin/end of sentence tokens to the batch of sentences. Given a batch of sentences with size ``(batch_size, timesteps)`` or ``(batch_size, timesteps, dim)`` this returns a tensor of shape ``(batch_size, timesteps + 2)`` or ``(batch_size, timesteps + 2, dim)`` respectively. Returns both the new tensor and updated mask. Parameters ---------- tensor : ``torch.Tensor`` A tensor of shape ``(batch_size, timesteps)`` or ``(batch_size, timesteps, dim)`` mask : ``torch.Tensor`` A tensor of shape ``(batch_size, timesteps)`` sentence_begin_token: Any (anything that can be broadcast in torch for assignment) For 2D input, a scalar with the id. For 3D input, a tensor with length dim. sentence_end_token: Any (anything that can be broadcast in torch for assignment) For 2D input, a scalar with the id. For 3D input, a tensor with length dim. Returns ------- tensor_with_boundary_tokens : ``torch.Tensor`` The tensor with the appended and prepended boundary tokens. If the input was 2D, it has shape (batch_size, timesteps + 2) and if the input was 3D, it has shape (batch_size, timesteps + 2, dim). new_mask : ``torch.Tensor`` The new mask for the tensor, taking into account the appended tokens marking the beginning and end of the sentence. """ # TODO: matthewp, profile this transfer sequence_lengths = mask.sum(dim=1).detach().cpu().numpy() tensor_shape = list(tensor.data.shape) new_shape = list(tensor_shape) new_shape[1] = tensor_shape[1] + 2 tensor_with_boundary_tokens = tensor.new_zeros(*new_shape) if len(tensor_shape) == 2: tensor_with_boundary_tokens[:, 1:-1] = tensor tensor_with_boundary_tokens[:, 0] = sentence_begin_token for i, j in enumerate(sequence_lengths): tensor_with_boundary_tokens[i, j + 1] = sentence_end_token new_mask = (tensor_with_boundary_tokens != 0).long() elif len(tensor_shape) == 3: tensor_with_boundary_tokens[:, 1:-1, :] = tensor for i, j in enumerate(sequence_lengths): tensor_with_boundary_tokens[i, 0, :] = sentence_begin_token tensor_with_boundary_tokens[i, j + 1, :] = sentence_end_token new_mask = ((tensor_with_boundary_tokens > 0).long().sum(dim=-1) > 0).long() else: raise ValueError("add_sentence_boundary_token_ids only accepts 2D and 3D input") return tensor_with_boundary_tokens, new_mask def _make_bos_eos( character: int, padding_character: int, beginning_of_word_character: int, end_of_word_character: int, max_word_length: int, ): # pragma: no cover char_ids = [padding_character] * max_word_length char_ids[0] = beginning_of_word_character char_ids[1] = character char_ids[2] = end_of_word_character return char_ids class _ElmoCharacterEncoder(torch.nn.Module): # pragma: no cover """ Compute context sensitive token representation using pretrained biLM. This embedder has input character ids of size (batch_size, sequence_length, 50) and returns (batch_size, sequence_length + 2, embedding_dim), where embedding_dim is specified in the options file (typically 512). We add special entries at the beginning and end of each sequence corresponding to and , the beginning and end of sentence tokens. Note: this is a lower level class useful for advanced usage. Most users should use ``ElmoTokenEmbedder`` or ``allennlp.modules.Elmo`` instead. Parameters ---------- options_file : ``str`` ELMo JSON options file weight_file : ``str`` ELMo hdf5 weight file requires_grad: ``bool``, optional If True, compute gradient of ELMo parameters for fine tuning. The relevant section of the options file is something like: .. example-code:: .. code-block:: python {'char_cnn': { 'activation': 'relu', 'embedding': {'dim': 4}, 'filters': [[1, 4], [2, 8], [3, 16], [4, 32], [5, 64]], 'max_characters_per_token': 50, 'n_characters': 262, 'n_highway': 2 } } """ def __init__(self, options_file: str, weight_file: str, requires_grad: bool = False) -> None: super(_ElmoCharacterEncoder, self).__init__() with open(options_file, "r") as fin: self._options = json.load(fin) self._weight_file = weight_file self.output_dim = self._options["lstm"]["projection_dim"] self.requires_grad = requires_grad self._load_weights() max_word_length = 50 # char ids 0-255 come from utf-8 encoding bytes # assign 256-300 to special chars beginning_of_sentence_character = 256 # end_of_sentence_character = 257 # beginning_of_word_character = 258 # end_of_word_character = 259 # padding_character = 260 # beginning_of_sentence_characters = _make_bos_eos( beginning_of_sentence_character, padding_character, beginning_of_word_character, end_of_word_character, max_word_length, ) end_of_sentence_characters = _make_bos_eos( end_of_sentence_character, padding_character, beginning_of_word_character, end_of_word_character, max_word_length, ) # Cache the arrays for use in forward -- +1 due to masking. self._beginning_of_sentence_characters = torch.from_numpy( numpy.array(beginning_of_sentence_characters) + 1 ) self._end_of_sentence_characters = torch.from_numpy( numpy.array(end_of_sentence_characters) + 1 ) def get_output_dim(self): return self.output_dim @overrides def forward( self, inputs: torch.Tensor ) -> Dict[str, torch.Tensor]: # pylint: disable=arguments-differ """ Compute context insensitive token embeddings for ELMo representations. Parameters ---------- inputs: ``torch.Tensor`` Shape ``(batch_size, sequence_length, 50)`` of character ids representing the current batch. Returns ------- Dict with keys: ``'token_embedding'``: ``torch.Tensor`` Shape ``(batch_size, sequence_length + 2, embedding_dim)`` tensor with context insensitive token representations. ``'mask'``: ``torch.Tensor`` Shape ``(batch_size, sequence_length + 2)`` long tensor with sequence mask. """ # Add BOS/EOS mask = ((inputs > 0).long().sum(dim=-1) > 0).long() character_ids_with_bos_eos, mask_with_bos_eos = add_sentence_boundary_token_ids( inputs, mask, self._beginning_of_sentence_characters, self._end_of_sentence_characters ) # the character id embedding max_chars_per_token = self._options["char_cnn"]["max_characters_per_token"] # (batch_size * sequence_length, max_chars_per_token, embed_dim) character_embedding = torch.nn.functional.embedding( character_ids_with_bos_eos.view(-1, max_chars_per_token), self._char_embedding_weights ) # run convolutions cnn_options = self._options["char_cnn"] if cnn_options["activation"] == "tanh": activation = torch.nn.functional.tanh elif cnn_options["activation"] == "relu": activation = torch.nn.functional.relu else: raise ValueError("Unknown activation") # (batch_size * sequence_length, embed_dim, max_chars_per_token) character_embedding = torch.transpose(character_embedding, 1, 2) convs = [] for i in range(len(self._convolutions)): conv = getattr(self, "char_conv_{}".format(i)) convolved = conv(character_embedding) # (batch_size * sequence_length, n_filters for this width) convolved, _ = torch.max(convolved, dim=-1) convolved = activation(convolved) convs.append(convolved) # (batch_size * sequence_length, n_filters) token_embedding = torch.cat(convs, dim=-1) # apply the highway layers (batch_size * sequence_length, n_filters) token_embedding = self._highways(token_embedding) # final projection (batch_size * sequence_length, embedding_dim) token_embedding = self._projection(token_embedding) # reshape to (batch_size, sequence_length, embedding_dim) batch_size, sequence_length, _ = character_ids_with_bos_eos.size() return { "mask": mask_with_bos_eos, "token_embedding": token_embedding.view(batch_size, sequence_length, -1), } def _load_weights(self): self._load_char_embedding() self._load_cnn_weights() self._load_highway() self._load_projection() def _load_char_embedding(self): with h5py.File(self._weight_file, "r") as fin: char_embed_weights = fin["char_embed"][...] weights = numpy.zeros( (char_embed_weights.shape[0] + 1, char_embed_weights.shape[1]), dtype="float32" ) weights[1:, :] = char_embed_weights self._char_embedding_weights = torch.nn.Parameter( torch.FloatTensor(weights), requires_grad=self.requires_grad ) def _load_cnn_weights(self): cnn_options = self._options["char_cnn"] filters = cnn_options["filters"] char_embed_dim = cnn_options["embedding"]["dim"] convolutions = [] for i, (width, num) in enumerate(filters): conv = torch.nn.Conv1d( in_channels=char_embed_dim, out_channels=num, kernel_size=width, bias=True ) # load the weights with h5py.File(self._weight_file, "r") as fin: weight = fin["CNN"]["W_cnn_{}".format(i)][...] bias = fin["CNN"]["b_cnn_{}".format(i)][...] w_reshaped = numpy.transpose(weight.squeeze(axis=0), axes=(2, 1, 0)) if w_reshaped.shape != tuple(conv.weight.data.shape): raise ValueError("Invalid weight file") conv.weight.data.copy_(torch.FloatTensor(w_reshaped)) conv.bias.data.copy_(torch.FloatTensor(bias)) conv.weight.requires_grad = self.requires_grad conv.bias.requires_grad = self.requires_grad convolutions.append(conv) self.add_module("char_conv_{}".format(i), conv) self._convolutions = convolutions def _load_highway(self): # pylint: disable=protected-access # the highway layers have same dimensionality as the number of cnn filters cnn_options = self._options["char_cnn"] filters = cnn_options["filters"] n_filters = sum(f[1] for f in filters) n_highway = cnn_options["n_highway"] # create the layers, and load the weights self._highways = Highway(n_filters, n_highway, activation=torch.nn.functional.relu) for k in range(n_highway): # The AllenNLP highway is one matrix multplication with concatenation of # transform and carry weights. with h5py.File(self._weight_file, "r") as fin: # The weights are transposed due to multiplication order assumptions in tf # vs pytorch (tf.matmul(X, W) vs pytorch.matmul(W, X)) w_transform = numpy.transpose(fin["CNN_high_{}".format(k)]["W_transform"][...]) # -1.0 since AllenNLP is g * x + (1 - g) * f(x) but tf is (1 - g) * x + g * f(x) w_carry = -1.0 * numpy.transpose(fin["CNN_high_{}".format(k)]["W_carry"][...]) weight = numpy.concatenate([w_transform, w_carry], axis=0) self._highways._layers[k].weight.data.copy_(torch.FloatTensor(weight)) self._highways._layers[k].weight.requires_grad = self.requires_grad b_transform = fin["CNN_high_{}".format(k)]["b_transform"][...] b_carry = -1.0 * fin["CNN_high_{}".format(k)]["b_carry"][...] bias = numpy.concatenate([b_transform, b_carry], axis=0) self._highways._layers[k].bias.data.copy_(torch.FloatTensor(bias)) self._highways._layers[k].bias.requires_grad = self.requires_grad def _load_projection(self): cnn_options = self._options["char_cnn"] filters = cnn_options["filters"] n_filters = sum(f[1] for f in filters) self._projection = torch.nn.Linear(n_filters, self.output_dim, bias=True) with h5py.File(self._weight_file, "r") as fin: weight = fin["CNN_proj"]["W_proj"][...] bias = fin["CNN_proj"]["b_proj"][...] self._projection.weight.data.copy_(torch.FloatTensor(numpy.transpose(weight))) self._projection.bias.data.copy_(torch.FloatTensor(bias)) self._projection.weight.requires_grad = self.requires_grad self._projection.bias.requires_grad = self.requires_grad class ElmoLstm(_EncoderBase): # pragma: no cover """ A stacked, bidirectional LSTM which uses :class:`~allennlp.modules.lstm_cell_with_projection.LstmCellWithProjection`'s with highway layers between the inputs to layers. The inputs to the forward and backward directions are independent - forward and backward states are not concatenated between layers. Additionally, this LSTM maintains its `own` state, which is updated every time ``forward`` is called. It is dynamically resized for different batch sizes and is designed for use with non-continuous inputs (i.e inputs which aren't formatted as a stream, such as text used for a language modelling task, which is how stateful RNNs are typically used). This is non-standard, but can be thought of as having an "end of sentence" state, which is carried across different sentences. Parameters ---------- input_size : ``int``, required The dimension of the inputs to the LSTM. hidden_size : ``int``, required The dimension of the outputs of the LSTM. cell_size : ``int``, required. The dimension of the memory cell of the :class:`~allennlp.modules.lstm_cell_with_projection.LstmCellWithProjection`. num_layers : ``int``, required The number of bidirectional LSTMs to use. requires_grad: ``bool``, optional If True, compute gradient of ELMo parameters for fine tuning. recurrent_dropout_probability: ``float``, optional (default = 0.0) The dropout probability to be used in a dropout scheme as stated in `A Theoretically Grounded Application of Dropout in Recurrent Neural Networks `_ . state_projection_clip_value: ``float``, optional, (default = None) The magnitude with which to clip the hidden_state after projecting it. memory_cell_clip_value: ``float``, optional, (default = None) The magnitude with which to clip the memory cell. """ def __init__( self, input_size: int, hidden_size: int, cell_size: int, num_layers: int, requires_grad: bool = False, recurrent_dropout_probability: float = 0.0, memory_cell_clip_value: Optional[float] = None, state_projection_clip_value: Optional[float] = None, ) -> None: super(ElmoLstm, self).__init__(stateful=True) # Required to be wrapped with a :class:`PytorchSeq2SeqWrapper`. self.input_size = input_size self.hidden_size = hidden_size self.num_layers = num_layers self.cell_size = cell_size self.requires_grad = requires_grad forward_layers = [] backward_layers = [] lstm_input_size = input_size go_forward = True for layer_index in range(num_layers): forward_layer = LstmCellWithProjection( lstm_input_size, hidden_size, cell_size, go_forward, recurrent_dropout_probability, memory_cell_clip_value, state_projection_clip_value, ) backward_layer = LstmCellWithProjection( lstm_input_size, hidden_size, cell_size, not go_forward, recurrent_dropout_probability, memory_cell_clip_value, state_projection_clip_value, ) lstm_input_size = hidden_size self.add_module("forward_layer_{}".format(layer_index), forward_layer) self.add_module("backward_layer_{}".format(layer_index), backward_layer) forward_layers.append(forward_layer) backward_layers.append(backward_layer) self.forward_layers = forward_layers self.backward_layers = backward_layers def forward( self, inputs: torch.Tensor, mask: torch.LongTensor # pylint: disable=arguments-differ ) -> torch.Tensor: """ Parameters ---------- inputs : ``torch.Tensor``, required. A Tensor of shape ``(batch_size, sequence_length, hidden_size)``. mask : ``torch.LongTensor``, required. A binary mask of shape ``(batch_size, sequence_length)`` representing the non-padded elements in each sequence in the batch. Returns ------- A ``torch.Tensor`` of shape (num_layers, batch_size, sequence_length, hidden_size), where the num_layers dimension represents the LSTM output from that layer. """ batch_size, total_sequence_length = mask.size() stacked_sequence_output, final_states, restoration_indices = self.sort_and_run_forward( self._lstm_forward, inputs, mask ) num_layers, num_valid, returned_timesteps, encoder_dim = stacked_sequence_output.size() # Add back invalid rows which were removed in the call to sort_and_run_forward. if num_valid < batch_size: zeros = stacked_sequence_output.new_zeros( num_layers, batch_size - num_valid, returned_timesteps, encoder_dim ) stacked_sequence_output = torch.cat([stacked_sequence_output, zeros], 1) # The states also need to have invalid rows added back. new_states = [] for state in final_states: state_dim = state.size(-1) zeros = state.new_zeros(num_layers, batch_size - num_valid, state_dim) new_states.append(torch.cat([state, zeros], 1)) final_states = new_states # It's possible to need to pass sequences which are padded to longer than the # max length of the sequence to a Seq2StackEncoder. However, packing and unpacking # the sequences mean that the returned tensor won't include these dimensions, because # the RNN did not need to process them. We add them back on in the form of zeros here. sequence_length_difference = total_sequence_length - returned_timesteps if sequence_length_difference > 0: zeros = stacked_sequence_output.new_zeros( num_layers, batch_size, sequence_length_difference, stacked_sequence_output[0].size(-1), ) stacked_sequence_output = torch.cat([stacked_sequence_output, zeros], 2) self._update_states(final_states, restoration_indices) # Restore the original indices and return the sequence. # Has shape (num_layers, batch_size, sequence_length, hidden_size) return stacked_sequence_output.index_select(1, restoration_indices) def _lstm_forward( self, inputs: PackedSequence, initial_state: Optional[Tuple[torch.Tensor, torch.Tensor]] = None, ) -> Tuple[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: """ Parameters ---------- inputs : ``PackedSequence``, required. A batch first ``PackedSequence`` to run the stacked LSTM over. initial_state : ``Tuple[torch.Tensor, torch.Tensor]``, optional, (default = None) A tuple (state, memory) representing the initial hidden state and memory of the LSTM, with shape (num_layers, batch_size, 2 * hidden_size) and (num_layers, batch_size, 2 * cell_size) respectively. Returns ------- output_sequence : ``torch.FloatTensor`` The encoded sequence of shape (num_layers, batch_size, sequence_length, hidden_size) final_states: ``Tuple[torch.FloatTensor, torch.FloatTensor]`` The per-layer final (state, memory) states of the LSTM, with shape (num_layers, batch_size, 2 * hidden_size) and (num_layers, batch_size, 2 * cell_size) respectively. The last dimension is duplicated because it contains the state/memory for both the forward and backward layers. """ if initial_state is None: hidden_states: List[Optional[Tuple[torch.Tensor, torch.Tensor]]] = [None] * len( self.forward_layers ) elif initial_state[0].size()[0] != len(self.forward_layers): raise ValueError( "Initial states were passed to forward() but the number of " "initial states does not match the number of layers." ) else: hidden_states = list(zip(initial_state[0].split(1, 0), initial_state[1].split(1, 0))) inputs, batch_lengths = pad_packed_sequence(inputs, batch_first=True) forward_output_sequence = inputs backward_output_sequence = inputs final_states = [] sequence_outputs = [] for layer_index, state in enumerate(hidden_states): forward_layer = getattr(self, "forward_layer_{}".format(layer_index)) backward_layer = getattr(self, "backward_layer_{}".format(layer_index)) forward_cache = forward_output_sequence backward_cache = backward_output_sequence if state is not None: forward_hidden_state, backward_hidden_state = state[0].split(self.hidden_size, 2) forward_memory_state, backward_memory_state = state[1].split(self.cell_size, 2) forward_state = (forward_hidden_state, forward_memory_state) backward_state = (backward_hidden_state, backward_memory_state) else: forward_state = None backward_state = None forward_output_sequence, forward_state = forward_layer( forward_output_sequence, batch_lengths, forward_state ) backward_output_sequence, backward_state = backward_layer( backward_output_sequence, batch_lengths, backward_state ) # Skip connections, just adding the input to the output. if layer_index != 0: forward_output_sequence += forward_cache backward_output_sequence += backward_cache sequence_outputs.append( torch.cat([forward_output_sequence, backward_output_sequence], -1) ) # Append the state tuples in a list, so that we can return # the final states for all the layers. final_states.append( ( torch.cat([forward_state[0], backward_state[0]], -1), torch.cat([forward_state[1], backward_state[1]], -1), ) ) stacked_sequence_outputs: torch.FloatTensor = torch.stack(sequence_outputs) # Stack the hidden state and memory for each layer into 2 tensors of shape # (num_layers, batch_size, hidden_size) and (num_layers, batch_size, cell_size) # respectively. final_hidden_states, final_memory_states = zip(*final_states) final_state_tuple: Tuple[torch.FloatTensor, torch.FloatTensor] = ( torch.cat(final_hidden_states, 0), torch.cat(final_memory_states, 0), ) return stacked_sequence_outputs, final_state_tuple def load_weights(self, weight_file: str) -> None: """ Load the pre-trained weights from the file. """ requires_grad = self.requires_grad with h5py.File(weight_file, "r") as fin: for i_layer, lstms in enumerate(zip(self.forward_layers, self.backward_layers)): for j_direction, lstm in enumerate(lstms): # lstm is an instance of LSTMCellWithProjection cell_size = lstm.cell_size dataset = fin["RNN_%s" % j_direction]["RNN"]["MultiRNNCell"][ "Cell%s" % i_layer ]["LSTMCell"] # tensorflow packs together both W and U matrices into one matrix, # but pytorch maintains individual matrices. In addition, tensorflow # packs the gates as input, memory, forget, output but pytorch # uses input, forget, memory, output. So we need to modify the weights. tf_weights = numpy.transpose(dataset["W_0"][...]) torch_weights = tf_weights.copy() # split the W from U matrices input_size = lstm.input_size input_weights = torch_weights[:, :input_size] recurrent_weights = torch_weights[:, input_size:] tf_input_weights = tf_weights[:, :input_size] tf_recurrent_weights = tf_weights[:, input_size:] # handle the different gate order convention for torch_w, tf_w in [ [input_weights, tf_input_weights], [recurrent_weights, tf_recurrent_weights], ]: torch_w[(1 * cell_size) : (2 * cell_size), :] = tf_w[ (2 * cell_size) : (3 * cell_size), : ] torch_w[(2 * cell_size) : (3 * cell_size), :] = tf_w[ (1 * cell_size) : (2 * cell_size), : ] lstm.input_linearity.weight.data.copy_(torch.FloatTensor(input_weights)) lstm.state_linearity.weight.data.copy_(torch.FloatTensor(recurrent_weights)) lstm.input_linearity.weight.requires_grad = requires_grad lstm.state_linearity.weight.requires_grad = requires_grad # the bias weights tf_bias = dataset["B"][...] # tensorflow adds 1.0 to forget gate bias instead of modifying the # parameters... tf_bias[(2 * cell_size) : (3 * cell_size)] += 1 torch_bias = tf_bias.copy() torch_bias[(1 * cell_size) : (2 * cell_size)] = tf_bias[ (2 * cell_size) : (3 * cell_size) ] torch_bias[(2 * cell_size) : (3 * cell_size)] = tf_bias[ (1 * cell_size) : (2 * cell_size) ] lstm.state_linearity.bias.data.copy_(torch.FloatTensor(torch_bias)) lstm.state_linearity.bias.requires_grad = requires_grad # the projection weights proj_weights = numpy.transpose(dataset["W_P_0"][...]) lstm.state_projection.weight.data.copy_(torch.FloatTensor(proj_weights)) lstm.state_projection.weight.requires_grad = requires_grad ================================================ FILE: claf/tokens/embedding/__init__.py ================================================ from .bert_embedding import BertEmbedding from .char_embedding import CharEmbedding from .cove_embedding import CoveEmbedding from .elmo_embedding import ELMoEmbedding from .frequent_word_embedding import FrequentTuningWordEmbedding from .sparse_feature import SparseFeature from .word_embedding import WordEmbedding __all__ = [ "BertEmbedding", "CharEmbedding", "CoveEmbedding", "ELMoEmbedding", "FrequentTuningWordEmbedding", "SparseFeature", "WordEmbedding", ] ================================================ FILE: claf/tokens/embedding/base.py ================================================ import torch class TokenEmbedding(torch.nn.Module): """ Token Embedding It can be embedding matrix, language model (ELMo), neural machine translation model (CoVe) and features. * Args: vocab: Vocab (rqa.tokens.vocab) """ def __init__(self, vocab): super(TokenEmbedding, self).__init__() self.vocab = vocab def forward(self, tokens): """ embedding look-up """ raise NotImplementedError def get_output_dim(self): """ get embedding dimension """ raise NotImplementedError def get_vocab_size(self): return len(self.vocab) ================================================ FILE: claf/tokens/embedding/bert_embedding.py ================================================ from overrides import overrides from transformers import BertModel import claf.modules.functional as f from .base import TokenEmbedding class BertEmbedding(TokenEmbedding): """ BERT Embedding(Encoder) BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: pretrained_model_name: ... use_as_embedding: ... trainable: Finetune or fixed """ def __init__(self, vocab, pretrained_model_name=None, trainable=False, unit="subword"): super(BertEmbedding, self).__init__(vocab) self.trainable = trainable self.pad_index = vocab.get_index(vocab.pad_token) self.sep_index = vocab.get_index(vocab.sep_token) if unit != "subword": raise NotImplementedError("BertEmbedding is only available 'subword' unit, right now.") self.bert_model = BertModel.from_pretrained(pretrained_model_name) # BertModel with config @overrides def forward(self, inputs): if inputs.size(1) > self.bert_model.config.max_position_embeddings: raise ValueError( f"max_seq_length in this bert_model is '{self.bert_model.config.max_position_embeddings}'. (input seq_length: {inputs.size(1)})" ) # TODO: add text_unit option # current: sub_word (default) / later: sub_words --(average)--> word attention_mask = (inputs != self.pad_index).long() sequence_output, pooled_output = self.bert_model( inputs, attention_mask=attention_mask, output_all_encoded_layers=False ) sequence_output = f.masked_zero(sequence_output, attention_mask) if not self.trainable: sequence_output = sequence_output.detach() pooled_output = pooled_output.detach() sequence_output = self.remove_cls_sep_token(inputs, sequence_output) return sequence_output @overrides def get_output_dim(self): return self.bert_model.config.hidden_size def remove_cls_sep_token(self, inputs, outputs): seq_mask = inputs.eq(self.sep_index).eq(0) outputs = f.masked_zero(outputs, seq_mask) return outputs[:, 1:-1, :] # B, S_L, D ================================================ FILE: claf/tokens/embedding/char_embedding.py ================================================ from overrides import overrides import torch import torch.nn as nn import torch.nn.functional as F from claf.modules.activation import get_activation_fn from .base import TokenEmbedding class CharEmbedding(TokenEmbedding): """ Character Embedding (CharCNN) (https://arxiv.org/abs/1509.01626) * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: dropout: The number of dropout probability embed_dim: The number of embedding dimension kernel_sizes: The list of kernel size (n-gram) num_filter: The number of cnn filter activation: Activation Function (eg. ReLU) """ def __init__( self, vocab, dropout=0.2, embed_dim=16, kernel_sizes=[5], num_filter=100, activation="relu" ): super(CharEmbedding, self).__init__(vocab) self.embed_dim = embed_dim self.num_filter = num_filter self.weight = self._init_weight(trainable=True) self.convs = [ nn.Conv1d( in_channels=1, out_channels=num_filter, kernel_size=embed_dim * kernel_size, stride=embed_dim, ) for kernel_size in kernel_sizes ] # kernel_size = n-gram for i, conv in enumerate(self.convs): self.add_module(f"conv_{i}", conv) self.activation_fn = get_activation_fn(activation)() self.dropout = nn.Dropout(p=dropout) self.projection = None if len(kernel_sizes) > 1: maxpool_output_dim = len(kernel_sizes) * num_filter self.projection = nn.Linear(maxpool_output_dim, num_filter) def _init_weight(self, trainable=False): weight = torch.FloatTensor(self.get_vocab_size(), self.embed_dim) weight = torch.nn.Parameter(weight, requires_grad=trainable) torch.nn.init.xavier_uniform_(weight) return weight @overrides def forward(self, chars): mask_chars = (chars != 0).long() B, W_L, C_L = chars.size() # (batch_size, word_maxlen, char_maxlen) chars = chars.view(B, W_L * C_L) char_embedds = F.embedding(chars, self.weight) char_embedds = char_embedds.view(B, W_L, C_L, -1) # Masking char_embedds = char_embedds * mask_chars.unsqueeze(-1).float() char_embedds = char_embedds.view(B * W_L, 1, -1) conv_outputs = [] for i in range(len(self.convs)): conv = getattr(self, f"conv_{i}") output = self.activation_fn(conv(char_embedds)) pooled = F.max_pool1d(output, output.size(2)).squeeze(2) conv_outputs.append(pooled) encoded = conv_outputs[0] if len(conv_outputs) > 1: encoded = torch.cat(conv_outputs, dim=1) encoded = encoded.view(B, W_L, -1) if self.projection: encoded = self.projection(encoded) return self.dropout(encoded) @overrides def get_output_dim(self): return self.num_filter ================================================ FILE: claf/tokens/embedding/cove_embedding.py ================================================ from overrides import overrides import torch.nn as nn from claf.tokens.cove import MTLSTM from .base import TokenEmbedding from .word_embedding import WordEmbedding class CoveEmbedding(TokenEmbedding): """ Cove Embedding Learned in Translation: Contextualized Word Vectors (http://papers.nips.cc/paper/7209-learned-in-translation-contextualized-word-vectors.pdf) * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: dropout: The number of dropout probability pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed project_dim: The number of project (linear) dimension """ def __init__( self, vocab, glove_pretrained_path=None, model_pretrained_path=None, dropout=0.2, trainable=False, project_dim=None, ): super(CoveEmbedding, self).__init__(vocab) self.embed_dim = 600 # MTLSTM (hidden_size=300 + bidirectional => 600) word_embedding = WordEmbedding( vocab, dropout=0, embed_dim=300, pretrained_path=glove_pretrained_path ) self.cove = MTLSTM( word_embedding, pretrained_path=model_pretrained_path, requires_grad=trainable ) if dropout and dropout > 0: self.dropout = nn.Dropout(p=dropout) else: self.dropout = lambda x: x self.project_dim = project_dim self.project_linear = None if project_dim: self.project_linear = nn.Linear(self.elmo.get_output_dim(), project_dim) @overrides def forward(self, words): embedded_words = self.cove(words) return self.dropout(embedded_words) @overrides def get_output_dim(self): if self.project_linear: return self.project_dim return self.embed_dim ================================================ FILE: claf/tokens/embedding/elmo_embedding.py ================================================ from overrides import overrides import torch.nn as nn from claf.data.data_handler import CachePath, DataHandler from claf.tokens.elmo import Elmo from .base import TokenEmbedding DEFAULT_OPTIONS_FILE = "elmo_2x4096_512_2048cnn_2xhighway_options.json" DEFAULT_WEIGHT_FILE = "elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5" HIDDEN_SIZE = 1024 class ELMoEmbedding(TokenEmbedding): """ ELMo Embedding Embedding From Language Model Deep contextualized word representations (https://arxiv.org/abs/1802.0536) * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: options_file: ELMo model config file path weight_file: ELMo model weight file path do_layer_norm: Should we apply layer normalization (passed to ``ScalarMix``)? default is False dropout: The number of dropout probability trainable: Finetune or fixed project_dim: The number of project (linear) dimension """ def __init__( self, vocab, options_file=DEFAULT_OPTIONS_FILE, weight_file=DEFAULT_WEIGHT_FILE, do_layer_norm=False, dropout=0.5, trainable=False, project_dim=None, ): super(ELMoEmbedding, self).__init__(vocab) data_handler = DataHandler(cache_path=CachePath.PRETRAINED_VECTOR) option_path = data_handler.read(options_file, return_path=True) weight_path = data_handler.read(weight_file, return_path=True) self.elmo = Elmo(option_path, weight_path, 1, requires_grad=trainable, dropout=dropout) self.project_dim = project_dim self.project_linear = None if project_dim: self.project_linear = nn.Linear(self.elmo.get_output_dim(), project_dim) @overrides def forward(self, chars): elmo_output = self.elmo(chars) elmo_representations = elmo_output["elmo_representations"][0] if self.project_linear: elmo_representations = self.project_linear(elmo_representations) return elmo_representations @overrides def get_output_dim(self): if self.project_linear: return self.project_dim return self.elmo.get_output_dim() ================================================ FILE: claf/tokens/embedding/frequent_word_embedding.py ================================================ from overrides import overrides import torch import torch.nn as nn import claf.modules.functional as f from .base import TokenEmbedding from .word_embedding import WordEmbedding class FrequentTuningWordEmbedding(TokenEmbedding): """ Frequent Word Finetuning Embedding Finetuning embedding matrix, according to 'threshold_index' * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx (initialized to zeros) whenever it encounters the index. max_norm: If given, will renormalize the embedding vectors to have a norm lesser than this before extracting. Note: this will modify weight in-place. norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of frequency of the words in the mini-batch. Default False. sparse: if True, gradient w.r.t. weight will be a sparse tensor. See Notes under torch.nn.Embedding for more details regarding sparse gradients. pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed """ def __init__( self, vocab, dropout=0.2, embed_dim=100, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, pretrained_path=None, ): super(FrequentTuningWordEmbedding, self).__init__(vocab) self.threshold_index = vocab.threshold_index self.embed_dim = embed_dim self.fine_tune_word_embedding = WordEmbedding( vocab, dropout=0, embed_dim=embed_dim, padding_idx=padding_idx, max_norm=max_norm, norm_type=norm_type, scale_grad_by_freq=scale_grad_by_freq, sparse=sparse, pretrained_path=pretrained_path, ) self.fixed_word_embedding = WordEmbedding( vocab, dropout=0, embed_dim=embed_dim, padding_idx=padding_idx, max_norm=max_norm, norm_type=norm_type, scale_grad_by_freq=scale_grad_by_freq, sparse=sparse, pretrained_path=pretrained_path, ) if dropout > 0: self.dropout = nn.Dropout(p=dropout) else: self.dropout = lambda x: x @overrides def forward(self, words, frequent_tuning=False): if frequent_tuning and self.training: padding_mask = words.eq(0).long() # Fine-tuning - N the most frequent fine_tune_mask = torch.lt(words, self.threshold_index) * padding_mask.eq( 0 ) # < threshold_index fine_tune_words = words * fine_tune_mask.long() fine_tune_embedded = self.fine_tune_word_embedding(fine_tune_words) fine_tune_embedded = f.masked_zero(fine_tune_embedded, fine_tune_mask) # Fixed - under N frequent fixed_mask = torch.ge(words, self.threshold_index) # >= threshold_index fixed_embedeed = self.fixed_word_embedding(words).detach() # Fixed fixed_embedeed = f.masked_zero(fixed_embedeed, fixed_mask) embedded_words = fine_tune_embedded + fixed_embedeed else: embedded_words = self.fixed_word_embedding(words) return self.dropout(embedded_words) @overrides def get_output_dim(self): return self.embed_dim ================================================ FILE: claf/tokens/embedding/sparse_feature.py ================================================ from overrides import overrides import torch import torch.nn as nn import torch.nn.functional as F from claf.tokens.vocabulary import Vocab from .base import TokenEmbedding from .word_embedding import WordEmbedding class SparseFeature(TokenEmbedding): """ Sparse Feature 1. Sparse to Embedding 2. One Hot Encoding * Args: vocab: Vocab (claf.tokens.vocab) embed_type: The type of embedding [one_hot|embedding] feature_count: The number of feature count * Kwargs: params: additional parameters for embedding module """ def __init__(self, vocab, embed_type, feature_count, params={}): super(SparseFeature, self).__init__(vocab) self.feature_count = feature_count if embed_type == "embedding": embed_module = SparseToEmbedding else: embed_module = OneHotEncoding self.embed_modules = nn.ModuleList( [embed_module(i, vocab.token_name, **params) for i in range(feature_count)] ) indexs = torch.arange(feature_count).long() indexs = indexs.view(feature_count, 1) self.indexs = nn.Parameter(indexs, requires_grad=False) @overrides def forward(self, inputs): embedded_inputs = [] for i in range(len(self.embed_modules)): tensors = torch.index_select(inputs, -1, self.indexs[i]).squeeze(-1) embedded = self.embed_modules[i](tensors) embedded_inputs.append(embedded) return torch.cat(embedded_inputs, dim=-1) @overrides def get_output_dim(self): return sum(e.get_output_dim() for e in self.embed_modules) class SparseToEmbedding(nn.Module): """ Sparse to Embedding * Args: token_name: token_name * Kwargs: dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx (initialized to zeros) whenever it encounters the index. max_norm: If given, will renormalize the embedding vectors to have a norm lesser than this before extracting. Note: this will modify weight in-place. norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of frequency of the words in the mini-batch. Default False. sparse: if True, gradient w.r.t. weight will be a sparse tensor. See Notes under torch.nn.Embedding for more details regarding sparse gradients. pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed """ def __init__( self, index, token_name, classes, dropout=0, embed_dim=15, trainable=True, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, ): super(SparseToEmbedding, self).__init__() self.embed_dim = embed_dim vocab = Vocab(token_name) vocab.init() for c in classes[index]: vocab.add(c) embedding_params = { "vocab": vocab, "dropout": dropout, "embed_dim": embed_dim, "trainable": trainable, "padding_idx": padding_idx, "max_norm": max_norm, "norm_type": norm_type, "scale_grad_by_freq": scale_grad_by_freq, "sparse": sparse, } self.embedding = WordEmbedding(**embedding_params) @overrides def forward(self, inputs): return self.embedding(inputs) def get_output_dim(self): return self.embed_dim class OneHotEncoding(nn.Module): """ Sparse to one-hot encoding * Args: vocab: Vocab (claf.tokens.vocab) """ def __init__(self, index, token_name, classes): super(OneHotEncoding, self).__init__() vocab = Vocab(token_name) vocab.init() for c in classes[index]: vocab.add(c) num_class = len(vocab) self.num_class = num_class one_hot_encoding = torch.eye(num_class) self.one_hots = nn.Parameter(one_hot_encoding, requires_grad=False) @overrides def forward(self, inputs): if self.num_class == 4: inputs = inputs - 2 # make 0, 1 binary_feature return inputs.float().unsqueeze(-1) return F.embedding(inputs, self.one_hots) def get_output_dim(self): if self.num_class == 4: # binary_feature return 1 # 0 or 1 return self.num_class ================================================ FILE: claf/tokens/embedding/word_embedding.py ================================================ import logging from overrides import overrides import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from claf.data.data_handler import CachePath, DataHandler from .base import TokenEmbedding logger = logging.getLogger(__name__) class WordEmbedding(TokenEmbedding): """ Word Embedding Default Token Embedding * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx (initialized to zeros) whenever it encounters the index. max_norm: If given, will renormalize the embedding vectors to have a norm lesser than this before extracting. Note: this will modify weight in-place. norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of frequency of the words in the mini-batch. Default False. sparse: if True, gradient w.r.t. weight will be a sparse tensor. See Notes under torch.nn.Embedding for more details regarding sparse gradients. pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed """ def __init__( self, vocab, dropout=0.2, embed_dim=100, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, pretrained_path=None, trainable=True, ): super(WordEmbedding, self).__init__(vocab) self.data_handler = DataHandler(cache_path=CachePath.PRETRAINED_VECTOR) self.embed_dim = embed_dim if dropout and dropout > 0: self.dropout = nn.Dropout(p=dropout) else: self.dropout = lambda x: x if pretrained_path: weight = self._read_pretrained_file(pretrained_path) self.weight = torch.nn.Parameter(weight, requires_grad=trainable) else: self.weight = self._init_weight(trainable=trainable) # nn.functional.embedding = optional paramters # (padding_idx, max_norm, norm_type, scale_grad_by_freq, sparse) # check - https://pytorch.org/docs/master/nn.html#torch.nn.functional.embeddin\ # ://pytorch.org/docs/master/nn.html#torch.nn.functional.embedding self.padding_idx = padding_idx self.max_norm = max_norm self.norm_type = norm_type self.scale_grad_by_freq = scale_grad_by_freq self.sparse = sparse def _init_weight(self, trainable=True): weight = torch.FloatTensor(self.get_vocab_size(), self.embed_dim) weight = torch.nn.Parameter(weight, requires_grad=trainable) torch.nn.init.xavier_uniform_(weight) return weight @overrides def forward(self, words): input_size = words.size() if len(input_size) > 2: words = words.view(-1, input_size[-1]) embedded_words = F.embedding( words, self.weight, padding_idx=self.padding_idx, max_norm=self.max_norm, norm_type=self.norm_type, scale_grad_by_freq=self.scale_grad_by_freq, sparse=self.sparse, ) if len(input_size) > 2: embedded_size = list(input_size) + [embedded_words.size(-1)] embedded_words = embedded_words.view(*embedded_size) return self.dropout(embedded_words) def _read_pretrained_file(self, file_path): words_to_keep = set(self.vocab.get_all_tokens()) vocab_size = self.get_vocab_size() embeddings = {} # First we read the embeddings from the file, only keeping vectors for the words we need. logger.info("Reading embeddings from file") file_path = self.data_handler.read(file_path, return_path=True) with open(file_path, "rb") as embeddings_file: for line in embeddings_file: fields = line.decode("utf-8").rstrip().split(" ") if len(fields) - 1 != self.embed_dim: logger.info( f"Found line with wrong number of dimensions (expected {self.embed_dim}, was {len(fields)}): {line}" ) continue word = fields[0] if word in words_to_keep: vector = np.asarray(fields[1:], dtype="float32") embeddings[word] = vector if not embeddings: raise ValueError( "No embeddings of correct dimension found. check input dimension value" ) all_embeddings = np.asarray(list(embeddings.values())) embeddings_mean = float(np.mean(all_embeddings)) embeddings_std = float(np.std(all_embeddings)) # Now we initialize the weight matrix for an embedding layer, starting with random vectors, # then filling in the word vectors we just read. logger.info("Initializing pre-trained embedding layer") embedding_matrix = torch.FloatTensor(vocab_size, self.embed_dim).normal_( embeddings_mean, embeddings_std ) match_count = 0 for i in range(0, vocab_size): word = self.vocab.get_token(i) if word in embeddings: embedding_matrix[i] = torch.FloatTensor(embeddings[word]) match_count += 1 else: # f"Word {word} was not found in the embedding file. Initialising randomly." pass logger.info(f"Match embedding vocab size: {match_count}. [{match_count}/{vocab_size}]") return embedding_matrix @overrides def get_output_dim(self): return self.embed_dim ================================================ FILE: claf/tokens/hangul.py ================================================ #!/usr/bin/env python # encoding: utf-8 """ Hangulpy.py Copyright (C) 2012 Ryan Rho, Hyunwoo Cho Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ import string import re ################################################################################ # Hangul Unicode Variables ################################################################################ # Code = 0xAC00 + (Chosung_index * NUM_JOONGSUNGS * NUM_JONGSUNGS) + (Joongsung_index * NUM_JONGSUNGS) + (Jongsung_index) CHOSUNGS = [ "ㄱ", "ㄲ", "ㄴ", "ㄷ", "ㄸ", "ㄹ", "ㅁ", "ㅂ", "ㅃ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅉ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ", ] JOONGSUNGS = [ "ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ", "ㅗ", "ㅘ", "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ", "ㅠ", "ㅡ", "ㅢ", "ㅣ", ] JONGSUNGS = [ "", "ㄱ", "ㄲ", "ㄳ", "ㄴ", "ㄵ", "ㄶ", "ㄷ", "ㄹ", "ㄺ", "ㄻ", "ㄼ", "ㄽ", "ㄾ", "ㄿ", "ㅀ", "ㅁ", "ㅂ", "ㅄ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ", ] NUM_CHOSUNGS = 19 NUM_JOONGSUNGS = 21 NUM_JONGSUNGS = 28 FIRST_HANGUL_UNICODE = 0xAC00 # '가' LAST_HANGUL_UNICODE = 0xD7A3 # '힣' ################################################################################ # Boolean Hangul functions ################################################################################ def is_hangul(phrase): # pragma: no cover """Check whether the phrase is Hangul. This method ignores white spaces, punctuations, and numbers. @param phrase a target string @return True if the phrase is Hangul. False otherwise.""" # If the input is only one character, test whether the character is Hangul. if len(phrase) == 1: return is_all_hangul(phrase) # Remove all white spaces, punctuations, numbers. exclude = set(string.whitespace + string.punctuation + "0123456789") phrase = "".join(ch for ch in phrase if ch not in exclude) return is_all_hangul(phrase) def is_all_hangul(phrase): # pragma: no cover """Check whether the phrase contains all Hangul letters @param phrase a target string @return True if the phrase only consists of Hangul. False otherwise.""" for unicode_value in map(lambda letter: ord(letter), phrase): if unicode_value < FIRST_HANGUL_UNICODE or unicode_value > LAST_HANGUL_UNICODE: # Check whether the letter is chosungs, joongsungs, or jongsungs. if unicode_value not in map(lambda v: ord(v), CHOSUNGS + JOONGSUNGS + JONGSUNGS[1:]): return False return True def has_jongsung(letter): # pragma: no cover """Check whether this letter contains Jongsung""" if len(letter) != 1: raise Exception("The target string must be one letter.") if not is_hangul(letter): raise NotHangulException("The target string must be Hangul") unicode_value = ord(letter) return (unicode_value - FIRST_HANGUL_UNICODE) % NUM_JONGSUNGS > 0 def has_batchim(letter): # pragma: no cover """This method is the same as has_jongsung()""" return has_jongsung(letter) def has_approximant(letter): # pragma: no cover """Approximant makes complex vowels, such as ones starting with y or w. In Korean there is a unique approximant euㅡ making uiㅢ, but ㅢ does not make many irregularities.""" if len(letter) != 1: raise Exception("The target string must be one letter.") if not is_hangul(letter): raise NotHangulException("The target string must be Hangul") jaso = decompose(letter) diphthong = (2, 3, 6, 7, 9, 10, 12, 14, 15, 17) # [u'ㅑ',u'ㅒ',',u'ㅕ',u'ㅖ',u'ㅘ',u'ㅙ',u'ㅛ',u'ㅝ',u'ㅞ',u'ㅠ'] # excluded 'ㅢ' because y- and w-based complex vowels are irregular. # vowels with umlauts (ㅐ, ㅔ, ㅚ, ㅟ) are not considered complex vowels. return jaso[1] in diphthong ################################################################################ # Decomposition & Combination ################################################################################ def compose(chosung, joongsung, jongsung=""): # pragma: no cover """This function returns a Hangul letter by composing the specified chosung, joongsung, and jongsung. @param chosung @param joongsung @param jongsung the terminal Hangul letter. This is optional if you do not need a jongsung.""" if jongsung is None: jongsung = "" try: chosung_index = CHOSUNGS.index(chosung) joongsung_index = JOONGSUNGS.index(joongsung) jongsung_index = JONGSUNGS.index(jongsung) except Exception as e: raise NotHangulException( "No valid Hangul character can be generated using given combination of chosung, joongsung, and jongsung." ) return chr( 0xAC00 + chosung_index * NUM_JOONGSUNGS * NUM_JONGSUNGS + joongsung_index * NUM_JONGSUNGS + jongsung_index ) def decompose(hangul_letter): # pragma: no cover """This function returns letters by decomposing the specified Hangul letter.""" if len(hangul_letter) < 1: raise NotLetterException("") elif not is_hangul(hangul_letter): raise NotHangulException("") code = ord(hangul_letter) - FIRST_HANGUL_UNICODE jongsung_index = int(code % NUM_JONGSUNGS) code /= NUM_JONGSUNGS joongsung_index = int(code % NUM_JOONGSUNGS) code /= NUM_JOONGSUNGS chosung_index = int(code) return (CHOSUNGS[chosung_index], JOONGSUNGS[joongsung_index], JONGSUNGS[jongsung_index]) ################################################################################ # Josa functions ################################################################################ def josa_en(word): # pragma: no cover """add josa either '은' or '는' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "은" if has_jongsung(last_letter) else "는" return word + josa def josa_eg(word): # pragma: no cover """add josa either '이' or '가' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "이" if has_jongsung(last_letter) else "가" return word + josa def josa_el(word): # pragma: no cover """add josa either '을' or '를' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "을" if has_jongsung(last_letter) else "를" return word + josa def josa_ro(word): # pragma: no cover """add josa either '으로' or '로' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] if not has_jongsung(last_letter): josa = "로" elif (ord(last_letter) - FIRST_HANGUL_UNICODE) % NUM_JONGSUNGS == 9: # ㄹ josa = "로" else: josa = "으로" return word + josa def josa_gwa(word): # pragma: no cover """add josa either '과' or '와' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "과" if has_jongsung(last_letter) else "와" return word + josa def josa_ida(word): # pragma: no cover """add josa either '이다' or '다' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "이다" if has_jongsung(last_letter) else "다" return word + josa ################################################################################ # Prefixes and suffixes # Practice area; need more organization ################################################################################ def add_ryul(word): # pragma: no cover """add suffix either '률' or '율' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] if not has_jongsung(last_letter): ryul = "율" elif (ord(last_letter) - FIRST_HANGUL_UNICODE) % NUM_JONGSUNGS == 4: # ㄴ ryul = "율" else: ryul = "률" return word + ryul ################################################################################ # The formatter, or ultimately, a template system # Practice area; need more organization ################################################################################ def ili(word): # pragma: no cover """convert {가} or {이} to their correct respective particles automagically.""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[word.find("{가}") - 1] word = word.replace("{가}", ("이" if has_jongsung(last_letter) else "가")) last_letter = word[word.find("{이}") - 1] word = word.replace("{이}", ("이" if has_jongsung(last_letter) else "가")) return word ################################################################################ # Exceptions ################################################################################ class NotHangulException(Exception): # pragma: no cover pass class NotLetterException(Exception): # pragma: no cover pass class NotWordException(Exception): # pragma: no cover pass ================================================ FILE: claf/tokens/indexer/__init__.py ================================================ from .bert_indexer import BertIndexer from .char_indexer import CharIndexer from .elmo_indexer import ELMoIndexer from .exact_match_indexer import ExactMatchIndexer from .linguistic_indexer import LinguisticIndexer from .word_indexer import WordIndexer __all__ = [ "BertIndexer", "CharIndexer", "ELMoIndexer", "ExactMatchIndexer", "LinguisticIndexer", "WordIndexer", ] ================================================ FILE: claf/tokens/indexer/base.py ================================================ class TokenIndexer: """ Token Indexer indexing tokens (eg. 'hi' -> 4) """ def __init__(self, tokenizer): self.param_key = None self.tokenizer = tokenizer def index(self, token): """ indexing function """ raise NotImplementedError def set_vocab(self, vocab): self.vocab = vocab ================================================ FILE: claf/tokens/indexer/bert_indexer.py ================================================ from overrides import overrides from .base import TokenIndexer class BertIndexer(TokenIndexer): """ Bert Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: SubwordTokenizer * Kwargs: lowercase: word token to lowercase insert_start: insert start_token to first insert_end: append end_token """ def __init__(self, tokenizer, do_tokenize=True): super(BertIndexer, self).__init__(tokenizer) self.do_tokenize = do_tokenize @overrides def index(self, text): input_type = type(text) if input_type == str: return self._index_text(text) elif input_type == list: texts = text # List of text case return [self._index_text(text) for text in texts] else: raise ValueError(f"Not supported type: {type(text)}") def _index_text(self, text): if self.do_tokenize: tokens = self.tokenizer.tokenize(text) else: tokens = [text] indexed_tokens = [self.vocab.get_index(token) for token in tokens] # Insert CLS_TOKEN ans SEP_TOKEN insert_start = self.vocab.get_index(self.vocab.cls_token) indexed_tokens.insert(0, insert_start) insert_end = self.vocab.get_index(self.vocab.sep_token) indexed_tokens.append(insert_end) return indexed_tokens ================================================ FILE: claf/tokens/indexer/char_indexer.py ================================================ from overrides import overrides from .base import TokenIndexer class CharIndexer(TokenIndexer): """ Character Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: CharTokenizer * Kwargs: insert_char_start: insert start index (eg. ['h', 'i'] -> ['', 'h', 'i'] ) default is None insert_char_end: insert end index (eg. ['h', 'i'] -> ['h', 'i', ''] ) default is None """ def __init__(self, tokenizer, insert_char_start=None, insert_char_end=None): super(CharIndexer, self).__init__(tokenizer) self.insert_char_start = insert_char_start self.insert_char_end = insert_char_end @overrides def index(self, text): indexed_tokens = [self.index_token(token) for token in self.tokenizer.tokenize(text)] return indexed_tokens def index_token(self, chars): char_ids = [self.vocab.get_index(char) for char in chars] if self.insert_char_start is not None: char_ids.insert(0, self.vocab.get_index(self.vocab.start_token)) if self.insert_char_end is not None: char_ids.append(self.vocab.get_index(self.vocab.end_token)) return char_ids ================================================ FILE: claf/tokens/indexer/elmo_indexer.py ================================================ """ This code is from allenai/allennlp (https://github.com/allenai/allennlp/blob/master/allennlp/data/token_indexers/elmo_indexer.py) """ from overrides import overrides from .base import TokenIndexer def _make_bos_eos( character: int, padding_character: int, beginning_of_word_character: int, end_of_word_character: int, max_word_length: int, ): char_ids = [padding_character] * max_word_length char_ids[0] = beginning_of_word_character char_ids[1] = character char_ids[2] = end_of_word_character return char_ids class ELMoIndexer(TokenIndexer): """ Maps individual tokens to sequences of character ids, compatible with ELMo. To be consistent with previously trained models, we include it here as special of existing character indexers. """ max_word_length = 50 # char ids 0-255 come from utf-8 encoding bytes # assign 256-300 to special chars beginning_of_sentence_character = 256 # end_of_sentence_character = 257 # beginning_of_word_character = 258 # end_of_word_character = 259 # padding_character = 260 # beginning_of_sentence_characters = _make_bos_eos( beginning_of_sentence_character, padding_character, beginning_of_word_character, end_of_word_character, max_word_length, ) end_of_sentence_characters = _make_bos_eos( end_of_sentence_character, padding_character, beginning_of_word_character, end_of_word_character, max_word_length, ) BOS_TOKEN = "" EOS_TOKEN = "" def __init__(self, tokenizer): super(ELMoIndexer, self).__init__(tokenizer) @overrides def index(self, text): indexed_tokens = [self.index_token(token) for token in self.tokenizer.tokenize(text)] return indexed_tokens def index_token(self, word): if word == self.BOS_TOKEN: char_ids = self.beginning_of_sentence_characters elif word == self.EOS_TOKEN: char_ids = self.end_of_sentence_characters else: word_encodeds = word.encode("utf-8", "ignore")[: (self.max_word_length - 2)] char_ids = [char_id for char_id in word_encodeds] char_ids = [self.beginning_of_word_character] + char_ids + [self.end_of_word_character] return [c + 1 for c in char_ids] ================================================ FILE: claf/tokens/indexer/exact_match_indexer.py ================================================ from overrides import overrides from nltk.stem import WordNetLemmatizer from .base import TokenIndexer class ExactMatchIndexer(TokenIndexer): """ Exact Match Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: WordTokenizer * Kwargs: lower: add lower feature. default is True (0 or 1) lemma: add lemma case feature. feature is True (0 or 1) """ def __init__(self, tokenizer, lower=True, lemma=True): super(ExactMatchIndexer, self).__init__(tokenizer) self.param_key = "question" self.lemmatizer = WordNetLemmatizer() self.lower = lower self.lemma = lemma @overrides def index(self, text, query_text): tokenized_query_text = self.tokenizer.tokenize(query_text) query_tokens = { "origin": set(tokenized_query_text), "lower": set([token.lower() for token in tokenized_query_text]), "lemma": set( [self.lemmatizer.lemmatize(token.lower()) for token in tokenized_query_text] ), } indexed_tokens = [ self.index_token(token, query_tokens) for token in self.tokenizer.tokenize(text) ] return indexed_tokens def index_token(self, token, query_tokens): em_feature = [] # 1. origin origin_case = 1 if token in query_tokens["origin"] else 0 em_feature.append(origin_case + 2) # 2. lower if self.lower: lower_case = 1 if token.lower() in query_tokens["lower"] else 0 em_feature.append(lower_case + 2) # 3. lemma if self.lemma: lemma_case = ( 1 if self.lemmatizer.lemmatize(token.lower()) in query_tokens["lemma"] else 0 ) em_feature.append(lemma_case + 2) return em_feature ================================================ FILE: claf/tokens/indexer/linguistic_indexer.py ================================================ from overrides import overrides import spacy from claf.tokens.linguistic import POSTag, NER from .base import TokenIndexer class LinguisticIndexer(TokenIndexer): """ Linguistic Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: WordTokenizer * Kwargs: pos_tag: POS Tagging ner: Named Entity Recognition dep: Dependency Parser """ def __init__(self, tokenizer, pos_tag=None, ner=None, dep=None): super(LinguisticIndexer, self).__init__(tokenizer) self.spacy_model = None # Features self.use_pos_tag = pos_tag self.pos_to_index = {t: i for i, t in enumerate(POSTag.classes)} self.use_ner = ner self.ner_to_index = {t: i for i, t in enumerate(NER.classes)} self.use_dep = dep if dep: raise NotImplementedError("Dependency Parser feature") @overrides def index(self, text): package = self.tokenizer.name return getattr(self, f"_{package}")(text) """ Need to match with Tokenizer's package """ def _mecab_ko(self, text): raise NotImplementedError("Linguistic Feature with mecab package") def _nltk_en(self, text): raise NotImplementedError("Linguistic Feature with nltk package") def _spacy_en(self, text): if self.spacy_model is None: from claf.tokens.tokenizer.utils import load_spacy_model_for_tokenizer disables = ["vectors", "textcat", "parser"] if not self.use_pos_tag: disables.apppend("tagger") if not self.use_ner: disables.apppend("ner") self.spacy_model = spacy.load("en_core_web_sm", disable=disables) self.spacy_model.tokenizer = load_spacy_model_for_tokenizer( self.tokenizer.extra_split_chars_re ) sent_tokenizer = self.tokenizer.sent_tokenizer sentences = sent_tokenizer.tokenize(text) ner_entities = {} docs = [] for sentence in sentences: doc = self.spacy_model(sentence) docs.append(doc) if self.use_ner: for e in doc.ents: ner_entities[e.text] = e.label_ linguistic_features = [] for doc in docs: for token in doc: if token.is_space: continue feature = [] if self.use_pos_tag: feature.append(self.pos_to_index[token.pos_]) if self.use_ner: feature.append(self.ner_to_index[ner_entities.get(token.text, "NONE")]) linguistic_features.append(feature) return linguistic_features ================================================ FILE: claf/tokens/indexer/word_indexer.py ================================================ from overrides import overrides from .base import TokenIndexer class WordIndexer(TokenIndexer): """ Word Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: WordTokenizer * Kwargs: lowercase: word token to lowercase insert_start: insert start_token to first insert_end: append end_token """ def __init__( self, tokenizer, do_tokenize=True, lowercase=False, insert_start=None, insert_end=None ): super(WordIndexer, self).__init__(tokenizer) self.do_tokenize = do_tokenize self.lowercase = lowercase self.insert_start = insert_start self.insert_end = insert_end @overrides def index(self, text): input_type = type(text) if input_type == str: indexed_tokens = self._index_text(text) elif input_type == list: indexed_tokens = self._index_list_of_text(text) else: raise ValueError(f"Not supported type: {type(text)}") if self.insert_start is not None: insert_start = self.vocab.get_index(self.vocab.start_token) indexed_tokens.insert(0, insert_start) if self.insert_end is not None: insert_end = self.vocab.get_index(self.vocab.end_token) indexed_tokens.append(insert_end) return indexed_tokens def _index_text(self, text): if not self.do_tokenize: raise ValueError("input text type is 'str'. 'do_tokenize' is required.") return [self._index_token(token) for token in self.tokenizer.tokenize(text)] def _index_list_of_text(self, list_of_text): if self.do_tokenize: indexed_tokens = [ [self._index_token(token) for token in self.tokenizer.tokenize(text)] for text in list_of_text ] else: indexed_tokens = [self._index_token(text) for text in list_of_text] return indexed_tokens def _index_token(self, token): if self.lowercase: token = token.lower() return self.vocab.get_index(token) ================================================ FILE: claf/tokens/linguistic.py ================================================ class POSTag: """ Universal POS tags expends by spacy (https://spacy.io/api/annotation#section-pos-tagging) """ classes = [ "ADJ", # adjectives "ADP", # adpositions (prepositions and postpositions) "ADV", # adverbs "AUX", # auxiliary (spacy) "CONJ", # conjunctions "CCONJ", # coordinating conjunction (spacy) "DET", # determiners "INTJ", # interjection (spacy) "NOUN", # nouns (common and proper) "NUM", # cardinal numbers "PART", # particles or other function words (spacy) "PRON", # pronouns "PROPN", # proper noun "PUNCT", # punctuation "SCONJ", # subordinating conjunction "SYM", # symbol "VERB", # verbs (all tenses and modes) "X", # other: foreign words, typos, abbreviations "SPACE", # space ] class NER: """ Named Entity Recognition Models trained on the OntoNotes 5 corpus support the following entity types: (https://spacy.io/api/annotation#section-dependency-parsing) """ classes = [ "NONE", # None "PERSON", # People, including fictional. "NORP", # Nationalities or religious or political groups. "FAC", # Buildings, airports, highways, bridges, etc. "ORG", # Companies, agencies, institutions, etc. "GPE", # Countries, cities, states. "LOC", # Non-GPE locations, mountain ranges, bodies of water. "PRODUCT", # Objects, vehicles, foods, etc. (Not services.) "EVENT", # Named hurricanes, battles, wars, sports events, etc. "WORK_OF_ART", # Titles of books, songs, etc. "LAW", # Named documents made into laws. "LANGUAGE", # Any named language. "DATE", # Absolute or relative dates or periods. "TIME", # Times smaller than a day. "PERCENT", # Percentage, including "%". "MONEY", # Monetary values, including unit. "QUANTITY", # Measurements, as of weight or distance. "ORDINAL", # "first", "second", etc. "CARDINAL", # Numerals that do not fall under another type. ] ================================================ FILE: claf/tokens/text_handler.py ================================================ from collections import Counter import logging import time from tqdm import tqdm from claf.data.data_handler import CachePath, DataHandler from claf.data.utils import padding_tokens, transpose from claf.tokens.token_maker import TokenMaker from claf.tokens.vocabulary import Vocab from claf import utils as common_utils logger = logging.getLogger(__name__) class TextHandler: """ Text Handler - voacb and token_counter - raw_features -> indexed_features - raw_features -> tensor * Args: token_makers: Dictionary consisting of - key: token_name - value: TokenMaker (claf.tokens.token_maker) * Kwargs: lazy_indexing: Apply `Lazy Evaluation` to text indexing """ def __init__(self, token_makers, lazy_indexing=True): self.token_makers = token_makers self.lazy_indexing = lazy_indexing self.data_handler = DataHandler(cache_path=CachePath.TOKEN_COUNTER) def build_vocabs(self, token_counters): logger.info("Start build vocab") vocab_start_time = time.time() vocabs = {} for token_name, token_maker in self.token_makers.items(): is_defined_config = type(token_maker.vocab_config) == dict if is_defined_config: token_counter = token_counters[token_name] vocab = self._build_vocab_with_config(token_name, token_maker, token_counter) else: vocab = Vocab(token_name) vocab.init() vocabs[token_name] = vocab logger.info( f" => {token_name} vocab size: {len(vocab)} (use predefine vocab: {vocab.pretrained_path is not None})" ) vocab_elapased_time = time.time() - vocab_start_time logger.info(f"Complete build vocab... elapsed_time: {vocab_elapased_time}\n") # Setting Indexer (vocab) for token_name, token_maker in self.token_makers.items(): token_maker.set_vocab(vocabs[token_name]) return vocabs def _build_vocab_with_config(self, token_name, token_maker, token_counter): token_maker.vocab_config["token_name"] = token_name vocab = Vocab(**token_maker.vocab_config) if vocab.pretrained_path is not None: vocab.build_with_pretrained_file(token_counter) else: vocab.build(token_counter) return vocab def is_all_vocab_use_pretrained(self): for token_name, token_maker in self.token_makers.items(): if token_maker.vocab_config.get("pretrained_path", None) is None: return False if token_maker.vocab_config.get("pretrained_token", "") != Vocab.PRETRAINED_ALL: return False return True def make_token_counters(self, texts, config=None): token_counters = {} for token_name, token_maker in self.token_makers.items(): token_vocab_config = token_maker.vocab_config if type(token_vocab_config) == dict: if token_vocab_config.get("pretrained_token", None) == Vocab.PRETRAINED_ALL: texts = [ "" ] # do not use token_counter from dataset -> make empty token_counter token_counter = self._make_token_counter( texts, token_maker.tokenizer, config=config, desc=f"{token_name}-vocab" ) logger.info(f" * {token_name} token_counter size: {len(token_counter)}") token_counters[token_name] = token_counter return token_counters def _make_token_counter(self, texts, tokenizer, config=None, desc=None): tokenizer_name = tokenizer.name cache_token_counter = None if config is not None: data_reader_config = config.data_reader cache_token_counter = self.data_handler.cache_token_counter( data_reader_config, tokenizer_name ) if cache_token_counter: return cache_token_counter else: tokens = [ token for text in tqdm(texts, desc=desc) for token in tokenizer.tokenize(text) ] flatten_list = list(common_utils.flatten(tokens)) token_counter = Counter(flatten_list) if config is not None: # Cache TokenCounter self.data_handler.cache_token_counter( data_reader_config, tokenizer_name, obj=token_counter ) return token_counter def index(self, datas, text_columns): logger.info(f"Start token indexing, Lazy: {self.lazy_indexing}") indexing_start_time = time.time() for data_type, data in datas.items(): if type(data) == list: # Multi-Data Indexing for d in data: self._index_features( d.features, text_columns, desc=f"indexing features ({data_type})" ) else: self._index_features( data.features, text_columns, desc=f"indexing features ({data_type})" ) indexing_elapased_time = time.time() - indexing_start_time logger.info(f"Complete token indexing... elapsed_time: {indexing_elapased_time} \n") def _index_features(self, features, text_columns, desc=None, suppress_tqdm=False): for feature in tqdm(features, desc=desc, disable=suppress_tqdm): for key, text in feature.items(): if key not in text_columns: continue # Set data_type (text => {"text": ..., "token1": ..., ...}) if type(feature[key]) != dict: feature[key] = {"text": text} if type(text) == dict: text = text["text"] for token_name, token_maker in self.token_makers.items(): param_key = token_maker.indexer.param_key if param_key == key: continue feature[key][token_name] = self._index_token(token_maker, text, feature) def _index_token(self, token_maker, text, data): def index(): indexer = token_maker.indexer params = {} if token_maker.type_name == TokenMaker.EXACT_MATCH_TYPE: param_text = data[indexer.param_key] if type(param_text) == dict: param_text = param_text["text"] params["query_text"] = param_text return indexer.index(text, **params) if self.lazy_indexing: return index else: return index() def raw_to_tensor_fn(self, data_reader, cuda_device=None, helper={}): def raw_to_tensor(inputs): is_one = True # batch_size 1 flag feature, _helper = data_reader.read_one_example(inputs) nonlocal helper helper.update(_helper) if type(feature) == list: is_one = False features = feature else: features = [feature] self._index_features(features, data_reader.text_columns, suppress_tqdm=True) if is_one: indexed_features = features[0] else: # when features > 1, need to transpose (dict_of_list -> list_of_dict) indexed_features = {} for key in features[0]: feature_with_key = [feature[key] for feature in features] indexed_features[key] = transpose(feature_with_key, skip_keys=["text"]) for key in indexed_features: for token_name in self.token_makers: if token_name not in indexed_features[key]: continue indexed_values = indexed_features[key][token_name] if is_one: indexed_values = [indexed_values] tensor = padding_tokens(indexed_values, token_name=token_name) if cuda_device is not None and type(tensor) != list: tensor = tensor.cuda(cuda_device) indexed_features[key][token_name] = tensor for key in indexed_features: if "text" in indexed_features[key]: del indexed_features[key]["text"] return indexed_features, helper return raw_to_tensor ================================================ FILE: claf/tokens/token_embedder/__init__.py ================================================ from .basic_embedder import BasicTokenEmbedder from .reading_comprehension_embedder import RCTokenEmbedder __all__ = ["BasicTokenEmbedder", "RCTokenEmbedder"] ================================================ FILE: claf/tokens/token_embedder/base.py ================================================ import torch class TokenEmbedder(torch.nn.Module): """ Token Embedder Take a tensor(indexed token) look up Embedding modules. * Args: token_makers: dictionary of TokenMaker (claf.token_makers.token) """ def __init__(self, token_makers): super(TokenEmbedder, self).__init__() self.embed_dims = {} self.vocabs = { token_name: token_maker.vocab for token_name, token_maker in token_makers.items() } self.add_embedding_modules(token_makers) def add_embedding_modules(self, token_makers): """ add embedding module to TokenEmbedder """ self.token_names = [] for token_name, token_maker in token_makers.items(): self.token_names.append(token_name) vocab = token_maker.vocab embedding = token_maker.embedding_fn(vocab) self.add_module(token_name, embedding) self.embed_dims[token_name] = embedding.get_output_dim() def get_embed_dim(self): raise NotImplementedError def forward(self, inputs, params={}): raise NotImplementedError ================================================ FILE: claf/tokens/token_embedder/basic_embedder.py ================================================ from overrides import overrides import torch from .base import TokenEmbedder class BasicTokenEmbedder(TokenEmbedder): """ Basic Token Embedder Take a tensor(indexed token) look up Embedding modules. Output is concatenating all embedded tensors. * Args: token_makers: dictionary of TokenMaker (claf.tokens.token_maker) """ def __init__(self, token_makers): super(BasicTokenEmbedder, self).__init__(token_makers) @overrides def get_embed_dim(self, except_keys=[]): return sum(self.embed_dims.values()) @overrides def forward(self, inputs, except_keys=[], params={}): token_names = [name for name in self.token_names if name not in except_keys] if set(token_names) != set(inputs.keys()): raise ValueError( f"Mismatch token_names inputs: {inputs.keys()}, embeddings: {self.token_names}" ) embedded_tokens = [] for token_name, tensors in inputs.items(): embedding = getattr(self, token_name) embedded_token = embedding(tensors, **params) embedded_tokens.append(embedded_token) output = torch.cat(embedded_tokens, dim=-1) return output ================================================ FILE: claf/tokens/token_embedder/reading_comprehension_embedder.py ================================================ from overrides import overrides import torch import claf.modules.functional as f import claf.modules.attention as attention from .base import TokenEmbedder class RCTokenEmbedder(TokenEmbedder): """ Reading Comprehension Token Embedder Take a tensor(indexed token) look up Embedding modules. Inputs are seperated context and query for individual token setting. * Args: token_makers: dictionary of TokenMaker (claf.tokens.token_maker) vocabs: dictionary of vocab {"token_name": Vocab (claf.token_makers.vocaburary), ...} """ EXCLUSIVE_TOKENS = ["exact_match"] # only context def __init__(self, token_makers): super(RCTokenEmbedder, self).__init__(token_makers) self.context_embed_dim = sum(self.embed_dims.values()) self.query_embed_dim = sum(self._filter(self.embed_dims, exclusive=False).values()) self.align_attention = attention.SeqAttnMatch(self.query_embed_dim) @overrides def get_embed_dim(self): return self.context_embed_dim, self.query_embed_dim @overrides def forward(self, context, query, context_params={}, query_params={}, query_align=False): """ * Args: context: context inputs (eg. {"token_name1": tensor, "token_name2": tensor, ...}) query: query inputs (eg. {"token_name1": tensor, "token_name2": tensor, ...}) * Kwargs: context_params: custom context parameters query_params: query context parameters query_align: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. """ if set(self.token_names) != set(context.keys()): raise ValueError( f"Mismatch token_names inputs: {context.keys()}, embeddings: {self.token_names}" ) context_tokens, query_tokens = {}, {} for token_name, context_tensors in context.items(): embedding = getattr(self, token_name) context_tokens[token_name] = embedding( context_tensors, **context_params.get(token_name, {}) ) if token_name in query: query_tokens[token_name] = embedding( query[token_name], **query_params.get(token_name, {}) ) # query_align_embedding if query_align: common_context = self._filter(context_tokens, exclusive=False) embedded_common_context = torch.cat(list(common_context.values()), dim=-1) exclusive_context = self._filter(context_tokens, exclusive=True) embedded_exclusive_context = None if exclusive_context != {}: embedded_exclusive_context = torch.cat(list(exclusive_context.values()), dim=-1) query_mask = f.get_mask_from_tokens(query_tokens) embedded_query = torch.cat(list(query_tokens.values()), dim=-1) embedded_aligned_query = self.align_attention( embedded_common_context, embedded_query, query_mask ) # Merge context embedded embedded_context = [embedded_common_context, embedded_aligned_query] if embedded_exclusive_context is not None: embedded_context.append(embedded_exclusive_context) context_output = torch.cat(embedded_context, dim=-1) query_output = embedded_query else: context_output = torch.cat(list(context_tokens.values()), dim=-1) query_output = torch.cat(list(query_tokens.values()), dim=-1) return context_output, query_output def _filter(self, token_data, exclusive=False): if exclusive: return {k: v for k, v in token_data.items() if k in self.EXCLUSIVE_TOKENS} else: return {k: v for k, v in token_data.items() if k not in self.EXCLUSIVE_TOKENS} ================================================ FILE: claf/tokens/token_maker.py ================================================ class TokenMaker: """ Token Maker (Data Transfer Object) Token Maker consists of Tokenizer, Indexer, Embedding and Vocab * Kwargs: tokenizer: Tokenizer (claf.tokens.tokenizer.base) indexer: TokenIndexer (claf.tokens.indexer.base) embedding_fn: wrapper function of TokenEmbedding (claf.tokens.embedding.base) vocab_config: config dict of Vocab (claf.tokens.vocaburary) """ # Token Type List FEATURE_TYPE = "feature" # Do not use embedding, pass indexed_feature BERT_TYPE = "bert" CHAR_TYPE = "char" COVE_TYPE = "cove" ELMO_TYPE = "elmo" EXACT_MATCH_TYPE = "exact_match" WORD_TYPE = "word" FREQUENT_WORD_TYPE = "frequent_word" LINGUISTIC_TYPE = "linguistic" def __init__( self, token_type, tokenizer=None, indexer=None, embedding_fn=None, vocab_config=None ): self.type_name = token_type self._tokenizer = tokenizer self._indexer = indexer self._embedding_fn = embedding_fn self._vocab_config = vocab_config @property def tokenizer(self): return self._tokenizer @tokenizer.setter def tokenizer(self, tokenizer): self._tokenizer = tokenizer @property def indexer(self): return self._indexer @indexer.setter def indexer(self, indexer): self._indexer = indexer @property def embedding_fn(self): return self._embedding_fn @embedding_fn.setter def embedding_fn(self, embedding_fn): self._embedding_fn = embedding_fn @property def vocab_config(self): return self._vocab_config @vocab_config.setter def vocab_config(self, vocab_config): self._vocab_config = vocab_config @property def vocab(self): return self._vocab @vocab.setter def vocab(self, vocab): self._vocab = vocab def set_vocab(self, vocab): self._indexer.set_vocab(vocab) self._vocab = vocab ================================================ FILE: claf/tokens/tokenizer/__init__.py ================================================ from .pass_text import PassText from .bpe import BPETokenizer from .char import CharTokenizer from .subword import SubwordTokenizer from .word import WordTokenizer from .sent import SentTokenizer __all__ = ["PassText", "BPETokenizer", "CharTokenizer", "SubwordTokenizer", "WordTokenizer", "SentTokenizer"] ================================================ FILE: claf/tokens/tokenizer/base.py ================================================ class Tokenizer: """ Tokenizer Base Class """ MAX_TO_KEEP_CACHE = 3 def __init__(self, name, cache_name): self.cache = {} # dict: {text: tokenized_tokens} self.name = name self.cache_name = cache_name def tokenize(self, text, unit="text"): if type(text) == str and text in self.cache: return self.cache[text] tokenized_tokens = self._tokenize(text, unit="text") # Cache if len(self.cache) <= self.MAX_TO_KEEP_CACHE: self.cache[text] = tokenized_tokens else: first_key = next(iter(self.cache.keys())) del self.cache[first_key] return tokenized_tokens def _tokenize(self, text, unit="text"): """ splitting text into tokens. """ if type(text) != str: raise ValueError(f"text type is must be str. not {type(text)}") return getattr(self, f"_{self.name}")(text, unit=unit) ================================================ FILE: claf/tokens/tokenizer/bpe.py ================================================ from transformers import RobertaTokenizer from claf.data.data_handler import CachePath, DataHandler from .base import Tokenizer class BPETokenizer(Tokenizer): """ BPTE(Byte-Pair Encoding) Tokenizer text -> ... * Args: name: tokenizer name [roberta] """ def __init__(self, name, config={}): super(BPETokenizer, self).__init__(name, f"bpe-{name}") self.data_handler = DataHandler(CachePath.VOCAB) self.config = config self.bpe_tokenizer = None """ Tokenizers """ def _roberta(self, text, unit="text"): """ ex) """ if self.bpe_tokenizer is None: vocab_path = self.data_handler.read(self.config["vocab_path"], return_path=True) merges_path = self.data_handler.read(self.config["merges_path"], return_path=True) del self.config["vocab_path"] del self.config["merges_path"] self.bpe_tokenizer = RobertaTokenizer(vocab_path, merges_path, **self.config) return self.bpe_tokenizer._tokenize(text) ================================================ FILE: claf/tokens/tokenizer/char.py ================================================ from claf.tokens import hangul as hg from .base import Tokenizer class CharTokenizer(Tokenizer): """ Character Tokenizer text -> word tokens -> [char tokens] * Args: name: tokenizer name [character|decompose_ko] word_tokenizer: word tokenizer object """ def __init__(self, name, word_tokenizer, config={}): super(CharTokenizer, self).__init__(name, f"char-{name}+{word_tokenizer.cache_name}") self.config = config self.word_tokenizer = word_tokenizer """ Tokenizers """ def _character(self, text, unit="text"): """ ex) Hello World -> ['Hello', 'World'] -> [['H', 'e', 'l', 'l', 'o'], ['W', 'o', 'r', 'l', 'd']] """ if unit == "word": return [char for char in text] else: return [[char for char in word] for word in self.word_tokenizer.tokenize(text)] def _jamo_ko(self, text, unit="text"): """ ex) 안녕 세상 -> ['안녕', '세상'] -> [['ㅇ', 'ㅏ', 'ㄴ', 'ㄴ', 'ㅕ', 'ㅇ'], ['ㅅ', 'ㅔ', 'ㅅ', 'ㅏ', 'ㅇ']] """ def decompose(char): if hg.is_hangul(char): try: return [c for c in hg.decompose(char) if c != ""] except IndexError: # Case: ㅋㅋㅋㅋ return [char] else: return [char] tokens = [] if unit == "word": chars = [] for char in text: chars.extend(decompose(char)) tokens.append(chars) else: for word in self.word_tokenizer.tokenize(text): chars = [] for char in word: chars.extend(decompose(char)) tokens.append(chars) return tokens ================================================ FILE: claf/tokens/tokenizer/pass_text.py ================================================ class PassText: """ Pass text without tokenize """ def __init__(self): self.name = "pass" self.cache_name = "pass" def tokenize(self, text): return text ================================================ FILE: claf/tokens/tokenizer/sent.py ================================================ import nltk.data from .base import Tokenizer class SentTokenizer(Tokenizer): """ Sentence Tokenizer text -> [sent tokens] * Args: name: tokenizer name [punkt] """ def __init__(self, name, config={}): super(SentTokenizer, self).__init__(name, f"sent-{name}") self.config = config """ Tokenizers """ def _punkt(self, text, unit="text"): """ ex) Hello World. This is punkt tokenizer -> ['Hello World', 'This is punkt tokenizer'] """ sent_tokenizer = nltk.data.load("tokenizers/punkt/english.pickle") return sent_tokenizer.tokenize(text) ================================================ FILE: claf/tokens/tokenizer/subword.py ================================================ from transformers import WordpieceTokenizer from transformers.tokenization_bert import load_vocab from claf.data.data_handler import CachePath, DataHandler from .base import Tokenizer class SubwordTokenizer(Tokenizer): """ Subword Tokenizer text -> [word tokens] -> [[sub word tokens], ...] * Args: name: tokenizer name [wordpiece] """ def __init__(self, name, word_tokenizer, config={}): super(SubwordTokenizer, self).__init__(name, f"subword-{name}+{word_tokenizer.cache_name}") self.data_handler = DataHandler(CachePath.VOCAB) self.config = config self.word_tokenizer = word_tokenizer self.subword_tokenizer = None """ Tokenizers """ def _wordpiece(self, text, unit="text"): """ ex) Hello World -> ['Hello', 'World'] -> ['He', '##llo', 'Wo', '##rld'] """ if self.subword_tokenizer is None: vocab_path = self.data_handler.read(self.config["vocab_path"], return_path=True) vocab = load_vocab(vocab_path) self.subword_tokenizer = WordpieceTokenizer( vocab, unk_token=self.config.get("unk_token", "[UNK]")) tokens = [] if unit == "word": for sub_token in self.subword_tokenizer.tokenize(text): tokens.append(sub_token) else: for token in self.word_tokenizer.tokenize(text): for sub_token in self.subword_tokenizer.tokenize(token): tokens.append(sub_token) return tokens ================================================ FILE: claf/tokens/tokenizer/utils.py ================================================ import spacy def create_tokenizer_with_regex(nlp, split_regex): prefixes_re = spacy.util.compile_prefix_regex(nlp.Defaults.prefixes) infix_re = split_regex suffix_re = spacy.util.compile_suffix_regex(nlp.Defaults.suffixes) return spacy.tokenizer.Tokenizer( nlp.vocab, nlp.Defaults.tokenizer_exceptions, prefix_search=prefixes_re.search, infix_finditer=infix_re.finditer, suffix_search=suffix_re.search, token_match=None, ) def load_spacy_model_for_tokenizer(split_regex): model = spacy.load("en_core_web_sm", disable=["vectors", "textcat", "tagger", "parser", "ner"]) if split_regex is not None: spacy_tokenizer = create_tokenizer_with_regex(model, split_regex) model.tokenizer = spacy_tokenizer return model ================================================ FILE: claf/tokens/tokenizer/word.py ================================================ import re from overrides import overrides from claf import utils as common_utils from .base import Tokenizer class WordTokenizer(Tokenizer): """ Word Tokenizer * Args: name: tokenizer name [treebank_en|spacy_en|mecab_ko|bert_basic] * Kwargs: flatten: return type as flatten list split_with_regex: post split action. Split tokens that the tokenizer cannot split. """ def __init__(self, name, sent_tokenizer, config={}, split_with_regex=True): super(WordTokenizer, self).__init__(name, f"word-{name}+{sent_tokenizer.cache_name}") self.config = config self.sent_tokenizer = sent_tokenizer self.word_tokenizer = None self.split_with_regex = split_with_regex if split_with_regex: self.extra_split_chars_re = self.make_split_regex_expression() def make_split_regex_expression(self): """ Apply a small amount of extra splitting to the given tokens, this is in particular to avoid UNK tokens due to contraction, quotation, or other forms of puncutation. I haven't really done tests to see if/how much difference this makes, but it does avoid some common UNKs I noticed in SQuAD/TriviaQA """ extra_split_chars = ( "-", "£", "€", "¥", "¢", "₹", "*", "\u2212", "\u2014", "\u2013", "/", "~", '"', "'", "\ud01C", "\u2019", "\u201D", "\u2018", "\u00B0", ".", ":", ) extra_split_tokens = ( "``", "(?<=[^_])_(?=[^_])", # dashes w/o a preceeding or following dash, so __wow___ -> ___ wow ___ "''", "[" + "".join(extra_split_chars) + "]", ) return re.compile("(" + "|".join(extra_split_tokens) + ")") @overrides def _tokenize(self, text, unit="text"): """ Text -> word tokens """ if type(text) != str: raise ValueError(f"text type is must be str. not {type(text)}") if unit == "sentence": tokens = getattr(self, f"_{self.name}")(text) else: sentences = self.sent_tokenizer.tokenize(text) tokens = [getattr(self, f"_{self.name}")(sentence) for sentence in sentences] if self.split_with_regex and self.name != "spacy_en": tokens = self._split_with_regex(tokens) return list(common_utils.flatten(tokens)) def _split_with_regex(self, sentences): for i, sentence in enumerate(sentences): sentences[i] = [token for token in self._post_split_tokens(sentence)] return sentences def _post_split_tokens(self, tokens): return [[x for x in self.extra_split_chars_re.split(token) if x != ""] for token in tokens] """ Tokenizers """ def _space_all(self, text): def is_whitespace(c): if c == " " or c == "\t" or c == "\r" or c == "\n" or ord(c) == 0x202F: return True return False prev_is_whitespace = True tokens = [] for char in text: if is_whitespace(char): prev_is_whitespace = True else: if prev_is_whitespace: tokens.append(char) else: tokens[-1] += char prev_is_whitespace = False return tokens def _treebank_en(self, text): if self.word_tokenizer is None: import nltk self.word_tokenizer = nltk.TreebankWordTokenizer() return [ token.replace("''", '"').replace("``", '"') for token in self.word_tokenizer.tokenize(text) ] def _spacy_en(self, text): if self.word_tokenizer is None: from claf.tokens.tokenizer.utils import load_spacy_model_for_tokenizer self.word_tokenizer = load_spacy_model_for_tokenizer(self.extra_split_chars_re) def _remove_spaces(tokens): return [token.text for token in tokens if not token.is_space] return _remove_spaces(self.word_tokenizer(text)) def _bert_basic(self, text): if self.word_tokenizer is None: from transformers import BasicTokenizer self.word_tokenizer = BasicTokenizer(**self.config) return self.word_tokenizer.tokenize(text) def _mecab_ko(self, text): if self.word_tokenizer is None: from konlpy.tag import Mecab self.word_tokenizer = Mecab() return self.word_tokenizer.morphs(text) ================================================ FILE: claf/tokens/vocabulary.py ================================================ from collections import defaultdict import json from claf.data.data_handler import CachePath, DataHandler class VocabDict(defaultdict): """ Vocab DefaultDict Class * Kwargs: oov_value: out-of-vocaburary token value (eg. ) """ def __init__(self, oov_value): self.oov_value = oov_value def __missing__(self, key): return self.oov_value class Vocab: """ Vocaburary Class Vocab consists of token_to_index and index_to_token. * Args: token_name: Token name (Token and Vocab is one-to-one relationship) * Kwargs: pad_token: padding token value (eg. ) oov_token: out-of-vocaburary token value (eg. ) start_token: start token value (eg. , ) end_token: end token value (eg. , ) cls_token: CLS token value for BERT (eg. [CLS]) sep_token: SEP token value for BERT (eg. [SEP]) min_count: token's minimal frequent count. when you define min_count, tokens remain that bigger than min_count. max_vocab_size: vocaburary's maximun size. when you define max_vocab_size, tokens are selected according to frequent count. frequent_count: get frequent_count threshold_index. (eg. frequent_count = 1000, threshold_index is the tokens that frequent_count is 999 index number.) pretrained_path: pretrained vocab file path (format: A\nB\nC\nD\n...) """ DEFAULT_PAD_INDEX, DEFAULT_PAD_TOKEN = 0, "[PAD]" DEFAULT_OOV_INDEX, DEFAULT_OOV_TOKEN = 1, "[UNK]" # pretrained_vocab handle methods PRETRAINED_ALL = "all" # Case. embedding matrix - predefine_vocab fixed PRETRAINED_INTERSECT = "intersect" # add token that included in predefine_vocab, else UNK_token def __init__( self, token_name, pad_token=None, oov_token=None, start_token=None, end_token=None, cls_token=None, sep_token=None, min_count=None, max_vocab_size=None, frequent_count=None, pretrained_path=None, pretrained_token=None, ): self.token_name = token_name # basic token (pad and oov) self.pad_index = self.DEFAULT_PAD_INDEX self.pad_token = pad_token if pad_token is None: self.pad_token = self.DEFAULT_PAD_TOKEN self.oov_index = self.DEFAULT_OOV_INDEX self.oov_token = oov_token if oov_token is None: self.oov_token = self.DEFAULT_OOV_TOKEN # special_tokens self.start_token = start_token self.end_token = end_token self.cls_token = cls_token self.sep_token = sep_token self.min_count = min_count self.max_vocab_size = max_vocab_size self.token_counter = None self.frequent_count = frequent_count self.threshold_index = None self.pretrained_path = pretrained_path self.pretrained_token = pretrained_token self.pretrained_token_methods = [self.PRETRAINED_ALL, self.PRETRAINED_INTERSECT] def init(self): self.token_to_index = VocabDict(self.oov_index) self.index_to_token = VocabDict(self.oov_token) # add default token (pad, oov) self.add(self.pad_token) self.add(self.oov_token) special_tokens = [self.start_token, self.end_token, self.cls_token, self.sep_token] for token in special_tokens: if token is not None: self.add(token) def build(self, token_counter, predefine_vocab=None): """ build token with token_counter * Args: token_counter: (collections.Counter) token's frequent_count Counter. """ if predefine_vocab is not None: if ( self.pretrained_token is None or self.pretrained_token not in self.pretrained_token_methods ): raise ValueError( f"When use 'predefine_vocab', need to set 'pretrained_token' {self.pretrained_token_methods}" ) if predefine_vocab: if self.pretrained_token == self.PRETRAINED_ALL: self.from_texts(predefine_vocab) return else: predefine_vocab = set(predefine_vocab) self.token_counter = token_counter self.init() token_counts = list(token_counter.items()) token_counts.sort(key=lambda x: x[1], reverse=True) # order: DESC if self.max_vocab_size is not None: token_counts = token_counts[: self.max_vocab_size] for token, count in token_counts: if self.min_count is not None: if count >= self.min_count: self.add(token, predefine_vocab=predefine_vocab) else: self.add(token, predefine_vocab=predefine_vocab) if self.threshold_index is None and self.frequent_count is not None: if count < self.frequent_count: self.threshold_index = len(self.token_to_index) def build_with_pretrained_file(self, token_counter): data_handler = DataHandler(CachePath.VOCAB) vocab_texts = data_handler.read(self.pretrained_path) if self.pretrained_path.endswith(".txt"): predefine_vocab = vocab_texts.split("\n") elif self.pretrained_path.endswith(".json"): vocab_texts = json.loads(vocab_texts) # {token: id} predefine_vocab = [item[0] for item in sorted(vocab_texts.items(), key=lambda x: x[1])] else: raise ValueError(f"support vocab extention. .txt or .json") self.build(token_counter, predefine_vocab=predefine_vocab) def __len__(self): return len(self.token_to_index) def add(self, token, predefine_vocab=None): if token in self.token_to_index: return # already added if predefine_vocab: if self.pretrained_token == self.PRETRAINED_INTERSECT and token not in predefine_vocab: return index = len(self.token_to_index) self.token_to_index[token] = index self.index_to_token[index] = token def get_index(self, token): return self.token_to_index[token] def get_token(self, index): return self.index_to_token[index] def get_all_tokens(self): return list(self.token_to_index.keys()) def dump(self, path): with open(path, "w", encoding="utf-8") as out_file: out_file.write(self.to_text()) def load(self, path): with open(path, "r", encoding="utf-8") as in_file: texts = in_file.read() self.from_texts(texts) def to_text(self): return "\n".join(self.get_all_tokens()) def from_texts(self, texts): if type(texts) == list: tokens = texts else: tokens = [token for token in texts.split("\n")] tokens = [token for token in tokens if token] # filtering empty string # basic token (pad and oov) if self.pad_token in tokens: self.pad_index = tokens.index(self.pad_token) else: self.pad_index = len(tokens) tokens.append(self.pad_token) if self.oov_token in tokens: self.oov_index = tokens.index(self.oov_token) else: self.oov_index = len(tokens) tokens.append(self.oov_token) self.token_to_index = VocabDict(self.oov_index) self.index_to_token = VocabDict(self.oov_token) for token in tokens: self.add(token) return self ================================================ FILE: claf/utils.py ================================================ import logging import os import sys from claf.learn.mode import Mode """ Interface """ def get_user_input(category): print(f"{category.capitalize()} > ", end="") sys.stdout.flush() user_input = sys.stdin.readline() try: return eval(user_input) except BaseException: return str(user_input) def flatten(l): for item in l: if isinstance(item, list): for in_item in flatten(item): yield in_item else: yield item """ Logging """ def set_logging_config(mode, config): stdout_handler = logging.StreamHandler(sys.stdout) logging_handlers = [stdout_handler] logging_level = logging.INFO if mode == Mode.TRAIN: log_path = os.path.join( config.trainer.log_dir, f"{config.data_reader.dataset}_{config.model.name}.log" ) os.makedirs(os.path.dirname(log_path), exist_ok=True) file_handler = logging.FileHandler(log_path) logging_handlers.append(file_handler) elif mode == Mode.PREDICT: logging_level = logging.WARNING logging.basicConfig( format="%(asctime)s (%(filename)s:%(lineno)d): [%(levelname)s] - %(message)s", handlers=logging_handlers, level=logging_level, ) ================================================ FILE: docs/Makefile ================================================ # Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SPHINXPROJ = rqa SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) ================================================ FILE: docs/_build/html/.buildinfo ================================================ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. config: efcb1307cc0fb9d7a5cb183d8528bc89 tags: 645f666f9bcd5a90fca523b33c5a78b7 ================================================ FILE: docs/_build/html/.nojekyll ================================================ ================================================ FILE: docs/_build/html/_modules/claf/config/args.html ================================================ claf.config.args — CLaF 0.2.0 documentation

Source code for claf.config.args


import argparse
from argparse import RawTextHelpFormatter
import json
import os
import sys

import torch

from claf import nsml
from claf.config import utils
from claf.config.namespace import NestedNamespace
from claf.learn.mode import Mode


[docs]def config(argv=None, mode=None): if argv is None: argv = sys.argv[1:] # 0 is excute file_name parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter) general(parser) if mode == Mode.EVAL: evaluate(parser) return parser.parse_args(argv, namespace=NestedNamespace()) if mode == Mode.PREDICT: predict(parser) return parser.parse_args(argv, namespace=NestedNamespace()) if mode == Mode.MACHINE: machine(parser) config = parser.parse_args(argv, namespace=NestedNamespace()) if config.machine_config is None: raise ValueError("--machine_config is required.") machine_config_path = os.path.join("machine_config", config.machine_config + ".json") with open(machine_config_path, "r") as f: defined_config = json.load(f) config.overwrite(defined_config) return config return train_config(parser, input_argv=argv)
[docs]def train_config(parser, input_argv=None): """ Add argument only for hyperparameter tuning. """ data(parser) token(parser) model(parser) if nsml.IS_ON_NSML: nsml_for_internal(parser) trainer(parser) # Use from config file base_config(parser) config = parser.parse_args(input_argv, namespace=NestedNamespace()) use_base_config = config.base_config # use pre-defined base_config if use_base_config: base_config_path = os.path.join("base_config", config.base_config + ".json") with open(base_config_path, "r") as f: defined_config = json.load(f) # config.overwrite(defined_config) config = NestedNamespace() config.load_from_json(defined_config) # overwrite input argument when base_config and arguments are provided. # (eg. --base_config bidaf --learning_rate 2) -> set bidaf.json then overwrite learning_rate 2) input_args = get_input_arguments(parser, input_argv) for k, v in input_args.items(): setattr(config, k, v) if not use_base_config: config = optimize_config(config) set_gpu_env(config) set_batch_size(config) return config
[docs]def get_input_arguments(parser, input_arguments): flat_config = parser.parse_args(input_arguments) config_dict = utils.convert_config2dict(flat_config) config_default_none = {k: None for k in config_dict.keys()} input_parser = argparse.ArgumentParser(parents=[parser], conflict_handler="resolve") input_parser.set_defaults(**config_default_none) input_config = input_parser.parse_args(input_arguments) input_config = utils.convert_config2dict(input_config) if "base_config" in input_config: del input_config["base_config"] return {k: v for k, v in input_config.items() if v is not None}
[docs]def optimize_config(config, is_test=False): if not is_test: # Remove unselected argument token_excepts = config.token.names + ["names", "types", "tokenizer"] config.delete_unselected(config.token, excepts=token_excepts) config.delete_unselected(config.model, excepts=["name", config.model.name]) config.delete_unselected( config.optimizer, excepts=[ "op_type", config.optimizer.op_type, "learning_rate", "lr_scheduler_type", config.optimizer.lr_scheduler_type, "exponential_moving_average", ], ) return config
[docs]def set_gpu_env(config): # GPU & NSML config.use_gpu = torch.cuda.is_available() or nsml.IS_ON_NSML if nsml.IS_ON_NSML: if getattr(config, "nsml", None) is None: config.nsml = NestedNamespace() config.nsml.dataset_path = nsml.DATASET_PATH config.gpu_num = int(nsml.GPU_NUM) else: config.gpu_num = len(getattr(config, "cuda_devices", [])) if not config.use_gpu: config.gpu_num = 0 config.cuda_devices = None
[docs]def set_batch_size(config): # dynamic batch_size (multi-gpu and gradient_accumulation_steps) batch_size = config.iterator.batch_size if config.gpu_num > 1: batch_size *= config.gpu_num if getattr(config.optimizer, "gradient_accumulation_steps", None): batch_size = batch_size // config.optimizer.gradient_accumulation_steps config.iterator.batch_size = int(batch_size)
[docs]def arg_str2bool(v): if v.lower() in ("yes", "true", "True", "t", "y", "1"): return True elif v.lower() in ("no", "false", "False", "f", "n", "0"): return False else: raise argparse.ArgumentTypeError("Boolean value expected.")
# fmt: off
[docs]def general(parser): group = parser.add_argument_group("General") group.add_argument( "--seed_num", type=int, default=21, dest="seed_num", help=""" Manually set seed_num (Python, Numpy, Pytorch) default is 21 """, ) group.add_argument( "--cuda_devices", nargs="+", type=int, default=[], dest="cuda_devices", help=""" Set cuda_devices ids (use GPU). if you use NSML, use GPU_NUM""", ) group.add_argument( "--slack_url", type=str, default=None, dest="slack_url", help=""" Slack notification (Incoming Webhook) """, )
[docs]def data(parser): group = parser.add_argument_group("Data Reader") group.add_argument( "--dataset", type=str, default="squad", dest="data_reader.dataset", help=""" Dataset Name [squad|squad2] """, ) group.add_argument( "--train_file_path", type=str, default="train-v1.1.json", dest="data_reader.train_file_path", help=""" train file path. """, ) group.add_argument( "--valid_file_path", type=str, default="dev-v1.1.json", dest="data_reader.valid_file_path", help=""" validation file path. """, ) group.add_argument( "--test_file_path", type=str, default=None, dest="data_reader.test_file_path", help=""" test file path. """, ) group = parser.add_argument_group(" # SQuAD DataSet") group.add_argument( "--squad.context_max_length", type=int, default=None, dest="data_reader.squad.context_max_length", help=""" The number of SQuAD Context maximum length. """, ) group = parser.add_argument_group(" # HistoryQA DataSet") group.add_argument( "--history.context_max_length", type=int, default=None, dest="data_reader.history.context_max_length", help=""" The number of HistoryQA Context maximum length. """, ) group = parser.add_argument_group(" # SeqCls DataSet") group.add_argument( "--seq_cls.class_key", type=int, default=None, dest="data_reader.seq_cls.class_key", help=""" Name of the label to use for classification. """, ) group.add_argument( "--seq_cls.sequence_max_length", type=int, default=None, dest="data_reader.seq_cls.sequence_max_length", help=""" The number of maximum sequence length. """, ) group = parser.add_argument_group(" # SeqClsBert DataSet") group.add_argument( "--seq_cls_bert.class_key", type=int, default=None, dest="data_reader.seq_cls_bert.class_key", help=""" Name of the label to use for classification. """, ) group.add_argument( "--seq_cls_bert.sequence_max_length", type=int, default=None, dest="data_reader.seq_cls_bert.sequence_max_length", help=""" The number of maximum sequence length. """, ) group = parser.add_argument_group(" # TokClsBert DataSet") group.add_argument( "--tok_cls_bert.tag_key", type=int, default=None, dest="data_reader.tok_cls_bert.tag_key", help=""" Name of the label to use for classification. """, ) group.add_argument( "--tok_cls_bert.ignore_tag_idx", type=int, default=None, dest="data_reader.tok_cls_bert.ignore_tag_idx", help=""" Index of the tag to ignore when calculating loss. (tag pad value) """, ) group.add_argument( "--tok_cls_bert.sequence_max_length", type=int, default=None, dest="data_reader.tok_cls_bert.sequence_max_length", help=""" The number of maximum sequence length. """, ) group = parser.add_argument_group("Iterator") group.add_argument( "--batch_size", type=int, default=32, dest="iterator.batch_size", help=""" Maximum batch size for trainer""", )
[docs]def token(parser): group = parser.add_argument_group("Token") group.add_argument( "--token_names", nargs="+", type=str, default=["char", "word"], dest="token.names", help=""" Define tokens name""", ) group.add_argument( "--token_types", nargs="+", type=str, default=["char", "word"], dest="token.types", help="""\ Use pre-defined token (tokenizer -> indexer -> embedder) [char|cove|elmo|exact_match|frequent_word|word]""", ) group = parser.add_argument_group(" # Vocabulary") group.add_argument( "--char.pad_token", type=str, default=None, dest="token.char.vocab.pad_token", help=""" Padding Token value""", ) group.add_argument( "--char.oov_token", type=str, default=None, dest="token.char.vocab.oov_token", help=""" Out-of-Vocabulary Token value""", ) group.add_argument( "--char.start_token", type=str, default=None, dest="token.char.vocab.start_token", help=""" Start Token value""", ) group.add_argument( "--char.end_token", type=str, default=None, dest="token.char.vocab.end_token", help=""" End Token value""", ) group.add_argument( "--char.min_count", type=int, default=None, dest="token.char.vocab.min_count", help=""" The number of token's min count""", ) group.add_argument( "--char.max_vocab_size", type=int, default=260, dest="token.char.vocab.max_vocab_size", help=""" The number of vocab's max size""", ) group.add_argument( "--feature.pretrained_path", type=str, default=None, dest="token.feature.vocab.pretrained_path", help=""" Add pretrained vocab_path""", ) group.add_argument( "--feature.pad_token", type=str, default=None, dest="token.feature.vocab.pad_token", help=""" Set pad_token""", ) group.add_argument( "--feature.oov_token", type=str, default=None, dest="token.feature.vocab.oov_token", help=""" Set oov_token""", ) group.add_argument( "--feature.cls_token", type=str, default=None, dest="token.feature.vocab.cls_token", help=""" Set cls_token""", ) group.add_argument( "--feature.sep_token", type=str, default=None, dest="token.feature.vocab.sep_token", help=""" Set sep_token""", ) group.add_argument( "--word.pad_token", type=str, default=None, dest="token.word.vocab.pad_token", help=""" Padding Token value""", ) group.add_argument( "--word.oov_token", type=str, default=None, dest="token.word.vocab.oov_token", help=""" Out-of-Vocabulary Token value""", ) group.add_argument( "--word.min_count", type=int, default=None, dest="token.word.vocab.min_count", help=""" The number of token's min count""", ) group.add_argument( "--word.max_vocab_size", type=int, default=None, dest="token.word.vocab.max_vocab_size", help=""" The number of vocab's max size""", ) group.add_argument( "--frequent_word.frequent_count", type=int, default=1000, dest="token.frequent_word.vocab.frequent_count", help="""\ The number of threshold frequent count (>= threshold -> fine-tune, < threshold -> fixed)""", ) group = parser.add_argument_group(" # Tokenizer") group.add_argument( "--tokenizer.bpe.name", type=str, default="roberta", dest="token.tokenizer.bpe.name", help="""\ BPE Tokenizer package name [roberta] Default is 'roberta' """, ) group.add_argument( "--tokenizer.bpe.roberta.vocab_path", type=str, default=None, dest="token.tokenizer.bpe.roberta.vocab_path", help="""\ RoBERTa BPE Tokenizer vocab_path Default is 'None' """, ) group.add_argument( "--tokenizer.bpe.roberta.merges_path", type=str, default=None, dest="token.tokenizer.bpe.roberta.merges_path", help="""\ RoBERTa BPE Tokenizer merges_path Default is 'None' """, ) group.add_argument( "--tokenizer.char.name", type=str, default="character", dest="token.tokenizer.char.name", help="""\ CharTokenizer package name [character|jamo_ko] Default is 'character' """, ) group.add_argument( "--tokenizer.subword.name", type=str, default="wordpiece", dest="token.tokenizer.subword.name", help="""\ SubWordTokenizer package name [wordpiece] Default is 'wordpiece' """, ) group.add_argument( "--tokenizer.subword.wordpiece.vocab_path", type=str, default=None, dest="token.tokenizer.subword.wordpiece.vocab_path", help="""\ Wordpiece Tokenizer vocab_path Default is 'None' """, ) group.add_argument( "--tokenizer.word.name", type=str, default="treebank_en", dest="token.tokenizer.word.name", help="""\ WordTokenizer package name [treebank_en|spacy_en|mecab_ko] Default is 'treebank_en' """, ) group.add_argument( "--tokenizer.word.split_with_regex", type=arg_str2bool, default=False, dest="token.tokenizer.word.split_with_regex", help=""" preprocess for SQuAD Context data (simple regex) """, ) group.add_argument( "--tokenizer.word.bert_basic.do_lower_case", type=arg_str2bool, default=True, dest="token.tokenizer.word.bert_basic.do_lower_case", help="""\ Wordpiece Tokenizer do_lower_case or not Default is 'True' """, ) group.add_argument( "--tokenizer.sent.name", type=str, default="punkt", dest="token.tokenizer.sent.name", help="""\ SentTokenizer package name [punkt] Default is 'punkt' """, ) group = parser.add_argument_group(" # Indexer") group.add_argument( "--char.insert_char_start", type=arg_str2bool, default=False, dest="token.char.indexer.insert_char_start", help=""" insert first start_token to tokens""", ) group.add_argument( "--char.insert_char_end", type=arg_str2bool, default=False, dest="token.char.indexer.insert_char_end", help=""" append end_token to tokens""", ) group.add_argument( "--exact_match.lower", type=arg_str2bool, default=True, dest="token.exact_match.indexer.lower", help=""" add lower case feature """, ) group.add_argument( "--exact_match.lemma", type=arg_str2bool, default=True, dest="token.exact_match.indexer.lemma", help=""" add lemma case feature """, ) group.add_argument( "--linguistic.pos_tag", type=arg_str2bool, default=True, dest="token.linguistic.indexer.pos_tag", help=""" add POS Tagging feature """, ) group.add_argument( "--linguistic.ner", type=arg_str2bool, default=True, dest="token.linguistic.indexer.ner", help=""" add Named Entity Recognition feature """, ) group.add_argument( "--linguistic.dep", type=arg_str2bool, default=False, dest="token.linguistic.indexer.dep", help=""" add Dependency Parser feature """, ) group.add_argument( "--word.lowercase", type=arg_str2bool, default=False, dest="token.word.indexer.lowercase", help=""" Apply word token to lowercase""", ) group.add_argument( "--word.insert_start", type=arg_str2bool, default=False, dest="token.word.indexer.insert_start", help=""" insert first start_token to tokens""", ) group.add_argument( "--word.insert_end", type=arg_str2bool, default=False, dest="token.word.indexer.insert_end", help=""" append end_token to tokens""", ) group = parser.add_argument_group(" # Embedding") group.add_argument( "--char.embed_dim", type=int, default=16, dest="token.char.embedding.embed_dim", help=""" The number of Embedding dimension""", ) group.add_argument( "--char.kernel_sizes", nargs="+", type=int, default=[5], dest="token.char.embedding.kernel_sizes", help=""" CharCNN kernel_sizes (n-gram)""", ) group.add_argument( "--char.num_filter", type=int, default=100, dest="token.char.embedding.num_filter", help=""" The number of CNN filter""", ) group.add_argument( "--char.activation", type=str, default="relu", dest="token.char.embedding.activation", help=""" CharCNN activation Function (default: ReLU)""", ) group.add_argument( "--char.dropout", type=float, default=0.2, dest="token.char.embedding.dropout", help=""" Embedding dropout prob (default: 0.2)""", ) group.add_argument( "--cove.glove_pretrained_path", type=str, default=None, dest="token.cove.embedding.glove_pretrained_path", help=""" CoVe's word embedding pretrained_path (GloVE 840B.300d)""", ) group.add_argument( "--cove.model_pretrained_path", type=str, default=None, dest="token.cove.embedding.model_pretrained_path", help=""" CoVe Model pretrained_path """, ) group.add_argument( "--cove.trainable", type=arg_str2bool, default=True, dest="token.cove.embedding.trainable", help=""" CoVe Embedding Trainable""", ) group.add_argument( "--cove.dropout", type=float, default=0.2, dest="token.cove.embedding.dropout", help=""" Embedding dropout prob (default: 0.2)""", ) group.add_argument( "--cove.project_dim", type=int, default=None, dest="token.cove.embedding.project_dim", help=""" The number of projection dimension""", ) group.add_argument( "--elmo.options_file", type=str, default="elmo_2x4096_512_2048cnn_2xhighway_options.json", dest="token.elmo.embedding.options_file", help=""" The option file path of ELMo""", ) group.add_argument( "--elmo.weight_file", type=str, default="elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5", dest="token.elmo.embedding.weight_file", help=""" The weight file path of ELMo""", ) group.add_argument( "--elmo.trainable", type=arg_str2bool, default=False, dest="token.elmo.embedding.trainable", help=""" elmo Embedding Trainable""", ) group.add_argument( "--elmo.dropout", type=float, default=0.5, dest="token.elmo.embedding.dropout", help=""" Embedding dropout prob (default: 0.5)""", ) group.add_argument( "--elmo.project_dim", type=int, default=None, dest="token.elmo.embedding.project_dim", help=""" The number of projection dimension (default is None)""", ) group.add_argument( "--word_permeability.memory_clip", type=int, default=3, dest="token.word_permeability.embedding.memory_clip", help=""" The number of memory cell clip value """, ) group.add_argument( "--word_permeability.proj_clip", type=int, default=3, dest="token.word_permeability.embedding.proj_clip", help=""" The number of p clip value after projection """, ) group.add_argument( "--word_permeability.embed_dim", type=int, default=1024, dest="token.word_permeability.embedding.embed_dim", help=""" The number of Embedding dimension""", ) group.add_argument( "--word_permeability.linear_dim", type=int, default=None, dest="token.word_permeability.embedding.linear_dim", help=""" The number of linear projection dimension""", ) group.add_argument( "--word_permeability.trainable", type=arg_str2bool, default=False, dest="token.word_permeability.embedding.trainable", help=""" word_permeability Embedding Trainable """, ) group.add_argument( "--word_permeability.dropout", type=float, default=0.5, dest="token.word_permeability.embedding.dropout", help=""" Embedding dropout prob (default: 0.5)""", ) group.add_argument( "--word_permeability.activation", type=str, default="tanh", dest="token.word_permeability.embedding.activation", help=""" Activation Function (default is 'tanh') """, ) group.add_argument( "--word_permeability.bidirectional", type=arg_str2bool, default=False, dest="token.word_permeability.embedding.bidirectional", help=""" bidirectional use or not ([forward;backward]) (default is False) """, ) group.add_argument( "--frequent_word.embed_dim", type=int, default=100, dest="token.frequent_word.embedding.embed_dim", help=""" The number of Embedding dimension""", ) group.add_argument( "--frequent_word.pretrained_path", type=str, default=None, dest="token.frequent_word.embedding.pretrained_path", help=""" Add pretrained Word vector model's path. (support file format like Glove)""", ) group.add_argument( "--frequent_word.dropout", type=float, default=0.2, dest="token.frequent_word.embedding.dropout", help=""" Embedding dropout prob (default: 0.2)""", ) group.add_argument( "--word.embed_dim", type=int, default=100, dest="token.word.embedding.embed_dim", help=""" The number of Embedding dimension""", ) group.add_argument( "--word.pretrained_path", type=str, default=None, dest="token.word.embedding.pretrained_path", help=""" Add pretrained word vector model's path. (support file format like Glove)""", ) group.add_argument( "--word.trainable", type=arg_str2bool, default=True, dest="token.word.embedding.trainable", help=""" Word Embedding Trainable""", ) group.add_argument( "--word.dropout", type=float, default=0.2, dest="token.word.embedding.dropout", help=""" Embedding dropout prob (default: 0.2)""", )
[docs]def model(parser): group = parser.add_argument_group("Model") group.add_argument( "--model_name", type=str, default="bidaf", dest="model.name", help="""\ Pre-defined model * Reading Comprehension [bert_for_qa|bidaf|bidaf_no_answer|docqa|docqa_no_answer|dclaf|qanet|simple] * Regression [bert_for_reg|roberta_for_reg] * Semantic Parsing [sqlnet] * Sequence Classification [bert_for_seq_cls|roberta_for_seq_cls|structured_self_attention] * Token Classification [bert_for_tok_cls] """, ) reading_comprehension_title = "ㅁReading Comprehension" group = parser.add_argument_group(f"{reading_comprehension_title}\n # BERT for QuestionAnswering") group.add_argument( "--bert_for_qa.pretrained_model_name", type=str, default=None, dest="model.bert_for_qa.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `bert-base-uncased` . `bert-large-uncased` . `bert-base-cased` . `bert-base-multilingual` . `bert-base-chinese` """, ) group.add_argument( "--bert_for_qa.answer_maxlen", type=int, default=None, dest="model.bert_for_qa.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group = parser.add_argument_group(f" # RoBERTa") group.add_argument( "--roberta_for_qa.pretrained_model_name", type=str, default=None, dest="model.roberta_for_qa.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `roberta-base` . `roberta-large` """, ) group.add_argument( "--roberta_for_qa.answer_maxlen", type=int, default=None, dest="model.roberta_for_qa.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group = parser.add_argument_group(f" # BiDAF") group.add_argument( "--bidaf.aligned_query_embedding", type=int, default=False, dest="model.bidaf.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--bidaf.answer_maxlen", type=int, default=None, dest="model.bidaf.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--bidaf.model_dim", type=int, default=100, dest="model.bidaf.model_dim", help=""" The number of BiDAF model dimension""", ) group.add_argument( "--bidaf.contextual_rnn_num_layer", type=int, default=1, dest="model.bidaf.contextual_rnn_num_layer", help=""" The number of BiDAF model contextual_rnn's recurrent layers""", ) group.add_argument( "--bidaf.modeling_rnn_num_layer", type=int, default=2, dest="model.bidaf.modeling_rnn_num_layer", help=""" The number of BiDAF model modeling_rnn's recurrent layers""", ) group.add_argument( "--bidaf.predict_rnn_num_layer", type=int, default=1, dest="model.bidaf.predict_rnn_num_layer", help=""" The number of BiDAF model predict_rnn's recurrent layers""", ) group.add_argument( "--bidaf.dropout", type=float, default=0.2, dest="model.bidaf.dropout", help=""" The prob of BiDAF dropout""", ) group = parser.add_argument_group(" # BiDAF + Simple bias") group.add_argument( "--bidaf_no_answer.aligned_query_embedding", type=int, default=False, dest="model.bidaf_no_answer.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--bidaf_no_answer.answer_maxlen", type=int, default=None, dest="model.bidaf_no_answer.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--bidaf_no_answer.model_dim", type=int, default=100, dest="model.bidaf_no_answer.model_dim", help=""" The number of BiDAF model dimension""", ) group.add_argument( "--bidaf_no_answer.contextual_rnn_num_layer", type=int, default=1, dest="model.bidaf_no_answer.contextual_rnn_num_layer", help=""" The number of BiDAF model contextual_rnn's recurrent layers""", ) group.add_argument( "--bidaf_no_answer.modeling_rnn_num_layer", type=int, default=2, dest="model.bidaf_no_answer.modeling_rnn_num_layer", help=""" The number of BiDAF model modeling_rnn's recurrent layers""", ) group.add_argument( "--bidaf_no_answer.predict_rnn_num_layer", type=int, default=1, dest="model.bidaf_no_answer.predict_rnn_num_layer", help=""" The number of BiDAF model predict_rnn's recurrent layers""", ) group.add_argument( "--bidaf_no_answer.dropout", type=float, default=0.2, dest="model.bidaf_no_answer.dropout", help=""" The prob of BiDAF dropout""", ) group = parser.add_argument_group(" # Simple") group.add_argument( "--simple.answer_maxlen", type=int, default=None, dest="model.simple.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--simple.model_dim", type=int, default=100, dest="model.simple.model_dim", help=""" The number of Simple model dimension""", ) group.add_argument( "--simple.dropout", type=float, default=0.2, dest="model.simple.dropout", help=""" The prob of Simple dropout""", ) group = parser.add_argument_group(" # QANet") group.add_argument( "--qanet.aligned_query_embedding", type=int, default=False, dest="model.qanet.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--qanet.answer_maxlen", type=int, default=30, dest="model.qanet.answer_maxlen", help=""" The number of maximum answer's length (default: 30)""", ) group.add_argument( "--qanet.model_dim", type=int, default=128, dest="model.qanet.model_dim", help=""" The number of QANet model dimension""", ) group.add_argument( "--qanet.kernel_size_in_embedding", type=int, default=7, dest="model.qanet.kernel_size_in_embedding", help=""" The number of QANet model Embed Encoder kernel_size""", ) group.add_argument( "--qanet.num_head_in_embedding", type=int, default=8, dest="model.qanet.num_head_in_embedding", help=""" The number of QANet model Multi-Head Attention's head in Embedding Block""", ) group.add_argument( "--qanet.num_conv_block_in_embedding", type=int, default=4, dest="model.qanet.num_conv_block_in_embedding", help=""" The number of QANet model Conv Blocks in Embedding Block""", ) group.add_argument( "--qanet.num_embedding_encoder_block", type=int, default=1, dest="model.qanet.num_embedding_encoder_block", help=""" The number of QANet model Embedding Encoder Blocks""", ) group.add_argument( "--qanet.kernel_size_in_modeling", type=int, default=5, dest="model.qanet.kernel_size_in_modeling", help=""" The number of QANet model Model Encoder kernel_size""", ) group.add_argument( "--qanet.num_head_in_modeling", type=int, default=8, dest="model.qanet.num_head_in_modeling", help=""" The number of QANet model Multi-Head Attention's head in Modeling Block""", ) group.add_argument( "--qanet.num_conv_block_in_modeling", type=int, default=2, dest="model.qanet.num_conv_block_in_modeling", help=""" The number of QANet model Conv Blocks in Modeling Block""", ) group.add_argument( "--qanet.num_modeling_encoder_block", type=int, default=7, dest="model.qanet.num_modeling_encoder_block", help=""" The number of QANet model Modeling Encoder Blocks""", ) group.add_argument( "--qanet.layer_dropout", type=float, default=0.9, dest="model.qanet.layer_dropout", help=""" The prob of QANet model layer dropout""", ) group.add_argument( "--qanet.dropout", type=float, default=0.1, dest="model.qanet.dropout", help=""" The prob of QANet dropout""", ) group = parser.add_argument_group(" # DocQA") group.add_argument( "--docqa.aligned_query_embedding", type=arg_str2bool, default=False, dest="model.docqa.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--docqa.answer_maxlen", type=int, default=17, dest="model.docqa.answer_maxlen", help=""" The number of maximum answer's length (default: 17)""", ) group.add_argument( "--docqa.rnn_dim", type=int, default=100, dest="model.docqa.rnn_dim", help=""" The number of DocQA model rnn dimension""", ) group.add_argument( "--docqa.linear_dim", type=int, default=200, dest="model.docqa.linear_dim", help=""" The number of DocQA model linear dimension""", ) group.add_argument( "--docqa.preprocess_rnn_num_layer", type=int, default=1, dest="model.docqa.preprocess_rnn_num_layer", help=""" The number of DocQA model preprocess_rnn's recurrent layers""", ) group.add_argument( "--docqa.modeling_rnn_num_layer", type=int, default=1, dest="model.docqa.modeling_rnn_num_layer", help=""" The number of DocQA model modeling_rnn's recurrent layers""", ) group.add_argument( "--docqa.predict_rnn_num_layer", type=int, default=1, dest="model.docqa.predict_rnn_num_layer", help=""" The number of DocQA model predict_rnn's recurrent layers""", ) group.add_argument( "--docqa.dropout", type=float, default=0.2, dest="model.docqa.dropout", help=""" The prob of DocQA dropout""", ) group.add_argument( "--docqa.weight_init", type=arg_str2bool, default=True, dest="model.docqa.weight_init", help=""" Weight Init""", ) group = parser.add_argument_group(" # DocQA + No_Answer Option") group.add_argument( "--docqa_no_answer.aligned_query_embedding", type=arg_str2bool, default=False, dest="model.docqa_no_answer.aligned_query_embedding", help=""" Aligned Question Embedding (default: False)""", ) group.add_argument( "--docqa_no_answer.answer_maxlen", type=int, default=17, dest="model.docqa_no_answer.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--docqa_no_answer.rnn_dim", type=int, default=100, dest="model.docqa_no_answer.rnn_dim", help=""" The number of docqa_no_answer model rnn dimension""", ) group.add_argument( "--docqa_no_answer.linear_dim", type=int, default=200, dest="model.docqa_no_answer.linear_dim", help=""" The number of docqa_no_answer model linear dimension""", ) group.add_argument( "--docqa_no_answer.dropout", type=float, default=0.2, dest="model.docqa_no_answer.dropout", help=""" The prob of QANet dropout""", ) group.add_argument( "--docqa_no_answer.weight_init", type=arg_str2bool, default=True, dest="model.docqa_no_answer.weight_init", help=""" Weight Init""", ) group = parser.add_argument_group(" # DrQA") group.add_argument( "--drqa.aligned_query_embedding", type=int, default=True, dest="model.drqa.aligned_query_embedding", help=""" Aligned Question Embedding (default: True)""", ) group.add_argument( "--drqa.answer_maxlen", type=int, default=15, dest="model.drqa.answer_maxlen", help=""" The number of maximum answer's length (default: None)""", ) group.add_argument( "--drqa.model_dim", type=int, default=128, dest="model.drqa.model_dim", help=""" The number of document reader model dimension""", ) group.add_argument( "--drqa.dropout", type=int, default=0.3, dest="model.drqa.dropout", help=""" The number of document reader model dropout""", ) regression_title = "ㅁRegression" group = parser.add_argument_group(f"{regression_title}\n # BERT for Regression") group.add_argument( "--bert_for_reg.pretrained_model_name", type=str, default=None, dest="model.bert_for_reg.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `bert-base-uncased` . `bert-large-uncased` . `bert-base-cased` . `bert-base-multilingual` . `bert-base-chinese` """, ) group.add_argument( "--bert_for_reg.dropout", type=float, default=0.2, dest="model.bert_for_reg.dropout", help=""" The prob of fc layer dropout """ ) group = parser.add_argument_group(f" # RoBERTa") group.add_argument( "--roberta_for_reg.pretrained_model_name", type=str, default=None, dest="model.roberta_for_reg.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `roberta-base` . `roberta-large` """, ) group.add_argument( "--roberta_for_reg.dropout", type=float, default=0.2, dest="model.roberta_for_reg.dropout", help=""" The prob of fc layer dropout """ ) semantic_parsing_title = "ㅁSemantic Parsing" group = parser.add_argument_group(f"{semantic_parsing_title}\n # SQLNet") group.add_argument( "--sqlnet.column_attention", type=int, default=True, dest="model.sqlnet.column_attention", help=""" Compute attention map on a question conditioned on the column names (default: True)""", ) group.add_argument( "--sqlnet.model_dim", type=int, default=100, dest="model.sqlnet.model_dim", help=""" The number of document reader model dimension""", ) group.add_argument( "--sqlnet.rnn_num_layer", type=int, default=2, dest="model.sqlnet.rnn_num_layer", help=""" The number of SQLNet model rnn's recurrent layers""", ) group.add_argument( "--sqlnet.dropout", type=int, default=0.3, dest="model.sqlnet.dropout", help=""" The prob of model dropout """, ) group.add_argument( "--sqlnet.column_maxlen", type=int, default=4, dest="model.sqlnet.column_maxlen", help=""" The number of maximum column's length (default: 4)""", ) group.add_argument( "--sqlnet.token_maxlen", type=int, default=200, dest="model.sqlnet.token_maxlen", help=""" An upper-bound N on the number of decoder tokeni """, ) group.add_argument( "--sqlnet.conds_column_loss_alpha", type=int, default=0.3, dest="model.sqlnet.conds_column_loss_alpha", help=""" balance the positive data versus negative data """, ) sequence_classification_title = "ㅁSequence Classification" group = parser.add_argument_group(f"{sequence_classification_title}\n # BERT for Sequence Classification") group.add_argument( "--bert_for_seq_cls.pretrained_model_name", type=str, default=None, dest="model.bert_for_seq_cls.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `bert-base-uncased` . `bert-large-uncased` . `bert-base-cased` . `bert-base-multilingual` . `bert-base-chinese` """, ) group.add_argument( "--bert_for_seq_cls.dropout", type=float, default=0.2, dest="model.bert_for_seq_cls.dropout", help=""" The prob of fc layer dropout """ ) group = parser.add_argument_group(f" # RoBERTa") group.add_argument( "--roberta_for_seq_cls.pretrained_model_name", type=str, default=None, dest="model.roberta_for_seq_cls.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `roberta-base` . `roberta-large` """, ) group.add_argument( "--roberta_for_seq_cls.dropout", type=float, default=0.2, dest="model.roberta_for_seq_cls.dropout", help=""" The prob of fc layer dropout """ ) group = parser.add_argument_group(f"{sequence_classification_title}\n # Structured Self Attention") group.add_argument( "--structured_self_attention.token_encoder", type=str, default="bilstm", dest="model.structured_self_attention.token_encoder", help=""" Token encoder type [none|bilstm] """ ) group.add_argument( "--structured_self_attention.encoding_rnn_hidden_dim", type=int, default=600, dest="model.structured_self_attention.encoding_rnn_hidden_dim", help=""" The number of hidden dimension for each token """ ) group.add_argument( "--structured_self_attention.encoding_rnn_num_layer", type=int, default=2, dest="model.structured_self_attention.encoding_rnn_num_layer", help=""" The number of layers of token encoding rnn """ ) group.add_argument( "--structured_self_attention.encoding_rnn_dropout", type=float, default=0., dest="model.structured_self_attention.encoding_rnn_dropout", help=""" The prob of token encoding rnn dropout (between layers) """ ) group.add_argument( "--structured_self_attention.attention_dim", type=int, default=350, dest="model.structured_self_attention.attention_dim", help=""" The number of embedding dimension for attention """ ) group.add_argument( "--structured_self_attention.num_attention_heads", type=int, default=30, dest="model.structured_self_attention.num_attention_heads", help=""" The number of rows for attention (attention heads) """ ) group.add_argument( "--structured_self_attention.project_dim", type=int, default=2000, dest="model.structured_self_attention.project_dim", help=""" The number of bottleneck layer embedding dimension """ ) group.add_argument( "--structured_self_attention.dropout", type=float, default=0.5, dest="model.structured_self_attention.dropout", help=""" The prob of bottleneck-making fnn dropout """ ) group.add_argument( "--structured_self_attention.penalization_coefficient", type=float, default=1., dest="model.structured_self_attention.penalization_coefficient", help=""" The coefficient of penalization term """ ) token_classification_title = "ㅁToken Classification" group = parser.add_argument_group(f"{token_classification_title}\n # BERT for Token Classification") group.add_argument( "--bert_for_tok_cls.pretrained_model_name", type=str, default=None, dest="model.bert_for_tok_cls.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `bert-base-uncased` . `bert-large-uncased` . `bert-base-cased` . `bert-base-multilingual` . `bert-base-chinese` """, ) group.add_argument( "--bert_for_tok_cls.dropout", type=float, default=0.2, dest="model.bert_for_tok_cls.dropout", help=""" The prob of fc layer dropout """ ) group = parser.add_argument_group(f" # RoBERTa") group.add_argument( "--roberta_for_tok_cls.pretrained_model_name", type=str, default=None, dest="model.roberta_for_tok_cls.pretrained_model_name", help=""" A str with the name of a pre-trained model to load selected in the list of (default: None): . `roberta-base` . `roberta-large` """, ) group.add_argument( "--roberta_for_tok_cls.dropout", type=float, default=0.2, dest="model.roberta_for_tok_cls.dropout", help=""" The prob of fc layer dropout """ )
[docs]def nsml_for_internal(parser): group = parser.add_argument_group("NSML") group.add_argument( "--pause", type=int, default=0, dest="nsml.pause", help=""" NSML default setting""" ) group.add_argument( "--iteration", type=int, default=0, dest="nsml.iteration", help=""" Start from NSML epoch count""", )
[docs]def trainer(parser): group = parser.add_argument_group("Trainer") group.add_argument( "--num_epochs", type=int, default=20, dest="trainer.num_epochs", help=""" The number of training epochs""", ) group.add_argument( "--patience", type=int, default=10, dest="trainer.early_stopping_threshold", help=""" The number of early stopping threshold""", ) group.add_argument( "--metric_key", type=str, default="em", dest="trainer.metric_key", help=""" The key of metric for model's score""", ) group.add_argument( "--verbose_step_count", type=int, default=100, dest="trainer.verbose_step_count", help=""" The number of training verbose""", ) group.add_argument( "--eval_and_save_step_count", type=int, default=1, dest="trainer.eval_and_save_step_count", help=""" The number of save and evaluate step_count (e.g. 'epoch' or 1000)""", ) group.add_argument( "--save_checkpoint", type=arg_str2bool, default=True, dest="trainer.save_checkpoint", help=""" The boolean value of save checkpoint""", ) group.add_argument( "--log_dir", type=str, default="logs/experiment_1", dest="trainer.log_dir", help=""" TensorBoard and Checkpoint log directory""", ) group = parser.add_argument_group("Gradient") group.add_argument( "--grad_max_norm", type=float, default=None, dest="trainer.grad_max_norm", help=""" Clips gradient norm of an iterable of parameters. (Default: None)""") group = parser.add_argument_group("Optimizer") group.add_argument( "--optimizer_type", type=str, default="adam", dest="optimizer.op_type", help=""" Optimizer (https://pytorch.org/docs/stable/optim.html#algorithms) - adadelta: ADADELTA: An Adaptive Learning Rate Method (https://arxiv.org/abs/1212.5701) - adagrad: Adaptive Subgradient Methods for Online Learning and Stochastic Optimization (http://jmlr.org/papers/v12/duchi11a.html) - adam: Adam: A Method for Stochastic Optimization (https://arxiv.org/abs/1412.6980) - adamw: Adam: Adam algorithm with weight decay fix. (BertAdam) - sparse_adam: Implements lazy version of Adam algorithm suitable for sparse tensors. In this variant, only moments that show up in the gradient get updated, and only those portions of the gradient get applied to the parameters. - adamax: Implements Adamax algorithm (a variant of Adam based on infinity norm). - averaged_sgd: Acceleration of stochastic approximation by averaging (http://dl.acm.org/citation.cfm?id=131098) - rmsprop: Implements RMSprop algorithm. (https://arxiv.org/pdf/1308.0850v5.pdf) - rprop: Implements the resilient backpropagation algorithm. - sgd: Implements stochastic gradient descent (optionally with momentum). Nesterov momentum: (http://www.cs.toronto.edu/~hinton/absps/momentum.pdf) [adadelta|adagrad|adam|adamw|sparse_adam|adamax|averaged_sgd|rmsprop|rprop|sgd]""", ) group.add_argument( "--learning_rate", type=float, default=0.5, dest="optimizer.learning_rate", help="""\ Starting learning rate. Recommended settings: sgd = 1, adagrad = 0.1, adadelta = 1, adam = 0.001 """, ) group = parser.add_argument_group(" # Adadelta") group.add_argument( "--adadelta.rho", type=float, default=0.9, dest="optimizer.adadelta.rho", help="""\ coefficient used for computing a running average of squared gradients Default: 0.9 """, ) group.add_argument( "--adadelta.eps", type=float, default=1e-6, dest="optimizer.adadelta.eps", help="""\ term added to the denominator to improve numerical stability Default: 1e-6 """, ) group.add_argument( "--adadelta.weight_decay", type=float, default=0, dest="optimizer.adadelta.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # Adagrad") group.add_argument( "--adagrad.lr_decay", type=float, default=0, dest="optimizer.adagrad.lr_decay", help="""\ learning rate decay Default: 0 """, ) group.add_argument( "--adagrad.weight_decay", type=float, default=0, dest="optimizer.adagrad.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # Adam") group.add_argument( "--adam.betas", nargs="+", type=float, default=[0.9, 0.999], dest="optimizer.adam.betas", help="""\ coefficients used for computing running averages of gradient and its square Default: (0.9, 0.999) """, ) group.add_argument( "--adam.eps", type=float, default=1e-8, dest="optimizer.adam.eps", help="""\ term added to the denominator to improve numerical stability Default: 1e-8 """, ) group.add_argument( "--adam.weight_decay", type=float, default=0, dest="optimizer.adam.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # AdamW") group.add_argument( "--adamw.betas", nargs="+", type=float, default=[0.9, 0.999], dest="optimizer.adamw.betas", help="""\ coefficients used for computing running averages of gradient and its square Default: (0.9, 0.999) """, ) group.add_argument( "--adamw.eps", type=float, default=1e-6, dest="optimizer.adamw.eps", help="""\ term added to the denominator to improve numerical stability Default: 1e-8 """, ) group.add_argument( "--adamw.weight_decay", type=float, default=0.0, dest="optimizer.adamw.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group.add_argument( "--adamw.correct_bias", type=arg_str2bool, default=True, dest="optimizer.adamw.correct_bias", help="""\ can be set to False to avoid correcting bias in Adam (e.g. like in Bert TF repository). Default: True """, ) group = parser.add_argument_group(" # SparseAdam") group.add_argument( "--sparse_adam.betas", nargs="+", type=float, default=[0.9, 0.999], dest="optimizer.sparse_adam.betas", help="""\ coefficients used for computing running averages of gradient and its square Default: (0.9, 0.999) """, ) group.add_argument( "--sparse_adam.eps", type=float, default=1e-8, dest="optimizer.sparse_adam.eps", help="""\ term added to the denominator to improve numerical stability Default: 1e-8 """, ) group = parser.add_argument_group(" # Adamax") group.add_argument( "--adamax.betas", nargs="+", type=float, default=[0.9, 0.999], dest="optimizer.adamax.betas", help="""\ coefficients used for computing running averages of gradient and its square. Default: (0.9, 0.999) """, ) group.add_argument( "--adamax.eps", type=float, default=1e-8, dest="optimizer.adamax.eps", help="""\ term added to the denominator to improve numerical stability. Default: 1e-8 """, ) group.add_argument( "--adamax.weight_decay", type=float, default=0, dest="optimizer.adamax.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # ASGD (Averaged Stochastic Gradient Descent)") group.add_argument( "--averaged_sgd.lambd", type=float, default=1e-4, dest="optimizer.averaged_sgd.lambd", help="""\ decay term Default: 1e-4 """, ) group.add_argument( "--averaged_sgd.alpha", type=float, default=0.75, dest="optimizer.averaged_sgd.alpha", help="""\ power for eta update Default: 0.75 """, ) group.add_argument( "--averaged_sgd.t0", type=float, default=1e6, dest="optimizer.averaged_sgd.t0", help="""\ point at which to start averaging Default: 1e6 """, ) group.add_argument( "--averaged_sgd.weight_decay", type=float, default=0, dest="optimizer.averaged_sgd.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # RMSprop") group.add_argument( "--rmsprop.momentum", type=float, default=0, dest="optimizer.rmsprop.momentum", help="""\ momentum factor Default: 0 """, ) group.add_argument( "--rmsprop.alpha", type=float, default=0.99, dest="optimizer.rmsprop.alpha", help="""\ smoothing constant Default: 0.99 """, ) group.add_argument( "--rmsprop.eps", type=float, default=1e-8, dest="optimizer.rmsprop.eps", help="""\ term added to the denominator to improve numerical stability. Default: 1e-8 """, ) group.add_argument( "--rmsprop.centered", type=arg_str2bool, default=False, dest="optimizer.rmsprop.centered", help="""\ if True, compute the centered RMSProp, the gradient is normalized by an estimation of its variance Default: False """, ) group.add_argument( "--rmsprop.weight_decay", type=float, default=0, dest="optimizer.rmsprop.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group(" # SGD (Stochastic Gradient Descent)") group.add_argument( "--sgd.momentum", type=float, default=0, dest="optimizer.sgd.momentum", help="""\ momentum factor Default: 0 """, ) group.add_argument( "--sgd.dampening", type=float, default=0, dest="optimizer.sgd.dampening", help="""\ dampening for momentum Default: 0 """, ) group.add_argument( "--sgd.nesterov", type=arg_str2bool, default=False, dest="optimizer.sgd.nesterov", help="""\ enables Nesterov momentum Default: False """, ) group.add_argument( "--sgd.weight_decay", type=float, default=0, dest="optimizer.sgd.weight_decay", help="""\ weight decay (L2 penalty) Default: 0 """, ) group = parser.add_argument_group("Learning Rate Scheduler") group.add_argument( "--lr_scheduler_type", type=str, default=None, dest="optimizer.lr_scheduler_type", help="""Learning Rate Schedule (https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate) \n - lambda: Sets the learning rate of each parameter group to the initial lr times a given function. - step: Sets the learning rate of each parameter group to the initial lr decayed by gamma every step_size epochs. - multi_step: Set the learning rate of each parameter group to the initial lr decayed by gamma once the number of epoch reaches one of the milestones. - exponential: Set the learning rate of each parameter group to the initial lr decayed by gamma every epoch. - cosine: Set the learning rate of each parameter group using a cosine annealing schedule, where ηmax is set to the initial lr and Tcur is the number of epochs since the last restart in SGDR: SGDR: Stochastic Gradient Descent with Warm Restarts (https://arxiv.org/abs/1608.03983) When last_epoch=-1, sets initial lr as lr. - reduce_on_plateau: Reduce learning rate when a metric has stopped improving. Models often benefit from reducing the learning rate by a factor of 2-10 once learning stagnates. This scheduler reads a metrics quantity and if no improvement is seen for a ‘patience’ number of epochs, the learning rate is reduced. - warmup_constant: Linear warmup and then constant. Linearly increases learning rate schedule from 0 to 1 over `warmup_steps` training steps. Keeps learning rate schedule equal to 1. after warmup_steps. - warmup_linear: Linear warmup and then linear decay. Linearly increases learning rate from 0 to 1 over `warmup_steps` training steps. Linearly decreases learning rate from 1. to 0. over remaining `t_total - warmup_steps` steps. - warmup_consine: Linear warmup and then cosine decay. Linearly increases learning rate from 0 to 1 over `warmup_steps` training steps. Decreases learning rate from 1. to 0. over remaining `t_total - warmup_steps` steps following a cosine curve. If `cycles` (default=0.5) is different from default, learning rate follows cosine function after warmup. - warmup_consine_with_hard_restart: Linear warmup and then cosine cycles with hard restarts. Linearly increases learning rate from 0 to 1 over `warmup_steps` training steps. If `cycles` (default=1.) is different from default, learning rate follows `cycles` times a cosine decaying learning rate (with hard restarts). [step|multi_step|exponential|reduce_on_plateau|cosine| warmup_constant|warmup_linear|warmup_consine|warmup_consine_with_hard_restart] """, ) group = parser.add_argument_group(" # StepLR") group.add_argument( "--step.step_size", type=int, default=1, dest="optimizer.step.step_size", help="""\ Period of learning rate decay. Default: 1""", ) group.add_argument( "--step.gamma", type=float, default=0.1, dest="optimizer.step.gamma", help="""\ Multiplicative factor of learning rate decay. Default: 0.1. """, ) group.add_argument( "--step.last_epoch", type=int, default=-1, dest="optimizer.step.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # MultiStepLR") group.add_argument( "--multi_step.milestones", nargs="+", type=int, dest="optimizer.multi_step.milestones", help="""\ List of epoch indices. Must be increasing list of int""", ) group.add_argument( "--multi_step.gamma", type=float, default=0.1, dest="optimizer.multi_step.gamma", help="""\ Multiplicative factor of learning rate decay. Default: 0.1. """, ) group.add_argument( "--multi_step.last_epoch", type=int, default=-1, dest="optimizer.multi_step.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # ExponentialLR") group.add_argument( "--exponential.gamma", type=float, default=0.1, dest="optimizer.exponential.gamma", help="""\ Multiplicative factor of learning rate decay. Default: 0.1. """, ) group.add_argument( "--exponential.last_epoch", type=int, default=-1, dest="optimizer.exponential.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # CosineAnnealingLR") group.add_argument( "--cosine.T_max", type=int, default=50, dest="optimizer.cosine.T_max", help="""\ Maximum number of iterations. Default: 50""", ) group.add_argument( "--cosine.eta_min", type=float, default=0, dest="optimizer.cosine.eta_min", help="""\ Minimum learning rate. Default: 0. """, ) group.add_argument( "--cosine.last_epoch", type=int, default=-1, dest="optimizer.cosine.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # ReduceLROnPlateau") group.add_argument( "--reduce_on_plateau.factor", type=float, default=0.1, dest="optimizer.reduce_on_plateau.factor", help=""" Factor by which the learning rate will be reduced. new_lr = lr * factor. Default: 0.1. """, ) group.add_argument( "--reduce_on_plateau.mode", type=str, default="min", dest="optimizer.reduce_on_plateau.mode", help="""\ One of `min`, `max`. In `min` mode, lr will be reduced when the quantity monitored has stopped decreasing; in `max` mode it will be reduced when the quantity monitored has stopped increasing. Default: 'min'. """, ) group.add_argument( "--reduce_on_plateau.patience", type=int, default=10, dest="optimizer.reduce_on_plateau.patience", help="""\ Number of epochs with no improvement after which learning rate will be reduced. Default: 10. """, ) group.add_argument( "--reduce_on_plateau.threshold", type=float, default=1e-4, dest="optimizer.reduce_on_plateau.threshold", help="""\ Threshold for measuring the new optimum, to only focus on significant changes. Default: 1e-4 """, ) group.add_argument( "--reduce_on_plateau.threshold_mode", type=str, default="rel", dest="optimizer.reduce_on_plateau.threshold_mode", help="""\ One of rel, abs. In rel mode, dynamic_threshold = best * ( 1 + threshold ) in ‘max’ mode or best * ( 1 - threshold ) in min mode. In abs mode, dynamic_threshold = best + threshold in max mode or best - threshold in min mode. Default: ‘rel’. """ ) group.add_argument( "--reduce_on_plateau.cooldown", type=int, default=0, dest="optimizer.reduce_on_plateau.cooldown", help="""\ Number of epochs to wait before resuming normal operation after lr has been reduced. Default: 0. """, ) group.add_argument( "--reduce_on_plateau.min_lr", nargs="+", type=float, default=0, dest="optimizer.reduce_on_plateau.min_lr", help="""\ A scalar or a list of scalars. A lower bound on the learning rate of all param groups or each group respectively. Default: 0. """, ) group.add_argument( "--reduce_on_plateau.eps", type=float, default=1e-8, dest="optimizer.reduce_on_plateau.eps", help="""\ Minimal decay applied to lr. If the difference between new and old lr is smaller than eps, the update is ignored. Default: 1e-8 """, ) group = parser.add_argument_group(" # WarmUp Constant") group.add_argument( "--warmup_constant.warmup_steps", type=int, default=None, dest="optimizer.warmup_constant.warmup_steps", help="""\ The number of steps to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_constant.last_epoch", type=int, default=-1, dest="optimizer.warmup_constant.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # WarmUp Linear") group.add_argument( "--warmup_linear.warmup_steps", type=int, default=None, dest="optimizer.warmup_linear.warmup_steps", help="""\ The number of steps to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_linear_warmup_proportion", type=float, default=None, dest="optimizer.warmup_linear.warmup_proportion", help="""\ The number of steps (proportion of total_step) to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_linear.last_epoch", type=int, default=-1, dest="optimizer.warmup_linear.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group = parser.add_argument_group(" # WarmUp Cosine") group.add_argument( "--warmup_cosine.warmup_steps", type=int, default=None, dest="optimizer.warmup_cosine.warmup_steps", help="""\ The number of steps to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_cosine.last_epoch", type=int, default=-1, dest="optimizer.warmup_cosine.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group.add_argument( "--warmup_cosine.cycles", type=float, default=.5, dest="optimizer.warmup_cosine.cycles", help="""\ If `cycles` is different from default, learning rate follows cosine function after warmup Default: .5 """ ) group = parser.add_argument_group(" # WarmUp Cosine with hard restarts") group.add_argument( "--warmup_cosine_with_hard_restart.warmup_steps", type=int, default=None, dest="optimizer.warmup_cosine_with_hard_restart.warmup_steps", help="""\ The number of steps to increase the learning rate from 0 to 1. Default: None """, ) group.add_argument( "--warmup_cosine_with_hard_restart.last_epoch", type=int, default=-1, dest="optimizer.warmup_cosine_with_hard_restart.last_epoch", help="""\ The index of last epoch. Default: -1. """ ) group.add_argument( "--warmup_cosine_with_hard_restart.cycles", type=float, default=1., dest="optimizer.warmup_cosine_with_hard_restart.cycles", help="""\ If `cycles` is different from default, learning rate follows cosine_with_hard_restart function after warmup Default: 1. """ ) group = parser.add_argument_group("Exponential Moving Average") group.add_argument( "--ema", type=float, default=None, dest="optimizer.exponential_moving_average", help="""\ Exponential Moving Average Default: None (don't use)""", )
[docs]def base_config(parser): group = parser.add_argument_group("Base Config") group.add_argument( "--base_config", type=str, default=None, dest="base_config", help=f"""\ Use pre-defined base_config: {_get_define_config()} * CoNLL 2003: {_get_define_config(category='conll2003')} * GLUE: {_get_define_config(category='glue')} * KorQuAD: {_get_define_config(category='korquad')} * SQuAD: {_get_define_config(category='squad')} * WikiSQL: {_get_define_config(category='wikisql')} """, )
def _get_define_config(category=None, config_dir="base_config"): if category is not None: config_dir = os.path.join(config_dir, category) config_files = [ config_path.replace(".json", "") for config_path in os.listdir(config_dir) if config_path.endswith(".json") ] if category is not None: config_files = [category + "/" + fname for fname in config_files] return config_files
[docs]def evaluate(parser): group = parser.add_argument_group("Run evaluate") group.add_argument( "data_file_path", type=str, help=" Path to the file containing the evaluation data" ) group.add_argument("checkpoint_path", type=str, help="Path to an checkpoint trained model") group.add_argument( "--infer", default=None, dest="inference_latency", type=int, help=""" Evaluate with inference-latency with maximum value (ms)""", ) group.add_argument( "--prev_cuda_device_id", type=int, default=0, dest="prev_cuda_device_id", help=""" Previous cuda device id (need to mapping)""", )
[docs]def predict(parser): group = parser.add_argument_group("Run inference") group.add_argument( "checkpoint_path", type=str, help=" Path to an checkpoint trained model") group.add_argument( "-i", "--interactive", default=False, dest="interactive", action="store_true", help=""" Interactive Mode """, ) group.add_argument( "--prev_cuda_device_id", type=int, default=0, dest="prev_cuda_device_id", help=""" Previous cuda device id (need to mapping)""", ) group.add_argument("--question", type=str, dest="question", help=""" Input Question (required)""") group = parser.add_argument_group(" # Reading Comprehension") group.add_argument("--context", type=str, dest="context", help=""" Input Context """) group = parser.add_argument_group(" # Semantic Parsing") group.add_argument("--column", nargs="+", type=str, dest="column", help=""" Input Database Columns """) group.add_argument("--db_path", type=str, dest="db_path", help=""" Input Database file path """) group.add_argument("--table_id", type=str, dest="table_id", help=""" Input Database Table Id """) group = parser.add_argument_group(" # Document Retrieval") group.add_argument("--doc_path", type=str, dest="doc_path", help=""" Document file Path """) group.add_argument( "--retrieval", type=str, default=None, dest="doc_retrieval", help=""" Document Retrieval Model [tfidf] """, ) group.add_argument("--k", type=int, default=1, dest="top_k", help=""" Return Top K results """) group = parser.add_argument_group(" # Sequence/Token Classification") group.add_argument("--sequence", type=str, dest="sequence", help=""" Input Sequence """)
[docs]def machine(parser): group = parser.add_argument_group("Machine Config") group.add_argument( "--machine_config", type=str, default=None, dest="machine_config", help=f"""\ Use pre-defined machine_config (.json) {_get_define_config(config_dir="./machine_config")} """)
# fmt: on
================================================ FILE: docs/_build/html/_modules/claf/config/factory/base.html ================================================ claf.config.factory.base — CLaF 0.2.0 documentation

Source code for claf.config.factory.base

[docs]class Factory: """ Factory Base Class Factory method pattern In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor. """ def __init__(self): pass
[docs] def create(self): """ interface """ raise NotImplementedError
================================================ FILE: docs/_build/html/_modules/claf/config/factory/data_loader.html ================================================ claf.config.factory.data_loader — CLaF 0.2.0 documentation

Source code for claf.config.factory.data_loader


from overrides import overrides
from torch.utils.data import DataLoader

from .base import Factory


[docs]def make_data_loader(dataset, batch_size=32, shuffle=True, cuda_device_id=None): is_cpu = cuda_device_id is None return DataLoader( dataset, batch_size=batch_size, shuffle=shuffle, collate_fn=dataset.collate_fn(cuda_device_id=cuda_device_id), num_workers=0, pin_memory=is_cpu, # only CPU memory can be pinned )
[docs]class DataLoaderFactory(Factory): """ DataLoader Factory Class * Args: config: data_loader config from argument (config.data_loader) """ def __init__(self, config): self.batch_size = config.batch_size self.cuda_device_id = None if config.cuda_devices: self.cuda_device_id = config.cuda_devices[0]
[docs] @overrides def create(self, datasets): """ create train, valid and test iterator """ dataset_key = next(iter(datasets)) dataset = datasets[dataset_key] if getattr(dataset, "name", None) is None: raise ValueError("unknown dataset.") train_loader = None if "train" in datasets: train_loader = make_data_loader( datasets["train"], batch_size=self.batch_size, shuffle=True, cuda_device_id=self.cuda_device_id, ) valid_loader = None if "valid" in datasets: valid_loader = make_data_loader( datasets["valid"], batch_size=self.batch_size, shuffle=False, cuda_device_id=self.cuda_device_id, ) test_loader = None if "test" in datasets: test_loader = make_data_loader( datasets["test"], batch_size=self.batch_size, shuffle=False, cuda_device_id=self.cuda_device_id, ) return train_loader, valid_loader, test_loader
================================================ FILE: docs/_build/html/_modules/claf/config/factory/data_reader.html ================================================ claf.config.factory.data_reader — CLaF 0.2.0 documentation

Source code for claf.config.factory.data_reader


from overrides import overrides

from claf.config.registry import Registry

from .base import Factory


[docs]class DataReaderFactory(Factory): """ DataReader Factory Class Create Concrete reader according to config.dataset Get reader from reader registries (eg. @register("reader:{reader_name}")) * Args: config: data_reader config from argument (config.data_reader) """ def __init__(self, config): self.registry = Registry() self.dataset_name = config.dataset file_paths = {} if getattr(config, "train_file_path", None) and config.train_file_path != "": file_paths["train"] = config.train_file_path if getattr(config, "valid_file_path", None) and config.valid_file_path != "": file_paths["valid"] = config.valid_file_path self.reader_config = {"file_paths": file_paths} if "params" in config and type(config.params) == dict: self.reader_config.update(config.params) if "tokenizers" in config: self.reader_config["tokenizers"] = config.tokenizers dataset_config = getattr(config, config.dataset, None) if dataset_config is not None: dataset_config = vars(dataset_config) self.reader_config.update(dataset_config)
[docs] @overrides def create(self): reader = self.registry.get(f"reader:{self.dataset_name.lower()}") return reader(**self.reader_config)
================================================ FILE: docs/_build/html/_modules/claf/config/factory/model.html ================================================ claf.config.factory.model — CLaF 0.2.0 documentation

Source code for claf.config.factory.model


from overrides import overrides

from claf.config.registry import Registry
from claf.model.base import ModelWithTokenEmbedder, ModelWithoutTokenEmbedder
from claf.model.reading_comprehension.mixin import ReadingComprehension
from claf.tokens import token_embedder

from .base import Factory


[docs]class ModelFactory(Factory): """ Model Factory Class Create Concrete model according to config.model_name Get model from model registries (eg. @register("model:{model_name}")) * Args: config: model config from argument (config.model) """ def __init__(self, config): self.registry = Registry() self.name = config.name self.model_config = {} if getattr(config, config.name, None): self.model_config = vars(getattr(config, config.name)) self.is_independent = getattr(config, "independent", False)
[docs] @overrides def create(self, token_makers, **params): model = self.registry.get(f"model:{self.name}") if issubclass(model, ModelWithTokenEmbedder): token_embedder = self.create_token_embedder(model, token_makers) self.model_config["token_embedder"] = token_embedder elif issubclass(model, ModelWithoutTokenEmbedder): self.model_config["token_makers"] = token_makers else: raise ValueError( "Model must have inheritance. (ModelWithTokenEmbedder or ModelWithoutTokenEmbedder)" ) return model(**self.model_config, **params)
[docs] def create_token_embedder(self, model, token_makers): # 1. Specific case # ... # 2. Base case if issubclass(model, ReadingComprehension): return token_embedder.RCTokenEmbedder(token_makers) else: return token_embedder.BasicTokenEmbedder(token_makers)
================================================ FILE: docs/_build/html/_modules/claf/config/factory/optimizer.html ================================================ claf.config.factory.optimizer — CLaF 0.2.0 documentation

Source code for claf.config.factory.optimizer


from overrides import overrides
import torch

from claf.config.namespace import NestedNamespace
from claf.learn.optimization.learning_rate_scheduler import get_lr_schedulers
from claf.learn.optimization.learning_rate_scheduler import (
    LearningRateWithoutMetricsWrapper,
    LearningRateWithMetricsWrapper,
)
from claf.learn.optimization.optimizer import get_optimizer_by_name
from claf.model.sequence_classification import BertForSeqCls, RobertaForSeqCls

from .base import Factory


[docs]class OptimizerFactory(Factory): """ Optimizer Factory Class include optimizer, learning_rate_scheduler and exponential_moving_average * Args: config: optimizer config from argument (config.optimizer) """ def __init__(self, config): # Optimizer self.op_type = config.op_type self.optimizer_params = {"lr": config.learning_rate} op_config = getattr(config, self.op_type, None) if op_config is not None: op_config = vars(op_config) self.optimizer_params.update(op_config) # LearningRate Scheduler self.lr_scheduler_type = getattr(config, "lr_scheduler_type", None) if self.lr_scheduler_type is not None: self.lr_scheduler_config = getattr(config, self.lr_scheduler_type, {}) if type(self.lr_scheduler_config) == NestedNamespace: self.lr_scheduler_config = vars(self.lr_scheduler_config) if "warmup" in self.lr_scheduler_type: self.lr_scheduler_config["t_total"] = config.num_train_steps self.set_warmup_steps(config) # EMA self.ema = getattr(config, "exponential_moving_average", 0)
[docs] def set_warmup_steps(self, config): warmup_proportion = self.lr_scheduler_config.get("warmup_proportion", None) warmup_steps = self.lr_scheduler_config.get("warmup_steps", None) if warmup_steps and warmup_proportion: raise ValueError("Check 'warmup_steps' and 'warmup_proportion'.") elif not warmup_steps and warmup_proportion: self.lr_scheduler_config["warmup_steps"] = int(config.num_train_steps * warmup_proportion) + 1 del self.lr_scheduler_config["warmup_proportion"] elif warmup_steps and not warmup_proportion: pass else: raise ValueError("Check 'warmup_steps' and 'warmup_proportion'.")
[docs] @overrides def create(self, model): if not issubclass(type(model), torch.nn.Module): raise ValueError("optimizer model is must be subclass of torch.nn.Module.") if getattr(model, "use_pytorch_transformers", False): weight_decay = self.optimizer_params.get("weight_decay", 0) model_parameters = self._group_parameters_for_transformers(model, weight_decay=weight_decay) else: model_parameters = [param for param in model.parameters() if param.requires_grad] optimizer = get_optimizer_by_name(self.op_type)(model_parameters, **self.optimizer_params) op_dict = {"optimizer": optimizer} # learning_rate_scheduler if self.lr_scheduler_type: self.lr_scheduler_config["optimizer"] = op_dict["optimizer"] lr_scheduler = get_lr_schedulers()[self.lr_scheduler_type](**self.lr_scheduler_config) if self.lr_scheduler_type == "reduce_on_plateau": lr_scheduler = LearningRateWithMetricsWrapper(lr_scheduler) else: lr_scheduler = LearningRateWithoutMetricsWrapper(lr_scheduler) op_dict["learning_rate_scheduler"] = lr_scheduler # exponential_moving_average if self.ema and self.ema > 0: op_dict["exponential_moving_average"] = self.ema return op_dict
def _group_parameters_for_transformers(self, model, weight_decay=0): # Prepare optimizer param_optimizer = list(model.named_parameters()) # hack to remove pooler, which is not used # thus it produce None grad that break apex if not isinstance(model, BertForSeqCls) or not isinstance(model, RobertaForSeqCls): param_optimizer = [n for n in param_optimizer if "pooler" not in n[0]] no_decay = ["bias", "LayerNorm.weight"] optimizer_grouped_parameters = [ { "params": [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)], "weight_decay": weight_decay, }, { "params": [p for n, p in param_optimizer if any(nd in n for nd in no_decay)], "weight_decay": 0.0, }, ] return optimizer_grouped_parameters
================================================ FILE: docs/_build/html/_modules/claf/config/factory/tokens.html ================================================ claf.config.factory.tokens — CLaF 0.2.0 documentation

Source code for claf.config.factory.tokens


from overrides import overrides

from claf.config.registry import Registry
from claf.config.utils import convert_config2dict
from claf.tokens import tokenizer

from .base import Factory


[docs]def make_tokenizer(tokenizer_cls, tokenizer_config, parent_tokenizers={}): if tokenizer_config is None or "name" not in tokenizer_config: return None package_name = tokenizer_config["name"] package_config = tokenizer_config.get(package_name, {}) tokenizer_config["config"] = package_config if package_name in tokenizer_config: del tokenizer_config[package_name] tokenizer_config.update(parent_tokenizers) return tokenizer_cls(**tokenizer_config)
[docs]def make_all_tokenizers(all_tokenizer_config): """ Tokenizer is resource used all token together """ sent_tokenizer = make_tokenizer( tokenizer.SentTokenizer, all_tokenizer_config.get("sent", {"name": "punkt"}) ) word_tokenizer = make_tokenizer( tokenizer.WordTokenizer, all_tokenizer_config.get("word", None), parent_tokenizers={"sent_tokenizer": sent_tokenizer}, ) subword_tokenizer = make_tokenizer( tokenizer.SubwordTokenizer, all_tokenizer_config.get("subword", None), parent_tokenizers={"word_tokenizer": word_tokenizer}, ) char_tokenizer = make_tokenizer( tokenizer.CharTokenizer, all_tokenizer_config.get("char", None), parent_tokenizers={"word_tokenizer": word_tokenizer}, ) bpe_tokenizer = make_tokenizer( tokenizer.BPETokenizer, all_tokenizer_config.get("bpe", None), ) return { "bpe": bpe_tokenizer, "char": char_tokenizer, "subword": subword_tokenizer, "word": word_tokenizer, "sent": sent_tokenizer, }
[docs]class TokenMakersFactory(Factory): """ TokenMakers Factory Class * Args: config: token config from argument (config.token) """ LANGS = ["eng", "kor"] def __init__(self, config): self.config = config self.registry = Registry()
[docs] @overrides def create(self): if getattr(self.config, "tokenizer", None): tokenizers = make_all_tokenizers(convert_config2dict(self.config.tokenizer)) else: tokenizers = {} token_names, token_types = self.config.names, self.config.types if len(token_names) != len(token_types): raise ValueError("token_names and token_types must be same length.") token_makers = {"tokenizers": tokenizers} for token_name, token_type in sorted(zip(token_names, token_types)): token_config = getattr(self.config, token_name, {}) if token_config != {}: token_config = convert_config2dict(token_config) # Token (tokenizer, indexer, embedding, vocab) token_config = { "tokenizers": tokenizers, "indexer_config": token_config.get("indexer", {}), "embedding_config": token_config.get("embedding", {}), "vocab_config": token_config.get("vocab", {}), } token_makers[token_name] = self.registry.get(f"token:{token_type}")(**token_config) return token_makers
================================================ FILE: docs/_build/html/_modules/claf/config/namespace.html ================================================ claf.config.namespace — CLaF 0.2.0 documentation

Source code for claf.config.namespace


import argparse


[docs]class NestedNamespace(argparse.Namespace): """ Nested Namespace (Simple class used by default by parse_args() to create an object holding attributes and return it.) """ def __setattr__(self, name, value): if "." in name: group, name = name.split(".", 1) namespace = getattr(self, group, NestedNamespace()) setattr(namespace, name, value) self.__dict__[group] = namespace else: self.__dict__[name] = value
[docs] def delete_unselected(self, namespace, excepts=[]): delete_keys = [] for key in namespace.__dict__: if key not in excepts: delete_keys.append(key) for key in delete_keys: delattr(namespace, key)
[docs] def overwrite(self, config): def _overwrite(namespace, d): for k, v in d.items(): if type(v) == dict: nested_namespace = getattr(namespace, k, None) if nested_namespace is None: nested_namespace = NestedNamespace() nested_namespace.load_from_json(v) setattr(namespace, k, nested_namespace) else: _overwrite(nested_namespace, v) else: setattr(namespace, k, v) return namespace return _overwrite(self, config)
[docs] def load_from_json(self, dict_data): name_value_pairs = [] def make_key_value_pairs(d, prefix=""): for k, v in d.items(): if type(v) == dict: next_prefix = k if prefix != "": next_prefix = f"{prefix}.{k}" make_key_value_pairs(v, prefix=next_prefix) else: key_with_prefix = k if prefix != "": key_with_prefix = f"{prefix}.{k}" name_value_pairs.append((key_with_prefix, v)) make_key_value_pairs(dict_data) for (name, value) in name_value_pairs: self.__setattr__(name, value)
================================================ FILE: docs/_build/html/_modules/claf/config/pattern.html ================================================ claf.config.pattern — CLaF 0.2.0 documentation

Source code for claf.config.pattern

[docs]class Singleton(type): """ Design Pattern Base Singleton Meta Class the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. """ _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls]
================================================ FILE: docs/_build/html/_modules/claf/config/registry.html ================================================ claf.config.registry — CLaF 0.2.0 documentation

Source code for claf.config.registry


import logging

from claf.config.pattern import Singleton

logger = logging.getLogger(__name__)


[docs]class Registry(metaclass=Singleton): """ Registry class (Singleton) """ def __init__(self): self._name_to_subclass = { "component": {}, "reader": {}, "machine": {}, "model": {}, "token": {}, }
[docs] def add(self, name, obj): component_type, component_name = self._split_component_type_and_name(name) if component_name in self._name_to_subclass[component_type]: logger.info( f"{component_name} is already included in Registry. It override with {obj}." ) self._name_to_subclass[component_type][component_name] = obj
[docs] def get(self, name): component_type, component_name = self._split_component_type_and_name(name) if component_type not in self._name_to_subclass: raise ValueError(f"There is no {component_type} in _name_to_subclass.") if component_name not in self._name_to_subclass[component_type]: raise ValueError(f"There is no {component_name} object in {component_type}.") return self._name_to_subclass[component_type][component_name]
def _split_component_type_and_name(self, name): if ":" in name: names = name.split(":") return names[0], names[1] else: raise ValueError("do not recognize component_type.")
================================================ FILE: docs/_build/html/_modules/claf/config/utils.html ================================================ claf.config.utils — CLaF 0.2.0 documentation

Source code for claf.config.utils


from argparse import Namespace
import copy
import json

import jsbeautifier
import numpy as np
import random
import torch


[docs]def pretty_json_dumps(inputs): js_opts = jsbeautifier.default_options() js_opts.indent_size = 2 inputs = remove_none(inputs) return jsbeautifier.beautify(json.dumps(inputs))
[docs]def remove_none(obj): if isinstance(obj, (list, tuple, set)): return type(obj)(remove_none(x) for x in obj if x is not None) elif isinstance(obj, dict): return type(obj)( (remove_none(k), remove_none(v)) for k, v in obj.items() if k is not None and v is not None ) else: return obj
[docs]def convert_config2dict(config): config_dict = copy.deepcopy(config) if isinstance(config_dict, Namespace): config_dict = vars(config_dict) for k, v in config_dict.items(): if isinstance(v, Namespace): config_dict[k] = convert_config2dict(v) return config_dict
[docs]def set_global_seed(seed=21): # Tensorflow try: import tensorflow as tf except ImportError: pass else: tf.set_random_seed(seed) # PyTorch torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) # NumPy np.random.seed(seed) # Python random.seed(seed)
================================================ FILE: docs/_build/html/_modules/claf/data/batch.html ================================================ claf.data.batch — CLaF 0.1.6 documentation

Source code for claf.data.batch


import logging

logger = logging.getLogger(__name__)


[docs]def make_batch(features, labels): return Batch(**{"features": features, "labels": labels})
[docs]class Batch: """ Batch Data Transfer Object (DTO) Class dictionary consisting of - features: (dict) input - labels: (dict) output """ def __init__(self, **kwargs): if set(kwargs.keys()) != set(["features", "labels"]): raise ValueError("You can use only 'features' and 'labels' as dictionary key.") self.__dict__ = kwargs def __repr__(self): return str(self.__dict__) def __len__(self): return len(self.__dict__)
[docs] def sort_by_key(self, sort_key): logger.info(f"Start sort by key: {sort_key}'s length") zipped = zip(self.__dict__["features"], self.__dict__["labels"]) features = self.__dict__["features"] if type(features) == list: feature_keys = list(features[0].keys()) else: feature_keys = features.keys() key_index = 0 if sort_key in feature_keys else 1 # sort_key in features or labels sorted_features, sorted_labels = [], [] for data in sorted(zipped, key=lambda x: len(x[key_index][sort_key])): feature, label = data sorted_features.append(feature) sorted_labels.append(label) self.__dict__["features"] = sorted_features self.__dict__["labels"] = sorted_labels zipped = None logger.info("Complete sorting...")
[docs] def to_dict(self, flatten=False, recursive=True): def _flatten(d): if d == {}: return d k, v = d.popitem() if isinstance(v, dict): flat_v = _flatten(v) for f_k in list(flat_v.keys()): flat_v[k + "#" + f_k] = flat_v[f_k] del flat_v[f_k] return {**flat_v, **_flatten(d)} else: return {k: v, **_flatten(d)} def _recursive(d): if not isinstance(d, dict): return d for k, v in d.items(): if isinstance(v, dict): dict_v = dict(v) d[k] = _recursive(dict_v) return d if flatten: d = {} d.update(_flatten(self.__dict__["features"])) d.update(_flatten(self.__dict__["labels"])) return d if recursive: return _recursive(self.__dict__) return dict(self.__dict__)
================================================ FILE: docs/_build/html/_modules/claf/data/collate.html ================================================ claf.data.collate — CLaF 0.2.0 documentation

Source code for claf.data.collate


from overrides import overrides

import torch
from torch.autograd import Variable

from claf.data import utils


[docs]class PadCollator: """ Collator apply pad and make tensor Minimizes amount of padding needed while producing mini-batch. * Kwargs: cuda_device_id: tensor assign to cuda device id Default is None (CPU) skip_keys: skip to make tensor """ def __init__(self, cuda_device_id=None, pad_value=0, skip_keys=["text"]): self.cuda_device_id = cuda_device_id self.pad_value = pad_value self.skip_keys = skip_keys def __call__(self, features, labels): self.collate(features, pad_value=self.pad_value) self.collate(labels, apply_pad=False, pad_value=self.pad_value) return utils.make_batch(features, labels)
[docs] def collate(self, datas, apply_pad=True, pad_value=0): for data_name, data in datas.items(): if isinstance(data, dict): for key, value in data.items(): data[key] = self._collate( value, apply_pad=apply_pad, token_name=key, pad_value=pad_value) else: datas[data_name] = self._collate(data, apply_pad=apply_pad)
def _collate(self, value, apply_pad=True, token_name=None, pad_value=0): if apply_pad: value = self._apply_pad(value, token_name=token_name, pad_value=pad_value) return self._make_tensor(value) def _apply_pad(self, value, token_name=None, pad_value=0): return utils.padding_tokens(value, token_name=token_name, pad_value=pad_value) def _make_tensor(self, value): if not isinstance(value, torch.Tensor): value_type = utils.get_token_type(value) if value_type == int: value = torch.LongTensor(value) else: value = torch.FloatTensor(value) value = Variable(value, requires_grad=False) if self.cuda_device_id is not None: value = value.cuda(self.cuda_device_id) return value
[docs]class FeatLabelPadCollator(PadCollator): """ Collator apply pad and make tensor Minimizes amount of padding needed while producing mini-batch. FeatLabelPadCollator allows applying pad to not only features, but also labels. * Kwargs: cuda_device_id: tensor assign to cuda device id Default is None (CPU) skip_keys: skip to make tensor """ @overrides def __call__(self, features, labels, apply_pad_labels=(), apply_pad_values=()): self.collate(features) self.collate(labels, apply_pad=False, apply_pad_labels=apply_pad_labels, apply_pad_values=apply_pad_values) return utils.make_batch(features, labels)
[docs] @overrides def collate(self, datas, apply_pad=True, apply_pad_labels=(), apply_pad_values=()): for data_name, data in datas.items(): if not apply_pad and data_name in apply_pad_labels: _apply_pad = True # ignore apply_pad pad_value = apply_pad_values[apply_pad_labels.index(data_name)] else: _apply_pad = apply_pad pad_value = 0 if isinstance(data, dict): for key, value in data.items(): data[key] = self._collate( value, apply_pad=_apply_pad, token_name=key, pad_value=pad_value) else: datas[data_name] = self._collate(data, apply_pad=_apply_pad, pad_value=pad_value)
================================================ FILE: docs/_build/html/_modules/claf/data/data_handler.html ================================================ claf.data.data_handler — CLaF 0.2.0 documentation

Source code for claf.data.data_handler


import logging
import pickle
import os
from pathlib import Path, PosixPath
import shutil
import tempfile

import msgpack
import requests
from tqdm import tqdm

from claf import nsml

logger = logging.getLogger(__name__)


[docs]class CachePath: if nsml.IS_ON_NSML: ROOT = Path("./claf_cache") else: ROOT = Path.home() / ".claf_cache" DATASET = ROOT / "dataset" MACHINE = ROOT / "machine" PRETRAINED_VECTOR = ROOT / "pretrained_vector" TOKEN_COUNTER = ROOT / "token_counter" VOCAB = ROOT / "vocab"
[docs]class DataHandler: """ DataHandler with CachePath - read (from_path, from_http) - dump (.msgpack or .pkl (pickle)) - load """ def __init__(self, cache_path=CachePath.ROOT): if type(cache_path) != PosixPath: raise ValueError(f"cache_path type is PosixPath (use pathlib.Path). not f{type(cache_path)}") self.cache_path = cache_path cache_path.mkdir(parents=True, exist_ok=True)
[docs] def convert_cache_path(self, path): cache_data_path = self.cache_path / Path(path) return cache_data_path
[docs] def read_embedding(self, file_path): raise NotImplementedError()
[docs] def read(self, file_path, encoding="utf-8", return_path=False): if file_path.startswith("http"): file_path = self._read_from_http(file_path, encoding) path = Path(file_path) if path.exists(): if return_path: return path return path.read_bytes().decode(encoding) if nsml.IS_ON_NSML: dataset_path = Path(nsml.DATASET_PATH) path = dataset_path / file_path if not path.exists(): path = dataset_path / "train" / file_path if not path.exists(): raise FileNotFoundError(path) if path.exists(): if return_path: return path return path.read_bytes().decode(encoding) else: raise FileNotFoundError(f"{file_path} is not found.")
def _read_from_http(self, file_path, encoding, return_path=False): cache_data_path = self.cache_path / Path(file_path).name if cache_data_path.exists(): logger.info(f"'{file_path}' is already downloaded.") pass else: with tempfile.TemporaryFile() as temp_file: self._download_from_http(temp_file, file_path) temp_file.flush() temp_file.seek(0) with open(cache_data_path, 'wb') as cache_file: shutil.copyfileobj(temp_file, cache_file) return cache_data_path def _download_from_http(self, temp_file, url): req = requests.get(url, stream=True) content_length = req.headers.get('Content-Length') total = int(content_length) if content_length is not None else None with tqdm(total=total, unit="B", unit_scale=True, desc="download...") as pbar: for chunk in req.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks temp_file.write(chunk) pbar.update(len(chunk))
[docs] def cache_token_counter(self, data_reader_config, tokenizer_name, obj=None): data_paths = os.path.basename(data_reader_config.train_file_path) if getattr(data_reader_config, "valid_file_path", None): data_paths += "#" + os.path.basename(data_reader_config.valid_file_path) path = self.cache_path / data_reader_config.dataset / data_paths path.mkdir(parents=True, exist_ok=True) path = path / tokenizer_name if obj: self.dump(path, obj) else: return self.load(path)
[docs] def load(self, file_path, encoding="utf-8"): path = self.cache_path / file_path logger.info(f"load path: {path}") msgpack_path = path.with_suffix(".msgpack") if msgpack_path.exists(): return self._load_msgpack(msgpack_path, encoding) pickle_path = path.with_suffix(".pkl") if pickle_path.exists(): return self._load_pickle(pickle_path, encoding) return None
def _load_msgpack(self, path, encoding): with open(path, "rb") as in_file: return msgpack.unpack(in_file, encoding=encoding) def _load_pickle(self, path, encoding): with open(path, "rb") as in_file: return pickle.load(in_file, encoding=encoding)
[docs] def dump(self, file_path, obj, encoding="utf-8"): path = self.cache_path / file_path path.parent.mkdir(parents=True, exist_ok=True) try: with open(path.with_suffix(".msgpack"), "wb") as out_file: msgpack.pack(obj, out_file, encoding=encoding) except TypeError: os.remove(path.with_suffix(".msgpack")) with open(path.with_suffix(".pkl"), "wb") as out_file: pickle.dump(obj, out_file, protocol=pickle.HIGHEST_PROTOCOL)
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/base.html ================================================ claf.data.dataset.base — CLaF 0.2.0 documentation

Source code for claf.data.dataset.base


from torch.utils.data.dataset import Dataset

from claf.data import utils


[docs]class DatasetBase(Dataset): """ Dataset Base Model An abstract class representing a Dataset. """ def __init__(self): # Features - Lazy Evaluation self.f_count = 0 self.features = [] def __getitem__(self, index): raise NotImplementedError def _get_feature_maxlen(self, features): max_len = -1 for feature in features: for token_name, sentence in feature.items(): if token_name == "text": continue if callable(sentence): continue max_len = max(max_len, len(sentence)) return max_len
[docs] def collate_fn(self, cuda_device_id): raise NotImplementedError
[docs] def get_ground_truths(self, data_idxs): data_idxs_dim = utils.get_token_dim(data_idxs) if data_idxs_dim > 2: raise ValueError(f"data_idxs dimension can't be larger than 2.({data_idxs_dim})") if data_idxs_dim == 2: return [self.get_ground_truth(data_id) for data_id in data_idxs] elif data_idxs_dim == 1: return self.get_ground_truth(data_idxs) else: raise ValueError(f"data_idxs dimension must be 1 or 2. not {data_idxs_dim}")
[docs] def get_ground_truth(self): raise NotImplementedError
[docs] def get_predict(self): raise NotImplementedError
[docs] def lazy_evaluation(self, index): if self.f_count < self.__len__(): self.f_count += 1 for feature in self.features: for k, v in feature[index].items(): if utils.is_lazy(v): feature[index][k] = v()
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/bert/multi_task.html ================================================ claf.data.dataset.bert.multi_task — CLaF 0.2.0 documentation

Source code for claf.data.dataset.bert.multi_task


import json
from overrides import overrides
import torch
import random

from claf.config.factory.data_loader import make_data_loader
from claf.data.dataset.base import DatasetBase


[docs]class MultiTaskBertDataset(DatasetBase): """ Dataset for Multi-Task GLUE using BERT * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batches, vocab, helper=None): super(MultiTaskBertDataset, self).__init__() self.name = "multitask_bert" self.vocab = vocab task_helpers = helper["task_helpers"] self.multi_dataset_size = 0 self.batch_sizes = [] self.task_datasets = [] for b, h in zip(batches, task_helpers): batch_size = h["batch_size"] self.batch_sizes.append(batch_size) dataset_cls = h["dataset"] dataset = dataset_cls(b, vocab, helper=h) self.task_datasets.append(dataset) task_dataset_size, remain = divmod(len(dataset), batch_size) if remain > 0: task_dataset_size += 1 self.multi_dataset_size += task_dataset_size self.init_iterators()
[docs] def init_iterators(self): cuda_device_id = None if torch.cuda.is_available(): cuda_device_id = 0 # TODO: Hard-code self.iterators = [] for batch_size, dataset in zip(self.batch_sizes, self.task_datasets): data_loader = make_data_loader(dataset, batch_size=batch_size, cuda_device_id=cuda_device_id) # TODO: cuda_device_id self.iterators.append(iter(data_loader)) self.available_iterators = list(range(len(self.iterators)))
[docs] @overrides def collate_fn(self, cuda_device_id=None): def pass_tensor(data): task_idx, tensor_datas = zip(*data) tensor_batch = tensor_datas[0] task_id_tensor = torch.LongTensor(list(task_idx)) if torch.cuda.is_available(): task_id_tensor.cuda(cuda_device_id) tensor_batch.features["task_index"] = task_id_tensor return tensor_batch return pass_tensor
@overrides def __getitem__(self, index): # self.lazy_evaluation(index) if len(self.available_iterators) == 0: self.init_iterators() random_index = random.choice(self.available_iterators) task_iterator = self.iterators[random_index] try: return random_index, next(task_iterator) except StopIteration: self.available_iterators.remove(random_index) return self.__getitem__(index) def __len__(self): return self.multi_dataset_size def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "dataset_count": len(self.iterators), "task_dataset_sizes": [len(dataset) for dataset in self.task_datasets], } return json.dumps(dataset_properties, indent=4)
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/bert/regression.html ================================================ claf.data.dataset.bert.regression — CLaF 0.2.0 documentation

Source code for claf.data.dataset.bert.regression


import json
from overrides import overrides

from claf.data import utils
from claf.data.collate import PadCollator
from claf.data.dataset.base import DatasetBase


[docs]class RegressionBertDataset(DatasetBase): """ Dataset for Regression using BERT * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(RegressionBertDataset, self).__init__() self.name = "reg_bert" self.vocab = vocab self.helper = helper # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.features = [self.bert_input_idx, self.token_type_idx] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.labels = { label["id"]: { "score": label["score"], } for label in batch.labels } self.label_scores = [label["score"] for label in batch.labels]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): data_idxs, bert_input_idxs, token_type_idxs, label_scores = zip(*data) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), } labels = { "data_idx": data_idxs, "score": label_scores, } return collator(features, labels) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.bert_input_idx[index], self.token_type_idx[index], self.label_scores[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "sequence_maxlen": self.sequence_maxlen, } return json.dumps(dataset_properties, indent=4) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx)
[docs] def get_id(self, data_index): return self.data_ids[data_index]
[docs] @overrides def get_ground_truth(self, data_id): return self.labels[data_id]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/bert/seq_cls.html ================================================ claf.data.dataset.bert.seq_cls — CLaF 0.2.0 documentation

Source code for claf.data.dataset.bert.seq_cls


import json
from overrides import overrides

from claf.data import utils
from claf.data.collate import PadCollator
from claf.data.dataset.base import DatasetBase


[docs]class SeqClsBertDataset(DatasetBase): """ Dataset for Sequence Classification using BERT * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(SeqClsBertDataset, self).__init__() self.name = "seq_cls_bert" self.vocab = vocab self.helper = helper self.class_idx2text = helper["class_idx2text"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.features = [self.bert_input_idx, self.token_type_idx] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.classes = { label["id"]: { "class_idx": label["class_idx"], "class_text": label["class_text"], } for label in batch.labels } self.class_text = [label["class_text"] for label in batch.labels] self.class_idx = [label["class_idx"] for label in batch.labels]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): data_idxs, bert_input_idxs, token_type_idxs, class_idxs = zip(*data) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), } labels = { "class_idx": class_idxs, "data_idx": data_idxs, } return collator(features, labels) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.bert_input_idx[index], self.token_type_idx[index], self.class_idx[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "num_classes": self.num_classes, "sequence_maxlen": self.sequence_maxlen, "classes": self.class_idx2text, } return json.dumps(dataset_properties, indent=4) @property def num_classes(self): return len(self.class_idx2text) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx)
[docs] def get_id(self, data_index): return self.data_ids[data_index]
[docs] @overrides def get_ground_truth(self, data_id): return self.classes[data_id]
[docs] def get_class_text_with_idx(self, class_index): if class_index is None: raise ValueError("class_index is required.") return self.class_idx2text[class_index]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/bert/squad.html ================================================ claf.data.dataset.bert.squad — CLaF 0.2.0 documentation

Source code for claf.data.dataset.bert.squad


import json
from overrides import overrides

from claf.data import utils
from claf.data.collate import PadCollator
from claf.data.dataset.base import DatasetBase


[docs]class SQuADBertDataset(DatasetBase): """ SQuAD Dataset for BERT compatible with v1.1 and v2.0 * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(SQuADBertDataset, self).__init__() self.name = "squad_bert" self.vocab = vocab self.helper = helper self.raw_dataset = helper["raw_dataset"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.features = [self.bert_input_idx, self.token_type_idx] # for lazy_evaluation # Labels self.qids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.qids.keys()) self.answers = { label["id"]: ( label["answerable"], (label["answer_start"], label["answer_end"]), ) for label in batch.labels } self.answer_starts = [label["answer_start"] for label in batch.labels] self.answer_ends = [label["answer_end"] for label in batch.labels] self.answerables = [label["answerable"] for label in batch.labels]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): bert_input_idxs, token_type_idxs, data_idxs, answer_starts, answer_ends, answerables = zip( *data ) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), } labels = { "data_idx": data_idxs, "answer_start_idx": answer_starts, "answer_end_idx": answer_ends, "answerable": answerables, } return collator(features, labels) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.bert_input_idx[index], self.token_type_idx[index], self.data_indices[index], self.answer_starts[index], self.answer_ends[index], self.answerables[index], ) def __len__(self): return len(self.qids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "HasAns_count": len([True for k, v in self.answers.items() if v[1] == 1]), "NoAns_count": len([False for k, v in self.answers.items() if v[1] == 0]), "bert_input_maxlen": self.bert_input_maxlen, } return json.dumps(dataset_properties, indent=4) @property def bert_input_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx)
[docs] def get_qid(self, data_index): qid = self.qids[data_index] if "#" in qid: qid = qid.split("#")[0] return qid
[docs] def get_id(self, data_index): return self.get_qid(data_index)
[docs] def get_qid_index(self, data_index): qid = self.qids[data_index] if "#" in qid: return qid.split("#")[1] return None
[docs] def get_context(self, data_index): qid = self.get_qid(data_index) return self.helper["examples"][qid]["context"]
[docs] @overrides def get_ground_truths(self, data_index): qid = self.get_qid(data_index) answer_texts = self.helper["examples"][qid]["answers"] answerable, answer_span = self.answers[qid] return answer_texts, answerable, answer_span
[docs] @overrides def get_predict(self, data_index, start, end): return self.get_text_with_index(data_index, start, end)
[docs] def get_text_with_index(self, data_index, start, end): if data_index is None: raise ValueError("data_id or text is required.") context_text = self.get_context(data_index) bert_token = self.get_bert_tokens(data_index) if ( start <= 0 or end >= len(bert_token) or bert_token[start].text_span is None or bert_token[end].text_span is None ): # No_Answer Case return "<noanswer>" char_start = bert_token[start].text_span[0] char_end = bert_token[end].text_span[1] if char_start > char_end or len(context_text) <= char_end: return "" return context_text[char_start:char_end]
[docs] def get_bert_tokens(self, data_index): qid = self.get_qid(data_index) index = self.get_qid_index(data_index) if index is None: raise ValueError("bert_qid must have 'bert_index' (bert_id: qid#bert_index)") bert_index = f"bert_tokens_{index}" return self.helper["examples"][qid][bert_index]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/bert/tok_cls.html ================================================ claf.data.dataset.bert.tok_cls — CLaF 0.2.0 documentation

Source code for claf.data.dataset.bert.tok_cls


import json
from overrides import overrides

from claf.data import utils
from claf.data.collate import FeatLabelPadCollator
from claf.data.dataset.base import DatasetBase


[docs]class TokClsBertDataset(DatasetBase): """ Dataset for Token Classification * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(TokClsBertDataset, self).__init__() self.name = "tok_cls_bert" self.vocab = vocab self.helper = helper self.tag_idx2text = helper["tag_idx2text"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.tagged_sub_token_idxs = [{"feature": feature["tagged_sub_token_idxs"]} for feature in batch.features] self.num_tokens = [{"feature": feature["num_tokens"]} for feature in batch.features] self.features = [self.bert_input_idx, self.token_type_idx] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.tags = { label["id"]: { "tag_idxs": label["tag_idxs"], "tag_texts": label["tag_texts"], } for label in batch.labels } self.tag_texts = [label["tag_texts"] for label in batch.labels] self.tag_idxs = [label["tag_idxs"] for label in batch.labels] self.ignore_tag_idx = helper["ignore_tag_idx"]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = FeatLabelPadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): data_idxs, bert_input_idxs, token_type_idxs, tagged_token_idxs, num_tokens, tag_idxs_list = zip(*data) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), "tagged_sub_token_idxs": utils.transpose(tagged_token_idxs, skip_keys=["text"]), "num_tokens": utils.transpose(num_tokens, skip_keys=["text"]), } labels = { "tag_idxs": tag_idxs_list, "data_idx": data_idxs, } return collator( features, labels, apply_pad_labels=["tag_idxs"], apply_pad_values=[self.ignore_tag_idx] ) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.bert_input_idx[index], self.token_type_idx[index], self.tagged_sub_token_idxs[index], self.num_tokens[index], self.tag_idxs[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "num_tags": self.num_tags, "sequence_maxlen": self.sequence_maxlen, "tags": self.tag_idx2text, } return json.dumps(dataset_properties, indent=4) @property def num_tags(self): return len(self.tag_idx2text) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx)
[docs] def get_id(self, data_index): return self.data_ids[data_index]
[docs] @overrides def get_ground_truth(self, data_id): return self.tags[data_id]
[docs] def get_tag_texts_with_idxs(self, tag_idxs): return [self.get_tag_text_with_idx(tag_idx)for tag_idx in tag_idxs]
[docs] def get_tag_text_with_idx(self, tag_index): if tag_index is None: raise ValueError("tag_index is required.") return self.tag_idx2text[tag_index]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/seq_cls.html ================================================ claf.data.dataset.seq_cls — CLaF 0.2.0 documentation

Source code for claf.data.dataset.seq_cls


import json
from overrides import overrides
import torch

from claf.data import utils
from claf.data.collate import PadCollator
from claf.data.dataset.base import DatasetBase


[docs]class SeqClsDataset(DatasetBase): """ Dataset for Sequence Classification * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(SeqClsDataset, self).__init__() self.name = "seq_cls" self.vocab = vocab self.helper = helper self.class_idx2text = helper["class_idx2text"] self.sequences = {feature["id"]: feature["sequence"]["text"] for feature in batch.features} # Features self.sequence_idxs = [feature["sequence"] for feature in batch.features] self.features = [self.sequence_idxs] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.classes = { label["id"]: { "class_idx": label["class_idx"], "class_text": label["class_text"], } for label in batch.labels } self.class_text = [label["class_text"] for label in batch.labels] self.class_idx = [label["class_idx"] for label in batch.labels]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): data_idxs, sequence_idxs, class_idxs = zip(*data) features = { "sequence": utils.transpose(sequence_idxs, skip_keys=["text"]), } labels = { "class_idx": class_idxs, "data_idx": data_idxs, } return collator(features, labels) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.sequence_idxs[index], self.class_idx[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "num_classes": self.num_classes, "sequence_maxlen": self.sequence_maxlen, "classes": self.class_idx2text, } return json.dumps(dataset_properties, indent=4) @property def num_classes(self): return len(self.class_idx2text) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.sequence_idxs)
[docs] def get_id(self, data_index): return self.data_ids[data_index]
[docs] @overrides def get_ground_truth(self, data_id): return self.classes[data_id]
[docs] def get_class_text_with_idx(self, class_index): if class_index is None: raise ValueError("class_index is required.") return self.class_idx2text[class_index]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/seq_cls_bert.html ================================================ claf.data.dataset.seq_cls_bert — CLaF 0.1.0 documentation

Source code for claf.data.dataset.seq_cls_bert


import json
from overrides import overrides
import torch

from claf.data import utils
from claf.data.collate import PadCollator
from claf.data.dataset.base import DatasetBase


[docs]class SeqClsBertDataset(DatasetBase): """ Dataset for Sequence Classification using BERT * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, helper=None): super(SeqClsBertDataset, self).__init__() self.name = "seq_cls_bert" self.helper = helper self.raw_dataset = helper["raw_dataset"] self.class_idx2text = helper["class_idx2text"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.features = [self.bert_input_idx, self.token_type_idx] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.classes = { label["id"]: { "class_idx": label["class_idx"], "class_text": label["class_text"], } for label in batch.labels } self.class_text = [label["class_text"] for label in batch.labels] self.class_idx = [label["class_idx"] for label in batch.labels]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id) def make_tensor_fn(data): data_idxs, bert_input_idxs, token_type_idxs, class_idxs = zip(*data) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), } labels = { "class_idx": class_idxs, "data_idx": data_idxs, } return collator(features, labels) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.bert_input_idx[index], self.token_type_idx[index], self.class_idx[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "num_classes": self.num_classes, "sequence_maxlen": self.sequence_maxlen, "classes": self.class_idx2text, } return json.dumps(dataset_properties, indent=4) @property def num_classes(self): return len(self.class_idx2text) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx)
[docs] def get_id(self, data_index): return self.data_ids[data_index]
[docs] @overrides def get_ground_truth(self, data_id): return self.classes[data_id]
[docs] def get_class_text_with_idx(self, class_index): if class_index is None: raise ValueError("class_index is required.") return self.class_idx2text[class_index]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/squad.html ================================================ claf.data.dataset.squad — CLaF 0.2.0 documentation

Source code for claf.data.dataset.squad


import json
from overrides import overrides

from claf.data import utils
from claf.data.collate import PadCollator
from claf.data.dataset.base import DatasetBase


[docs]class SQuADDataset(DatasetBase): """ SQuAD Dataset compatible with v1.1 and v2.0 * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(SQuADDataset, self).__init__() self.name = "squad" self.vocab = vocab self.helper = helper self.raw_dataset = helper["raw_dataset"] # for SQuAD official metric # Features self.context_idx = [feature["context"] for feature in batch.features] self.question_idx = [feature["question"] for feature in batch.features] self.features = [self.context_idx, self.question_idx] # for lazy_evaluation # Labels self.qids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.qids.keys()) self.answers = { label["id"]: ( label["answerable"], (label["answer_start"], label["answer_end"]), ) for label in batch.labels } self.answer_starts = [label["answer_start"] for label in batch.labels] self.answer_ends = [label["answer_end"] for label in batch.labels] self.answerables = [label["answerable"] for label in batch.labels]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): context_idxs, question_idxs, data_idxs, \ answer_starts, answer_ends, answerables = zip(*data) features = { "context": utils.transpose(context_idxs, skip_keys=["text"]), "question": utils.transpose(question_idxs, skip_keys=["text"]), } labels = { "data_idx": data_idxs, "answer_start_idx": answer_starts, "answer_end_idx": answer_ends, "answerable": answerables, } return collator(features, labels) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.context_idx[index], self.question_idx[index], self.data_indices[index], self.answer_starts[index], self.answer_ends[index], self.answerables[index], ) def __len__(self): return len(self.qids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "HasAns_count": len([True for item in self.answerables if item == 1]), "NoAns_count": len([False for item in self.answerables if item == 0]), "context_maxlen": self.context_maxlen, "question_maxlen": self.question_maxlen, } return json.dumps(dataset_properties, indent=4) @property def context_maxlen(self): return self._get_feature_maxlen(self.context_idx) @property def question_maxlen(self): return self._get_feature_maxlen(self.question_idx)
[docs] def get_qid(self, data_index): return self.qids[data_index]
[docs] def get_context(self, data_index): qid = self.get_qid(data_index) return self.helper["examples"][qid]["context"]
[docs] def get_text_span(self, data_index): qid = self.get_qid(data_index) return self.helper["examples"][qid]["text_span"]
[docs] @overrides def get_ground_truths(self, data_index): qid = self.get_qid(data_index) answer_texts = self.helper["examples"][qid]["answers"] answerable, answer_span = self.answers[qid] return answer_texts, answerable, answer_span
[docs] @overrides def get_predict(self, data_index, start, end): return self.get_text_with_index(data_index, start, end)
[docs] def get_text_with_index(self, data_index, start, end): if data_index is None: raise ValueError("qid or text is required.") context_text = self.get_context(data_index) text_span = self.get_text_span(data_index) if start >= len(text_span) or end >= len(text_span): # No_Answer Case return "<noanswer>" char_start = text_span[start][0] char_end = text_span[end][1] if char_start > char_end or len(context_text) <= char_end: return "" return context_text[char_start:char_end]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/squad_bert.html ================================================ claf.data.dataset.squad_bert — CLaF 0.1.0 documentation

Source code for claf.data.dataset.squad_bert


import json
from overrides import overrides

from claf.data import utils
from claf.data.collate import PadCollator
from claf.data.dataset.base import DatasetBase


[docs]class SQuADBertDataset(DatasetBase): """ SQuAD Dataset for BERT compatible with v1.1 and v2.0 * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, helper=None): super(SQuADBertDataset, self).__init__() self.name = "squad_bert" self.helper = helper self.raw_dataset = helper["raw_dataset"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.features = [self.bert_input_idx, self.token_type_idx] # for lazy_evaluation # Labels self.qids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.qids.keys()) self.answers = { label["id"]: ( label["answerable"], (label["answer_start"], label["answer_end"]), ) for label in batch.labels } self.answer_starts = [label["answer_start"] for label in batch.labels] self.answer_ends = [label["answer_end"] for label in batch.labels] self.answerables = [label["answerable"] for label in batch.labels]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id) def make_tensor_fn(data): bert_input_idxs, token_type_idxs, data_idxs, answer_starts, answer_ends, answerables = zip( *data ) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), } labels = { "answer_idx": data_idxs, "answer_start_idx": answer_starts, "answer_end_idx": answer_ends, "answerable": answerables, } return collator(features, labels) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.bert_input_idx[index], self.token_type_idx[index], self.data_indices[index], self.answer_starts[index], self.answer_ends[index], self.answerables[index], ) def __len__(self): return len(self.qids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "HasAns_count": len([True for k, v in self.answers.items() if v[1] == 1]), "NoAns_count": len([False for k, v in self.answers.items() if v[1] == 0]), "bert_input_maxlen": self.bert_input_maxlen, } return json.dumps(dataset_properties, indent=4) @property def bert_input_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx)
[docs] def get_qid(self, data_index): qid = self.qids[data_index] if "#" in qid: qid = qid.split("#")[0] return qid
[docs] def get_qid_index(self, data_index): qid = self.qids[data_index] if "#" in qid: return qid.split("#")[1] return None
[docs] def get_context(self, data_index): qid = self.get_qid(data_index) return self.helper["examples"][qid]["context"]
[docs] @overrides def get_ground_truths(self, data_index): qid = self.get_qid(data_index) answer_texts = self.helper["examples"][qid]["answers"] answerable, answer_span = self.answers[qid] return answer_texts, answerable, answer_span
[docs] @overrides def get_predict(self, data_index, start, end): return self.get_text_with_index(data_index, start, end)
[docs] def get_text_with_index(self, data_index, start, end): if data_index is None: raise ValueError("data_id or text is required.") context_text = self.get_context(data_index) bert_token = self.get_bert_tokens(data_index) if ( start <= 0 or end >= len(bert_token) or bert_token[start].text_span is None or bert_token[end].text_span is None ): # No_Answer Case return "<noanswer>" char_start = bert_token[start].text_span[0] char_end = bert_token[end].text_span[1] if char_start > char_end or len(context_text) <= char_end: return "" return context_text[char_start:char_end]
[docs] def get_bert_tokens(self, data_index): qid = self.get_qid(data_index) index = self.get_qid_index(data_index) if index is None: raise ValueError("bert_qid must have 'bert_index' (bert_id: qid#bert_index)") bert_index = f"bert_tokens_{index}" return self.helper["examples"][qid][bert_index]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/tok_cls_bert.html ================================================ claf.data.dataset.tok_cls_bert — CLaF 0.1.0 documentation

Source code for claf.data.dataset.tok_cls_bert


import json
from collections import defaultdict
from overrides import overrides
import torch
from seqeval.metrics.sequence_labeling import get_entities

from claf.data import utils
from claf.data.collate import FeatLabelPadCollator
from claf.data.dataset.base import DatasetBase


[docs]class TokClsBertDataset(DatasetBase): """ Dataset for Token Classification * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, helper=None): super(TokClsBertDataset, self).__init__() self.name = "tok_cls_bert" self.helper = helper self.raw_dataset = helper["raw_dataset"] self.tag_idx2text = helper["tag_idx2text"] # Features self.bert_input_idx = [feature["bert_input"] for feature in batch.features] SEP_token = self.helper.get("sep_token", "[SEP]") self.token_type_idx = utils.make_bert_token_types(self.bert_input_idx, SEP_token=SEP_token) self.tagged_sub_token_idxs = [{"feature": feature["tagged_sub_token_idxs"]} for feature in batch.features] self.num_tokens = [{"feature": feature["num_tokens"]} for feature in batch.features] self.features = [self.bert_input_idx, self.token_type_idx] # for lazy evaluation # Labels self.data_ids = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_ids.keys()) self.tags = { label["id"]: { "tag_idxs": label["tag_idxs"], "tag_texts": label["tag_texts"], } for label in batch.labels } self.tag_texts = [label["tag_texts"] for label in batch.labels] self.tag_idxs = [label["tag_idxs"] for label in batch.labels] self.ignore_tag_idx = helper["ignore_tag_idx"]
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = FeatLabelPadCollator(cuda_device_id=cuda_device_id) def make_tensor_fn(data): data_idxs, bert_input_idxs, token_type_idxs, tagged_token_idxs, num_tokens, tag_idxs_list = zip(*data) features = { "bert_input": utils.transpose(bert_input_idxs, skip_keys=["text"]), "token_type": utils.transpose(token_type_idxs, skip_keys=["text"]), "tagged_sub_token_idxs": utils.transpose(tagged_token_idxs, skip_keys=["text"]), "num_tokens": utils.transpose(num_tokens, skip_keys=["text"]), } labels = { "tag_idxs": tag_idxs_list, "data_idx": data_idxs, } return collator( features, labels, apply_pad_labels=["tag_idxs"], apply_pad_values=[self.ignore_tag_idx] ) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.data_indices[index], self.bert_input_idx[index], self.token_type_idx[index], self.tagged_sub_token_idxs[index], self.num_tokens[index], self.tag_idxs[index], ) def __len__(self): return len(self.data_ids) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "num_tags": self.num_tags, "sequence_maxlen": self.sequence_maxlen, "tags": self.tag_idx2text, } return json.dumps(dataset_properties, indent=4) @property def num_tags(self): return len(self.tag_idx2text) @property def sequence_maxlen(self): return self._get_feature_maxlen(self.bert_input_idx)
[docs] def get_id(self, data_index): return self.data_ids[data_index]
[docs] @overrides def get_ground_truth(self, data_id): return self.tags[data_id]
[docs] def get_tag_texts_with_idxs(self, tag_idxs): return [self.get_tag_text_with_idx(tag_idx)for tag_idx in tag_idxs]
[docs] def get_tag_text_with_idx(self, tag_index): if tag_index is None: raise ValueError("tag_index is required.") return self.tag_idx2text[tag_index]
================================================ FILE: docs/_build/html/_modules/claf/data/dataset/wikisql.html ================================================ claf.data.dataset.wikisql — CLaF 0.2.0 documentation

Source code for claf.data.dataset.wikisql


import json
from overrides import overrides

import torch

from claf.data import utils
from claf.data.collate import PadCollator
from claf.data.dataset.base import DatasetBase



[docs]class WikiSQLDataset(DatasetBase): """ WikiSQL Dataset * Args: batch: Batch DTO (claf.data.batch) * Kwargs: helper: helper from data_reader """ def __init__(self, batch, vocab, helper=None): super(WikiSQLDataset, self).__init__() self.name = "wikisql" self.vocab = vocab self.helper = helper # Features self.column_idx = [feature["column"] for feature in batch.features] self.question_idx = [feature["question"] for feature in batch.features] self.features = [self.column_idx, self.question_idx] # Labels self.data_idx = {data_index: label["id"] for (data_index, label) in enumerate(batch.labels)} self.data_indices = list(self.data_idx.keys()) self.table_idx = {data_index: label["table_id"] for (data_index, label) in enumerate(batch.labels)} self.tokenized_question = {label["id"]: label["tokenized_question"] for label in batch.labels} self.labels = { label["id"]: { "agg_idx": label["aggregator_idx"], "sel_idx": label["select_column_idx"], "conds_num": label["conditions_num"], "conds_col": label["conditions_column_idx"], "conds_op": label["conditions_operator_idx"], "conds_val_str": label["conditions_value_string"], "conds_val_pos": label["conditions_value_position"], "sql_query": label["sql_query"], "execution_result": label["execution_result"], } for label in batch.labels }
[docs] @overrides def collate_fn(self, cuda_device_id=None): """ collate: indexed features and labels -> tensor """ collator = PadCollator(cuda_device_id=cuda_device_id, pad_value=self.vocab.pad_index) def make_tensor_fn(data): column_idxs, question_idxs, data_idxs = zip(*data) features = { "column": utils.transpose(column_idxs, skip_keys=["text"]), "question": utils.transpose(question_idxs, skip_keys=["text"]), } labels = { "data_idx": data_idxs, } return collator(features, labels) return make_tensor_fn
@overrides def __getitem__(self, index): self.lazy_evaluation(index) return ( self.column_idx[index], self.question_idx[index], self.data_indices[index], ) def __len__(self): return len(self.data_idx) def __repr__(self): dataset_properties = { "name": self.name, "total_count": self.__len__(), "question_maxlen": self.question_maxlen, } return json.dumps(dataset_properties, indent=4) @property def question_maxlen(self): return self._get_feature_maxlen(self.question_idx)
[docs] def get_id(self, data_index): if type(data_index) == torch.Tensor: data_index = data_index.item() return self.data_idx[data_index]
[docs] def get_table_id(self, data_index): if type(data_index) == torch.Tensor: data_index = data_index.item() return self.table_idx[data_index]
[docs] def get_tokenized_question(self, data_index): data_id = self.get_id(data_index) return self.tokenized_question[data_id]
[docs] @overrides def get_ground_truth(self, data_index): if type(data_index) == torch.Tensor: data_id = self.get_id(data_index) else: data_id = data_index return self.labels[data_id]
================================================ FILE: docs/_build/html/_modules/claf/data/reader/base.html ================================================ claf.data.reader.base — CLaF 0.2.0 documentation

Source code for claf.data.reader.base


import logging

from claf.data.data_handler import CachePath, DataHandler
from claf import utils as common_utils

logger = logging.getLogger(__name__)


[docs]class DataReader: """ DataReader Base Class * Args: file_paths: dictionary of consisting ('train' and 'vaild') file_path dataset_obj: Dataset Object (claf.data.dataset.base) """ def __init__(self, file_paths, dataset_obj): self.file_paths = file_paths self.dataset_obj = dataset_obj self.data_handler = DataHandler(cache_path=CachePath.DATASET) # for Concrete DataReader self.text_columns = None
[docs] def filter_texts(self, dataset): texts = [] def append_texts(datas): for data in datas: for key, value in data.items(): if key in self.text_columns: texts.append(value) for data_type, dataset in dataset.items(): append_texts(dataset.features) # append_texts(dataset.labels) texts = list(common_utils.flatten(texts)) texts = list(set(texts)) # remove duplicate return texts
[docs] def read(self): """ read with Concrete DataReader each type """ if type(self.file_paths) != dict: raise ValueError(f"file_paths type is must be dict. not {type(self.file_paths)}") logger.info("Start read dataset") datasets, helpers = {}, {} for data_type, file_path in self.file_paths.items(): if data_type is None: continue batch, helper = self._read(file_path, data_type=data_type) datasets[data_type] = batch helpers[data_type] = helper logger.info("Complete read dataset...\n") return datasets, helpers
def _read(self, file_path, desc=None): raise NotImplementedError
[docs] def read_one_example(self, inputs): helper = None return inputs, helper
[docs] def convert_to_dataset(self, datas, vocab, helpers=None): """ Batch to Dataset """ datasets = {} for k, batch in datas.items(): if batch is None: continue datasets[k] = self.dataset_obj(batch, vocab, helper=helpers[k]) logger.info(f"{k} dataset. {datasets[k]}") return datasets
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/cola.html ================================================ claf.data.reader.bert.cola — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.cola


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:cola_bert") class CoLABertReader(SeqClsBertReader): """ CoLA DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(CoLABertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): line_tokens = line.split("\t") if len(line_tokens) <= 3: continue data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[3], self.class_key: str(line_tokens[1]) }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/conll2003.html ================================================ claf.data.reader.bert.conll2003 — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.conll2003


import logging
from itertools import chain

from overrides import overrides

from claf.data.reader import TokClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:conll2003_bert") class CoNLL2003BertReader(TokClsBertReader): """ CoNLL2003 for BERT * Args: file_paths: file paths (train and dev) * Kwargs: ignore_tag_idx: prediction results that have this number as ground-truth idx are ignored """ def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", ignore_tag_idx=-1, ): super(CoNLL2003BertReader, self).__init__( file_paths, tokenizers, lang_code=None, sequence_max_length=sequence_max_length, cls_token=cls_token, sep_token=sep_token, ignore_tag_idx=ignore_tag_idx, ) @overrides def _get_data(self, file_path): _file = self.data_handler.read(file_path) texts = _file.split("\n\n") texts.pop(0) data = [] for text in texts: tokens = text.split("\n") if len(tokens) > 1: example = list(zip(*[token.split() for token in tokens])) data.append({ "sequence": " ".join(example[0]), self.tag_key: list(example[-1]), }) return data, data @overrides def _get_tag_dicts(self, **kwargs): data = kwargs["data"] tags = sorted(list(set(chain.from_iterable(d[self.tag_key] for d in data)))) tag_idx2text = {tag_idx: tag_text for tag_idx, tag_text in enumerate(tags)} tag_text2idx = {tag_text: tag_idx for tag_idx, tag_text in tag_idx2text.items()} return tag_idx2text, tag_text2idx
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/cola.html ================================================ claf.data.reader.bert.glue.cola — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.cola


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:cola_bert") class CoLABertReader(SeqClsBertReader): """ CoLA DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "matthews_corr" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(CoLABertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): line_tokens = line.split("\t") if len(line_tokens) <= 3: continue data.append({ "uid": f"cola-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[3], self.class_key: str(line_tokens[1]) }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/mnli.html ================================================ claf.data.reader.bert.glue.mnli — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.mnli


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:mnli_bert") class MNLIBertReader(SeqClsBertReader): """ MNLI DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["contradiction", "entailment", "neutral"] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(MNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"mnli-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[8], "sequence_b": line_tokens[9], self.class_key: str(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/mrpc.html ================================================ claf.data.reader.bert.glue.mrpc — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.mrpc


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:mrpc_bert") class MRPCBertReader(SeqClsBertReader): """ MRPC DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "f1" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(MRPCBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) != 5: continue data.append({ "uid": f"mrpc-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[3], "sequence_b": line_tokens[4], self.class_key: str(line_tokens[0]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/qnli.html ================================================ claf.data.reader.bert.glue.qnli — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.qnli


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:qnli_bert") class QNLIBertReader(SeqClsBertReader): """ QNLI DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["entailment", "not_entailment"] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(QNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"qnli-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/qqp.html ================================================ claf.data.reader.bert.glue.qqp — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.qqp


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:qqp_bert") class QQPBertReader(SeqClsBertReader): """ Quora Question Pairs DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "f1" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(QQPBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") try: data.append({ "uid": f"qqp-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[3], "sequence_b": line_tokens[4], self.class_key: str(line_tokens[5]) }) except IndexError: continue return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/rte.html ================================================ claf.data.reader.bert.glue.rte — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.rte


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:rte_bert") class RTEBertReader(SeqClsBertReader): """ RTE (Recognizing Textual Entailment) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["entailment", "not_entailment"] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(RTEBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"rte-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/sst.html ================================================ claf.data.reader.bert.glue.sst — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.sst


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:sst_bert") class SSTBertReader(SeqClsBertReader): """ SST DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(SSTBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") if data_type == "train": lines.pop(0) data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"sst-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[0], self.class_key: str(line_tokens[1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/stsb.html ================================================ claf.data.reader.bert.glue.stsb — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.stsb


import logging

from overrides import overrides

from claf.data.reader import RegressionBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:stsb_bert") class STSBBertReader(RegressionBertReader): """ STS-B (Semantic Textual Similarity Benchmark) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ METRIC_KEY = "pearson_spearman_corr" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(STSBBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, label_key="score", cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"stsb-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[7], "sequence_b": line_tokens[8], "score": float(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/glue/wnli.html ================================================ claf.data.reader.bert.glue.wnli — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.glue.wnli


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:wnli_bert") class WNLIBertReader(SeqClsBertReader): """ WNLI (Winograd NLI) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] METRIC_KEY = "accuracy" def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(WNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"wnli-{file_path}-{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/mnli.html ================================================ claf.data.reader.bert.mnli — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.mnli


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:mnli_bert") class MNLIBertReader(SeqClsBertReader): """ MNLI DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["contradiction", "entailment", "neutral"] def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(MNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[8], "sequence_b": line_tokens[9], self.class_key: str(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/mrpc.html ================================================ claf.data.reader.bert.mrpc — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.mrpc


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:mrpc_bert") class MRPCBertReader(SeqClsBertReader): """ MRPC DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(MRPCBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) != 5: continue data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[3], "sequence_b": line_tokens[4], self.class_key: str(line_tokens[0]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/multi_task.html ================================================ claf.data.reader.bert.multi_task — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.multi_task


import logging

from overrides import overrides

from claf.config.factory import DataReaderFactory
from claf.config.namespace import NestedNamespace
from claf.config.registry import Registry
from claf.data.dataset import MultiTaskBertDataset
from claf.data.dto import Helper
from claf.data.reader.base import DataReader
from claf.decorator import register
from claf.model.multi_task.category import TaskCategory

from .seq_cls import SeqClsBertReader
from .squad import SQuADBertReader
from .regression import RegressionBertReader
from .tok_cls import TokClsBertReader

logger = logging.getLogger(__name__)


[docs]@register("reader:multitask_bert") class MultiTaskBertReader(DataReader): """ DataReader for Multi-Task using BERT * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword) * Kwargs: class_key: name of the label in .json file to use for classification """ CLASS_DATA = None def __init__( self, file_paths, tokenizers, batch_sizes=[], readers=[], ): super(MultiTaskBertReader, self).__init__(file_paths, MultiTaskBertDataset) assert len(batch_sizes) == len(readers) self.registry = Registry() self.text_columns = ["bert_input"] self.tokenizers = tokenizers self.batch_sizes = batch_sizes self.dataset_batches = [] self.dataset_helpers = [] self.tasks = [] for reader in readers: data_reader = self.make_data_reader(reader) batches, helpers = data_reader.read() self.dataset_batches.append(batches) self.dataset_helpers.append(helpers) dataset_name = reader["dataset"] helper = helpers["train"] task = self.make_task_by_reader(dataset_name, data_reader, helper) self.tasks.append(task)
[docs] def make_data_reader(self, config_dict): config = NestedNamespace() config.load_from_json(config_dict) config.tokenizers = self.tokenizers data_reader_factory = DataReaderFactory(config) return data_reader_factory.create()
[docs] def make_task_by_reader(self, name, data_reader, helper): task = {} task["name"] = name task["metric_key"] = data_reader.METRIC_KEY if isinstance(data_reader, SeqClsBertReader): task["category"] = TaskCategory.SEQUENCE_CLASSIFICATION task["num_label"] = helper["model"]["num_classes"] elif isinstance(data_reader, SQuADBertReader): task["category"] = TaskCategory.READING_COMPREHENSION task["num_label"] = None elif isinstance(data_reader, RegressionBertReader): task["category"] = TaskCategory.REGRESSION task["num_label"] = 1 elif isinstance(data_reader, TokClsBertReader): task["category"] = TaskCategory.TOKEN_CLASSIFICATION task["num_label"] = helper["model"]["num_tags"] else: raise ValueError("Check data_reader.") task["model_params"] = helper.get("model", {}) return task
@overrides def _read(self, file_path, data_type=None): """ TODO: Doc-String """ batches = [] helper = Helper() helper.task_helpers = [] for b in self.dataset_batches: batches.append(b[data_type]) for i, h in enumerate(self.dataset_helpers): task_helper = h[data_type] task_helper["batch_size"] = self.batch_sizes[i] helper.task_helpers.append(task_helper) helper.set_model_parameter({ "tasks": self.tasks, }) return batches, helper.to_dict()
[docs] def read_one_example(self, inputs): pass
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/qnli.html ================================================ claf.data.reader.bert.qnli — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.qnli


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:qnli_bert") class QNLIBertReader(SeqClsBertReader): """ QNLI DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["entailment", "not_entailment"] def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(QNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/qqp.html ================================================ claf.data.reader.bert.qqp — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.qqp


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:qqp_bert") class QQPBertReader(SeqClsBertReader): """ Quora Question Pairs DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(QQPBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") try: data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[3], "sequence_b": line_tokens[4], self.class_key: str(line_tokens[5]) }) except IndexError: continue return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/regression.html ================================================ claf.data.reader.bert.regression — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.regression


import logging
import json
import uuid

from overrides import overrides
from tqdm import tqdm

from claf.data.dataset import RegressionBertDataset
from claf.data.dto import BertFeature, Helper
from claf.data.reader.base import DataReader
from claf.data import utils
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:regression_bert") class RegressionBertReader(DataReader): """ Regression DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ METRIC_KEY = None def __init__( self, file_paths, tokenizers, sequence_max_length=None, label_key="score", cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(RegressionBertReader, self).__init__(file_paths, RegressionBertDataset) self.sequence_max_length = sequence_max_length self.text_columns = ["bert_input", "sequence"] # Tokenizers # - BERT: Word + Subword or Word + Char # - RoBERTa: BPE if input_type == "bert": self.tokenizer = tokenizers.get("subword", None) if self.tokenizer is None: self.tokenizer["char"] elif input_type == "roberta": self.tokenizer = tokenizers["bpe"] else: raise ValueError("'bert' and 'roberta' are available input_type.") self.label_key = label_key self.cls_token = cls_token self.sep_token = sep_token self.input_type = input_type self.is_test = is_test def _get_data(self, file_path, **kwargs): data = self.data_handler.read(file_path) seq_cls_data = json.loads(data) return seq_cls_data["data"] @overrides def _read(self, file_path, data_type=None): """ .json file structure should be something like this: { "data": [ { "sequence_a": "what a wonderful day!", "sequence_b": "what a great day!", "score": 0.9 }, ... ] } """ data = self._get_data(file_path, data_type=data_type) helper = Helper(**{ "file_path": file_path, "cls_token": self.cls_token, "sep_token": self.sep_token, "dataset": RegressionBertDataset, "metric_key": self.METRIC_KEY, }) features, labels = [], [] for example in tqdm(data, desc=data_type): sequence_a = utils.get_sequence_a(example) sequence_b = example.get("sequence_b", None) sequence_a_tokens = self.tokenizer.tokenize(sequence_a) sequence_b_tokens = None if sequence_b: sequence_b_tokens = self.tokenizer.tokenize(sequence_b) bert_input = utils.make_bert_input( sequence_a, sequence_b, self.tokenizer, max_seq_length=self.sequence_max_length, data_type=data_type, cls_token=self.cls_token, sep_token=self.sep_token, input_type=self.input_type, ) if bert_input is None: continue if "uid" in example: data_uid = example["uid"] else: data_uid = str(uuid.uuid1()) feature_row = { "id": data_uid, "bert_input": bert_input, } features.append(feature_row) score = example[self.label_key] label_row = { "id": data_uid, "score": score, } labels.append(label_row) helper.set_example(data_uid, { "sequence_a": sequence_a, "sequence_a_tokens": sequence_a_tokens, "sequence_b": sequence_b, "sequence_b_tokens": sequence_b_tokens, "score": score, }) if self.is_test and len(features) >= 10: break return utils.make_batch(features, labels), helper.to_dict()
[docs] def read_one_example(self, inputs): """ inputs keys: sequence_a and sequence_b """ sequence_a = utils.get_sequence_a(inputs) sequence_b = inputs.get("sequence_b", None) bert_feature = BertFeature() bert_feature.set_input_with_speical_token( sequence_a, sequence_b, self.tokenizer, max_seq_length=self.sequence_max_length, data_type="predict", cls_token=self.cls_token, sep_token=self.sep_token, input_type=self.input_type, ) features = [bert_feature.to_dict()] helper = {} return features, helper
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/rte.html ================================================ claf.data.reader.bert.rte — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.rte


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:rte_bert") class RTEBertReader(SeqClsBertReader): """ RTE (Recognizing Textual Entailment) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = ["entailment", "not_entailment"] def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(RTEBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/seq_cls.html ================================================ claf.data.reader.bert.seq_cls — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.seq_cls


import json
import logging
import uuid

from overrides import overrides
from tqdm import tqdm

from claf.data.dataset import SeqClsBertDataset
from claf.data.dto import BertFeature, Helper
from claf.data.reader.base import DataReader
from claf.data import utils
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:seq_cls_bert") class SeqClsBertReader(DataReader): """ DataReader for Sequence (Single and Pair) Classification using BERT * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword) * Kwargs: class_key: name of the label in .json file to use for classification """ CLASS_DATA = None METRIC_KEY = None def __init__( self, file_paths, tokenizers, sequence_max_length=None, class_key="class", cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(SeqClsBertReader, self).__init__(file_paths, SeqClsBertDataset) self.sequence_max_length = sequence_max_length self.text_columns = ["bert_input", "sequence"] # Tokenizers # - BERT: Word + Subword or Word + Char # - RoBERTa: BPE if input_type == "bert": self.tokenizer = tokenizers.get("subword", None) if self.tokenizer is None: self.tokenizer["char"] elif input_type == "roberta": self.tokenizer = tokenizers["bpe"] else: raise ValueError("'bert' and 'roberta' are available input_type.") self.class_key = class_key self.cls_token = cls_token self.sep_token = sep_token self.input_type = input_type self.is_test = is_test def _get_data(self, file_path, **kwargs): data = self.data_handler.read(file_path) seq_cls_data = json.loads(data) return seq_cls_data["data"] def _get_class_dicts(self, **kwargs): seq_cls_data = kwargs["data"] if self.class_key is None: class_data = self.CLASS_DATA else: class_data = [item[self.class_key] for item in seq_cls_data] class_data = list(set(class_data)) # remove duplicate class_idx2text = { class_idx: str(class_text) for class_idx, class_text in enumerate(class_data) } class_text2idx = {class_text: class_idx for class_idx, class_text in class_idx2text.items()} return class_idx2text, class_text2idx @overrides def _read(self, file_path, data_type=None): """ .json file structure should be something like this: { "data": [ { "sequence": "what a wonderful day!", "emotion": "happy" }, ... ], "emotion": [ // class_key "angry", "happy", "sad", ... ] } """ data = self._get_data(file_path, data_type=data_type) class_idx2text, class_text2idx = self._get_class_dicts(data=data) helper = Helper(**{ "file_path": file_path, "class_idx2text": class_idx2text, "class_text2idx": class_text2idx, "cls_token": self.cls_token, "sep_token": self.sep_token, "dataset": SeqClsBertDataset, "metric_key": self.METRIC_KEY, }) helper.set_model_parameter({ "num_classes": len(class_idx2text), }) helper.set_predict_helper({ "class_idx2text": class_idx2text, }) features, labels = [], [] for example in tqdm(data, desc=data_type): sequence_a = utils.get_sequence_a(example) sequence_b = example.get("sequence_b", None) sequence_a_tokens = self.tokenizer.tokenize(sequence_a) sequence_b_tokens = None if sequence_b: sequence_b_tokens = self.tokenizer.tokenize(sequence_b) bert_input = utils.make_bert_input( sequence_a, sequence_b, self.tokenizer, max_seq_length=self.sequence_max_length, data_type=data_type, cls_token=self.cls_token, sep_token=self.sep_token, input_type=self.input_type, ) if bert_input is None: continue if "uid" in example: data_uid = example["uid"] else: data_uid = str(uuid.uuid1()) # token_type(segment_ids) will be added in dataset feature_row = { "id": data_uid, "bert_input": bert_input, } features.append(feature_row) class_text = example[self.class_key] label_row = { "id": data_uid, "class_idx": class_text2idx[class_text], "class_text": class_text, } labels.append(label_row) helper.set_example(data_uid, { "sequence_a": sequence_a, "sequence_a_tokens": sequence_a_tokens, "sequence_b": sequence_b, "sequence_b_tokens": sequence_b_tokens, "class_idx": class_text2idx[class_text], "class_text": class_text, }) if self.is_test and len(features) >= 10: break return utils.make_batch(features, labels), helper.to_dict()
[docs] def read_one_example(self, inputs): """ inputs keys: sequence_a and sequence_b """ sequence_a = utils.get_sequence_a(inputs) sequence_b = inputs.get("sequence_b", None) bert_feature = BertFeature() bert_feature.set_input_with_speical_token( sequence_a, sequence_b, self.tokenizer, max_seq_length=self.sequence_max_length, data_type="predict", cls_token=self.cls_token, sep_token=self.sep_token, input_type=self.input_type, ) features = [bert_feature.to_dict()] helper = {} return features, helper
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/squad.html ================================================ claf.data.reader.bert.squad — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.squad


from collections import Counter
import json
import logging
import re

from overrides import overrides
from tqdm import tqdm

from claf.data.dataset import SQuADBertDataset
from claf.data.dto import BertFeature, Helper
from claf.data.reader.base import DataReader
from claf.data import utils
from claf.decorator import register
from claf.metric.squad_v1_official import normalize_answer
from claf.tokens.tokenizer import SentTokenizer, WordTokenizer

logger = logging.getLogger(__name__)


[docs]class Token: def __init__(self, text, text_span=None): self.text = text self.text_span = text_span
[docs]@register("reader:squad_bert") class SQuADBertReader(DataReader): """ SQuAD DataReader for BERT * Args: file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word) """ METRIC_KEY = "f1" def __init__( self, file_paths, lang_code, tokenizers, max_seq_length=384, context_stride=128, max_question_length=64, cls_token="[CLS]", sep_token="[SEP]", ): super(SQuADBertReader, self).__init__(file_paths, SQuADBertDataset) self.lang_code = lang_code self.max_seq_length = max_seq_length self.context_stride = context_stride self.max_question_length = max_question_length self.cls_token = cls_token self.sep_token = sep_token self.text_columns = ["bert_input", "context", "question"] sent_tokenizer = SentTokenizer("punkt", {}) if lang_code == "ko": self.word_tokenizer = WordTokenizer("mecab_ko", sent_tokenizer, split_with_regex=True) else: self.word_tokenizer = WordTokenizer( "treebank_en", sent_tokenizer, split_with_regex=True ) if tokenizers["bpe"] is not None: self.sub_level_tokenizer = tokenizers["bpe"] # RoBERTa elif tokenizers["subword"] is not None: self.sub_level_tokenizer = tokenizers["subword"] # BERT else: raise ValueError("'bpe' or 'subword' tokenizer is required.") @overrides def _read(self, file_path, data_type=None): word_tokenized_error_count, sub_level_tokenized_error_count = 0, 0 data = self.data_handler.read(file_path) squad = json.loads(data) if "data" in squad: squad = squad["data"] helper = Helper(**{ "file_path": file_path, "raw_dataset": squad, "cls_token": self.cls_token, "sep_token": self.sep_token, "dataset": SQuADBertDataset, }) helper.set_model_parameter({ "lang_code": self.lang_code, }) features, labels = [], [] is_training = data_type == "train" for article in tqdm(squad, desc=data_type): for paragraph in article["paragraphs"]: context_text = paragraph["context"].replace("``", '" ').replace("''", '" ') context_tokens = self.word_tokenizer.tokenize(context_text) context_spans, char_to_word_offset = self._convert_to_spans( context_text, context_tokens ) context_tokens = [ Token(text, span) for (text, span) in zip(context_tokens, context_spans) ] context_sub_tokens = [] for token in context_tokens: for sub_token in self.sub_level_tokenizer.tokenize(token.text): context_sub_tokens.append(Token(sub_token, token.text_span)) for qa in paragraph["qas"]: question_text = qa["question"] question_text = " ".join(self.word_tokenizer.tokenize(question_text)) question_sub_tokens = [ Token(sub_token) for sub_token in self.sub_level_tokenizer.tokenize(question_text) ] id_ = qa["id"] answers = qa["answers"] answer_texts, answer_indices = [], [] if qa.get("is_impossible", None): answers = qa["plausible_answers"] answerable = 0 else: answers = qa["answers"] answerable = 1 for answer in answers: answer_start = answer["answer_start"] answer_end = answer_start + len(answer["text"]) - 1 answer_texts.append(answer["text"]) answer_indices.append((answer_start, answer_end)) if len(answer_indices) > 0: answer_char_start, answer_char_end = self._find_one_most_common( answer_indices ) answer_word_start = char_to_word_offset[answer_char_start] answer_word_end = char_to_word_offset[answer_char_end] char_answer_text = context_text[answer_char_start : answer_char_end + 1] word_answer_text = context_text[ context_spans[answer_word_start][0] : context_spans[answer_word_end][1] ] if not self._is_rebuild(char_answer_text, word_answer_text): logger.warning(f"word_tokenized_error: {char_answer_text} ### {word_answer_text}") word_tokenized_error_count += 1 else: # Unanswerable answers = ["<noanswer>"] answer_char_start, answer_char_end = -1, -1 answer_word_start, answer_word_end = -1, -1 bert_features, bert_labels = self._make_features_and_labels( context_sub_tokens, question_sub_tokens, answer_char_start, answer_char_end + 1, ) for (index, (feature, label)) in enumerate(zip(bert_features, bert_labels)): bert_tokens = feature answer_start, answer_end = label if is_training and ( answer_start < 0 or answer_start >= len(bert_tokens) or answer_end >= len(bert_tokens) or bert_tokens[answer_start].text_span is None or bert_tokens[answer_end].text_span is None ): continue if is_training: char_start = bert_tokens[answer_start].text_span[0] char_end = bert_tokens[answer_end].text_span[1] bert_answer = context_text[char_start:char_end] if char_answer_text != bert_answer: logger.warning(f"sub_level_tokenized_error: {char_answer_text} ### {word_answer_text})") sub_level_tokenized_error_count += 1 feature_row = { "bert_input": [token.text for token in bert_tokens], "bert_token": bert_tokens, } features.append(feature_row) bert_id = id_ + f"#{index}" label_row = { "id": bert_id, # question_id + bert_index "answer_texts": "\t".join(answer_texts), "answer_start": answer_start, "answer_end": answer_end, "answerable": answerable, } labels.append(label_row) if id_ not in helper.examples: helper.set_example(id_, { "context": context_text, "question": question_text, "answers": answer_texts, }) helper.set_example(id_, { f"bert_tokens_{index}": bert_tokens, }, update=True) logger.info( f"tokenized_error_count - word: {word_tokenized_error_count} | sub_level: {sub_level_tokenized_error_count}" ) return utils.make_batch(features, labels), helper.to_dict()
[docs] @overrides def read_one_example(self, inputs): """ inputs keys: question, context """ context_text = inputs["context"].replace("``", '" ').replace("''", '" ') tokenized_context = self.word_tokenizer.tokenize(context_text) context_spans, char_to_word_offset = self._convert_to_spans(context_text, tokenized_context) context_tokens = [ Token(text, span) for (text, span) in zip(tokenized_context, context_spans) ] context_sub_tokens = [] for token in context_tokens: for sub_token in self.sub_level_tokenizer.tokenize(token.text): context_sub_tokens.append(Token(sub_token, token.text_span)) question_text = inputs["question"] question_text = " ".join(self.word_tokenizer.tokenize(question_text)) question_sub_tokens = [ Token(sub_token) for sub_token in self.sub_level_tokenizer.tokenize(question_text) ] bert_tokens, _ = self._make_features_and_labels( context_sub_tokens, question_sub_tokens, -1, -1 ) features = [] helper = Helper(**{ "bert_token": [], "tokenized_context": tokenized_context, "token_key": "tokenized_context" # for 1-example inference latency key }) for bert_token in bert_tokens: bert_input = [token.text for token in bert_token] bert_feature = BertFeature() bert_feature.set_input(bert_input) features.append(bert_feature.to_dict()) helper.bert_token.append(bert_token) return features, helper.to_dict()
def _find_one_most_common(self, answers): answer_counter = Counter(answers) value = answer_counter.most_common(1)[0][0] return value[0], value[1] def _convert_to_spans(self, raw_text, tokenized_text): """ Convert a tokenized version of `raw_text` into a series character spans referencing the `raw_text` """ double_quote_re = re.compile("\"|``|''") curr_idx = 0 spans = [] char_to_words = [-1 for _ in range(len(raw_text))] for token in tokenized_text: # Tokenizer might transform double quotes, for this case search over several # possible encodings if double_quote_re.match(token): span = double_quote_re.search(raw_text[curr_idx:]) temp = curr_idx + span.start() token_length = span.end() - span.start() else: temp = raw_text.find(token, curr_idx) token_length = len(token) if temp < curr_idx: joined_tokenized_text = " ".join(tokenized_text) raise ValueError( f"\n{raw_text} \n\n{joined_tokenized_text} \nToken: {token}, Index: {temp}, Current Index: {curr_idx}" ) curr_idx = temp spans.append((curr_idx, curr_idx + token_length)) curr_idx += token_length start, end = spans[-1] for i in range(start, end): char_to_words[i] = len(spans) - 1 for i in range(len(raw_text)): if char_to_words[i] != -1: continue for j, span in enumerate(spans): start, end = span if start < i <= end: char_to_words[i] = j return spans, char_to_words def _is_rebuild(self, char_answer_text, word_answer_text): norm_char_answer_text = normalize_answer(char_answer_text) norm_word_answer_text = normalize_answer(word_answer_text) if norm_char_answer_text != norm_word_answer_text: return False else: return True def _make_features_and_labels( self, context_sub_tokens, question_sub_tokens, answer_char_start, answer_char_end ): # sub_token, context_stride logic with context_max_length context_max_length = ( self.max_seq_length - len(question_sub_tokens) - 3 ) # [CLS], [SEP], [SEP] start_offset = 0 context_stride_spans = [] while start_offset < len(context_sub_tokens): strided_context_length = len(context_sub_tokens) - start_offset if strided_context_length > context_max_length: strided_context_length = context_max_length context_stride_spans.append((start_offset, strided_context_length)) if start_offset + strided_context_length == len(context_sub_tokens): break start_offset += min(strided_context_length, self.context_stride) features, labels = [], [] for (start_offset, length) in context_stride_spans: bert_tokens = [Token(self.cls_token)] bert_tokens += question_sub_tokens[: self.max_question_length] bert_tokens += [Token(self.sep_token)] bert_tokens += context_sub_tokens[start_offset : start_offset + length] bert_tokens += [Token(self.sep_token)] features.append(bert_tokens) if answer_char_start == -1 and answer_char_end == -1: answer_start, answer_end = 0, 0 else: answer_start, answer_end = self._get_closest_answer_spans( bert_tokens, answer_char_start, answer_char_end ) labels.append((answer_start, answer_end)) return features, labels def _get_closest_answer_spans(self, tokens, char_start, char_end): NONE_VALUE, DISTANCE_THRESHOLD = -100, 2 text_spans = [ (NONE_VALUE, NONE_VALUE) if token.text_span is None else token.text_span for token in tokens ] start_distances = [abs(span[0] - char_start) for span in text_spans] end_distances = [abs(span[1] - char_end) for span in text_spans] min_start_distance, min_end_distance = min(start_distances), min(end_distances) if min_start_distance < DISTANCE_THRESHOLD: answer_start = start_distances.index(min_start_distance) else: answer_start = 0 if min_end_distance < DISTANCE_THRESHOLD: answer_end = end_distances.index(min_end_distance) start_from = answer_end + 1 try: # e.g.) end_distances: [3, 1, 1, 4], min_end_distance = 1 => use 2 index instead of 1 answer_end = end_distances.index(min_end_distance, start_from) except ValueError: pass else: answer_end = 0 return answer_start, answer_end
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/sst.html ================================================ claf.data.reader.bert.sst — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.sst


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:sst_bert") class SSTBertReader(SeqClsBertReader): """ SST DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(SSTBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") if data_type == "train": lines.pop(0) data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[0], self.class_key: str(line_tokens[1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/stsb.html ================================================ claf.data.reader.bert.stsb — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.stsb


import logging

from overrides import overrides

from claf.data.reader import RegressionBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:stsb_bert") class STSBBertReader(RegressionBertReader): """ STS-B (Semantic Textual Similarity Benchmark) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(STSBBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, label_key="score", cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[7], "sequence_b": line_tokens[8], "score": float(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/tok_cls.html ================================================ claf.data.reader.bert.tok_cls — CLaF 0.2.0 documentation

Source code for claf.data.reader.bert.tok_cls


from itertools import chain
import json
import logging
import uuid

from overrides import overrides
from tqdm import tqdm

from claf.data.dataset import TokClsBertDataset
from claf.data.dto import BertFeature, Helper
from claf.data.reader.base import DataReader
from claf.decorator import register
from claf.tokens.tokenizer import WordTokenizer
import claf.data.utils as utils

logger = logging.getLogger(__name__)


[docs]@register("reader:tok_cls_bert") class TokClsBertReader(DataReader): """ DataReader for Token Classification using BERT * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword) * Kwargs: lang_code: language code: set as 'ko' if using BERT model trained with mecab-tokenized data tag_key: name of the label in .json file to use for classification ignore_tag_idx: prediction results that have this number as ground-truth idx are ignored """ def __init__( self, file_paths, tokenizers, lang_code=None, sequence_max_length=None, tag_key="tags", cls_token="[CLS]", sep_token="[SEP]", ignore_tag_idx=-1, ): super(TokClsBertReader, self).__init__(file_paths, TokClsBertDataset) self.sequence_max_length = sequence_max_length self.text_columns = ["bert_input", "sequence"] if "subword" not in tokenizers: raise ValueError("WordTokenizer and SubwordTokenizer is required.") self.subword_tokenizer = tokenizers["subword"] self.sent_tokenizer = tokenizers["sent"] self.word_tokenizer = tokenizers["word"] if lang_code == "ko": self.mecab_tokenizer = WordTokenizer("mecab_ko", self.sent_tokenizer, split_with_regex=False) self.lang_code = lang_code self.tag_key = tag_key self.cls_token = cls_token self.sep_token = sep_token self.ignore_tag_idx = ignore_tag_idx def _get_data(self, file_path): data = self.data_handler.read(file_path) tok_cls_data = json.loads(data) return tok_cls_data["data"] def _get_tag_dicts(self, **kwargs): data = kwargs["data"] if type(data) == dict: tag_idx2text = {tag_idx: tag_text for tag_idx, tag_text in enumerate(data[self.tag_key])} elif type(data) == list: tags = sorted(list(set(chain.from_iterable(d[self.tag_key] for d in data)))) tag_idx2text = {tag_idx: tag_text for tag_idx, tag_text in enumerate(tags)} else: raise ValueError("check _get_data return type.") tag_text2idx = {tag_text: tag_idx for tag_idx, tag_text in tag_idx2text.items()} return tag_idx2text, tag_text2idx @overrides def _read(self, file_path, data_type=None): """ .json file structure should be something like this: { "data": [ { "sequence": "i'm looking for a flight from New York to London.", "slots": ["O", "O", "O", "O", "O", "O", "B-city.dept", "I-city.dept" "O", "B-city.dest"] // the number of tokens in sequence.split() and tags must match }, ... ], "slots": [ // tag_key "O", // tags should be in IOB format "B-city.dept", "I-city.dept", "B-city.dest", "I-city.dest", ... ] } """ data = self._get_data(file_path) tag_idx2text, tag_text2idx = self._get_tag_dicts(data=data) helper = Helper(**{ "file_path": file_path, "tag_idx2text": tag_idx2text, "ignore_tag_idx": self.ignore_tag_idx, "cls_token": self.cls_token, "sep_token": self.sep_token, }) helper.set_model_parameter({ "num_tags": len(tag_idx2text), "ignore_tag_idx": self.ignore_tag_idx, }) helper.set_predict_helper({ "tag_idx2text": tag_idx2text, }) features, labels = [], [] for example in tqdm(data, desc=data_type): sequence_text = example["sequence"].strip().replace("\n", "") sequence_tokens = self.word_tokenizer.tokenize(sequence_text) naive_tokens = sequence_text.split() is_head_word = utils.get_is_head_of_word(naive_tokens, sequence_tokens) sequence_sub_tokens = [] tagged_sub_token_idxs = [] curr_sub_token_idx = 1 # skip CLS_TOKEN for token_idx, token in enumerate(sequence_tokens): for sub_token_pos, sub_token in enumerate( self.subword_tokenizer.tokenize(token, unit="word") ): sequence_sub_tokens.append(sub_token) if is_head_word[token_idx] and sub_token_pos == 0: tagged_sub_token_idxs.append(curr_sub_token_idx) curr_sub_token_idx += 1 bert_input = [self.cls_token] + sequence_sub_tokens + [self.sep_token] if ( self.sequence_max_length is not None and data_type == "train" and len(bert_input) > self.sequence_max_length ): continue if "uid" in example: data_uid = example["uid"] else: data_uid = str(uuid.uuid1()) tag_texts = example[self.tag_key] tag_idxs = [tag_text2idx[tag_text] for tag_text in tag_texts] utils.sanity_check_iob(naive_tokens, tag_texts) assert len(naive_tokens) == len(tagged_sub_token_idxs), \ f"""Wrong tagged_sub_token_idxs: followings mismatch. naive_tokens: {naive_tokens} sequence_sub_tokens: {sequence_sub_tokens} tagged_sub_token_idxs: {tagged_sub_token_idxs}""" feature_row = { "id": data_uid, "bert_input": bert_input, "tagged_sub_token_idxs": tagged_sub_token_idxs, "num_tokens": len(naive_tokens), } features.append(feature_row) label_row = { "id": data_uid, "tag_idxs": tag_idxs, "tag_texts": tag_texts, } labels.append(label_row) helper.set_example(data_uid, { "sequence": sequence_text, "sequence_sub_tokens": sequence_sub_tokens, "tag_idxs": tag_idxs, "tag_texts": tag_texts, }) return utils.make_batch(features, labels), helper.to_dict()
[docs] def read_one_example(self, inputs): """ inputs keys: sequence """ sequence_text = inputs["sequence"].strip().replace("\n", "") sequence_tokens = self.word_tokenizer.tokenize(sequence_text) naive_tokens = sequence_text.split() is_head_word = utils.get_is_head_of_word(naive_tokens, sequence_tokens) sequence_sub_tokens = [] tagged_sub_token_idxs = [] curr_sub_token_idx = 1 # skip CLS_TOKEN for token_idx, token in enumerate(sequence_tokens): for sub_token_pos, sub_token in enumerate( self.subword_tokenizer.tokenize(token, unit="word") ): sequence_sub_tokens.append(sub_token) if is_head_word[token_idx] and sub_token_pos == 0: tagged_sub_token_idxs.append(curr_sub_token_idx) curr_sub_token_idx += 1 if len(sequence_sub_tokens) > self.sequence_max_length: sequence_sub_tokens = sequence_sub_tokens[:self.sequence_max_length] bert_input = [self.cls_token] + sequence_sub_tokens + [self.sep_token] assert len(naive_tokens) == len(tagged_sub_token_idxs), \ f"""Wrong tagged_sub_token_idxs: followings mismatch. naive_tokens: {naive_tokens} sequence_sub_tokens: {sequence_sub_tokens} tagged_sub_token_idxs: {tagged_sub_token_idxs}""" bert_feature = BertFeature() bert_feature.set_input(bert_input) bert_feature.set_feature("tagged_sub_token_idxs", tagged_sub_token_idxs) bert_feature.set_feature("num_tokens", len(naive_tokens)) features = [bert_feature.to_dict()] helper = {} return features, helper
================================================ FILE: docs/_build/html/_modules/claf/data/reader/bert/wnli.html ================================================ claf.data.reader.bert.wnli — CLaF 0.1.6 documentation

Source code for claf.data.reader.bert.wnli


import logging

from overrides import overrides

from claf.data.reader import SeqClsBertReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:wnli_bert") class WNLIBertReader(SeqClsBertReader): """ WNLI (Winograd NLI) DataReader for BERT * Args: file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config """ CLASS_DATA = [0, 1] def __init__( self, file_paths, tokenizers, sequence_max_length=None, cls_token="[CLS]", sep_token="[SEP]", input_type="bert", is_test=False, ): super(WNLIBertReader, self).__init__( file_paths, tokenizers, sequence_max_length, class_key=None, cls_token=cls_token, sep_token=sep_token, input_type=input_type, is_test=is_test, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") data = [] for i, line in enumerate(lines): if i == 0: continue line_tokens = line.split("\t") if len(line_tokens) <= 1: continue data.append({ "uid": f"{data_type}-{i}", "sequence_a": line_tokens[1], "sequence_b": line_tokens[2], self.class_key: str(line_tokens[-1]), }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/cola.html ================================================ claf.data.reader.cola — CLaF 0.2.0 documentation

Source code for claf.data.reader.cola


import logging

from overrides import overrides

from claf.data.reader import SeqClsReader
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:cola") class CoLAReader(SeqClsReader): """ CoLA DataReader * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (word) """ CLASS_DATA = [0, 1] def __init__( self, file_paths, tokenizers, sequence_max_length=None, ): super(CoLAReader, self).__init__( file_paths, tokenizers, sequence_max_length=sequence_max_length, ) @overrides def _get_data(self, file_path, **kwargs): data_type = kwargs["data_type"] _file = self.data_handler.read(file_path) lines = _file.split("\n") if data_type == "train": lines.pop(0) data = [] for i, line in enumerate(lines): line_tokens = line.split("\t") if len(line_tokens) > 1: data.append({ "uid": f"{data_type}-{i}", "sequence": line_tokens[1] if data_type == "test" else line_tokens[3], self.class_key: str(0) if data_type == "test" else str(line_tokens[1]) }) return data
================================================ FILE: docs/_build/html/_modules/claf/data/reader/seq_cls.html ================================================ claf.data.reader.seq_cls — CLaF 0.2.0 documentation

Source code for claf.data.reader.seq_cls


import json
import logging
import uuid

from overrides import overrides
from tqdm import tqdm

from claf.data.dataset.seq_cls import SeqClsDataset
from claf.data.dto import Helper
from claf.data.reader.base import DataReader
from claf.data import utils
from claf.decorator import register

logger = logging.getLogger(__name__)


[docs]@register("reader:seq_cls") class SeqClsReader(DataReader): """ DataReader for Sequence Classification * Args: file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (word) * Kwargs: class_key: name of the label in .json file to use for classification """ CLASS_DATA = None def __init__(self, file_paths, tokenizers, sequence_max_length=None, class_key="class"): super(SeqClsReader, self).__init__(file_paths, SeqClsDataset) self.sequence_max_length = sequence_max_length self.text_columns = ["sequence"] if "word" not in tokenizers: raise ValueError("WordTokenizer is required. define WordTokenizer") self.word_tokenizer = tokenizers["word"] self.class_key = class_key def _get_data(self, file_path, **kwargs): data = self.data_handler.read(file_path) seq_cls_data = json.loads(data) return seq_cls_data["data"] def _get_class_dicts(self, **kwargs): seq_cls_data = kwargs["data"] if self.class_key is None: class_data = self.CLASS_DATA else: class_data = [item[self.class_key] for item in seq_cls_data] class_data = list(set(class_data)) # remove duplicate class_idx2text = { class_idx: str(class_text) for class_idx, class_text in enumerate(class_data) } class_text2idx = {class_text: class_idx for class_idx, class_text in class_idx2text.items()} return class_idx2text, class_text2idx @overrides def _read(self, file_path, data_type=None): """ .json file structure should be something like this: { "data": [ { "sequence": "what a wonderful day!", "emotion": "happy" }, ... ], "emotion": [ // class_key "angry", "happy", "sad", ... ] } """ data = self._get_data(file_path, data_type=data_type) class_idx2text, class_text2idx = self._get_class_dicts(data=data) helper = Helper(**{ "file_path": file_path, "class_idx2text": class_idx2text, "class_text2idx": class_text2idx, }) helper.set_model_parameter({ "num_classes": len(class_idx2text), }) helper.set_predict_helper({ "class_idx2text": class_idx2text, }) features, labels = [], [] for example in tqdm(data, desc=data_type): sequence = example["sequence"].strip().replace("\n", "") sequence_words = self.word_tokenizer.tokenize(sequence) if ( self.sequence_max_length is not None and data_type == "train" and len(sequence_words) > self.sequence_max_length ): continue if "uid" in example: data_uid = example["uid"] else: data_uid = str(uuid.uuid1()) feature_row = { "id": data_uid, "sequence": sequence, } features.append(feature_row) class_text = example[self.class_key] label_row = { "id": data_uid, "class_idx": class_text2idx[class_text], "class_text": class_text, } labels.append(label_row) helper.set_example(data_uid, { "sequence": sequence, "class_idx": class_text2idx[class_text], "class_text": class_text, }) return utils.make_batch(features, labels), helper.to_dict()
[docs] def read_one_example(self, inputs): """ inputs keys: sequence """ sequence = inputs["sequence"].strip().replace("\n", "") inputs["sequence"] = sequence return inputs, {}
================================================ FILE: docs/_build/html/_modules/claf/data/reader/squad.html ================================================ claf.data.reader.squad — CLaF 0.2.0 documentation

Source code for claf.data.reader.squad


from collections import Counter
import json
import logging
import re

from overrides import overrides
from tqdm import tqdm

from claf.data.dataset import SQuADDataset
from claf.data.dto import Helper
from claf.data.reader.base import DataReader
from claf.data import utils
from claf.decorator import register
from claf.metric.squad_v1_official import normalize_answer

logger = logging.getLogger(__name__)


[docs]@register("reader:squad") class SQuADReader(DataReader): """ SQuAD DataReader * Args: file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word) """ def __init__(self, file_paths, lang_code, tokenizers, context_max_length=None): super(SQuADReader, self).__init__(file_paths, SQuADDataset) self.lang_code = lang_code self.context_max_length = context_max_length self.text_columns = ["context", "question"] if "word" not in tokenizers: raise ValueError("WordTokenizer is required. define English WordTokenizer") self.word_tokenizer = tokenizers["word"] @overrides def _read(self, file_path, data_type=None): tokenized_error_count = 0 data = self.data_handler.read(file_path) squad = json.loads(data) if "data" in squad: squad = squad["data"] helper = Helper(**{ "file_path": file_path, "raw_dataset": squad, }) helper.set_model_parameter({ "lang_code": self.lang_code, }) features, labels = [], [] for article in tqdm(squad, desc=data_type): for paragraph in article["paragraphs"]: context = paragraph["context"].replace("``", '" ').replace("''", '" ') context_words = self.word_tokenizer.tokenize(context) if ( self.context_max_length is not None and data_type == "train" and len(context_words) > self.context_max_length ): continue for qa in paragraph["qas"]: question = qa["question"].strip().replace("\n", "") id_ = qa["id"] answer_texts, answer_indices = [], [] if qa.get("is_impossible", None): answers = qa["plausible_answers"] answerable = 0 else: answers = qa["answers"] answerable = 1 for answer in answers: answer_start = answer["answer_start"] answer_end = answer_start + len(answer["text"]) answer_texts.append(answer["text"]) answer_indices.append((answer_start, answer_end)) feature_row = { "context": self._clean_text(context), "question": question, } features.append(feature_row) if len(answer_indices) > 0: answer_start, answer_end = self._find_one_most_common(answer_indices) text_spans = self._convert_to_spans(context, context_words) word_idxs = self._get_word_span_idxs(text_spans, answer_start, answer_end) word_answer_start = word_idxs[0] word_answer_end = word_idxs[-1] # To check rebuild answer: char_answer_text - word_answer_text char_answer_text = context[answer_start:answer_end] word_answer_text = context[ text_spans[word_answer_start][0] : text_spans[word_answer_end][1] ] if not self._is_rebuild(char_answer_text, word_answer_text): logger.warning(f"word_tokenized_error: {char_answer_text} ### {word_answer_text}") tokenized_error_count += 1 else: # Unanswerable answers = ["<noanswer>"] text_spans = [] answer_start, answer_end = 0, 0 word_answer_start, word_answer_end = 0, 0 label_row = { "id": id_, "answer_start": word_answer_start, "answer_end": word_answer_end, "answerable": answerable, } labels.append(label_row) helper.set_example(id_, { "context": context, "text_span": text_spans, "question": question, "answers": answer_texts, }) logger.info(f"tokenized_error_count: {tokenized_error_count} ") return utils.make_batch(features, labels), helper.to_dict()
[docs] @overrides def read_one_example(self, inputs): """ inputs keys: question, context """ context_text = inputs["context"] tokenized_context = self.word_tokenizer.tokenize(context_text) question_text = inputs["question"].strip().replace("\n", "") features = {} features["context"] = self._clean_text(context_text) features["question"] = self._clean_text(question_text) helper = { "text_span": self._convert_to_spans(context_text, tokenized_context), "tokenized_context": tokenized_context, "token_key": "tokenized_context" # for 1-example inference latency key } return features, helper
def _clean_text(self, text): # https://github.com/allenai/document-qa/blob/2f9fa6878b60ed8a8a31bcf03f802cde292fe48b/docqa/data_processing/text_utils.py#L124 # be consistent with quotes, and replace \u2014 and \u2212 which I have seen being mapped to UNK # by glove word vecs return ( text.replace("''", '"') .replace("``", '"') .replace("\u2212", "-") .replace("\u2014", "\u2013") ) def _find_one_most_common(self, answers): answer_counter = Counter(answers) value = answer_counter.most_common(1)[0][0] return value[0], value[1] def _convert_to_spans(self, raw_text, tokenized_text): """ Convert a tokenized version of `raw_text` into a series character spans referencing the `raw_text` """ double_quote_re = re.compile("\"|``|''") curr_idx = 0 spans = [] for token in tokenized_text: # Tokenizer might transform double quotes, for this case search over several # possible encodings if double_quote_re.match(token): span = double_quote_re.search(raw_text[curr_idx:]) temp = curr_idx + span.start() token_length = span.end() - span.start() else: temp = raw_text.find(token, curr_idx) token_length = len(token) if temp < curr_idx: raise ValueError(f"{raw_text} \n{tokenized_text} \n{token}") curr_idx = temp spans.append((curr_idx, curr_idx + token_length)) curr_idx += token_length return spans def _get_word_span_idxs(self, spans, start, end): idxs = [] for word_ix, (s, e) in enumerate(spans): if e > start: if s < end: idxs.append(word_ix) else: break return idxs def _is_rebuild(self, char_answer_text, word_answer_text): norm_char_answer_text = normalize_answer(char_answer_text) norm_word_answer_text = normalize_answer(word_answer_text) if norm_char_answer_text != norm_word_answer_text: return False else: return True
================================================ FILE: docs/_build/html/_modules/claf/data/reader/wikisql.html ================================================ claf.data.reader.wikisql — CLaF 0.2.0 documentation

Source code for claf.data.reader.wikisql


import json
import logging
from pathlib import Path
import uuid

from overrides import overrides
from tqdm import tqdm

from claf.data.dataset import WikiSQLDataset
from claf.data.dto import Helper
from claf.data.reader.base import DataReader
from claf.data import utils
from claf.decorator import register
from claf.metric.wikisql_lib.dbengine import DBEngine
from claf.metric.wikisql_lib.query import Query

logger = logging.getLogger(__name__)


[docs]@register("reader:wikisql") class WikiSQLReader(DataReader): """ WikiSQL DataReader (http://arxiv.org/abs/1709.00103) * Args: file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word) """ def __init__(self, file_paths, tokenizers, context_max_length=None, is_test=None): super(WikiSQLReader, self).__init__(file_paths, WikiSQLDataset) self.is_test = is_test self.text_columns = ["column", "question"] if "word" not in tokenizers: raise ValueError("WordTokenizer is required. define English WordTokenizer") self.word_tokenizer = tokenizers["word"] self.dbengine = None @overrides def _read(self, file_path, data_type=None): file_path = self.data_handler.read(file_path, return_path=True) file_path = Path(file_path) data_dir = file_path.parent file_name = file_path.stem db_path = data_dir / f"{file_name}.db" table_path = data_dir / f"{file_name}.tables.jsonl" self.dbengine = DBEngine(db_path) helper = Helper(**{ "file_path": file_path, "db_path": db_path, }) features, labels = [], [] sql_datas, table_data = self.load_data(file_path, table_path, data_type=data_type) for sql_data in tqdm(sql_datas, desc=data_type): question = sql_data["question"] table_id = sql_data["table_id"] column_headers = table_data[table_id]["header"] feature_row = {"column": column_headers, "question": question} data_uid = str(uuid.uuid1()) conditions_value_position = self.get_coditions_value_position( sql_data["question"], [x[2] for x in sql_data["sql"]["conds"]] ) sql_query = Query.from_dict(sql_data["sql"], ordered=True) execution_result = self.dbengine.execute_query(table_id, sql_query, lower=True) label_row = { "id": data_uid, "table_id": table_id, "tokenized_question": self.word_tokenizer.tokenize(question), "aggregator_idx": sql_data["sql"]["agg"], "select_column_idx": sql_data["sql"]["sel"], "conditions_num": len(sql_data["sql"]["conds"]), "conditions_column_idx": [x[0] for x in sql_data["sql"]["conds"]], "conditions_operator_idx": [x[1] for x in sql_data["sql"]["conds"]], "conditions_value_string": [str(x[2]) for x in sql_data["sql"]["conds"]], "conditions_value_position": conditions_value_position, "sql_query": sql_query, "execution_result": execution_result, } features.append(feature_row) labels.append(label_row) helper.set_example(data_uid, { "question": question, "sql_query": sql_query, "execution_result": execution_result, }) if self.is_test and len(labels) == 10: break return utils.make_batch(features, labels), helper.to_dict()
[docs] @overrides def read_one_example(self, inputs): """ inputs keys: question, column, db_path, table_id """ question_text = inputs["question"] helper = {"tokenized_question": self.word_tokenizer.tokenize(question_text)} return inputs, helper
[docs] def load_data(self, sql_path, table_path, data_type=None): sql_data = [] table_data = {} logger.info(f"Loading data from {sql_path}") with open(sql_path) as inf: for line in tqdm(inf, desc=f"sql_{data_type}"): sql = json.loads(line.strip()) sql_data.append(sql) logger.info(f"Loading data from {table_path}") with open(table_path) as inf: for line in tqdm(inf, desc=f"table_{data_type}"): tab = json.loads(line.strip()) table_data[tab["id"]] = tab for sql in sql_data: assert sql["table_id"] in table_data return sql_data, table_data
[docs] def get_coditions_value_position(self, question, values): tokenized_question = self.word_tokenizer.tokenize(question.lower()) tokenized_values = [self.word_tokenizer.tokenize(str(value).lower()) for value in values] START_TOKEN, END_TOKEN = "<BEG>", "<END>" token_to_index = {START_TOKEN: 0} for token in tokenized_question: token_to_index[token] = len(token_to_index) token_to_index[END_TOKEN] = len(token_to_index) position_tokens = [] for value in tokenized_values: position_token = [token_to_index[START_TOKEN]] for token in value: if token in token_to_index: position_token.append(token_to_index[token]) else: for i in range(len(tokenized_question)): q_token = tokenized_question[i] if token in q_token: position_token.append(token_to_index[q_token]) position_token.append(token_to_index[END_TOKEN]) assert len(position_token) != 2 position_tokens.append(position_token) return position_tokens
================================================ FILE: docs/_build/html/_modules/claf/data/utils.html ================================================ claf.data.utils — CLaF 0.2.0 documentation

Source code for claf.data.utils


from collections import defaultdict

import numpy as np
import torch

from claf.data.dto.batch import Batch


[docs]def make_batch(features, labels): return Batch(**{"features": features, "labels": labels})
[docs]def make_bert_input( sequence_a, sequence_b, bert_tokenizer, max_seq_length=128, data_type="train", cls_token="[CLS]", sep_token="[SEP]", input_type="bert", ): sequence_a_tokens = bert_tokenizer.tokenize(sequence_a) bert_input = [cls_token] + sequence_a_tokens + [sep_token] if sequence_b: if input_type == "roberta": bert_input += [sep_token] sequence_b_tokens = bert_tokenizer.tokenize(sequence_b) bert_input += sequence_b_tokens + [sep_token] if len(bert_input) > max_seq_length: if data_type == "train": return None # for skip else: return bert_input[:max_seq_length-1] + [sep_token] return bert_input
[docs]def make_bert_token_types(bert_inputs, SEP_token="[SEP]"): """ Bert Inputs segment_ids ex) [CLS] hi [SEP] he ##llo [SEP] => 0 0 0 1 1 1 * Args: bert_inputs: feature dictionary consisting of - text: text from data_reader - token_name: text converted to corresponding token_type * Kwargs: SEP_token: SEP special token for BERT """ feature_keys = list(bert_inputs[0].keys()) # TODO: hard-code if "text" in feature_keys: feature_keys.remove("text") feature_key = feature_keys[0] token_types = [] for bert_input in bert_inputs: token_type = make_bert_token_type(bert_input["text"], SEP_token=SEP_token) token_types.append({feature_key: token_type}) return token_types
[docs]def make_bert_token_type(bert_input_text, SEP_token="[SEP]"): SEP_index = bert_input_text.index(SEP_token) + 1 token_type = [0] * SEP_index token_type += [1] * (len(bert_input_text) - SEP_index) assert len(token_type) == len(bert_input_text) return token_type
[docs]def padding_tokens(tokens, max_len=None, token_name=None, pad_value=0): """ Padding tokens according to token's dimension """ def _pad_tokens(seqs, maxlen, pad_id=0): lens = [len(seq) for seq in seqs] if pad_id == 0: padded_seqs = torch.zeros(len(seqs), maxlen).long() else: padded_seqs = torch.ones(len(seqs), maxlen).long() * pad_id for i, seq in enumerate(seqs): if type(seq[0]) == dict: pass else: seq = [int(s) for s in seq] end = lens[i] padded_seqs[i, :end] = torch.LongTensor(seq) return padded_seqs def _pad_char_tokens(seqs, seq_maxlen, char_minlen=10, char_maxlen=None, pad_value=0): if char_maxlen is None: char_maxlen = max([len(chars) for seq in seqs for chars in seq]) if char_maxlen < char_minlen: char_maxlen = char_minlen padded_chars = torch.zeros(len(seqs), seq_maxlen, char_maxlen).long() for i in range(len(seqs)): char_tokens = _pad_with_value(seqs[i], seq_maxlen, pad_value=[[pad_value]]) padded_chars[i] = _pad_tokens(char_tokens, char_maxlen, pad_id=pad_value) return padded_chars def _pad_with_value(data, size, pad_value=[0]): if type(pad_value) != list: raise ValueError("pad_value data type is list.") return data + pad_value * (size - len(data)) token_dim = get_token_dim(tokens) if token_dim > 1 and max_len is None: max_len = max(len(token) for token in tokens) if token_dim == 2: # word return _pad_tokens(tokens, max_len, pad_id=pad_value) elif token_dim == 3: # char if token_name == "elmo": return _pad_char_tokens( tokens, max_len, char_maxlen=50, pad_value=261, ) # 260: padding_character, +1 for mask elif token_name == "char": return _pad_char_tokens(tokens, max_len, char_minlen=10, pad_value=pad_value) else: return _pad_char_tokens(tokens, max_len, char_minlen=1, pad_value=pad_value) else: return tokens
[docs]def get_sequence_a(example): if "sequence" in example: return example["sequence"] elif "sequence_a" in example: return example["sequence_a"] else: raise ValueError("'sequence' or 'sequence_a' key is required.")
[docs]def get_token_dim(tokens, dim=0): if type(tokens) == torch.Tensor: dim = tokens.dim() if tokens.size(-1) > 1: dim += 1 return dim if type(tokens) == np.ndarray: dim = tokens.ndim if tokens.shape[-1] > 1: dim += 1 return dim if type(tokens) == list or type(tokens) == tuple: dim = get_token_dim(tokens[0], dim + 1) return dim
[docs]def get_token_type(tokens): token = tokens[0] while isinstance(token, np.ndarray) and isinstance(token, list): token = token[0] return type(token)
[docs]def is_lazy(tokens): if type(tokens) == list: tokens = tokens[0] if callable(tokens): return True else: return False
[docs]def transpose(list_of_dict, skip_keys=[]): if type(skip_keys) != list: raise ValueError(f"skip_keys type must be list. not {type(skip_keys)}") dict_of_list = defaultdict(lambda: []) for dic in list_of_dict: for key, value in dic.items(): if key in skip_keys: continue dict_of_list[key].append(value) return dict_of_list
[docs]def sanity_check_iob(naive_tokens, tag_texts): """ Check if the IOB tags are valid. * Args: naive_tokens: tokens split by .split() tag_texts: list of tags in IOB format """ def prefix(tag): if tag == "O": return tag return tag.split("-")[0] def body(tag): if tag == "O": return None return tag.split("-")[1] # same number check assert len(naive_tokens) == len(tag_texts), \ f"""Number of tokens and tags doest not match. original tokens: {naive_tokens} tags: {tag_texts}""" # IOB format check prev_tag = None for tag_text in tag_texts: curr_tag = tag_text if prev_tag is None: # first tag assert prefix(curr_tag) in ["B", "O"], \ f"""Wrong tag: first tag starts with I. tag: {curr_tag}""""" else: # following tags if prefix(prev_tag) in ["B", "I"]: assert ( (prefix(curr_tag) == "I" and body(curr_tag) == body(prev_tag)) or (prefix(curr_tag) == "B") or (prefix(curr_tag) == "O") ), f"""Wrong tag: following tag mismatch. previous tag: {prev_tag} current tag: {curr_tag}""" elif prefix(prev_tag) in ["O"]: assert prefix(curr_tag) in ["B", "O"], \ f"""Wrong tag: following tag mismatch. previous tag: {prev_tag} current tag: {curr_tag}""" else: raise RuntimeError(f"Encountered unknown tag: {prev_tag}.") prev_tag = curr_tag
[docs]def get_is_head_of_word(naive_tokens, sequence_tokens): """ Return a list of flags whether the token is head(prefix) of naively split tokens ex) naive_tokens: ["hello.", "how", "are", "you?"] sequence_tokens: ["hello", ".", "how", "are", "you", "?"] => [1, 0, 1, 1, 1, 0] * Args: naive_tokens: a list of tokens, naively split by whitespace sequence_tokens: a list of tokens, split by 'word_tokenizer' * Returns: is_head_of_word: a list with its length the same as that of 'sequence_tokens'. has 1 if the tokenized word at the position is head(prefix) of a `naive_token` and 0 if otherwise. """ is_head_of_word = [] for naive_token in naive_tokens: consumed_chars = 0 consumed_words = 0 for sequence_token in sequence_tokens: if naive_token[consumed_chars:].startswith(sequence_token): is_head_of_word.append(0 if consumed_chars else 1) consumed_chars += len(sequence_token) consumed_words += 1 else: break sequence_tokens = sequence_tokens[consumed_words:] return is_head_of_word
================================================ FILE: docs/_build/html/_modules/claf/decorator/arguments.html ================================================ claf.decorator.arguments — CLaF 0.2.0 documentation

Source code for claf.decorator.arguments

[docs]class arguments_required: """ Decorator Class check required arguments for predict function (eg. @arguments_required(["db_path", "table_id"])) """ def __init__(self, required_fields): self.required_fields = required_fields def __call__(self, fn): def wrapper(*args, **kwargs): arguments = args[2] for item in self.required_fields: if arguments.get(item, None) is None: raise ValueError(f"--{item} is required argument.") return fn(*args, **kwargs) return wrapper
================================================ FILE: docs/_build/html/_modules/claf/decorator/register.html ================================================ claf.decorator.register — CLaF 0.2.0 documentation

Source code for claf.decorator.register


from claf.config.registry import Registry


[docs]class register: """ Decorator Class register subclass with decorator. (eg. @register("model:bidaf"), @register("reader:squad") ) """ def __init__(self, name): self.name = name def __call__(self, obj): registry = Registry() registry.add(self.name, obj) return obj
================================================ FILE: docs/_build/html/_modules/claf/learn/experiment.html ================================================ claf.learn.experiment — CLaF 0.2.0 documentation

Source code for claf.learn.experiment


import atexit
import logging
from pathlib import Path

import torch

from claf import nsml
from claf.config.factory import (
    DataReaderFactory,
    DataLoaderFactory,
    TokenMakersFactory,
    ModelFactory,
    OptimizerFactory,
)
from claf import utils as common_utils
from claf.config.args import NestedNamespace
from claf.config.utils import convert_config2dict, pretty_json_dumps, set_global_seed
from claf.tokens.text_handler import TextHandler
from claf.learn.mode import Mode
from claf.learn.trainer import Trainer
from claf.learn import utils


logger = logging.getLogger(__name__)


[docs]class Experiment: """ Experiment settings with config. * Args: mode: Mode (ex. TRAIN, EVAL, INFER_EVAL, PREDICT) config: (NestedNamespace) Argument config according to mode """ def __init__(self, mode, config): common_utils.set_logging_config(mode, config) self.argument = ( config ) # self.config (experiment overall config) / config (argument according to mode) self.config = config self.mode = mode self.common_setting(mode, config) if mode != Mode.TRAIN: # evaluate and predict self.load_setting() # Set evaluation config if mode.endswith(Mode.EVAL): self.config.data_reader.train_file_path = "" self.config.data_reader.valid_file_path = self.argument.data_file_path self.config.cuda_devices = self.argument.cuda_devices self.config.iterator.cuda_devices = self.argument.cuda_devices if getattr(self.argument, "inference_latency", None): self.config.max_latency = self.argument.inference_latency self.predict_settings = None
[docs] def common_setting(self, mode, config): """ Common Setting - experiment config, use_gpu and cuda_device_ids """ self.config_dict = convert_config2dict(config) cuda_devices = self._get_cuda_devices() self.config.cuda_devices = cuda_devices self.config.slack_url = getattr(self.config, "slack_url", False)
def _get_cuda_devices(self): if getattr(self.config, "use_gpu", None) is None: self.config.use_gpu = torch.cuda.is_available() or nsml.IS_ON_NSML if self.config.use_gpu: if nsml.IS_ON_NSML: return list(range(self.config.gpu_num)) else: return self.config.cuda_devices else: return None
[docs] def load_setting(self): """ Load Setting - need to load checkpoint case (ex. evaluate and predict) """ cuda_devices = self.argument.cuda_devices checkpoint_path = self.argument.checkpoint_path prev_cuda_device_id = getattr(self.argument, "prev_cuda_device_id", None) self.model_checkpoint = self._read_checkpoint( cuda_devices, checkpoint_path, prev_cuda_device_id=prev_cuda_device_id ) self._set_saved_config(cuda_devices)
def _read_checkpoint(self, cuda_devices, checkpoint_path, prev_cuda_device_id=None): if cuda_devices == "cpu": return torch.load(checkpoint_path, map_location="cpu") # use CPU if torch.cuda.is_available(): checkpoint = torch.load( checkpoint_path, map_location={ f"cuda:{prev_cuda_device_id}": f"cuda:{cuda_devices[0]}" }, # different cuda_device id case (save/load) ) else: checkpoint = torch.load(checkpoint_path, map_location="cpu") # use CPU return checkpoint def _set_saved_config(self, cuda_devices): saved_config_dict = self.model_checkpoint["config"] self.config_dict = saved_config_dict logger.info("Load saved_config ...") logger.info(pretty_json_dumps(saved_config_dict)) saved_config = NestedNamespace() saved_config.load_from_json(saved_config_dict) is_use_gpu = self.config.use_gpu self.config = saved_config self.config.use_gpu = is_use_gpu self.config.cuda_devices = cuda_devices def __call__(self): """ Run Trainer """ set_global_seed(self.config.seed_num) # For Reproducible if self.mode == Mode.TRAIN: # exit trigger slack notification if self.config.slack_url: atexit.register(utils.send_message_to_slack) train_loader, valid_loader, optimizer = self.set_train_mode() assert train_loader is not None assert optimizer is not None if valid_loader is None: self.trainer.train(train_loader, optimizer) else: self.trainer.train_and_evaluate(train_loader, valid_loader, optimizer) self._summary_experiments() elif self.mode == Mode.EVAL: valid_loader = self.set_eval_mode() assert valid_loader is not None return self.trainer.evaluate(valid_loader) elif self.mode == Mode.INFER_EVAL: raw_examples, raw_to_tensor_fn = self.set_eval_inference_latency_mode() assert raw_examples is not None assert raw_to_tensor_fn is not None return self.trainer.evaluate_inference_latency(raw_examples, raw_to_tensor_fn, max_latency=self.config.max_latency) elif self.mode.endswith(Mode.PREDICT): raw_features, raw_to_tensor_fn, arguments = self.set_predict_mode() assert raw_features is not None assert raw_to_tensor_fn is not None return self.trainer.predict( raw_features, raw_to_tensor_fn, arguments, interactive=arguments.get("interactive", False), ) else: raise ValueError(f"unknown mode: {self.mode}")
[docs] def set_train_mode(self): """ Training Mode - Pipeline 1. read raw_data (DataReader) 2. build vocabs (DataReader, Token) 3. indexing tokens (DataReader, Token) 4. convert to DataSet (DataReader) 5. create DataLoader (DataLoader) 6. define model and optimizer 7. run! """ logger.info("Config. \n" + pretty_json_dumps(self.config_dict) + "\n") data_reader, token_makers = self._create_data_and_token_makers() datas, helpers = data_reader.read() # Token & Vocab text_handler = TextHandler(token_makers, lazy_indexing=True) if text_handler.is_all_vocab_use_pretrained(): token_counters = token_makers else: texts = data_reader.filter_texts(datas) token_counters = text_handler.make_token_counters(texts, config=self.config) vocabs = text_handler.build_vocabs(token_counters) text_handler.index(datas, data_reader.text_columns) # iterator vocab = vocabs[next(iter(vocabs))] datasets = data_reader.convert_to_dataset(datas, vocab, helpers=helpers) # with name self.config.iterator.cuda_devices = self.config.cuda_devices train_loader, valid_loader, test_loader = self._create_by_factory( DataLoaderFactory, self.config.iterator, param={"datasets": datasets} ) # calculate 'num_train_steps' num_train_steps = self._get_num_train_steps(train_loader) self.config.optimizer.num_train_steps = num_train_steps checkpoint_dir = Path(self.config.trainer.log_dir) / "checkpoint" checkpoints = None if checkpoint_dir.exists(): checkpoints = self._load_exist_checkpoints(checkpoint_dir) # contain model and optimizer if checkpoints is None: model = self._create_model(token_makers, helpers=helpers) op_dict = self._create_by_factory( OptimizerFactory, self.config.optimizer, param={"model": model} ) else: model = self._create_model(token_makers, checkpoint=checkpoints) op_dict = self._create_by_factory( OptimizerFactory, self.config.optimizer, param={"model": model} ) utils.load_optimizer_checkpoint(op_dict["optimizer"], checkpoints) self.set_trainer(model, op_dict=op_dict) return train_loader, valid_loader, op_dict["optimizer"]
def _create_data_and_token_makers(self): token_makers = self._create_by_factory(TokenMakersFactory, self.config.token) tokenizers = token_makers["tokenizers"] del token_makers["tokenizers"] self.config.data_reader.tokenizers = tokenizers data_reader = self._create_by_factory(DataReaderFactory, self.config.data_reader) return data_reader, token_makers def _create_by_factory(self, factory, item_config, param={}): return factory(item_config).create(**param) def _get_num_train_steps(self, train_loader): train_set_size = len(train_loader.dataset) batch_size = self.config.iterator.batch_size gradient_accumulation_steps = getattr(self.config.optimizer, "gradient_accumulation_steps", 1) num_epochs = self.config.trainer.num_epochs one_epoch_steps = int(train_set_size / batch_size / gradient_accumulation_steps) if one_epoch_steps == 0: one_epoch_steps = 1 num_train_steps = one_epoch_steps * num_epochs return num_train_steps def _load_exist_checkpoints(self, checkpoint_dir): # pragma: no cover checkpoints = utils.get_sorted_path(checkpoint_dir, both_exist=True) train_counts = list(checkpoints.keys()) if not train_counts: return None seperator = "-" * 50 message = f"{seperator}\n !! Find exist checkpoints {train_counts}.\n If you want to recover, input train_count in list.\n If you don't want to recover, input 0.\n{seperator}" selected_train_count = common_utils.get_user_input(message) if selected_train_count == 0: return None model_path = checkpoints[selected_train_count]["model"] model_checkpoint = self._read_checkpoint(self.config.cuda_devices, model_path) optimizer_path = checkpoints[selected_train_count]["optimizer"] optimizer_checkpoint = self._read_checkpoint("cpu", optimizer_path) checkpoints = {} checkpoints.update(model_checkpoint) checkpoints.update(optimizer_checkpoint) return checkpoints def _create_model(self, token_makers, checkpoint=None, helpers=None): if checkpoint is None: assert helpers is not None first_key = next(iter(helpers)) helper = helpers[first_key] # get first helper model_init_params = helper.get("model", {}) predict_helper = helper.get("predict_helper", {}) else: model_init_params = checkpoint.get("init_params", {}) predict_helper = checkpoint.get("predict_helper", {}) model_params = {"token_makers": token_makers} model_params.update(model_init_params) model = self._create_by_factory( ModelFactory, self.config.model, param=model_params ) # Save params model.init_params = model_init_params model.predict_helper = predict_helper if checkpoint is not None: model = utils.load_model_checkpoint(model, checkpoint) model = self._set_gpu_env(model) return model def _set_gpu_env(self, model): if self.config.use_gpu: cuda_devices = self._get_cuda_devices() num_gpu = len(cuda_devices) use_multi_gpu = num_gpu > 1 if use_multi_gpu: model = torch.nn.DataParallel(model, device_ids=cuda_devices) model.cuda() else: num_gpu = 0 num_gpu_state = str(num_gpu) if num_gpu > 1: num_gpu_state += " (Multi-GPU)" # TODO: distributed training and 16-bits training (FP16) logger.info(f"use_gpu: {self.config.use_gpu} num_gpu: {num_gpu_state}, distributed training: False, 16-bits training: False") return model
[docs] def set_trainer(self, model, op_dict={}, save_params={}): trainer_config = vars(self.config.trainer) trainer_config["config"] = self.config_dict trainer_config["model"] = model trainer_config["learning_rate_scheduler"] = op_dict.get("learning_rate_scheduler", None) trainer_config["exponential_moving_average"] = op_dict.get( "exponential_moving_average", None ) self.trainer = Trainer(**trainer_config) # Set NSML if nsml.IS_ON_NSML: utils.bind_nsml(model, optimizer=op_dict.get("optimizer", None)) if getattr(self.config.nsml, "pause", None): nsml.paused(scope=locals())
def _summary_experiments(self): hr_text = "-" * 50 summary_logs = f"\n\n\nExperiment Summary. {nsml.SESSION_NAME}\n{hr_text}\n" summary_logs += f"Config.\n{pretty_json_dumps(self.config_dict)}\n{hr_text}\n" summary_logs += ( f"Training Logs.\n{pretty_json_dumps(self.trainer.training_logs)}\n{hr_text}\n" ) summary_logs += f"Metric Logs.\n{pretty_json_dumps(self.trainer.metric_logs)}" logger.info(summary_logs) if self.config.slack_url: # pragma: no cover simple_summary_title = f"Session Name: {nsml.SESSION_NAME} " if getattr(self.config, "base_config", None): simple_summary_title += f"({self.config.base_config})" simple_summary_logs = f" - Dataset: {self.config.data_reader.dataset} \n" simple_summary_logs += f" - Model: {self.config.model.name}" best_metrics = {"epoch": self.trainer.metric_logs["best_epoch"]} best_metrics.update(self.trainer.metric_logs["best"]) simple_summary_logs += f" - Best metrics.\n {pretty_json_dumps(best_metrics)} " utils.send_message_to_slack(self.config.slack_url, title=simple_summary_title, message=simple_summary_logs)
[docs] def set_eval_mode(self): """ Evaluate Mode - Pipeline 1. read raw_data (DataReader) 2. load vocabs from checkpoint (DataReader, Token) 3. indexing tokens (DataReader, Token) 4. convert to DataSet (DataReader) 5. create DataLoader (DataLoader) 6. define and load model 7. run! """ data_reader, token_makers = self._create_data_and_token_makers() # DataReader datas, helpers = data_reader.read() # Token & Vocab vocabs = utils.load_vocabs(self.model_checkpoint) for token_name, token_maker in token_makers.items(): token_maker.set_vocab(vocabs[token_name]) text_handler = TextHandler(token_makers, lazy_indexing=False) text_handler.index(datas, data_reader.text_columns) # iterator vocab = vocabs[next(iter(vocabs))] datasets = data_reader.convert_to_dataset(datas, vocab, helpers=helpers) # with name self.config.iterator.cuda_devices = self.config.cuda_devices _, valid_loader, _ = self._create_by_factory( DataLoaderFactory, self.config.iterator, param={"datasets": datasets} ) # Model model = self._create_model(token_makers, checkpoint=self.model_checkpoint) self.set_trainer(model) return valid_loader
[docs] def set_eval_inference_latency_mode(self): """ Evaluate Inference Latency Mode - Pipeline 1. read raw_data (DataReader) 2. load vocabs from checkpoint (DataReader, Token) 3. define raw_to_tensor_fn (DataReader, Token) 4. define and load model 5. run! """ data_reader, token_makers = self._create_data_and_token_makers() # Token & Vocab vocabs = utils.load_vocabs(self.model_checkpoint) for token_name, token_maker in token_makers.items(): token_maker.set_vocab(vocabs[token_name]) text_handler = TextHandler(token_makers, lazy_indexing=False) _, helpers = data_reader.read() raw_examples = helpers["valid"]["examples"] cuda_device = self.config.cuda_devices[0] if self.config.use_gpu else None raw_to_tensor_fn = text_handler.raw_to_tensor_fn(data_reader, cuda_device=cuda_device) # Model model = self._create_model(token_makers, checkpoint=self.model_checkpoint) self.set_trainer(model) return raw_examples, raw_to_tensor_fn
[docs] def predict(self, raw_features): if self.predict_settings is None: raise ValueError( "To use 'predict()', you must call 'set_predict_mode()' first, with preload=True parameter" ) raw_to_tensor_fn = self.predict_settings["raw_to_tensor_fn"] arguments = self.predict_settings["arguments"] arguments.update(raw_features) assert raw_features is not None assert raw_to_tensor_fn is not None return self.trainer.predict( raw_features, raw_to_tensor_fn, arguments, interactive=arguments.get("interactive", False), )
[docs] def set_predict_mode(self, preload=False): """ Predict Mode - Pipeline 1. read raw_data (Argument) 2. load vocabs from checkpoint (DataReader, Token) 3. define raw_to_tensor_fn (DataReader, Token) 4. define and load model 5. run! """ data_reader, token_makers = self._create_data_and_token_makers() # Token & Vocab vocabs = utils.load_vocabs(self.model_checkpoint) for token_name, token_maker in token_makers.items(): token_maker.set_vocab(vocabs[token_name]) text_handler = TextHandler(token_makers, lazy_indexing=False) # Set predict config if self.argument.interactive: raw_features = {feature_name: "" for feature_name in data_reader.text_columns} else: raw_features = {} for feature_name in data_reader.text_columns: feature = getattr(self.argument, feature_name, None) # if feature is None: # raise ValueError(f"--{feature_name} argument is required!") raw_features[feature_name] = feature cuda_device = self.config.cuda_devices[0] if self.config.use_gpu else None raw_to_tensor_fn = text_handler.raw_to_tensor_fn( data_reader, cuda_device=cuda_device, helper=self.model_checkpoint.get("predict_helper", {}) ) # Model model = self._create_model(token_makers, checkpoint=self.model_checkpoint) self.set_trainer(model) arguments = vars(self.argument) if preload: self.predict_settings = {"raw_to_tensor_fn": raw_to_tensor_fn, "arguments": arguments} else: return raw_features, raw_to_tensor_fn, arguments
================================================ FILE: docs/_build/html/_modules/claf/learn/mode.html ================================================ claf.learn.mode — CLaF 0.2.0 documentation

Source code for claf.learn.mode

[docs]class Mode: """ Experiment Flag class """ TRAIN = "train" EVAL = "eval" INFER_EVAL = "infer_eval" PREDICT = "predict" MACHINE = "machine"
================================================ FILE: docs/_build/html/_modules/claf/learn/tensorboard.html ================================================ claf.learn.tensorboard — CLaF 0.2.0 documentation

Source code for claf.learn.tensorboard


import os

from tensorboardX import SummaryWriter

from claf import nsml


[docs]class TensorBoard: """ TensorBoard Wrapper for Pytorch """ def __init__(self, log_dir): if not os.path.exists(log_dir): os.makedirs(log_dir) self.writer = SummaryWriter(log_dir=log_dir)
[docs] def scalar_summaries(self, step, summary): if nsml.IS_ON_NSML: if type(summary) != dict: raise ValueError(f"summary type is dict. not {type(summary)}") kwargs = {"summary": True, "scope": locals(), "step": step} kwargs.update(summary) nsml.report(**kwargs) else: for tag, value in summary.items(): self.scalar_summary(step, tag, value)
[docs] def scalar_summary(self, step, tag, value): """Log a scalar variable.""" if nsml.IS_ON_NSML: nsml.report(**{"summary": True, "scope": locals(), "step": step, tag: value}) else: self.writer.add_scalar(tag, value, step)
[docs] def image_summary(self, tag, images, step): """Log a list of images.""" raise NotImplementedError()
[docs] def embedding_summary(self, features, metadata=None, label_img=None): raise NotImplementedError()
[docs] def histogram_summary(self, tag, values, step, bins=1000): """Log a histogram of the tensor of values.""" raise NotImplementedError()
[docs] def graph_summary(self, model, input_to_model=None): raise NotImplementedError()
================================================ FILE: docs/_build/html/_modules/claf/learn/trainer.html ================================================ claf.learn.trainer — CLaF 0.2.0 documentation

Source code for claf.learn.trainer

# -*- coding: utf-8 -*-

import json
import logging
import os
import time
import random

import torch
from torch.nn.utils import clip_grad_norm_
from tqdm import tqdm

from claf import nsml
from claf.config.utils import pretty_json_dumps
from claf.learn.optimization.exponential_moving_avarage import EMA
from claf.learn.tensorboard import TensorBoard
from claf.learn import utils

logger = logging.getLogger(__name__)


[docs]class Trainer: """ Trainer Run experiment - train - train_and_evaluate - evaluate - evaluate_inference_latency - predict * Args: config: experiment overall config model: Model based on torch.nn.Module * Kwargs: log_dir: path to directory for save model and other options grad_max_norm: Clips gradient norm of an iterable of parameters. learning_rate_scheduler: PyTorch's Learning Rate Scheduler. (https://pytorch.org/docs/stable/_modules/torch/optim/lr_scheduler.html) exponential_moving_average: the moving averages of all weights of the model are maintained with the exponential decay rate of {ema}. num_epochs: the number of maximun epochs (Default is 20) early_stopping_threshold: the number of early stopping threshold (Default is 10) max_eval_examples: print evaluation examples metric_key: metric score's control point verbose_step_count: print verbose step count (Default is 100) eval_and_save_step_count: evaluate valid_dataset then save every n step_count (Default is 'epoch') """ def __init__( self, model, config={}, log_dir="logs/experiment", grad_max_norm=None, gradient_accumulation_steps=1, learning_rate_scheduler=None, exponential_moving_average=None, num_epochs=20, early_stopping_threshold=10, max_eval_examples=5, metric_key=None, verbose_step_count=100, eval_and_save_step_count="epoch", save_checkpoint=True, ): assert metric_key is not None # CUDA self.use_multi_gpu = type(model) == torch.nn.DataParallel if getattr(model, "train_counter", None): self.train_counter = model.train_counter else: self.train_counter = utils.TrainCounter(display_unit=eval_and_save_step_count) self.model = model model_config = config.get("model", {}) self.model_name = model_config.get("name", "model") self.set_model_base_properties(config, log_dir) # Logs os.makedirs(log_dir, exist_ok=True) self.tensorboard = TensorBoard(log_dir) self.metric_logs = {"best_epoch": 0, "best_global_step": 0, "best": None, "best_score": 0} self.training_logs = {"early_stopping_count": 0} # optimization options self.grad_max_norm = grad_max_norm if gradient_accumulation_steps is None: gradient_accumulation_steps = 1 self.gradient_accumulation_steps = gradient_accumulation_steps self.learning_rate_scheduler = learning_rate_scheduler self.exponential_moving_average = exponential_moving_average if exponential_moving_average: self.exponential_moving_average = EMA(model, self.exponential_moving_average) # property self.num_epochs = num_epochs self.early_stopping = False self.early_stopping_threshold = early_stopping_threshold self.max_eval_examples = max_eval_examples self.metric_key = metric_key self.verbose_step_count = verbose_step_count self.eval_and_save_step_count = eval_and_save_step_count self.save_checkpoint = save_checkpoint self.log_dir = log_dir
[docs] def set_model_base_properties(self, config, log_dir): model = self.model if self.use_multi_gpu: model = self.model.module model.config = config model.log_dir = log_dir model.train_counter = self.train_counter assert model.is_ready() == True
[docs] def train_and_evaluate(self, train_loader, valid_loader, optimizer): """ Train and Evaluate """ start_time = time.time() for epoch in range(1, self.num_epochs + 1): self.train_counter.epoch = epoch # Training with metrics train_metrics = self._run_epoch( train_loader, valid_loader=valid_loader, is_training=True, optimizer=optimizer, verbose_step_count=self.verbose_step_count, eval_and_save_step_count=self.eval_and_save_step_count, ) valid_metrics = None if self.eval_and_save_step_count == "epoch": valid_metrics = self._run_epoch(valid_loader, is_training=False) self._check_valid_results(valid_metrics, report=False) self.save(optimizer) self._report_metrics(train_metrics=train_metrics, valid_metrics=valid_metrics) self._estimate_remainig_time(start_time) if self.early_stopping: break self._report_trainings(start_time, train_loader=train_loader, valid_loader=valid_loader)
[docs] def train(self, data_loader, optimizer): """ Train """ start_time = time.time() for epoch in range(1, self.num_epochs + 1): self.train_counter.epoch = epoch metrics = self._run_epoch( data_loader, is_training=True, optimizer=optimizer, verbose_step_count=self.verbose_step_count, ) self._report_metrics(train_metrics=metrics) self._estimate_remainig_time(start_time) self.save(optimizer) self._report_trainings(start_time, train_loader=data_loader)
[docs] def evaluate(self, data_loader): """ Evaluate """ print("evaluate:", type(data_loader), data_loader) eval_metrics = self._run_epoch(data_loader, is_training=False, disable_prograss_bar=False) self._report_metrics(tensorboard=False, valid_metrics=eval_metrics)
[docs] def evaluate_inference_latency(self, raw_examples, raw_to_tensor_fn, token_key=None, max_latency=1000): """ Evaluate with focusing inferece latency (Note: must use sorted synthetic data) * inference_latency: raw_data -> pre-processing -> model -> predict_value (elapsed_time) (elapsed_time) """ logger.info("\n# Evaluate Inference Latency Mode.") self.model.eval() total_raw_to_tensor_time = 0 tensor_to_predicts = [] raw_example_items = tqdm(raw_examples.items()) for _, raw_example in raw_example_items: # raw_data -> tensor raw_to_tensor_start_time = time.time() feature, helper = raw_to_tensor_fn(raw_example) raw_to_tensor_elapsted_time = time.time() - raw_to_tensor_start_time raw_to_tensor_elapsted_time *= 1000 # unit: sec -> ms total_raw_to_tensor_time += raw_to_tensor_elapsted_time # tensor to predict tensor_to_predict_start_time = time.time() output_dict = self.model(feature) tensor_to_predict_elapsed_time = time.time() - tensor_to_predict_start_time if "token_key" not in helper: raise ValueError( "helper must have 'token_key' data for 1-example inference latency." ) tensor_to_predict_elapsed_time *= 1000 # unit: sec -> ms tensor_to_predict = { "elapsed_time": tensor_to_predict_elapsed_time, "token_count": len(helper[helper["token_key"]]), } tensor_to_predicts.append(tensor_to_predict) if tensor_to_predict_elapsed_time > max_latency: raw_example_items.close() break total_tensor_to_predict = sum( [tensor_to_predict["elapsed_time"] for tensor_to_predict in tensor_to_predicts] ) max_token_count_per_times = {} max_times = list(range(0, max_latency+1, 100)) for t2p in sorted(tensor_to_predicts, key=lambda x: x["token_count"]): elapsed_time = t2p["elapsed_time"] token_count = t2p["token_count"] for max_time in max_times: if elapsed_time < max_time: max_token_count_per_times[max_time] = token_count result = { "average_raw_to_tensor": total_raw_to_tensor_time / len(raw_examples), "average_tensor_to_predict": total_tensor_to_predict / len(raw_examples), "average_end_to_end": (total_raw_to_tensor_time + total_tensor_to_predict) / len(raw_examples), "tensor_to_predicts": tensor_to_predicts, "max_token_count_per_time": max_token_count_per_times } env = "gpu" if torch.cuda.is_available() else "cpu" file_name = f"{self.model_name}-{env}.json" with open(file_name, "w") as f: json.dump(result, f, indent=4) logger.info(f"saved inference_latency results. {file_name}")
def _is_early_stopping(self, metrics): score = metrics[self.metric_key] if score > self.metric_logs["best_score"]: self.training_logs["early_stopping_count"] = 0 else: self.training_logs["early_stopping_count"] += 1 if self.training_logs["early_stopping_count"] >= self.early_stopping_threshold: self.training_logs["early_stopping"] = True return True else: return False def _report_metrics(self, tensorboard=True, train_metrics=None, valid_metrics=None): total_metrics = {} def update_metrics(metrics, category=""): if metrics is not None: for k, v in metrics.items(): total_metrics[f"{category}/{k}"] = v update_metrics(train_metrics, "train") update_metrics(valid_metrics, "valid") # TensorBoard if tensorboard: self.tensorboard.scalar_summaries(self.train_counter.get_display(), total_metrics) # Console metric_console = "" if train_metrics: metric_console += ( f"\n# Epoch: [{self.train_counter.epoch}/{self.num_epochs}]: Metrics \n" ) metric_console += json.dumps(total_metrics, indent=4) logger.info(metric_console) if valid_metrics: self._update_metric_logs(total_metrics) def _update_metric_logs(self, total_metrics): for k, v in total_metrics.items(): if self.metric_logs.get(k, None) is None: self.metric_logs[k] = [v] else: self.metric_logs[k].append(v) valid_score = total_metrics.get(f"valid/{self.metric_key}", None) if valid_score and valid_score > self.metric_logs["best_score"]: logger.info(f" * Best validation score so far. ({self.metric_key}) : {valid_score}") self.metric_logs["best_score"] = valid_score self.metric_logs["best"] = total_metrics self.metric_logs["best_epoch"] = self.train_counter.epoch self.metric_logs["best_global_step"] = self.train_counter.global_step else: logger.info( f" * Current best validation score. ({self.metric_key}) : {self.metric_logs['best_score']}" ) def _estimate_remainig_time(self, start_time): elapsed_time = time.time() - start_time estimated_time_remaining = elapsed_time * ( (self.num_epochs - self.train_counter.epoch) / float(self.train_counter.epoch) - 1 ) formatted_time = time.strftime("%H:%M:%S", time.gmtime(estimated_time_remaining)) logger.info(f"Estimated training time remaining: {formatted_time} ") def _report_trainings(self, start_time, train_loader=None, valid_loader=None): elapsed_time = time.time() - start_time self.training_logs["elapsed_time"] = (time.strftime("%H:%M:%S", time.gmtime(elapsed_time)),) if train_loader is not None: self.training_logs["train_dataset"] = json.loads(str(train_loader.dataset)) if valid_loader is not None: self.training_logs["valid_dataset"] = json.loads(str(valid_loader.dataset)) def _run_epoch( self, data_loader, valid_loader=None, is_training=True, optimizer=None, disable_prograss_bar=True, verbose_step_count=100, eval_and_save_step_count=None, ): """ Run Epoch 1. forward inputs to model 2. (training) backpropagation 3. update predictions 4. make metrics """ if is_training: logger.info("# Train Mode.") self.model.train() else: logger.info("# Evaluate Mode.") self.model.eval() # set dataset (train/valid) self._set_dataset_to_model(data_loader.dataset) metrics = {} predictions = {} epoch_loss = 0 epoch_start_time = time.time() step_start_time = time.time() eval_example_count = 0 for step, batch in enumerate(tqdm(data_loader, disable=disable_prograss_bar)): inputs = batch.to_dict() # for DataParallel output_dict = self.model(**inputs) loss = output_dict["loss"] if self.use_multi_gpu: loss = loss.mean() if self.gradient_accumulation_steps > 1: loss = loss / self.gradient_accumulation_steps epoch_loss += loss.item() if is_training: # Training Verbose if self.train_counter.global_step == 0: logger.info(f" Start - Batch Loss: {loss.item():.5f}") if ( self.train_counter.global_step != 0 and self.train_counter.global_step % verbose_step_count == 0 ): step_elapsed_time = time.time() - step_start_time logger.info( f" Step: {self.train_counter.global_step} Batch Loss: {loss.item():.5f} {step_elapsed_time:.5f} sec" ) self.tensorboard.scalar_summary( self.train_counter.global_step, "train/batch_loss", loss.item() ) step_start_time = time.time() loss.backward() if self.grad_max_norm: clip_grad_norm_(self._get_model_parameters(), self.grad_max_norm) if (step + 1) % self.gradient_accumulation_steps == 0: # Backpropagation if self.learning_rate_scheduler: self.learning_rate_scheduler.step_batch(self.train_counter.global_step) optimizer.step() optimizer.zero_grad() self.train_counter.global_step += 1 if self.exponential_moving_average: for name, param in self.model.named_parameters(): if param.requires_grad: param.data = self.exponential_moving_average(name, param.data) # Evaluate then Save checkpoint if ( valid_loader and type(eval_and_save_step_count) == int and self.train_counter.global_step % eval_and_save_step_count == 0 ): with torch.no_grad(): valid_metrics = self._run_epoch(valid_loader, is_training=False) self._check_valid_results(valid_metrics, report=True) self.save(optimizer) if is_training: # roll-back to train mode self.model.train() self._set_dataset_to_model(data_loader.dataset) else: if eval_example_count < self.max_eval_examples: total_step_count = int(len(data_loader) / data_loader.batch_size) random_num = random.randint(0, total_step_count) if random_num <= self.max_eval_examples: eval_example_predictions = {} self._update_predictions(eval_example_predictions, output_dict) random_index = random.randint(0, data_loader.batch_size) self._print_examples(random_index, inputs, eval_example_predictions) eval_example_count += 1 self._update_predictions(predictions, output_dict) epoch_loss /= len(data_loader) epoch_elapsed_time = time.time() - epoch_start_time logger.info("Epoch duration: " + time.strftime("%H:%M:%S", time.gmtime(epoch_elapsed_time))) # Updat metrics metrics["loss"] = epoch_loss metrics["epoch_time"] = epoch_elapsed_time metrics.update(self._make_metrics(predictions)) # model metric return metrics def _set_dataset_to_model(self, dataset): if self.use_multi_gpu: self.model.module.dataset = dataset else: self.model.dataset = dataset def _get_model_parameters(self): if self.use_multi_gpu: return self.model.module.parameters() else: return self.model.parameters() def _check_valid_results(self, metrics, report=False): if self.learning_rate_scheduler: # The LRScheduler API is agnostic to whether your schedule requires a validation metric - # if it doesn't, the validation metric passed here is ignored. this_epoch_val_metric = metrics[self.metric_key] self.learning_rate_scheduler.step(this_epoch_val_metric, self.train_counter.global_step) if self._is_early_stopping(metrics): self.early_stopping = True logger.info(" --- Early Stopping. --- ") if report: self._report_metrics(valid_metrics=metrics) def _make_metrics(self, predictions): model = self.model if self.use_multi_gpu: model = model.module model.train_counter = self.train_counter return model.make_metrics(predictions) def _update_predictions(self, predictions, output_dict): if self.use_multi_gpu: predictions.update(self.model.module.make_predictions(output_dict)) else: predictions.update(self.model.make_predictions(output_dict)) def _print_examples(self, index, inputs, predictions): try: if self.use_multi_gpu: self.model.module.print_examples(index, inputs, predictions) else: self.model.print_examples(index, inputs, predictions) except IndexError: pass
[docs] def predict(self, raw_feature, raw_to_tensor_fn, arguments, interactive=False): """ Inference / Predict """ self.model.eval() with torch.no_grad(): if interactive: # pragma: no cover while True: for k in raw_feature: raw_feature[k] = utils.get_user_input(k) tensor_feature, helper = raw_to_tensor_fn(raw_feature) output_dict = self.model(tensor_feature) arguments.update(raw_feature) predict = self.model.predict(output_dict, arguments, helper) print(f"Predict: {pretty_json_dumps(predict)} \n") else: tensor_feature, helper = raw_to_tensor_fn(raw_feature) output_dict = self.model(tensor_feature) return self.model.predict(output_dict, arguments, helper)
[docs] def save(self, optimizer): if not self.save_checkpoint: return # set all config to model model = self.model if self.use_multi_gpu: model = self.model.module model.train_counter = self.train_counter model.metrics = self.metric_logs if nsml.IS_ON_NSML: nsml.save(self.train_counter.get_display()) else: utils.save_checkpoint(self.log_dir, model, optimizer)
================================================ FILE: docs/_build/html/_modules/claf/learn/utils.html ================================================ claf.learn.utils — CLaF 0.2.0 documentation

Source code for claf.learn.utils


from collections import OrderedDict
import json
import logging
from pathlib import Path
import os
import re

import torch
from torch.nn import DataParallel
import requests

from claf import nsml
from claf.tokens.vocabulary import Vocab


logger = logging.getLogger(__name__)


""" Train Counter """


[docs]class TrainCounter: global_step = 0 epoch = 0 def __init__(self, display_unit="epoch"): if type(display_unit) == int: display_unit = f"every_{display_unit}_global_step" self.display_unit = display_unit
[docs] def get_display(self): if self.display_unit == "epoch": return self.epoch else: return self.global_step
""" Save and Load checkpoint """
[docs]def load_model_checkpoint(model, checkpoint): model.load_state_dict(checkpoint["weights"]) model.config = checkpoint["config"] model.metrics = checkpoint["metrics"] model.init_params = checkpoint["init_params"] model.predict_helper = checkpoint["predict_helper"] model.train_counter = checkpoint["train_counter"] model.vocabs = load_vocabs(checkpoint) logger.info(f"Load model checkpoints...!") return model
[docs]def load_optimizer_checkpoint(optimizer, checkpoint): optimizer.load_state_dict(checkpoint["optimizer"]) logger.info(f"Load optimizer checkpoints...!") return optimizer
[docs]def load_vocabs(model_checkpoint): vocabs = {} token_config = model_checkpoint["config"]["token"] for token_name in token_config["names"]: token = token_config[token_name] vocab_config = token.get("vocab", {}) texts = model_checkpoint["vocab_texts"][token_name] vocabs[token_name] = Vocab(token_name, **vocab_config).from_texts(texts) return vocabs
[docs]def save_checkpoint(path, model, optimizer, max_to_keep=10): path = Path(path) checkpoint_dir = path / "checkpoint" checkpoint_dir.mkdir(exist_ok=True) # Remove old checkpoints sorted_path = get_sorted_path(checkpoint_dir) if len(sorted_path) > max_to_keep: remove_train_counts = list(sorted_path.keys())[: -(max_to_keep - 1)] for train_count in remove_train_counts: optimizer_path = sorted_path[train_count].get("optimizer", None) if optimizer_path: os.remove(optimizer_path) model_path = sorted_path[train_count].get("model", None) if model_path: os.remove(model_path) train_counter = model.train_counter optimizer_path = checkpoint_dir / f"optimizer_{train_counter.get_display()}.pkl" torch.save({"optimizer": optimizer.state_dict()}, optimizer_path) model_path = checkpoint_dir / f"model_{train_counter.get_display()}.pkl" torch.save( { "config": model.config, "init_params": model.init_params, "predict_helper": model.predict_helper, "metrics": model.metrics, "train_counter": model.train_counter, "vocab_texts": {k: v.to_text() for k, v in model.vocabs.items()}, "weights": model.state_dict(), }, model_path, ) # Write Vocab as text file (Only once) vocab_dir = path / "vocab" vocab_dir.mkdir(exist_ok=True) for token_name, vocab in model.vocabs.items(): vocab_path = vocab_dir / f"{token_name}.txt" if not vocab_path.exists(): vocab.dump(vocab_path) logger.info(f"Save {train_counter.global_step} global_step checkpoints...!")
[docs]def get_sorted_path(checkpoint_dir, both_exist=False): paths = [] for root, dirs, files in os.walk(checkpoint_dir): for f_name in files: if "model" in f_name or "optimizer" in f_name: paths.append(Path(root) / f_name) path_with_train_count = {} for path in paths: train_count = re.findall("\d+", path.name)[0] train_count = int(train_count) if train_count not in path_with_train_count: path_with_train_count[train_count] = {} if "model" in path.name: path_with_train_count[train_count]["model"] = path if "optimizer" in path.name: path_with_train_count[train_count]["optimizer"] = path if both_exist: remove_keys = [] for key, checkpoint in path_with_train_count.items(): if not ("model" in checkpoint and "optimizer" in checkpoint): remove_keys.append(key) for key in remove_keys: del path_with_train_count[key] return OrderedDict(sorted(path_with_train_count.items()))
""" NSML """
[docs]def bind_nsml(model, **kwargs): # pragma: no cover if type(model) == DataParallel: model = model.module CHECKPOINT_FNAME = "checkpoint.bin" def infer(raw_data, **kwargs): print("raw_data:", raw_data) def load(dir_path, *args): checkpoint_path = os.path.join(dir_path, CHECKPOINT_FNAME) checkpoint = torch.load(checkpoint_path) model.load_state_dict(checkpoint["weights"]) model.config = checkpoint["config"] model.metrics = checkpoint["metrics"] model.init_params = checkpoint["init_params"], model.predict_helper = checkpoint["predict_helper"], model.train_counter = checkpoint["train_counter"] model.vocabs = load_vocabs(checkpoint) if "optimizer" in kwargs: kwargs["optimizer"].load_state_dict(checkpoint["optimizer"]) logger.info(f"Load checkpoints...! {checkpoint_path}") def save(dir_path, *args): # save the model with 'checkpoint' dictionary. checkpoint_path = os.path.join(dir_path, CHECKPOINT_FNAME) checkpoint = { "config": model.config, "init_params": model.init_params, "predict_helper": model.predict_helper, "metrics": model.metrics, "train_counter": model.train_counter, "vocab_texts": {k: v.to_text() for k, v in model.vocabs.items()}, "weights": model.state_dict(), } if "optimizer" in kwargs: checkpoint["optimizer"] = kwargs["optimizer"].state_dict() torch.save(checkpoint, checkpoint_path) train_counter = model.train_counter logger.info(f"Save {train_counter.global_step} global_step checkpoints...! {checkpoint_path}") # function in function is just used to divide the namespace. nsml.bind(save, load, infer)
""" Notification """
[docs]def get_session_name(): session_name = "local" if nsml.IS_ON_NSML: session_name = nsml.SESSION_NAME return session_name
[docs]def send_message_to_slack(webhook_url, title=None, message=None): # pragma: no cover if message is None: data = {"text": f"{get_session_name()} session is exited."} else: data = {"attachments": [{"title": title, "text": message, "color": "#438C56"}]} try: if webhook_url == "": print(data["text"]) else: requests.post(webhook_url, data=json.dumps(data)) except Exception as e: print(str(e))
================================================ FILE: docs/_build/html/_modules/claf/machine/base.html ================================================ claf.machine.base — CLaF 0.2.0 documentation

Source code for claf.machine.base


from argparse import Namespace
import json

from claf.config.namespace import NestedNamespace
from claf.config.registry import Registry
from claf.learn.experiment import Experiment
from claf.learn.mode import Mode
from claf.machine.module import Module


[docs]class Machine: """ Machine: Combine modules then make a NLP Machine * Args: config: machine_config """ def __init__(self, config): self.config = config self.registry = Registry()
[docs] def load(self): raise NotImplementedError("")
[docs] @classmethod def load_from_config(cls, config_path): with open(config_path, "r", encoding="utf-8") as in_file: machine_config = NestedNamespace() machine_config.load_from_json(json.load(in_file)) machine_name = machine_config.name config = getattr(machine_config, machine_name, {}) return cls(config)
def __call__(self, text): raise NotImplementedError("")
[docs] def make_module(self, config): """ Make component or experiment for claf Machine's module * Args: - config: module's config (claf.config.namespace.NestedNamespace) """ module_type = config.type if module_type == Module.COMPONENT: name = config.name module_config = getattr(config, name, {}) if isinstance(module_config, Namespace): module_config = vars(module_config) if getattr(config, "params", None): module_config.update(config.params) return self.registry.get(f"component:{name}")(**module_config) elif module_type == Module.EXPERIMENT: experiment_config = Namespace() experiment_config.checkpoint_path = config.checkpoint_path experiment_config.cuda_devices = getattr(config, "cuda_devices", None) experiment_config.interactive = False experiment = Experiment(Mode.PREDICT, experiment_config) experiment.set_predict_mode(preload=True) return experiment else: raise ValueError( f"module_type is available only [component|experiment]. not '{module_type}'" )
================================================ FILE: docs/_build/html/_modules/claf/machine/components/retrieval/tfidf.html ================================================ claf.machine.components.retrieval.tfidf — CLaF 0.2.0 documentation

Source code for claf.machine.components.retrieval.tfidf


from pathlib import Path

from gensim.corpora import Dictionary
from gensim.models import TfidfModel
from gensim.similarities import MatrixSimilarity, SparseMatrixSimilarity

from tqdm import tqdm

from claf.decorator import register


[docs]@register("component:tfidf") class TFIDF: """ TF-IDF document retrieval model - Term Frequency - Inverse Document Frequency - log(tf + 1) * log((N - Nt + 0.5) / (Nt + 0.5)) * Kwargs: k: the number of top k results """ VOCAB_FNAME = "vocab.txt" TFIDF_FNAME = "tfidf.model" INDEX_FNAME = "similarities.index" def __init__(self, texts, word_tokenizer, k=1): super(TFIDF, self).__init__() self.k = k self.texts = texts self.word_tokenizer = word_tokenizer
[docs] def init(self): corpus = [ self.word_tokenizer.tokenize(text) for text in tqdm(self.texts, desc="make corpus (Tokenize)") ] self.vocab = Dictionary(corpus) self.init_model()
[docs] def init_model(self): corpus = [] for text in tqdm(self.texts, desc="make corpus (BoW)"): corpus.append(self.parse(text)) self.model = TfidfModel(corpus) self.index = SparseMatrixSimilarity(self.model[corpus], num_features=len(self.vocab))
[docs] def get_closest(self, query): query_tfidf = self.text_to_tfidf(query) self.index.num_best = self.k results = self.index[query_tfidf] return [ (text_index, self.texts[text_index], score) # return (index, text, score) for (text_index, score) in results ]
[docs] def parse(self, query, ngram=1): query_tokens = self.word_tokenizer.tokenize(query) return self.vocab.doc2bow(query_tokens)
[docs] def text_to_tfidf(self, query): """ Create a tfidf-weighted word vector from query. tfidf = log(tf + 1) * log((N - Nt + 0.5) / (Nt + 0.5)) """ query_bow = self.parse(query) return self.model[query_bow]
[docs] def save(self, dir_path): dir_path = Path(dir_path) dir_path.mkdir(parents=True, exist_ok=True) vocab_path = str(dir_path / self.VOCAB_FNAME) model_path = str(dir_path / self.TFIDF_FNAME) index_path = str(dir_path / self.INDEX_FNAME) self.vocab.save(vocab_path) self.model.save(model_path) self.index.save(index_path)
[docs] def load(self, dir_path): dir_path = Path(dir_path) vocab_path = str(dir_path / self.VOCAB_FNAME) model_path = str(dir_path / self.TFIDF_FNAME) index_path = str(dir_path / self.INDEX_FNAME) self.vocab = Dictionary.load(vocab_path) self.model = TfidfModel.load(model_path) self.index = SparseMatrixSimilarity.load(index_path)
================================================ FILE: docs/_build/html/_modules/claf/machine/module.html ================================================ claf.machine.module — CLaF 0.2.0 documentation

Source code for claf.machine.module

[docs]class Module: """ Machine Flag class """ KNOWLEDGE_BASE = "knowledge_base" COMPONENT = "component" EXPERIMENT = "experiment"
================================================ FILE: docs/_build/html/_modules/claf/machine/nlu.html ================================================ claf.machine.nlu — CLaF 0.2.0 documentation

Source code for claf.machine.nlu


import logging

from overrides import overrides

from claf.data.data_handler import CachePath, DataHandler
from claf.decorator import register

from claf.machine.base import Machine


logger = logging.getLogger(__name__)


[docs]@register("machine:nlu") class NLU(Machine): """ Natural Language Understanding Machine * Args: config: machine_config """ def __init__(self, config): super(NLU, self).__init__(config) self.data_handler = DataHandler(CachePath.MACHINE / "nlu") self.load()
[docs] @overrides def load(self): # NLU # - Intent Classification Experiment # - Slot Filling Experiment nlu_config = self.config.nlu self.ic_experiment = self.make_module(nlu_config.intent) self.sf_experiment = self.make_module(nlu_config.slots) print("Ready ..! \n")
@overrides def __call__(self, utterance): nlu_result = dict() intent_info = self.intent_classification(utterance) nlu_result.update({"intent": intent_info["class_text"]}) slots_info = self.slot_filling(utterance) nlu_result.update({"slots": slots_info["tag_dict"]}) return nlu_result
[docs] def intent_classification(self, utterance): raw_feature = {"sequence": utterance} return self.ic_experiment.predict(raw_feature)
[docs] def slot_filling(self, utterance): raw_feature = {"sequence": utterance} return self.sf_experiment.predict(raw_feature)
================================================ FILE: docs/_build/html/_modules/claf/machine/open_qa.html ================================================ claf.machine.open_qa — CLaF 0.2.0 documentation

Source code for claf.machine.open_qa


import logging
import os

from overrides import overrides

from claf.config.factory.tokens import make_all_tokenizers
from claf.config.utils import convert_config2dict
from claf.data.data_handler import CachePath, DataHandler
from claf.decorator import register

from claf.machine.base import Machine
from claf.machine.knowlege_base.docs import read_wiki_articles


logger = logging.getLogger(__name__)


[docs]@register("machine:open_qa") class OpenQA(Machine): """ Open-Domain Question Answer Machine (DrQA) DrQA is a system for reading comprehension applied to open-domain question answering. * Args: config: machine_config """ def __init__(self, config): super(OpenQA, self).__init__(config) self.data_handler = DataHandler(CachePath.MACHINE / "open_qa") self.load()
[docs] @overrides def load(self): # Tokenizers tokenizers_config = convert_config2dict(self.config.tokenizers) tokenizers = make_all_tokenizers(tokenizers_config) # Knowledge Base # - Wiki knowledge_base_config = self.config.knowledge_base self.docs, doc_name = self._load_knowledge_base(knowledge_base_config) # Reasoning # - Document Retrieval # - Reading Comprehension Experiment reasoning_config = self.config.reasoning self.document_retrieval = self._load_document_retrieval( reasoning_config.document_retrieval, tokenizers["word"], basename=doc_name ) self.rc_experiment = self.make_module(reasoning_config.reading_comprehension) print("Ready ..! \n")
def _load_knowledge_base(self, config): docs = read_wiki_articles(config.wiki) # TODO: fix read whole wiki doc_name = f"{os.path.basename(config.wiki)}-{len(docs)}-articles" return docs, doc_name def _load_document_retrieval(self, config, word_tokenizer, basename="docs"): dir_path = f"doc-{config.type}-{config.name}-{word_tokenizer.cache_name}" doc_retrieval_path = os.path.join(dir_path, basename) config.params = { "texts": [doc.title for doc in self.docs], "word_tokenizer": word_tokenizer, } document_retrieval = self.make_module(config) doc_retrieval_path = self.data_handler.convert_cache_path(doc_retrieval_path) if doc_retrieval_path.exists(): document_retrieval.load(doc_retrieval_path) else: print("Start Document Retrieval Indexing ...") document_retrieval.init() document_retrieval.save(doc_retrieval_path) # Save Cache print("Completed!") return document_retrieval @overrides def __call__(self, question): result_docs = self.search_documents(question) print("-" * 50) print("Doc Scores:") for doc in result_docs: print(f" - {doc[1]} : {doc[2]}") print("-" * 50) passages = [] for result_doc in result_docs: doc_index = result_doc[0] doc = self.docs[doc_index] passages.append(doc.text) answers = [] for passage in passages: answer_text = self.machine_reading(passage, question) answers.append(answer_text) ranked_answers = sorted(answers, key=lambda x: x["score"], reverse=True) return ranked_answers
[docs] def search_documents(self, question): return self.document_retrieval.get_closest(question)
[docs] def machine_reading(self, context, question): raw_feature = {"context": context, "question": question} return self.rc_experiment.predict(raw_feature)
================================================ FILE: docs/_build/html/_modules/claf/metric/classification.html ================================================ claf.metric.classification — CLaF 0.2.0 documentation

Source code for claf.metric.classification


[docs]def recall(pycm_obj): return {key: pycm_obj.TPR[key] if pycm_obj.TPR[key] != "None" else 0. for key in pycm_obj.TPR}
[docs]def precision(pycm_obj): return {key: pycm_obj.PPV[key] if pycm_obj.PPV[key] != "None" else 0. for key in pycm_obj.PPV}
[docs]def f1(pycm_obj): return {key: pycm_obj.F1[key] if pycm_obj.F1[key] != "None" else 0. for key in pycm_obj.F1}
[docs]def macro_recall(pycm_obj): return sum(recall(pycm_obj).values()) / len(pycm_obj.classes)
[docs]def macro_precision(pycm_obj): return sum(precision(pycm_obj).values()) / len(pycm_obj.classes)
[docs]def macro_f1(pycm_obj): return sum(f1(pycm_obj).values()) / len(pycm_obj.classes)
================================================ FILE: docs/_build/html/_modules/claf/metric/squad_v1_official.html ================================================ claf.metric.squad_v1_official — CLaF 0.2.0 documentation

Source code for claf.metric.squad_v1_official

""" Official evaluation script for v1.1 of the SQuAD dataset. """
from __future__ import print_function
from collections import Counter
import string
import re
import argparse
import json
import sys


[docs]def normalize_answer(s): # pragma: no cover """Lower text and remove punctuation, articles and extra whitespace.""" def remove_articles(text): return re.sub(r"\b(a|an|the)\b", " ", text) def white_space_fix(text): return " ".join(text.split()) def remove_punc(text): exclude = set(string.punctuation) return "".join(ch for ch in text if ch not in exclude) def lower(text): return text.lower() return white_space_fix(remove_articles(remove_punc(lower(s))))
[docs]def f1_score(prediction, ground_truth): # pragma: no cover prediction_tokens = normalize_answer(prediction).split() ground_truth_tokens = normalize_answer(ground_truth).split() common = Counter(prediction_tokens) & Counter(ground_truth_tokens) num_same = sum(common.values()) if num_same == 0: return 0 precision = 1.0 * num_same / len(prediction_tokens) recall = 1.0 * num_same / len(ground_truth_tokens) f1 = (2 * precision * recall) / (precision + recall) return f1
[docs]def exact_match_score(prediction, ground_truth): # pragma: no cover return normalize_answer(prediction) == normalize_answer(ground_truth)
[docs]def metric_max_over_ground_truths(metric_fn, prediction, ground_truths): # pragma: no cover scores_for_ground_truths = [] for ground_truth in ground_truths: score = metric_fn(prediction, ground_truth) scores_for_ground_truths.append(score) return max(scores_for_ground_truths)
[docs]def evaluate(dataset, predictions): f1 = exact_match = total = 0 for article in dataset: for paragraph in article["paragraphs"]: for qa in paragraph["qas"]: total += 1 if qa["id"] not in predictions: message = "Unanswered question " + qa["id"] + " will receive score 0." print(message, file=sys.stderr) continue ground_truths = list(map(lambda x: x["text"], qa["answers"])) prediction = predictions[qa["id"]] exact_match += metric_max_over_ground_truths( exact_match_score, prediction, ground_truths ) f1 += metric_max_over_ground_truths(f1_score, prediction, ground_truths) exact_match = 100.0 * exact_match / total f1 = 100.0 * f1 / total return {"em": exact_match, "f1": f1}
if __name__ == "__main__": # pragma: no cover expected_version = "1.1" parser = argparse.ArgumentParser(description="Evaluation for SQuAD " + expected_version) parser.add_argument("dataset_file", help="Dataset file") parser.add_argument("prediction_file", help="Prediction File") args = parser.parse_args() with open(args.dataset_file) as dataset_file: dataset_json = json.load(dataset_file) if dataset_json["version"] != expected_version: print( "Evaluation expects v-" + expected_version + ", but got dataset with v-" + dataset_json["version"], file=sys.stderr, ) dataset = dataset_json["data"] with open(args.prediction_file) as prediction_file: predictions = json.load(prediction_file) print(json.dumps(evaluate(dataset, predictions)))
================================================ FILE: docs/_build/html/_modules/claf/metric/squad_v2_official.html ================================================ claf.metric.squad_v2_official — CLaF 0.2.0 documentation

Source code for claf.metric.squad_v2_official

"""Official evaluation script for SQuAD version 2.0.

In addition to basic functionality, we also compute additional statistics and
plot precision-recall curves if an additional na_prob.json file is provided.
This file is expected to map question ID's to the model's predicted probability
that a question is unanswerable.
"""
import argparse
import collections
import json
import numpy as np
import os
import re
import string
import sys

OPTS = None


[docs]def parse_args(): # pragma: no cover parser = argparse.ArgumentParser("Official evaluation script for SQuAD version 2.0.") parser.add_argument("data_file", metavar="data.json", help="Input data JSON file.") parser.add_argument("pred_file", metavar="pred.json", help="Model predictions.") parser.add_argument( "--out-file", "-o", metavar="eval.json", help="Write accuracy metrics to file (default is stdout).", ) parser.add_argument( "--na-prob-file", "-n", metavar="na_prob.json", help="Model estimates of probability of no answer.", ) parser.add_argument( "--na-prob-thresh", "-t", type=float, default=1.0, help='Predict "" if no-answer probability exceeds this (default = 1.0).', ) parser.add_argument( "--out-image-dir", "-p", metavar="out_images", default=None, help="Save precision-recall curves to directory.", ) parser.add_argument("--verbose", "-v", action="store_true") if len(sys.argv) == 1: parser.print_help() sys.exit(1) return parser.parse_args()
[docs]def make_qid_to_has_ans(dataset): # pragma: no cover qid_to_has_ans = {} for article in dataset: for p in article["paragraphs"]: for qa in p["qas"]: qid_to_has_ans[qa["id"]] = bool(qa["answers"]) return qid_to_has_ans
[docs]def normalize_answer(s): # pragma: no cover """Lower text and remove punctuation, articles and extra whitespace.""" def remove_articles(text): regex = re.compile(r"\b(a|an|the)\b", re.UNICODE) return re.sub(regex, " ", text) def white_space_fix(text): return " ".join(text.split()) def remove_punc(text): exclude = set(string.punctuation) return "".join(ch for ch in text if ch not in exclude) def lower(text): return text.lower() return white_space_fix(remove_articles(remove_punc(lower(s))))
[docs]def get_tokens(s): # pragma: no cover if not s: return [] return normalize_answer(s).split()
[docs]def compute_exact(a_gold, a_pred): # pragma: no cover return int(normalize_answer(a_gold) == normalize_answer(a_pred))
[docs]def compute_f1(a_gold, a_pred): # pragma: no cover gold_toks = get_tokens(a_gold) pred_toks = get_tokens(a_pred) common = collections.Counter(gold_toks) & collections.Counter(pred_toks) num_same = sum(common.values()) if len(gold_toks) == 0 or len(pred_toks) == 0: # If either is no-answer, then F1 is 1 if they agree, 0 otherwise return int(gold_toks == pred_toks) if num_same == 0: return 0 precision = 1.0 * num_same / len(pred_toks) recall = 1.0 * num_same / len(gold_toks) f1 = (2 * precision * recall) / (precision + recall) return f1
[docs]def get_raw_scores(dataset, preds): # pragma: no cover exact_scores = {} f1_scores = {} for article in dataset: for p in article["paragraphs"]: for qa in p["qas"]: qid = qa["id"] gold_answers = [a["text"] for a in qa["answers"] if normalize_answer(a["text"])] if not gold_answers: # For unanswerable questions, only correct answer is empty # string gold_answers = [""] if qid not in preds: # print('Missing prediction for %s' % qid) continue a_pred = preds[qid] # Take max over all gold answers exact_scores[qid] = max(compute_exact(a, a_pred) for a in gold_answers) f1_scores[qid] = max(compute_f1(a, a_pred) for a in gold_answers) return exact_scores, f1_scores
[docs]def apply_no_ans_threshold(scores, na_probs, qid_to_has_ans, na_prob_thresh): # pragma: no cover new_scores = {} for qid, s in scores.items(): pred_na = na_probs[qid] > na_prob_thresh if pred_na: new_scores[qid] = float(not qid_to_has_ans[qid]) else: new_scores[qid] = s return new_scores
[docs]def make_eval_dict(exact_scores, f1_scores, qid_list=None): # pragma: no cover if not qid_list: total = len(exact_scores) return collections.OrderedDict( [ ("exact", 100.0 * sum(exact_scores.values()) / total), ("f1", 100.0 * sum(f1_scores.values()) / total), ("total", total), ] ) else: total = len(qid_list) return collections.OrderedDict( [ ("exact", 100.0 * sum(exact_scores[k] for k in qid_list) / total), ("f1", 100.0 * sum(f1_scores[k] for k in qid_list) / total), ("total", total), ] )
[docs]def merge_eval(main_eval, new_eval, prefix): # pragma: no cover for k in new_eval: main_eval["%s_%s" % (prefix, k)] = new_eval[k]
[docs]def plot_pr_curve(precisions, recalls, out_image, title): # pragma: no cover plt.step(recalls, precisions, color="b", alpha=0.2, where="post") plt.fill_between(recalls, precisions, step="post", alpha=0.2, color="b") plt.xlabel("Recall") plt.ylabel("Precision") plt.xlim([0.0, 1.05]) plt.ylim([0.0, 1.05]) plt.title(title) plt.savefig(out_image) plt.clf()
[docs]def make_precision_recall_eval( scores, na_probs, num_true_pos, qid_to_has_ans, out_image=None, title=None ): # pragma: no cover qid_list = sorted(na_probs, key=lambda k: na_probs[k]) true_pos = 0.0 cur_p = 1.0 cur_r = 0.0 precisions = [1.0] recalls = [0.0] avg_prec = 0.0 for i, qid in enumerate(qid_list): if qid_to_has_ans[qid]: true_pos += scores[qid] cur_p = true_pos / float(i + 1) cur_r = true_pos / float(num_true_pos) if i == len(qid_list) - 1 or na_probs[qid] != na_probs[qid_list[i + 1]]: # i.e., if we can put a threshold after this point avg_prec += cur_p * (cur_r - recalls[-1]) precisions.append(cur_p) recalls.append(cur_r) if out_image: plot_pr_curve(precisions, recalls, out_image, title) return {"ap": 100.0 * avg_prec}
[docs]def run_precision_recall_analysis( main_eval, exact_raw, f1_raw, na_probs, qid_to_has_ans, out_image_dir ): # pragma: no cover if out_image_dir and not os.path.exists(out_image_dir): os.makedirs(out_image_dir) num_true_pos = sum(1 for v in qid_to_has_ans.values() if v) if num_true_pos == 0: return pr_exact = make_precision_recall_eval( exact_raw, na_probs, num_true_pos, qid_to_has_ans, out_image=os.path.join(out_image_dir, "pr_exact.png"), title="Precision-Recall curve for Exact Match score", ) pr_f1 = make_precision_recall_eval( f1_raw, na_probs, num_true_pos, qid_to_has_ans, out_image=os.path.join(out_image_dir, "pr_f1.png"), title="Precision-Recall curve for F1 score", ) oracle_scores = {k: float(v) for k, v in qid_to_has_ans.items()} pr_oracle = make_precision_recall_eval( oracle_scores, na_probs, num_true_pos, qid_to_has_ans, out_image=os.path.join(out_image_dir, "pr_oracle.png"), title="Oracle Precision-Recall curve (binary task of HasAns vs. NoAns)", ) merge_eval(main_eval, pr_exact, "pr_exact") merge_eval(main_eval, pr_f1, "pr_f1") merge_eval(main_eval, pr_oracle, "pr_oracle")
[docs]def histogram_na_prob(na_probs, qid_list, image_dir, name): # pragma: no cover if not qid_list: return x = [na_probs[k] for k in qid_list] weights = np.ones_like(x) / float(len(x)) plt.hist(x, weights=weights, bins=20, range=(0.0, 1.0)) plt.xlabel("Model probability of no-answer") plt.ylabel("Proportion of dataset") plt.title("Histogram of no-answer probability: %s" % name) plt.savefig(os.path.join(image_dir, "na_prob_hist_%s.png" % name)) plt.clf()
[docs]def find_best_thresh(preds, scores, na_probs, qid_to_has_ans): # pragma: no cover num_no_ans = sum(1 for k in qid_to_has_ans if not qid_to_has_ans[k]) cur_score = num_no_ans best_score = cur_score best_thresh = 0.0 qid_list = sorted(na_probs, key=lambda k: na_probs[k]) for i, qid in enumerate(qid_list): if qid not in scores: continue if qid_to_has_ans[qid]: diff = scores[qid] else: if preds[qid]: diff = -1 else: diff = 0 cur_score += diff if cur_score > best_score: best_score = cur_score best_thresh = na_probs[qid] return 100.0 * best_score / len(scores), best_thresh
[docs]def find_all_best_thresh( main_eval, preds, exact_raw, f1_raw, na_probs, qid_to_has_ans ): # pragma: no cover best_exact, exact_thresh = find_best_thresh(preds, exact_raw, na_probs, qid_to_has_ans) best_f1, f1_thresh = find_best_thresh(preds, f1_raw, na_probs, qid_to_has_ans) main_eval["best_exact"] = best_exact main_eval["best_exact_thresh"] = exact_thresh main_eval["best_f1"] = best_f1 main_eval["best_f1_thresh"] = f1_thresh
[docs]def evaluate(dataset, na_probs, preds, na_prob_thresh=1.0): qid_to_has_ans = make_qid_to_has_ans(dataset) # maps qid to True/False has_ans_qids = [k for k, v in qid_to_has_ans.items() if v] no_ans_qids = [k for k, v in qid_to_has_ans.items() if not v] exact_raw, f1_raw = get_raw_scores(dataset, preds) exact_thresh = apply_no_ans_threshold(exact_raw, na_probs, qid_to_has_ans, na_prob_thresh) f1_thresh = apply_no_ans_threshold(f1_raw, na_probs, qid_to_has_ans, na_prob_thresh) out_eval = make_eval_dict(exact_thresh, f1_thresh) if has_ans_qids: has_ans_eval = make_eval_dict(exact_thresh, f1_thresh, qid_list=has_ans_qids) merge_eval(out_eval, has_ans_eval, "HasAns") if no_ans_qids: no_ans_eval = make_eval_dict(exact_thresh, f1_thresh, qid_list=no_ans_qids) merge_eval(out_eval, no_ans_eval, "NoAns") find_all_best_thresh(out_eval, preds, exact_raw, f1_raw, na_probs, qid_to_has_ans) return out_eval
[docs]def main(): # pragma: no cover with open(OPTS.data_file) as f: dataset_json = json.load(f) dataset = dataset_json["data"] with open(OPTS.pred_file) as f: preds = json.load(f) if OPTS.na_prob_file: with open(OPTS.na_prob_file) as f: na_probs = json.load(f) else: na_probs = {k: 0.0 for k in preds} qid_to_has_ans = make_qid_to_has_ans(dataset) # maps qid to True/False has_ans_qids = [k for k, v in qid_to_has_ans.items() if v] no_ans_qids = [k for k, v in qid_to_has_ans.items() if not v] exact_raw, f1_raw = get_raw_scores(dataset, preds) exact_thresh = apply_no_ans_threshold(exact_raw, na_probs, qid_to_has_ans, OPTS.na_prob_thresh) f1_thresh = apply_no_ans_threshold(f1_raw, na_probs, qid_to_has_ans, OPTS.na_prob_thresh) out_eval = make_eval_dict(exact_thresh, f1_thresh) if has_ans_qids: has_ans_eval = make_eval_dict(exact_thresh, f1_thresh, qid_list=has_ans_qids) merge_eval(out_eval, has_ans_eval, "HasAns") if no_ans_qids: no_ans_eval = make_eval_dict(exact_thresh, f1_thresh, qid_list=no_ans_qids) merge_eval(out_eval, no_ans_eval, "NoAns") if OPTS.na_prob_file: find_all_best_thresh(out_eval, preds, exact_raw, f1_raw, na_probs, qid_to_has_ans) if OPTS.na_prob_file and OPTS.out_image_dir: run_precision_recall_analysis( out_eval, exact_raw, f1_raw, na_probs, qid_to_has_ans, OPTS.out_image_dir ) histogram_na_prob(na_probs, has_ans_qids, OPTS.out_image_dir, "hasAns") histogram_na_prob(na_probs, no_ans_qids, OPTS.out_image_dir, "noAns") if OPTS.out_file: with open(OPTS.out_file, "w") as f: json.dump(out_eval, f) else: print(json.dumps(out_eval, indent=2))
if __name__ == "__main__": # pragma: no cover OPTS = parse_args() if OPTS.out_image_dir: import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt main()
================================================ FILE: docs/_build/html/_modules/claf/metric/wikisql_official.html ================================================ claf.metric.wikisql_official — CLaF 0.2.0 documentation

Source code for claf.metric.wikisql_official

""" Official evaluation script for WikiSQL dataset. """

import json
from argparse import ArgumentParser
from tqdm import tqdm
from claf.metric.wikisql_lib.dbengine import DBEngine
from claf.metric.wikisql_lib.query import Query


[docs]def count_lines(fname): # pragma: no cover with open(fname) as f: return sum(1 for line in f)
[docs]def evaluate(labels, predictions, db_path, ordered=True): # pragma: no cover """ labels and predictions: dictionary {data_uid: sql_data, ...} """ engine = DBEngine(db_path) exact_match, grades = [], [] for idx, data_uid in enumerate(predictions): eg = labels[data_uid] ep = predictions[data_uid] qg = eg["sql_query"] gold = eg["execution_result"] pred = ep.get("error", None) qp = None if not ep.get("error", None): try: qp = Query.from_dict(ep["query"], ordered=ordered) pred = engine.execute_query(ep["table_id"], qp, lower=True) except Exception as e: pred = repr(e) correct = pred == gold match = qp == qg grades.append(correct) exact_match.append(match) return { "ex_accuracy": sum(grades) / len(grades) * 100.0, "lf_accuracy": sum(exact_match) / len(exact_match) * 100.0, }
if __name__ == "__main__": # pragma: no cover parser = ArgumentParser() parser.add_argument("source_file", help="source file for the prediction") parser.add_argument("db_file", help="source database for the prediction") parser.add_argument("pred_file", help="predictions by the model") parser.add_argument( "--ordered", action="store_true", help="whether the exact match should consider the order of conditions", ) args = parser.parse_args() engine = DBEngine(args.db_file) exact_match = [] with open(args.source_file) as fs, open(args.pred_file) as fp: grades = [] for ls, lp in tqdm(zip(fs, fp), total=count_lines(args.source_file)): eg = json.loads(ls) ep = json.loads(lp) qg = Query.from_dict(eg["sql"], ordered=args.ordered) gold = engine.execute_query(eg["table_id"], qg, lower=True) pred = ep.get("error", None) qp = None if not ep.get("error", None): try: qp = Query.from_dict(ep["query"], ordered=args.ordered) pred = engine.execute_query(eg["table_id"], qp, lower=True) except Exception as e: pred = repr(e) correct = pred == gold match = qp == qg grades.append(correct) exact_match.append(match) print( json.dumps( { "ex_accuracy": sum(grades) / len(grades), "lf_accuracy": sum(exact_match) / len(exact_match), }, indent=2, ) )
================================================ FILE: docs/_build/html/_modules/claf/model/base.html ================================================ claf.model.base — CLaF 0.2.0 documentation

Source code for claf.model.base


import json
from pathlib import Path

import torch.nn as nn


[docs]class ModelBase(nn.Module): """ Model Base Class Args: token_embedder: (claf.tokens.token_embedder.base) TokenEmbedder """ def __init__(self): super(ModelBase, self).__init__()
[docs] def forward(self, inputs): raise NotImplementedError
[docs] def make_metrics(self, predictions): raise NotImplementedError
[docs] def make_predictions(self, features): """ for Metrics """ raise NotImplementedError
[docs] def predict(self, features): """ Inference """ raise NotImplementedError
[docs] def print_examples(self, params): """ Print evaluation examples """ raise NotImplementedError
[docs] def write_predictions(self, predictions, file_path=None, is_dict=True): data_type = "train" if self.training else "valid" pred_dir = Path(self._log_dir) / "predictions" pred_dir.mkdir(exist_ok=True) if file_path is None: file_path = f"predictions-{data_type}-{self._train_counter.get_display()}.json" pred_path = pred_dir / file_path with open(pred_path, "w") as out_file: if is_dict: out_file.write(json.dumps(predictions, indent=4)) else: out_file.write(predictions)
[docs] def is_ready(self): properties = [ self._config, self._log_dir, # self._dataset, It's set at _run_epoch() # self._metrics, It's set at save() self._train_counter, self._vocabs ] return all([p is not None for p in properties])
@property def config(self): return self._config @config.setter def config(self, config): self._config = config @property def log_dir(self): return self._log_dir @log_dir.setter def log_dir(self, log_dir): self._log_dir = log_dir @property def dataset(self): return self._dataset @dataset.setter def dataset(self, dataset): self._dataset = dataset @property def metrics(self): return self._metrics @metrics.setter def metrics(self, metrics): self._metrics = metrics @property def train_counter(self): return self._train_counter @train_counter.setter def train_counter(self, train_counter): self._train_counter = train_counter @property def vocabs(self): return self._vocabs @vocabs.setter def vocabs(self, vocabs): self._vocabs = vocabs
[docs]class ModelWithTokenEmbedder(ModelBase): def __init__(self, token_embedder): super(ModelWithTokenEmbedder, self).__init__() self.token_embedder = token_embedder if token_embedder is not None: self._vocabs = token_embedder.vocabs
[docs]class ModelWithoutTokenEmbedder(ModelBase): def __init__(self, token_makers): super(ModelWithoutTokenEmbedder, self).__init__() self.token_makers = token_makers self._vocabs = { token_name: token_maker.vocab for token_name, token_maker in token_makers.items() }
================================================ FILE: docs/_build/html/_modules/claf/model/cls_utils.html ================================================ claf.model.cls_utils — CLaF 0.2.0 documentation

Source code for claf.model.cls_utils

import csv
from collections import defaultdict

from seqeval.metrics.sequence_labeling import get_entities


# pycm
[docs]def write_confusion_matrix_to_csv(file_path, pycm_obj): with open(file_path + ".csv", "w") as f: indicator = "target/predict" fieldnames = [indicator] + pycm_obj.classes + ["FN"] writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() data = dict(pycm_obj.matrix) FN = dict(pycm_obj.FN) for row_idx in fieldnames[1:-1]: # remove indicator and FN row = {indicator: row_idx} row.update( { col_idx: data[row_idx][col_idx] for col_idx in data[row_idx] if col_idx in fieldnames } ) row.update({"FN": FN[row_idx]}) writer.writerow(row) row = {indicator: "FP"} row.update(dict(pycm_obj.FP)) writer.writerow(row)
# seqeval
[docs]def get_tag_dict(sequence, tag_texts): words = sequence.split() entities = get_entities(tag_texts) slots = defaultdict(list) for slot, start_idx, end_idx in entities: slots[slot].append(" ".join(words[start_idx : end_idx + 1])) return dict(slots)
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/bert.html ================================================ claf.model.reading_comprehension.bert — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.bert



from overrides import overrides
from pytorch_transformers import BertForQuestionAnswering
import torch.nn as nn

from claf.data.data_handler import CachePath
from claf.decorator import register
from claf.model.base import ModelWithoutTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv1ForBert


[docs]@register("model:bert_for_qa") class BertForQA(SQuADv1ForBert, ModelWithoutTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] pretrained_model_name: the name of a pre-trained model answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} """ def __init__(self, token_makers, lang_code="en", pretrained_model_name=None, answer_maxlen=30): super(BertForQA, self).__init__(token_makers) self.lang_code = lang_code self.use_pytorch_transformers = True # for optimizer's model parameters self.answer_maxlen = answer_maxlen self.model = BertForQuestionAnswering.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] attention_mask = (bert_inputs > 0).long() span_start_logits, span_end_logits = self.model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # If we are on multi-GPU, split add a dimension if len(answer_start_idx.size()) > 1: answer_start_idx = answer_start_idx.squeeze(-1) if len(answer_end_idx.size()) > 1: answer_end_idx = answer_end_idx.squeeze(-1) # sometimes the start/end positions are outside our model inputs, we ignore these terms ignored_index = span_start_logits.size(1) answer_start_idx.clamp_(0, ignored_index) answer_end_idx.clamp_(0, ignored_index) # Loss criterion = nn.CrossEntropyLoss(ignore_index=ignored_index) loss = criterion(span_start_logits, answer_start_idx) loss += criterion(span_end_logits, answer_end_idx) loss /= 2 # (start + end) output_dict["loss"] = loss return output_dict
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/bert_for_qa.html ================================================ claf.model.reading_comprehension.bert_for_qa — CLaF 0.1.6 documentation

Source code for claf.model.reading_comprehension.bert_for_qa



from overrides import overrides
from pytorch_transformers import BertForQuestionAnswering
import torch.nn as nn

from claf.data.data_handler import CachePath
from claf.decorator import register
from claf.model.base import ModelWithoutTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv1


[docs]@register("model:bert_for_qa") class BertForQA(SQuADv1, ModelWithoutTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] pretrained_model_name: the name of a pre-trained model answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} """ def __init__(self, token_makers, lang_code="en", pretrained_model_name=None, answer_maxlen=30): super(BertForQA, self).__init__(token_makers) self.lang_code = lang_code self.bert = True # for optimizer's model parameters self.answer_maxlen = answer_maxlen self.model = BertForQuestionAnswering.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - answer_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] attention_mask = (bert_inputs > 0).long() span_start_logits, span_end_logits = self.model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: answer_idx = labels["answer_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["answer_idx"] = answer_idx # If we are on multi-GPU, split add a dimension if len(answer_start_idx.size()) > 1: answer_start_idx = answer_start_idx.squeeze(-1) if len(answer_end_idx.size()) > 1: answer_end_idx = answer_end_idx.squeeze(-1) # sometimes the start/end positions are outside our model inputs, we ignore these terms ignored_index = span_start_logits.size(1) answer_start_idx.clamp_(0, ignored_index) answer_end_idx.clamp_(0, ignored_index) # Loss criterion = nn.CrossEntropyLoss(ignore_index=ignored_index) loss = criterion(span_start_logits, answer_start_idx) loss += criterion(span_end_logits, answer_end_idx) loss /= 2 # (start + end) output_dict["loss"] = loss return output_dict
[docs] @overrides def make_metrics(self, predictions): """ BERT predictions need to get nbest result """ best_predictions = {} for index, prediction in predictions.items(): qid = self._dataset.get_qid(index) predict_text = prediction["predict_text"] start_logit = prediction["start_logits"][prediction["pred_span_start"]] end_logit = prediction["end_logits"][prediction["pred_span_end"]] predict_score = start_logit.item() + end_logit.item() if qid not in best_predictions: best_predictions[qid] = [] best_predictions[qid].append((predict_text, predict_score)) for qid, predictions in best_predictions.items(): sorted_predictions = sorted(predictions, key=lambda x: x[1], reverse=True) best_predictions[qid] = sorted_predictions[0][0] self.write_predictions(best_predictions) return self._make_metrics_with_official(best_predictions)
[docs] @overrides def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - answer_idx: question id - best_span: calculate the span_start_logits and span_end_logits to what is the best span arguments: arguments dictionary consisting of user_input helper: dictionary for helping get answer * Returns: span: predict best_span """ context_text = arguments["context"] bert_tokens = helper["bert_token"] predictions = [ (best_span, start_logits, end_logits) for best_span, start_logits, end_logits in zip( list(output_dict["best_span"].data), list(output_dict["start_logits"].data), list(output_dict["end_logits"].data), ) ] best_predictions = [] for index, prediction in enumerate(predictions): bert_token = bert_tokens[index] best_span, start_logits, end_logits = prediction pred_start, pred_end = best_span predict_text = "" if ( pred_start < len(bert_token) and pred_end < len(bert_token) and bert_token[pred_start].text_span is not None and bert_token[pred_end].text_span is not None ): char_start = bert_token[pred_start].text_span[0] char_end = bert_token[pred_end].text_span[1] predict_text = context_text[char_start:char_end] start_logit = start_logits[pred_start] end_logit = end_logits[pred_end] predict_score = start_logit.item() + end_logit.item() best_predictions.append((predict_text, predict_score)) sorted_predictions = sorted(best_predictions, key=lambda x: x[1], reverse=True) return {"text": sorted_predictions[0][0], "score": sorted_predictions[0][1]}
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/bidaf.html ================================================ claf.model.reading_comprehension.bidaf — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.bidaf


from overrides import overrides
import torch
import torch.nn as nn

from claf.decorator import register
from claf.model.base import ModelWithTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv1
import claf.modules.functional as f
import claf.modules.attention as attention
import claf.modules.layer as layer


[docs]@register("model:bidaf") class BiDAF(SQuADv1, ModelWithTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in BiDAF: Bidirectional Attention Flow for Machine Comprehension (https://arxiv.org/abs/1611.01603) - Embedding (Word + Char -> Contextual) - Attention Flow - Modeling (RNN) - Output * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension contextual_rnn_num_layer: the number of recurrent layers (contextual) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=None, model_dim=100, contextual_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, ): super(BiDAF, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_highway = layer.Highway(context_embed_dim) self.context_contextual_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) self.query_highway = layer.Highway(query_embed_dim) self.query_contextual_rnn = nn.LSTM( input_size=query_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) else: highway = layer.Highway(query_embed_dim) self.context_highway = highway self.query_highway = highway contextual_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) self.context_contextual_rnn = contextual_rnn self.query_contextual_rnn = contextual_rnn self.attention = attention.BiAttention(model_dim) self.modeling_rnn = nn.LSTM( input_size=8 * model_dim, hidden_size=model_dim, num_layers=modeling_rnn_num_layer, bidirectional=True, dropout=dropout, batch_first=True, ) self.output_end_rnn = nn.LSTM( input_size=14 * model_dim, hidden_size=model_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_start_linear = nn.Linear(10 * model_dim, 1) self.span_end_linear = nn.Linear(10 * model_dim, 1) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding Layer (Char + Word -> Contextual) query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() query_mask = f.get_mask_from_tokens(question).float() B, C_L = context_embed.size(0), context_embed.size(1) context_embed = self.context_highway(context_embed) query_embed = self.query_highway(query_embed) context_encoded = f.forward_rnn_with_pack( self.context_contextual_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_encoded = f.forward_rnn_with_pack( self.query_contextual_rnn, query_embed, query_seq_config ) query_encoded = self.dropout(query_encoded) # Attention Flow Layer attention_context_query = self.attention( context_encoded, context_mask, query_encoded, query_mask ) # Modeling Layer modeled_context = f.forward_rnn_with_pack( self.modeling_rnn, attention_context_query, context_seq_config ) modeled_context = self.dropout(modeled_context) M_D = modeled_context.size(-1) # Output Layer span_start_input = self.dropout( torch.cat([attention_context_query, modeled_context], dim=-1) ) # (B, C_L, 10d) span_start_logits = self.span_start_linear(span_start_input).squeeze(-1) # (B, C_L) span_start_probs = f.masked_softmax(span_start_logits, context_mask) span_start_representation = f.weighted_sum( attention=span_start_probs, matrix=modeled_context ) tiled_span_start_representation = span_start_representation.unsqueeze(1).expand(B, C_L, M_D) span_end_representation = torch.cat( [ attention_context_query, modeled_context, tiled_span_start_representation, modeled_context * tiled_span_start_representation, ], dim=-1, ) encoded_span_end = f.forward_rnn_with_pack( self.output_end_rnn, span_end_representation, context_seq_config ) encoded_span_end = self.dropout(encoded_span_end) span_end_input = self.dropout( torch.cat([attention_context_query, encoded_span_end], dim=-1) ) span_end_logits = self.span_end_linear(span_end_input).squeeze(-1) # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/bidaf_no_answer.html ================================================ claf.model.reading_comprehension.bidaf_no_answer — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.bidaf_no_answer


from overrides import overrides
import torch
import torch.nn as nn

from claf.decorator import register
from claf.model.base import ModelWithTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv2
import claf.modules.functional as f
import claf.modules.attention as attention
import claf.modules.layer as layer


[docs]@register("model:bidaf_no_answer") class BiDAF_No_Answer(SQuADv2, ModelWithTokenEmbedder): """ Question Answering Model. `Span Detector`, `No Answer` Bidirectional Attention Flow for Machine Comprehension + Bias (No_Answer) - Embedding (Word + Char -> Contextual) - Attention Flow - Modeling (RNN) - Output * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=None, model_dim=100, contextual_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, ): super(BiDAF_No_Answer, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_highway = layer.Highway(context_embed_dim) self.context_contextual_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) self.query_highway = layer.Highway(query_embed_dim) self.query_contextual_rnn = nn.LSTM( input_size=query_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) else: highway = layer.Highway(query_embed_dim) self.context_highway = highway self.query_highway = highway contextual_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, bidirectional=True, num_layers=contextual_rnn_num_layer, batch_first=True, ) self.context_contextual_rnn = contextual_rnn self.query_contextual_rnn = contextual_rnn self.attention = attention.BiAttention(model_dim) self.modeling_rnn = nn.LSTM( input_size=8 * model_dim, hidden_size=model_dim, num_layers=modeling_rnn_num_layer, bidirectional=True, dropout=dropout, batch_first=True, ) self.output_end_rnn = nn.LSTM( input_size=14 * model_dim, hidden_size=model_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_start_linear = nn.Linear(10 * model_dim, 1) self.span_end_linear = nn.Linear(10 * model_dim, 1) self.bias = nn.Parameter(torch.randn(1, 1)) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding Layer (Char + Word -> Contextual) query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() query_mask = f.get_mask_from_tokens(question).float() B, C_L = context_embed.size(0), context_embed.size(1) context_embed = self.context_highway(context_embed) query_embed = self.query_highway(query_embed) context_encoded = f.forward_rnn_with_pack( self.context_contextual_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_encoded = f.forward_rnn_with_pack( self.query_contextual_rnn, query_embed, query_seq_config ) query_encoded = self.dropout(query_encoded) # Attention Flow Layer attention_context_query = self.attention( context_encoded, context_mask, query_encoded, query_mask ) # Modeling Layer modeled_context = f.forward_rnn_with_pack( self.modeling_rnn, attention_context_query, context_seq_config ) modeled_context = self.dropout(modeled_context) M_D = modeled_context.size(-1) # Output Layer span_start_input = self.dropout( torch.cat([attention_context_query, modeled_context], dim=-1) ) # (B, C_L, 10d) span_start_logits = self.span_start_linear(span_start_input).squeeze(-1) # (B, C_L) span_start_probs = f.masked_softmax(span_start_logits, context_mask) span_start_representation = f.weighted_sum( attention=span_start_probs, matrix=modeled_context ) tiled_span_start_representation = span_start_representation.unsqueeze(1).expand(B, C_L, M_D) span_end_representation = torch.cat( [ attention_context_query, modeled_context, tiled_span_start_representation, modeled_context * tiled_span_start_representation, ], dim=-1, ) encoded_span_end = f.forward_rnn_with_pack( self.output_end_rnn, span_end_representation, context_seq_config ) encoded_span_end = self.dropout(encoded_span_end) span_end_input = self.dropout( torch.cat([attention_context_query, encoded_span_end], dim=-1) ) span_end_logits = self.span_end_linear(span_end_input).squeeze(-1) # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) # No_Answer Bias bias = self.bias.expand(B, 1) span_start_logits = torch.cat([span_start_logits, bias], dim=-1) span_end_logits = torch.cat([span_end_logits, bias], dim=-1) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits[:, :-1], span_end_logits[:, :-1], answer_maxlen=self.answer_maxlen, # except no_answer bias ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] answerable = labels["answerable"] # No_Asnwer Case C_L = context_mask.size(1) answer_start_idx = answer_start_idx.masked_fill(answerable.eq(0), C_L) answer_end_idx = answer_end_idx.masked_fill(answerable.eq(0), C_L) output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/docqa.html ================================================ claf.model.reading_comprehension.docqa — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.docqa

from overrides import overrides
import torch
import torch.nn as nn
import torch.nn.functional as F

from claf.decorator import register
from claf.model.base import ModelWithTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv1
from claf.modules import attention, initializer
from claf.modules import functional as f


[docs]@register("model:docqa") class DocQA(SQuADv1, ModelWithTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in Simple and Effective Multi-Paragraph Reading Comprehension (https://arxiv.org/abs/1710.10723) - Embedding (Word + Char -> Contextual) - Attention - Residual self-attention - Output * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} rnn_dim: the number of RNN cell dimension linear_dim: the number of attention linear dimension preprocess_rnn_num_layer: the number of recurrent layers (preprocess) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=17, rnn_dim=100, linear_dim=200, preprocess_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, weight_init=True, ): super(DocQA, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_preprocess_rnn = nn.GRU( input_size=context_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) self.query_preprocess_rnn = nn.GRU( input_size=query_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) else: preprocess_rnn = nn.GRU( input_size=context_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) self.context_preprocess_rnn = preprocess_rnn self.query_preprocess_rnn = preprocess_rnn self.bi_attention = attention.DocQAAttention(rnn_dim, linear_dim) self.attn_linear = nn.Linear(rnn_dim * 8, linear_dim) self.modeling_rnn = nn.GRU( input_size=linear_dim, hidden_size=rnn_dim, num_layers=modeling_rnn_num_layer, bidirectional=True, batch_first=True, ) self.self_attention = SelfAttention(rnn_dim, linear_dim, weight_init=weight_init) self.span_start_rnn = nn.GRU( input_size=linear_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_start_linear = nn.Linear(rnn_dim * 2, 1) self.span_end_rnn = nn.GRU( input_size=linear_dim + rnn_dim * 2, hidden_size=rnn_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_end_linear = nn.Linear(rnn_dim * 2, 1) self.activation_fn = F.relu self.criterion = nn.CrossEntropyLoss() if weight_init: modules = [ self.context_preprocess_rnn, self.query_preprocess_rnn, self.modeling_rnn, self.attn_linear, self.span_start_rnn, self.span_start_linear, self.span_end_rnn, self.span_end_linear, ] initializer.weight(modules)
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() # B X 1 X C_L query_mask = f.get_mask_from_tokens(question).float() # B X 1 X Q_L # Pre-process context_embed = self.dropout(context_embed) context_encoded = f.forward_rnn_with_pack( self.context_preprocess_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_embed = self.dropout(query_embed) query_encoded = f.forward_rnn_with_pack( self.query_preprocess_rnn, query_embed, query_seq_config ) query_encoded = self.dropout(query_encoded) # Attention -> Projection context_attnded = self.bi_attention( context_encoded, context_mask, query_encoded, query_mask ) context_attnded = self.activation_fn(self.attn_linear(context_attnded)) # B X C_L X dim*2 # Residual Self-Attention context_attnded = self.dropout(context_attnded) context_encoded = f.forward_rnn_with_pack( self.modeling_rnn, context_attnded, context_seq_config ) context_encoded = self.dropout(context_encoded) context_self_attnded = self.self_attention(context_encoded, context_mask) # B X C_L X dim*2 context_final = self.dropout(context_attnded + context_self_attnded) # B X C_L X dim*2 # Prediction span_start_input = f.forward_rnn_with_pack( self.span_start_rnn, context_final, context_seq_config ) # B X C_L X dim*2 span_start_input = self.dropout(span_start_input) span_start_logits = self.span_start_linear(span_start_input).squeeze(-1) # B X C_L span_end_input = torch.cat([span_start_input, context_final], dim=-1) # B X C_L X dim*4 span_end_input = f.forward_rnn_with_pack( self.span_end_rnn, span_end_input, context_seq_config ) # B X C_L X dim*2 span_end_input = self.dropout(span_end_input) span_end_logits = self.span_end_linear(span_end_input).squeeze(-1) # B X C_L # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs]class SelfAttention(nn.Module): """ Same bi-attention mechanism, only now between the passage and itself. """ def __init__(self, rnn_dim, linear_dim, dropout=0.2, weight_init=True): super(SelfAttention, self).__init__() self.self_attention = attention.DocQAAttention( rnn_dim, linear_dim, self_attn=True, weight_init=weight_init ) self.self_attn_Linear = nn.Linear(rnn_dim * 6, linear_dim) self.dropout = nn.Dropout(p=dropout) self.activation_fn = F.relu if weight_init: initializer.weight(self.self_attn_Linear)
[docs] def forward(self, context, context_mask): context_self_attnded = self.self_attention(context, context_mask, context, context_mask) return self.activation_fn(self.self_attn_Linear(context_self_attnded))
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/docqa_no_answer.html ================================================ claf.model.reading_comprehension.docqa_no_answer — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.docqa_no_answer

from overrides import overrides
import torch
import torch.nn as nn
import torch.nn.functional as F

from claf.decorator import register
from claf.model.base import ModelWithTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv2
from claf.modules import attention, initializer
from claf.modules import functional as f


[docs]@register("model:docqa_no_answer") class DocQA_No_Answer(SQuADv2, ModelWithTokenEmbedder): """ Question Answering Model. `Span Detector`, `No Answer` Implementation of model presented in Simple and Effective Multi-Paragraph Reading Comprehension + No_Asnwer (https://arxiv.org/abs/1710.10723) - Embedding (Word + Char -> Contextual) - Attention - Residual self-attention - Output * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} rnn_dim: the number of RNN cell dimension linear_dim: the number of attention linear dimension preprocess_rnn_num_layer: the number of recurrent layers (preprocess) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=17, rnn_dim=100, linear_dim=200, preprocess_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, weight_init=True, ): super(DocQA_No_Answer, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_preprocess_rnn = nn.GRU( input_size=context_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) self.query_preprocess_rnn = nn.GRU( input_size=query_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) else: preprocess_rnn = nn.GRU( input_size=context_embed_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=preprocess_rnn_num_layer, batch_first=True, ) self.context_preprocess_rnn = preprocess_rnn self.query_preprocess_rnn = preprocess_rnn self.bi_attention = attention.DocQAAttention(rnn_dim, linear_dim) self.attn_linear = nn.Linear(rnn_dim * 8, linear_dim) self.modeling_rnn = nn.GRU( input_size=linear_dim, hidden_size=rnn_dim, num_layers=modeling_rnn_num_layer, bidirectional=True, batch_first=True, ) self.self_attention = SelfAttention(rnn_dim, linear_dim, weight_init=weight_init) self.span_start_rnn = nn.GRU( input_size=linear_dim, hidden_size=rnn_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_start_linear = nn.Linear(rnn_dim * 2, 1) self.span_end_rnn = nn.GRU( input_size=linear_dim + rnn_dim * 2, hidden_size=rnn_dim, bidirectional=True, num_layers=predict_rnn_num_layer, batch_first=True, ) self.span_end_linear = nn.Linear(rnn_dim * 2, 1) self.no_answer_op = NoAnswer(context_embed_dim, 80) self.activation_fn = F.relu self.criterion = nn.CrossEntropyLoss() if weight_init: modules = [ self.context_preprocess_rnn, self.query_preprocess_rnn, self.modeling_rnn, self.attn_linear, self.span_start_rnn, self.span_start_linear, self.span_end_rnn, self.span_end_linear, ] initializer.weight(modules)
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() # B X C_L query_mask = f.get_mask_from_tokens(question).float() # B X Q_L # Pre-process context_embed = self.dropout(context_embed) context_encoded = f.forward_rnn_with_pack( self.context_preprocess_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_embed = self.dropout(query_embed) query_encoded = f.forward_rnn_with_pack( self.query_preprocess_rnn, query_embed, query_seq_config ) query_encoded = self.dropout(query_encoded) # Attention -> Projection context_attnded = self.bi_attention( context_encoded, context_mask, query_encoded, query_mask ) context_attnded = self.activation_fn(self.attn_linear(context_attnded)) # B X C_L X dim*2 # Residual Self-Attention context_attnded = self.dropout(context_attnded) context_encoded = f.forward_rnn_with_pack( self.modeling_rnn, context_attnded, context_seq_config ) context_encoded = self.dropout(context_encoded) context_self_attnded = self.self_attention(context_encoded, context_mask) # B X C_L X dim*2 context_final = self.dropout(context_attnded + context_self_attnded) # B X C_L X dim*2 # Prediction span_start_input = f.forward_rnn_with_pack( self.span_start_rnn, context_final, context_seq_config ) # B X C_L X dim*2 span_start_input = self.dropout(span_start_input) span_start_logits = self.span_start_linear(span_start_input).squeeze(-1) # B X C_L span_end_input = torch.cat([span_start_input, context_final], dim=-1) # B X C_L X dim*4 span_end_input = f.forward_rnn_with_pack( self.span_end_rnn, span_end_input, context_seq_config ) # B X C_L X dim*2 span_end_input = self.dropout(span_end_input) span_end_logits = self.span_end_linear(span_end_input).squeeze(-1) # B X C_L # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) # No_Asnwer Option bias = self.no_answer_op(context_embed, span_start_logits, span_end_logits) span_start_logits = torch.cat([span_start_logits, bias], dim=-1) span_end_logits = torch.cat([span_end_logits, bias], dim=-1) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits[:, :-1], span_end_logits[:, :-1], answer_maxlen=self.answer_maxlen, # except no_answer bias ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] answerable = labels["answerable"] # No_Asnwer Case C_L = context_mask.size(1) answer_start_idx = answer_start_idx.masked_fill(answerable.eq(0), C_L) answer_end_idx = answer_end_idx.masked_fill(answerable.eq(0), C_L) output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs]class SelfAttention(nn.Module): """ Same bi-attention mechanism, only now between the passage and itself. """ def __init__(self, rnn_dim, linear_dim, dropout=0.2, weight_init=True): super(SelfAttention, self).__init__() self.self_attention = attention.DocQAAttention( rnn_dim, linear_dim, self_attn=True, weight_init=weight_init ) self.self_attn_Linear = nn.Linear(rnn_dim * 6, linear_dim) self.dropout = nn.Dropout(p=dropout) self.activation_fn = F.relu if weight_init: initializer.weight(self.self_attn_Linear)
[docs] def forward(self, context, context_mask): context_self_attnded = self.self_attention(context, context_mask, context, context_mask) context_self_attnded = self.activation_fn(self.self_attn_Linear(context_self_attnded)) return context_self_attnded
[docs]class NoAnswer(nn.Module): """ No-Answer Option * Args: embed_dim: the number of passage embedding dimension bias_hidden_dim: bias use two layer mlp, the number of hidden_size """ def __init__(self, embed_dim, bias_hidden_dim): super(NoAnswer, self).__init__() self.self_attn = nn.Linear(embed_dim, 1) self.bias_mlp = nn.Sequential( nn.Linear(embed_dim * 3, bias_hidden_dim), nn.ReLU(), nn.Linear(bias_hidden_dim, 1) )
[docs] def forward(self, context_embed, span_start_logits, span_end_logits): p_1_h = F.softmax(span_start_logits, -1).unsqueeze(1) # B,1,T p_2_h = F.softmax(span_end_logits, -1).unsqueeze(1) # B,1,T p_3_h = self.self_attn(context_embed).transpose(1, 2) # B,1,T v_1 = torch.matmul(p_1_h, context_embed) # B,1,D v_2 = torch.matmul(p_2_h, context_embed) # B,1,D v_3 = torch.matmul(p_3_h, context_embed) # B,1,D return self.bias_mlp(torch.cat([v_1, v_2, v_3], -1)).squeeze(-1)
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/drqa.html ================================================ claf.model.reading_comprehension.drqa — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.drqa

from overrides import overrides

import torch.nn as nn

from claf.decorator import register
from claf.model.base import ModelWithTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv1
import claf.modules.functional as f
import claf.modules.attention as attention


[docs]@register("model:drqa") class DrQA(SQuADv1, ModelWithTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in Reading Wikipedia to Answer Open-Domain Questions (https://arxiv.org/abs/1704.00051) - Embedding + features - Align question embedding * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension dropout: the dropout probability """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=None, model_dim=128, dropout=0.3, ): super(DrQA, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder self.dropout = nn.Dropout(p=dropout) context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim self.paragraph_rnn = nn.LSTM( input_size=context_embed_dim, hidden_size=model_dim, num_layers=3, dropout=dropout, bidirectional=True, batch_first=True, ) self.query_rnn = nn.LSTM( input_size=query_embed_dim, hidden_size=model_dim, num_layers=3, dropout=dropout, bidirectional=True, batch_first=True, ) self.query_att = attention.LinearSeqAttn(model_dim * 2) self.start_attn = attention.BilinearSeqAttn(model_dim * 2, model_dim * 2) self.end_attn = attention.BilinearSeqAttn(model_dim * 2, model_dim * 2) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] # aka paragraph question = features["question"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward context_seq_config = f.get_sorted_seq_config(context) query_seq_config = f.get_sorted_seq_config(question) # Embedding query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() query_mask = f.get_mask_from_tokens(question).float() context_embed = self.dropout(context_embed) query_embed = self.dropout(query_embed) # RNN (LSTM) context_encoded = f.forward_rnn_with_pack( self.paragraph_rnn, context_embed, context_seq_config ) context_encoded = self.dropout(context_encoded) query_encoded = f.forward_rnn_with_pack( self.query_rnn, query_embed, query_seq_config ) # (B, Q_L, H*2) query_encoded = self.dropout(query_encoded) query_attention = self.query_att(query_encoded, query_mask) # (B, Q_L) query_att_sum = f.weighted_sum(query_attention, query_encoded) # (B, H*2) span_start_logits = self.start_attn(context_encoded, query_att_sum, context_mask) span_end_logits = self.end_attn(context_encoded, query_att_sum, context_mask) # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) return output_dict
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/mixin.html ================================================ claf.model.reading_comprehension.mixin — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.mixin


from collections import OrderedDict

import numpy as np
import torch
import torch.nn.functional as F

from claf.decorator import arguments_required
from claf.metric import korquad_v1_official, squad_v1_official, squad_v2_official
from claf.model.base import ModelBase


[docs]class ReadingComprehension: """ Reading Comprehension Mixin Class * Args: token_embedder: 'RCTokenEmbedder', Used to embed the 'context' and 'question'. """
[docs] def get_best_span(self, span_start_logits, span_end_logits, answer_maxlen=None): """ Take argmax of constrained score_s * score_e. * Args: span_start_logits: independent start logits span_end_logits: independent end logits * Kwargs: answer_maxlen: max span length to consider (default is None -> All) """ B = span_start_logits.size(0) best_word_span = span_start_logits.new_zeros((B, 2), dtype=torch.long) score_starts = F.softmax(span_start_logits, dim=-1) score_ends = F.softmax(span_end_logits, dim=-1) max_len = answer_maxlen or score_starts.size(1) for i in range(score_starts.size(0)): # Outer product of scores to get full p_s * p_e matrix scores = torch.ger(score_starts[i], score_ends[i]) # Zero out negative length and over-length span scores scores.triu_().tril_(max_len - 1) # Take argmax or top n scores = scores.detach().cpu().numpy() scores_flat = scores.flatten() idx_sort = [np.argmax(scores_flat)] s_idx, e_idx = np.unravel_index(idx_sort, scores.shape) best_word_span[i, 0] = int(s_idx[0]) best_word_span[i, 1] = int(e_idx[0]) return best_word_span
def _make_span_metrics(self, predictions): """ span accuracy metrics """ start_accuracy, end_accuracy, span_accuracy = 0, 0, 0 for index, preds in predictions.items(): _, _, (answer_start, answer_end) = self._dataset.get_ground_truths(index) start_acc = 1 if preds["pred_span_start"] == answer_start else 0 end_acc = 1 if preds["pred_span_end"] == answer_end else 0 span_acc = 1 if start_acc == 1 and end_acc == 1 else 0 start_accuracy += start_acc end_accuracy += end_acc span_accuracy += span_acc start_accuracy = 100.0 * start_accuracy / len(self._dataset) end_accuracy = 100.0 * end_accuracy / len(self._dataset) span_accuracy = 100.0 * span_accuracy / len(self._dataset) return {"start_acc": start_accuracy, "end_acc": end_accuracy, "span_acc": span_accuracy}
[docs] def make_predictions(self, output_dict): """ Make predictions with model's output_dict * Args: output_dict: model's output dictionary consisting of - data_idx: question id - best_span: calculate the span_start_logits and span_end_logits to what is the best span - start_logits: span start logits - end_logits: span end logits * Returns: predictions: prediction dictionary consisting of - key: 'id' (question id) - value: consisting of dictionary predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob """ data_indices = output_dict["data_idx"] best_word_span = output_dict["best_span"] return OrderedDict( [ ( index.item(), { "predict_text": self._dataset.get_text_with_index( index.item(), best_span[0], best_span[1] ), "pred_span_start": best_span[0], "pred_span_end": best_span[1], "start_logits": start_logits, "end_logits": end_logits, }, ) for index, best_span, start_logits, end_logits in zip( list(data_indices.data), list(best_word_span.data), list(output_dict["start_logits"].data), list(output_dict["end_logits"].data), ) ] )
@arguments_required(["context", "question"]) def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - data_idx: question id - best_span: calculate the span_start_logits and span_end_logits to what is the best span arguments: arguments dictionary consisting of user_input helper: dictionary for helping get answer * Returns: span: predict best_span """ span_start, span_end = list(output_dict["best_span"][0].data) word_start = span_start.item() word_end = span_end.item() text_span = helper["text_span"] char_start = text_span[word_start][0] char_end = text_span[word_end][1] context_text = arguments["context"] answer_text = context_text[char_start:char_end] start_logit = output_dict["start_logits"][0] end_logit = output_dict["end_logits"][0] score = start_logit[span_start] + end_logit[span_end] score = score.item() return {"text": answer_text, "score": score}
[docs] def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (question id) - value: consisting of dictionary predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob * Returns: print(Context, Question, Answers and Predict) """ data_index = inputs["labels"]["data_idx"][index].item() qid = self._dataset.get_qid(data_index) if "#" in qid: # bert case (qid#index) qid = qid.split("#")[0] helper = self._dataset.helper context = helper["examples"][qid]["context"] question = helper["examples"][qid]["question"] answers = helper["examples"][qid]["answers"] predict_text = predictions[data_index]["predict_text"] print() print("- Context:", context) print("- Question:", question) print("- Answers:", answers) print("- Predict:", predict_text) print()
[docs] def write_predictions(self, predictions, file_path=None, is_dict=True): pass
# TODO: start and end logits (TypeError: Object of type 'Tensor' is not JSON serializable) # try: # super(ReadingComprehension, self).write_predictions( # predictions, file_path=file_path, is_dict=is_dict # ) # except AttributeError: # # TODO: Need to Fix # model_base = ModelBase() # model_base._log_dir = self._log_dir # model_base._train_counter = self._train_counter # model_base.training = self.training # model_base.write_predictions(predictions, file_path=file_path, is_dict=is_dict)
[docs]class SQuADv1(ReadingComprehension): """ Reading Comprehension Mixin Class with SQuAD v1.1 evaluation * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. """
[docs] def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (question id) - value: (predict_text, pred_span_start, pred_span_end) * Returns: metrics: metric dictionary consisting of - 'em': exact_match (SQuAD v1.1 official evaluation) - 'f1': f1 (SQuAD v1.1 official evaluation) - 'start_acc': span_start accuracy - 'end_acc': span_end accuracy - 'span_acc': span accuracy (start and end) """ preds = {} for index, prediction in predictions.items(): _, _, (answer_start, answer_end) = self._dataset.get_ground_truths(index) qid = self._dataset.get_qid(index) preds[qid] = prediction["predict_text"] self.write_predictions(preds) squad_offical_metrics = self._make_metrics_with_official(preds) metrics = self._make_span_metrics(predictions) metrics.update(squad_offical_metrics) return metrics
def _make_metrics_with_official(self, preds): """ SQuAD v1.1 official evaluation """ dataset = self._dataset.raw_dataset if self.lang_code.startswith("ko"): scores = korquad_v1_official.evaluate(dataset, preds) else: scores = squad_v1_official.evaluate(dataset, preds) return scores
[docs]class SQuADv1ForBert(SQuADv1): """ Reading Comprehension Mixin Class with SQuAD v1.1 evaluation * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. """
[docs] def make_metrics(self, predictions): """ BERT predictions need to get nbest result """ best_predictions = {} for index, prediction in predictions.items(): qid = self._dataset.get_qid(index) predict_text = prediction["predict_text"] start_logit = prediction["start_logits"][prediction["pred_span_start"]] end_logit = prediction["end_logits"][prediction["pred_span_end"]] predict_score = start_logit.item() + end_logit.item() if qid not in best_predictions: best_predictions[qid] = [] best_predictions[qid].append((predict_text, predict_score)) for qid, predictions in best_predictions.items(): sorted_predictions = sorted(predictions, key=lambda x: x[1], reverse=True) best_predictions[qid] = sorted_predictions[0][0] self.write_predictions(best_predictions) return self._make_metrics_with_official(best_predictions)
[docs] def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - data_idx: question id - best_span: calculate the span_start_logits and span_end_logits to what is the best span arguments: arguments dictionary consisting of user_input helper: dictionary for helping get answer * Returns: span: predict best_span """ context_text = arguments["context"] bert_tokens = helper["bert_token"] predictions = [ (best_span, start_logits, end_logits) for best_span, start_logits, end_logits in zip( list(output_dict["best_span"].data), list(output_dict["start_logits"].data), list(output_dict["end_logits"].data), ) ] best_predictions = [] for index, prediction in enumerate(predictions): bert_token = bert_tokens[index] best_span, start_logits, end_logits = prediction pred_start, pred_end = best_span predict_text = "" if ( pred_start < len(bert_token) and pred_end < len(bert_token) and bert_token[pred_start].text_span is not None and bert_token[pred_end].text_span is not None ): char_start = bert_token[pred_start].text_span[0] char_end = bert_token[pred_end].text_span[1] predict_text = context_text[char_start:char_end] start_logit = start_logits[pred_start] end_logit = end_logits[pred_end] predict_score = start_logit.item() + end_logit.item() best_predictions.append((predict_text, predict_score)) sorted_predictions = sorted(best_predictions, key=lambda x: x[1], reverse=True) return {"text": sorted_predictions[0][0], "score": sorted_predictions[0][1]}
[docs]class SQuADv2(ReadingComprehension): """ Reading Comprehension Mixin Class with SQuAD v2.0 evaluation * Args: token_embedder: 'RCTokenEmbedder', Used to embed the 'context' and 'question'. """
[docs] def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (question id) - value: consisting of dictionary predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob * Returns: metrics: metric dictionary consisting of - 'start_acc': span_start accuracy - 'end_acc': span_end accuracy - 'span_acc': span accuracy (start and end) - 'em': exact_match (SQuAD v2.0 official evaluation) - 'f1': f1 (SQuAD v2.0 official evaluation) - 'HasAns_exact': has answer exact_match - 'HasAns_f1': has answer f1 - 'NoAns_exact': no answer exact_match - 'NoAns_f1': no answer f1 - 'best_exact': best exact_match score with best_exact_thresh - 'best_exact_thresh': best exact_match answerable threshold - 'best_f1': best f1 score with best_f1_thresh - 'best_f1_thresh': best f1 answerable threshold """ preds, na_probs = {}, {} for index, prediction in predictions.items(): _, _, (answer_start, answer_end) = self._dataset.get_ground_truths(index) # Metrics (SQuAD official metric) predict_text = prediction["predict_text"] if predict_text == "<noanswer>": predict_text = "" qid = self._dataset.get_qid(index) preds[qid] = predict_text span_start_probs = F.softmax(prediction["start_logits"], dim=-1) span_end_probs = F.softmax(prediction["end_logits"], dim=-1) start_no_prob = span_start_probs[-1].item() end_no_prob = span_end_probs[-1].item() no_answer_prob = start_no_prob * end_no_prob na_probs[qid] = no_answer_prob self.write_predictions(preds) model_type = "train" if self.training else "valid" self.write_predictions( na_probs, file_path=f"na_probs-{model_type}-{self._train_counter.get_display()}.json" ) squad_offical_metrics = self._make_metrics_with_official(preds, na_probs) metrics = self._make_span_metrics(predictions) metrics.update(squad_offical_metrics) return metrics
def _make_metrics_with_official(self, preds, na_probs, na_prob_thresh=1.0): """ SQuAD 2.0 official evaluation """ dataset = self._dataset.raw_dataset squad_scores = squad_v2_official.evaluate(dataset, na_probs, preds) squad_scores["em"] = squad_scores["exact"] remove_keys = ["total", "exact", "HasAns_total", "NoAns_total"] for key in remove_keys: if key in squad_scores: del squad_scores[key] return squad_scores
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/qanet.html ================================================ claf.model.reading_comprehension.qanet — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.qanet

import torch
import torch.nn as nn

from overrides import overrides

from claf.decorator import register
from claf.model.base import ModelWithTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv1
import claf.modules.functional as f
import claf.modules.attention as attention
import claf.modules.encoder as encoder
import claf.modules.conv as conv
import claf.modules.layer as layer


[docs]@register("model:qanet") class QANet(SQuADv1, ModelWithTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in QANet:Combining Local Convolution with Global Self-Attention for Reading Comprehension (https://arxiv.org/abs/1804.09541) - Input Embedding Layer - Embedding Encoder Layer - Context-Query Attention Layer - Model Encoder Layer - Output Layer * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension * Encoder Block Parameters (embedding, modeling) kernel_size: convolution kernel size in encoder block num_head: the number of multi-head attention's head num_conv_block: the number of convolution block in encoder block [Layernorm -> Conv (residual)] num_encoder_block: the number of the encoder block [position_encoding -> [n repeat conv block] -> Layernorm -> Self-attention (residual) -> Layernorm -> Feedforward (residual)] dropout: the dropout probability layer_dropout: the layer dropout probability (cf. Deep Networks with Stochastic Depth(https://arxiv.org/abs/1603.09382) ) """ def __init__( self, token_embedder, lang_code="en", aligned_query_embedding=False, answer_maxlen=None, model_dim=128, kernel_size_in_embedding=7, num_head_in_embedding=8, num_conv_block_in_embedding=4, num_embedding_encoder_block=1, kernel_size_in_modeling=5, num_head_in_modeling=8, num_conv_block_in_modeling=2, num_modeling_encoder_block=7, dropout=0.1, layer_dropout=0.9, ): super(QANet, self).__init__(token_embedder) self.lang_code = lang_code self.aligned_query_embedding = aligned_query_embedding self.answer_maxlen = answer_maxlen self.token_embedder = token_embedder context_embed_dim, query_embed_dim = token_embedder.get_embed_dim() if self.aligned_query_embedding: context_embed_dim += query_embed_dim if context_embed_dim != query_embed_dim: self.context_highway = layer.Highway(context_embed_dim) self.query_highway = layer.Highway(query_embed_dim) self.context_embed_pointwise_conv = conv.PointwiseConv(context_embed_dim, model_dim) self.query_embed_pointwise_conv = conv.PointwiseConv(query_embed_dim, model_dim) else: highway = layer.Highway(context_embed_dim) self.context_highway = highway self.query_highway = highway embed_pointwise_conv = conv.PointwiseConv(context_embed_dim, model_dim) self.context_embed_pointwise_conv = embed_pointwise_conv self.query_embed_pointwise_conv = embed_pointwise_conv self.embed_encoder_blocks = nn.ModuleList( [ EncoderBlock( model_dim=model_dim, kernel_size=kernel_size_in_embedding, num_head=num_head_in_embedding, num_conv_block=num_conv_block_in_modeling, dropout=dropout, layer_dropout=layer_dropout, ) for _ in range(num_embedding_encoder_block) ] ) self.co_attention = attention.CoAttention(model_dim) self.pointwise_conv = conv.PointwiseConv(model_dim * 4, model_dim) self.model_encoder_blocks = nn.ModuleList( [ EncoderBlock( model_dim=model_dim, kernel_size=kernel_size_in_modeling, num_head=num_head_in_modeling, num_conv_block=num_conv_block_in_modeling, dropout=dropout, layer_dropout=layer_dropout, ) for _ in range(num_modeling_encoder_block) ] ) self.span_start_linear = nn.Linear(model_dim * 2, 1, bias=False) self.span_end_linear = nn.Linear(model_dim * 2, 1, bias=False) self.dropout = nn.Dropout(p=dropout) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ context = features["context"] question = features["question"] # 1. Input Embedding Layer query_params = {"frequent_word": {"frequent_tuning": True}} context_embed, query_embed = self.token_embedder( context, question, query_params=query_params, query_align=self.aligned_query_embedding ) context_mask = f.get_mask_from_tokens(context).float() query_mask = f.get_mask_from_tokens(question).float() context_embed = self.context_highway(context_embed) context_embed = self.dropout(context_embed) context_embed = self.context_embed_pointwise_conv(context_embed) query_embed = self.query_highway(query_embed) query_embed = self.dropout(query_embed) query_embed = self.query_embed_pointwise_conv(query_embed) # 2. Embedding Encoder Layer for encoder_block in self.embed_encoder_blocks: context = encoder_block(context_embed) context_embed = context query = encoder_block(query_embed) query_embed = query # 3. Context-Query Attention Layer context_query_attention = self.co_attention(context, query, context_mask, query_mask) # Projection (memory issue) context_query_attention = self.pointwise_conv(context_query_attention) context_query_attention = self.dropout(context_query_attention) # 4. Model Encoder Layer model_encoder_block_inputs = context_query_attention # Stacked Model Encoder Block stacked_model_encoder_blocks = [] for i in range(3): for _, model_encoder_block in enumerate(self.model_encoder_blocks): output = model_encoder_block(model_encoder_block_inputs, context_mask) model_encoder_block_inputs = output stacked_model_encoder_blocks.append(output) # 5. Output Layer span_start_inputs = torch.cat( [stacked_model_encoder_blocks[0], stacked_model_encoder_blocks[1]], dim=-1 ) span_start_inputs = self.dropout(span_start_inputs) span_start_logits = self.span_start_linear(span_start_inputs).squeeze(-1) span_end_inputs = torch.cat( [stacked_model_encoder_blocks[0], stacked_model_encoder_blocks[2]], dim=-1 ) span_end_inputs = self.dropout(span_end_inputs) span_end_logits = self.span_end_linear(span_end_inputs).squeeze(-1) # Masked Value span_start_logits = f.add_masked_value(span_start_logits, context_mask, value=-1e7) span_end_logits = f.add_masked_value(span_end_logits, context_mask, value=-1e7) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span(span_start_logits, span_end_logits), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # Loss loss = self.criterion(span_start_logits, answer_start_idx) loss += self.criterion(span_end_logits, answer_end_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs]class EncoderBlock(nn.Module): """ Encoder Block []: residual position_encoding -> [convolution-layer] x # -> [self-attention-layer] -> [feed-forward-layer] - convolution-layer: depthwise separable convolutions - self-attention-layer: multi-head attention - feed-forward-layer: pointwise convolution * Args: model_dim: the number of model dimension num_heads: the number of head in multi-head attention kernel_size: convolution kernel size num_conv_block: the number of convolution block dropout: the dropout probability layer_dropout: the layer dropout probability (cf. Deep Networks with Stochastic Depth(https://arxiv.org/abs/1603.09382) ) """ def __init__( self, model_dim=128, num_head=8, kernel_size=5, num_conv_block=4, dropout=0.1, layer_dropout=0.9, ): super(EncoderBlock, self).__init__() self.position_encoding = encoder.PositionalEncoding(model_dim) self.dropout = nn.Dropout(dropout) self.num_conv_block = num_conv_block self.conv_blocks = nn.ModuleList( [conv.DepSepConv(model_dim, model_dim, kernel_size) for _ in range(num_conv_block)] ) self.self_attention = attention.MultiHeadAttention( num_head=num_head, model_dim=model_dim, dropout=dropout ) self.feedforward_layer = layer.PositionwiseFeedForward( model_dim, model_dim * 4, dropout=dropout ) # survival probability for stochastic depth if layer_dropout < 1.0: L = (num_conv_block) + 2 - 1 layer_dropout_prob = round(1 - (1 / L) * (1 - layer_dropout), 3) self.residuals = nn.ModuleList( layer.ResidualConnection( model_dim, layer_dropout=layer_dropout_prob, layernorm=True ) for l in range(num_conv_block + 2) ) else: self.residuals = nn.ModuleList( layer.ResidualConnection(model_dim, layernorm=True) for l in range(num_conv_block + 2) )
[docs] def forward(self, x, mask=None): # Positional Encoding x = self.position_encoding(x) # Convolution Block (LayerNorm -> Conv) for i, conv_block in enumerate(self.conv_blocks): x = self.residuals[i](x, sub_layer_fn=conv_block) x = self.dropout(x) # LayerNorm -> Self-attention self_attention = lambda x: self.self_attention(q=x, k=x, v=x, mask=mask) x = self.residuals[self.num_conv_block](x, sub_layer_fn=self_attention) x = self.dropout(x) # LayerNorm -> Feedforward layer x = self.residuals[self.num_conv_block + 1](x, sub_layer_fn=self.feedforward_layer) x = self.dropout(x) return x
================================================ FILE: docs/_build/html/_modules/claf/model/reading_comprehension/roberta.html ================================================ claf.model.reading_comprehension.roberta — CLaF 0.2.0 documentation

Source code for claf.model.reading_comprehension.roberta


from overrides import overrides
from pytorch_transformers import RobertaModel
import torch.nn as nn

from claf.data.data_handler import CachePath
from claf.decorator import register
from claf.model.base import ModelWithoutTokenEmbedder
from claf.model.reading_comprehension.mixin import SQuADv1ForBert


[docs]@register("model:roberta_for_qa") class RoBertaForQA(SQuADv1ForBert, ModelWithoutTokenEmbedder): """ Document Reader Model. `Span Detector` Implementation of model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: 'QATokenEmbedder', Used to embed the 'context' and 'question'. * Kwargs: lang_code: Dataset language code [en|ko] pretrained_model_name: the name of a pre-trained model answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} """ def __init__(self, token_makers, lang_code="en", pretrained_model_name=None, answer_maxlen=30): super(RoBertaForQA, self).__init__(token_makers) self.lang_code = lang_code self.use_pytorch_transformers = True # for optimizer's model parameters self.answer_maxlen = answer_maxlen self.model = RobertaModel.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.qa_outputs = nn.Linear(self.model.config.hidden_size, self.model.config.num_labels) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"feature_name1": { "token_name1": tensor, "toekn_name2": tensor}, "feature_name2": ...} * Kwargs: label: label dictionary like below. {"label_name1": tensor, "label_name2": tensor} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - start_logits: representing unnormalized log probabilities of the span start position. - end_logits: representing unnormalized log probabilities of the span end position. - best_span: the string from the original passage that the model thinks is the best answer to the question. - data_idx: the question id, mapping with answer - loss: A scalar loss to be optimised. """ bert_inputs = features["bert_input"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self.model( bert_inputs, token_type_ids=None, attention_mask=attention_mask ) sequence_output = outputs[0] logits = self.qa_outputs(sequence_output) span_start_logits, span_end_logits = logits.split(1, dim=-1) span_start_logits = span_start_logits.squeeze(-1) span_end_logits = span_end_logits.squeeze(-1) output_dict = { "start_logits": span_start_logits, "end_logits": span_end_logits, "best_span": self.get_best_span( span_start_logits, span_end_logits, answer_maxlen=self.answer_maxlen ), } if labels: data_idx = labels["data_idx"] answer_start_idx = labels["answer_start_idx"] answer_end_idx = labels["answer_end_idx"] output_dict["data_idx"] = data_idx # If we are on multi-GPU, split add a dimension if len(answer_start_idx.size()) > 1: answer_start_idx = answer_start_idx.squeeze(-1) if len(answer_end_idx.size()) > 1: answer_end_idx = answer_end_idx.squeeze(-1) # sometimes the start/end positions are outside our model inputs, we ignore these terms ignored_index = span_start_logits.size(1) answer_start_idx.clamp_(0, ignored_index) answer_end_idx.clamp_(0, ignored_index) # Loss criterion = nn.CrossEntropyLoss(ignore_index=ignored_index) loss = criterion(span_start_logits, answer_start_idx) loss += criterion(span_end_logits, answer_end_idx) loss /= 2 # (start + end) output_dict["loss"] = loss return output_dict
================================================ FILE: docs/_build/html/_modules/claf/model/semantic_parsing/mixin.html ================================================ claf.model.semantic_parsing.mixin — CLaF 0.2.0 documentation

Source code for claf.model.semantic_parsing.mixin


import torch

from claf.decorator import arguments_required
from claf.metric import wikisql_official
from claf.metric.wikisql_lib.dbengine import DBEngine
from claf.metric.wikisql_lib.query import Query


[docs]class WikiSQL: """ WikiSQL Mixin Class with official evaluation * Args: token_embedder: 'TokenEmbedder' """ AGG_OPS = ["None", "MAX", "MIN", "COUNT", "SUM", "AVG"] COND_OPS = ["EQL", "GT", "LT"]
[docs] def make_metrics(self, predictions): """ aggregator, select_column, conditions accuracy """ agg_accuracy, sel_accuracy, conds_accuracy = 0, 0, 0 for index, pred in predictions.items(): target = self._dataset.get_ground_truth(index) # Aggregator, Select_Column, Conditions agg_acc = 1 if pred["query"]["agg"] == target["agg_idx"] else 0 sel_acc = 1 if pred["query"]["sel"] == target["sel_idx"] else 0 pred_conds = pred["query"]["conds"] string_set_pred_conds = set(["#".join(map(str, cond)).lower() for cond in pred_conds]) target_conds = [ [target["conds_col"][i], target["conds_op"][i], target["conds_val_str"][i]] for i in range(target["conds_num"]) ] string_set_target_conds = set( ["#".join(map(str, cond)).lower() for cond in target_conds] ) conds_acc = ( 1 if string_set_pred_conds == string_set_target_conds else 0 ) # not matter in order agg_accuracy += agg_acc sel_accuracy += sel_acc conds_accuracy += conds_acc total_count = len(self._dataset) agg_accuracy = 100.0 * agg_accuracy / total_count sel_accuracy = 100.0 * sel_accuracy / total_count conds_accuracy = 100.0 * conds_accuracy / total_count metrics = { "agg_accuracy": agg_accuracy, "sel_accuracy": sel_accuracy, "conds_accuracy": conds_accuracy, } self.write_predictions(predictions) wikisql_official_metrics = self._make_metrics_with_official(predictions) metrics.update(wikisql_official_metrics) return metrics
def _make_metrics_with_official(self, preds): """ WikiSQL official evaluation lf_accuracy: Logical-form accuracy - Directly compare the synthesized SQL query with the ground truth to check whether they match each other. ex_accuracy: Execution accuracy - Execute both the synthesized query and the ground truth query and compare whether the results match to each other. """ labels = self._dataset.labels db_path = self._dataset.helper["db_path"] return wikisql_official.evaluate(labels, preds, db_path)
[docs] def make_predictions(self, output_dict): predictions = {} sql_quries = self.generate_queries(output_dict) for i in range(len(sql_quries)): query = sql_quries[i] prediction = {} prediction.update(query) data_id = self._dataset.get_id(output_dict["data_id"][i]) predictions[data_id] = prediction return predictions
[docs] def generate_queries(self, output_dict): preds_agg = torch.argmax(output_dict["agg_logits"], dim=-1) preds_sel = torch.argmax(output_dict["sel_logits"], dim=-1) conds_logits = output_dict["conds_logits"] conds_num_logits, conds_column_logits, conds_op_logits, conds_value_logits = conds_logits preds_conds_num = torch.argmax(conds_num_logits, dim=-1) preds_conds_op = torch.argmax(conds_op_logits, dim=-1) sql_quries = [] B = output_dict["agg_logits"].size(0) for i in range(B): if "table_id" in output_dict: table_id = output_dict["table_id"] else: table_id = self._dataset.get_table_id(output_dict["data_id"][i]) query = { "table_id": table_id, "query": {"agg": preds_agg[i].item(), "sel": preds_sel[i].item()}, } pred_conds_num = preds_conds_num[i].item() conds_pred = [] if pred_conds_num == 0: pass else: _, pred_conds_column_idx = torch.topk(conds_column_logits[i], pred_conds_num) if preds_conds_op.dim() == 1: # for one-example (TODO: fix hard-code) pred_conds_op = preds_conds_op conds_value_logits = conds_value_logits.squeeze(3) conds_value_logits = conds_value_logits.squeeze(0) else: pred_conds_op = preds_conds_op[i] if "tokenized_question" in output_dict: tokenized_question = output_dict["tokenized_question"] else: tokenized_question = self._dataset.get_tokenized_question( output_dict["data_id"][i] ) conds_pred = [ [ pred_conds_column_idx[j].item(), pred_conds_op[j].item(), self.decode_pointer(tokenized_question, conds_value_logits[i][j]), ] for j in range(pred_conds_num) ] query["query"]["conds"] = conds_pred sql_quries.append(query) return sql_quries
[docs] def decode_pointer(self, tokenized_question, cond_value_logits): question_text = " ".join(tokenized_question) tokenized_question = ["<BEG>"] + tokenized_question + ["<END>"] conds_value = [] for value_logit in cond_value_logits: pred_value_pos = torch.argmax(value_logit[: len(tokenized_question)]).item() pred_value_token = tokenized_question[pred_value_pos] if pred_value_token == "<END>": break conds_value.append(pred_value_token) conds_value = self.merge_tokens(conds_value, question_text) return conds_value
[docs] def merge_tokens(self, tok_list, raw_tok_str): lower_tok_str = raw_tok_str.lower() alphabet = set("abcdefghijklmnopqrstuvwxyz0123456789$(") special = { "-LRB-": "(", "-RRB-": ")", "-LSB-": "[", "-RSB-": "]", "``": '"', "''": '"', "--": "\u2013", } ret = "" double_quote_appear = 0 for raw_tok in tok_list: if not raw_tok: continue tok = special.get(raw_tok, raw_tok) lower_tok = tok.lower() if tok == '"': double_quote_appear = 1 - double_quote_appear if len(ret) == 0: pass elif len(ret) > 0 and ret + " " + lower_tok in lower_tok_str: ret = ret + " " elif len(ret) > 0 and ret + lower_tok in lower_tok_str: pass elif lower_tok == '"': if double_quote_appear: ret = ret + " " elif lower_tok[0] not in alphabet: pass elif (ret[-1] not in ["(", "/", "\u2013", "#", "$", "&"]) and ( ret[-1] != '"' or not double_quote_appear ): ret = ret + " " ret = ret + tok return ret.strip()
@arguments_required(["db_path", "table_id"]) def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of arguments: arguments dictionary consisting of user_input helper: dictionary for helping get answer * Returns: query: Generated SQL Query execute_result: Execute result by generated query """ output_dict["table_id"] = arguments["table_id"] output_dict["tokenized_question"] = helper["tokenized_question"] prediction = self.generate_queries(output_dict)[0] pred_query = Query.from_dict(prediction["query"], ordered=True) dbengine = DBEngine(arguments["db_path"]) try: pred_execute_result = dbengine.execute_query( prediction["table_id"], pred_query, lower=True ) except IndexError as e: pred_execute_result = str(e) return {"query": str(pred_query), "execute_result": pred_execute_result}
[docs] def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (question id) - value: consisting of dictionary table_id, query (agg, sel, conds) * Returns: print(Context, Question, Answers and Predict) """ data_index = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_index) helper = self._dataset.helper question = helper["examples"][data_id]["question"] label = self._dataset.get_ground_truth(data_id) dbengine = DBEngine(helper["db_path"]) prediction = predictions[data_id] pred_query = Query.from_dict(prediction["query"], ordered=True) pred_execute_result = dbengine.execute_query(prediction["table_id"], pred_query, lower=True) print("- Question:", question) print("- Answers:") print(" SQL Query: ", label["sql_query"]) print(" Execute Results:", label["execution_result"]) print("- Predict:") print(" SQL Query: ", pred_query) print(" Execute Results:", pred_execute_result) print("-" * 30)
================================================ FILE: docs/_build/html/_modules/claf/model/semantic_parsing/sqlnet.html ================================================ claf.model.semantic_parsing.sqlnet — CLaF 0.2.0 documentation

Source code for claf.model.semantic_parsing.sqlnet


from overrides import overrides

import numpy as np

import torch
import torch.nn as nn
import torch.nn.functional as F

from claf.decorator import register
from claf.model.base import ModelWithTokenEmbedder
from claf.model.semantic_parsing import utils
from claf.model.semantic_parsing.mixin import WikiSQL
import claf.modules.functional as f
import claf.modules.attention as attention


[docs]@register("model:sqlnet") class SQLNet(WikiSQL, ModelWithTokenEmbedder): """ Nature Language to SQL Query Model. `Semantic Parsing`, `NL2SQL` Implementation of model presented in SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning (https://arxiv.org/abs/1711.04436) * Args: token_embedder: 'WikiSQLTokenEmbedder', Used to embed the 'column' and 'question'. * Kwargs: column_attention: highlight that column attention is a special instance of the generic attention mechanism to compute the attention map on a question conditioned on the column names. model_dim: the number of model dimension rnn_num_layer: the number of recurrent layers (all of rnn) column_maxlen: an upper-bound N on the number of columns to choose token_maxlen: conds value slot - pointer network an upper-bound N on the number of token conds_column_loss_alpha: balance the positive data versus negative data """ def __init__( self, token_embedder, column_attention=None, model_dim=100, rnn_num_layer=2, dropout=0.3, column_maxlen=4, token_maxlen=200, conds_column_loss_alpha=3, ): super(SQLNet, self).__init__(token_embedder) embed_dim = token_embedder.get_embed_dim() # NOTE: need to fix self.token_maxlen = token_maxlen self.column_maxlen = column_maxlen self.conds_column_loss_alpha = conds_column_loss_alpha # Predict aggregator self.agg_predictor = AggPredictor( embed_dim, model_dim, rnn_num_layer, dropout, len(self.AGG_OPS) ) # Predict selected column self.sel_predictor = SelPredictor( embed_dim, model_dim, rnn_num_layer, dropout, column_attention=column_attention ) # #Predict number of conditions self.conds_predictor = CondsPredictor( embed_dim, model_dim, rnn_num_layer, dropout, len(self.COND_OPS), column_maxlen, token_maxlen, column_attention=column_attention, ) self.cross_entropy = nn.CrossEntropyLoss() self.bce_logit = nn.BCEWithLogitsLoss()
[docs] @overrides def forward(self, features, labels=None): column = features["column"] question = features["question"] column_embed = self.token_embedder(column) question_embed = self.token_embedder(question) B, C_L = column_embed.size(0), column_embed.size(1) column_indexed = column[next(iter(column))] column_name_mask = column_indexed.gt(0).float() # NOTE: hard-code column_lengths = utils.get_column_lengths(column_embed, column_name_mask) column_mask = column_lengths.view(B, C_L).gt(0).float() # NOTE: hard-code question_mask = f.get_mask_from_tokens(question).float() agg_logits = self.agg_predictor(question_embed, question_mask) sel_logits = self.sel_predictor( question_embed, question_mask, column_embed, column_name_mask, column_mask ) conds_col_idx, conds_val_pos = None, None if labels: data_idx = labels["data_idx"] ground_truths = self._dataset.get_ground_truths(data_idx) conds_col_idx = [ground_truth["conds_col"] for ground_truth in ground_truths] conds_val_pos = [ground_truth["conds_val_pos"] for ground_truth in ground_truths] conds_logits = self.conds_predictor( question_embed, question_mask, column_embed, column_name_mask, column_mask, conds_col_idx, conds_val_pos, ) # Convert GPU to CPU agg_logits = agg_logits.cpu() sel_logits = sel_logits.cpu() conds_logits = [logits.cpu() for logits in conds_logits] output_dict = { "agg_logits": agg_logits, "sel_logits": sel_logits, "conds_logits": conds_logits, } if labels: data_idx = labels["data_idx"] output_dict["data_id"] = data_idx ground_truths = self._dataset.get_ground_truths(data_idx) # Aggregator, Select Column target_agg_idx = torch.LongTensor( [ground_truth["agg_idx"] for ground_truth in ground_truths] ) target_sel_idx = torch.LongTensor( [ground_truth["sel_idx"] for ground_truth in ground_truths] ) loss = 0 loss += self.cross_entropy(agg_logits, target_agg_idx) loss += self.cross_entropy(sel_logits, target_sel_idx) conds_num_logits, conds_column_logits, conds_op_logits, conds_value_logits = ( conds_logits ) # Conditions # 1. The number of conditions target_conds_num = torch.LongTensor( [ground_truth["conds_num"] for ground_truth in ground_truths] ) target_conds_column = [ground_truth["conds_col"] for ground_truth in ground_truths] loss += self.cross_entropy(conds_num_logits, target_conds_num) # 2. Columns of conditions B = conds_column_logits.size(0) target_conds_columns = np.zeros(list(conds_column_logits.size()), dtype=np.float32) for i in range(B): target_conds_column_idx = target_conds_column[i] if len(target_conds_column_idx) == 0: continue target_conds_columns[i][target_conds_column_idx] = 1 target_conds_columns = torch.from_numpy(target_conds_columns) conds_column_probs = torch.sigmoid(conds_column_logits) bce_loss = -torch.mean( self.conds_column_loss_alpha * (target_conds_columns * torch.log(conds_column_probs + 1e-10)) + (1 - target_conds_columns) * torch.log(1 - conds_column_probs + 1e-10) ) loss += bce_loss # 3. Operator of conditions conds_op_loss = 0 for i in range(B): target_conds_op = ground_truths[i]["conds_op"] if len(target_conds_op) == 0: continue target_conds_op = torch.from_numpy(np.array(target_conds_op)) logits_conds_op = conds_op_logits[i, : len(target_conds_op)] target_op_count = len(target_conds_op) conds_op_loss += ( self.cross_entropy(logits_conds_op, target_conds_op) / target_op_count ) loss += conds_op_loss # 4. Value of conditions conds_val_pos = [ground_truth["conds_val_pos"] for ground_truth in ground_truths] conds_value_loss = 0 for i in range(B): for j in range(len(conds_val_pos[i])): cond_val_pos = conds_val_pos[i][j] if len(cond_val_pos) == 1: continue target_cond_val_pos = torch.from_numpy( np.array(cond_val_pos[1:]) ) # index 0: START_TOKEN logits_cond_val_pos = conds_value_logits[i, j, : len(cond_val_pos) - 1] conds_value_loss += self.cross_entropy( logits_cond_val_pos, target_cond_val_pos ) / len(conds_val_pos[i]) loss += conds_value_loss / B output_dict["loss"] = loss.unsqueeze(0) return output_dict
[docs]class AggPredictor(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, agg_count): super(AggPredictor, self).__init__() self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.seq_attn = attention.LinearSeqAttn(model_dim) self.mlp = nn.Sequential( nn.Linear(model_dim, model_dim), nn.Tanh(), nn.Linear(model_dim, agg_count) )
[docs] def forward(self, question_embed, question_mask): encoded_question, _ = self.question_rnn(question_embed) attn_matrix = self.seq_attn(encoded_question, question_mask) attn_question = f.weighted_sum(attn_matrix, encoded_question) logits = self.mlp(attn_question) return logits
[docs]class SelPredictor(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, column_attention=None): super(SelPredictor, self).__init__() self.column_attention = column_attention self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) if column_attention: self.linear_attn = nn.Linear(model_dim, model_dim) else: self.seq_attn = attention.LinearSeqAttn(model_dim) self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.linear_question = nn.Linear(model_dim, model_dim) self.linear_column = nn.Linear(model_dim, model_dim) self.mlp = nn.Sequential(nn.Tanh(), nn.Linear(model_dim, 1))
[docs] def forward(self, question_embed, question_mask, column_embed, column_name_mask, column_mask): B, C_L, N_L, embed_D = list(column_embed.size()) encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) encoded_question, _ = self.question_rnn(question_embed) if self.column_attention: attn_matrix = torch.bmm( encoded_column, self.linear_attn(encoded_question).transpose(1, 2) ) attn_matrix = f.add_masked_value(attn_matrix, question_mask.unsqueeze(1), value=-1e7) attn_matrix = F.softmax(attn_matrix, dim=-1) attn_question = (encoded_question.unsqueeze(1) * attn_matrix.unsqueeze(3)).sum(2) else: attn_matrix = self.seq_attn(encoded_question, question_mask) attn_question = f.weighted_sum(attn_matrix, encoded_question) attn_question = attn_question.unsqueeze(1) logits = self.mlp( self.linear_question(attn_question) + self.linear_column(encoded_column) ).squeeze() logits = f.add_masked_value(logits, column_mask, value=-1e7) return logits
[docs]class CondsPredictor(nn.Module): def __init__( self, embed_dim, model_dim, rnn_num_layer, dropout, conds_op_count, column_maxlen, token_maxlen, column_attention=None, ): super(CondsPredictor, self).__init__() self.num_predictor = CondsNumPredictor( embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen ) self.column_predictor = CondsColPredictor( embed_dim, model_dim, rnn_num_layer, dropout, column_attention=column_attention ) self.op_predictor = CondsOpPredictor( embed_dim, model_dim, rnn_num_layer, dropout, conds_op_count, column_maxlen, column_attention=column_attention, ) self.value_pointer = CondsValuePointer( embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen, token_maxlen )
[docs] def forward( self, question_embed, question_mask, column_embed, column_name_mask, column_mask, col_idx, conds_val_pos, ): num_logits = self.num_predictor( question_embed, question_mask, column_embed, column_name_mask, column_mask ) column_logits = self.column_predictor( question_embed, question_mask, column_embed, column_name_mask, column_mask ) if col_idx is None: col_idx = [] preds_num = torch.argmax(num_logits, dim=-1) for i in range(column_logits.size(0)): _, pred_conds_column_idx = torch.topk(column_logits[i], preds_num[i]) col_idx.append(pred_conds_column_idx.tolist()) op_logits = self.op_predictor( question_embed, question_mask, column_embed, column_name_mask, col_idx ) value_logits = self.value_pointer( question_embed, question_mask, column_embed, column_name_mask, col_idx, conds_val_pos ) return (num_logits, column_logits, op_logits, value_logits)
[docs]class CondsNumPredictor(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen): super(CondsNumPredictor, self).__init__() self.model_dim = model_dim self.column_maxlen = column_maxlen self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.column_seq_attn = attention.LinearSeqAttn(model_dim) self.column_to_hidden_state = nn.Linear(model_dim, 2 * model_dim) self.column_to_cell_state = nn.Linear(model_dim, 2 * model_dim) self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.question_seq_attn = attention.LinearSeqAttn(model_dim) self.mlp = nn.Sequential( nn.Linear(model_dim, model_dim), nn.Tanh(), nn.Linear(model_dim, column_maxlen + 1) )
[docs] def forward(self, question_embed, question_mask, column_embed, column_name_mask, column_mask): B, C_L, N_L, embed_D = list(column_embed.size()) encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) attn_column = self.column_seq_attn(encoded_column, column_mask) out_column = f.weighted_sum(attn_column, encoded_column) question_rnn_hidden_state = ( self.column_to_hidden_state(out_column) .view(B, self.column_maxlen, self.model_dim // 2) .transpose(0, 1) .contiguous() ) question_rnn_cell_state = ( self.column_to_cell_state(out_column) .view(B, self.column_maxlen, self.model_dim // 2) .transpose(0, 1) .contiguous() ) encoded_question, _ = self.question_rnn( question_embed, (question_rnn_hidden_state, question_rnn_cell_state) ) attn_question = self.question_seq_attn(encoded_question, question_mask) out_question = f.weighted_sum(attn_question, encoded_question) return self.mlp(out_question)
[docs]class CondsColPredictor(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, column_attention=None): super(CondsColPredictor, self).__init__() self.column_attention = column_attention self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) if column_attention: self.linear_attn = nn.Linear(model_dim, model_dim) else: self.seq_attn = attention.LinearSeqAttn(model_dim) self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.linear_question = nn.Linear(model_dim, model_dim) self.linear_column = nn.Linear(model_dim, model_dim) self.mlp = nn.Sequential(nn.ReLU(), nn.Linear(model_dim, 1))
[docs] def forward(self, question_embed, question_mask, column_embed, column_name_mask, column_mask): B, C_L, N_L, embed_D = list(column_embed.size()) # Column Encoder encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) encoded_question, _ = self.question_rnn(question_embed) if self.column_attention: attn_matrix = torch.bmm( encoded_column, self.linear_attn(encoded_question).transpose(1, 2) ) attn_matrix = f.add_masked_value(attn_matrix, question_mask.unsqueeze(1), value=-1e7) attn_matrix = F.softmax(attn_matrix, dim=-1) attn_question = (encoded_question.unsqueeze(1) * attn_matrix.unsqueeze(3)).sum(2) else: attn_matrix = self.seq_attn(encoded_question, question_mask) attn_question = f.weighted_sum(attn_matrix, encoded_question) attn_question = attn_question.unsqueeze(1) logits = self.mlp( self.linear_question(attn_question) + self.linear_column(encoded_column) ).squeeze() logits = f.add_masked_value(logits, column_mask, value=-1e7) return logits
[docs]class CondsOpPredictor(nn.Module): def __init__( self, embed_dim, model_dim, rnn_num_layer, dropout, op_count, column_maxlen, column_attention=None, ): super(CondsOpPredictor, self).__init__() self.column_attention = column_attention self.column_maxlen = column_maxlen self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) if column_attention: self.linear_attn = nn.Linear(model_dim, model_dim) else: self.seq_attn = attention.LinearSeqAttn(model_dim) self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.linear_question = nn.Linear(model_dim, model_dim) self.linear_column = nn.Linear(model_dim, model_dim) self.mlp = nn.Sequential( nn.Linear(model_dim, model_dim), nn.Tanh(), nn.Linear(model_dim, op_count) )
[docs] def forward(self, question_embed, question_mask, column_embed, column_name_mask, col_idx): B, C_L, N_L, embed_D = list(column_embed.size()) # Column Encoder encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) encoded_used_column = utils.filter_used_column( encoded_column, col_idx, padding_count=self.column_maxlen ) encoded_question, _ = self.question_rnn(question_embed) if self.column_attention: attn_matrix = torch.matmul( self.linear_attn(encoded_question).unsqueeze(1), encoded_used_column.unsqueeze(3) ).squeeze() attn_matrix = f.add_masked_value(attn_matrix, question_mask.unsqueeze(1), value=-1e7) attn_matrix = F.softmax(attn_matrix, dim=-1) attn_question = (encoded_question.unsqueeze(1) * attn_matrix.unsqueeze(3)).sum(2) else: attn_matrix = self.seq_attn(encoded_question, question_mask) attn_question = f.weighted_sum(attn_matrix, encoded_question) attn_question = attn_question.unsqueeze(1) return self.mlp( self.linear_question(attn_question) + self.linear_column(encoded_used_column) ).squeeze()
[docs]class CondsValuePointer(nn.Module): def __init__(self, embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen, token_maxlen): super(CondsValuePointer, self).__init__() self.model_dim = model_dim self.column_maxlen = column_maxlen self.token_maxlen = token_maxlen self.question_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.seq_attn = attention.LinearSeqAttn(model_dim) self.column_rnn = nn.LSTM( input_size=embed_dim, hidden_size=model_dim // 2, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, bidirectional=True, ) self.decoder = nn.LSTM( input_size=self.token_maxlen, hidden_size=model_dim, num_layers=rnn_num_layer, batch_first=True, dropout=dropout, ) self.linear_column = nn.Linear(model_dim, model_dim) self.linear_conds = nn.Linear(model_dim, model_dim) self.linear_question = nn.Linear(model_dim, model_dim) self.mlp = nn.Sequential(nn.ReLU(), nn.Linear(model_dim, 1))
[docs] def forward( self, question_embed, question_mask, column_embed, column_name_mask, col_idx, conds_val_pos ): B, C_L, N_L, embed_D = list(column_embed.size()) question_embed, question_mask = self.concat_start_and_end_zero_padding( question_embed, question_mask ) # Column Encoder encoded_column = utils.encode_column(column_embed, column_name_mask, self.column_rnn) encoded_used_column = utils.filter_used_column( encoded_column, col_idx, padding_count=self.column_maxlen ) encoded_question, _ = self.question_rnn(question_embed) encoded_used_column = encoded_used_column.unsqueeze(2).unsqueeze(2) encoded_question = encoded_question.unsqueeze(1).unsqueeze(1) if conds_val_pos is None: # inference MAX_DECODER_STEP = 50 decoder_input = torch.zeros(4 * B, 1, self.token_maxlen) decoder_input[:, 0, 0] = 2 # Set <s> Token if torch.cuda.is_available(): decoder_input = decoder_input.cuda() decoder_hidden = None logits = [] for _ in range(MAX_DECODER_STEP): step_logit, decoder_hidden = self.decode_then_output( encoded_used_column, encoded_question, question_mask, decoder_input, decoder_hidden=decoder_hidden, ) step_logit = step_logit.unsqueeze(1) logits.append(step_logit) # To ont-hot _, decoder_idxs = step_logit.view(B * self.column_maxlen, -1).max(1) decoder_input = torch.zeros(B * self.column_maxlen, self.token_maxlen).scatter_( 1, decoder_idxs.cpu().unsqueeze(1), 1 ) if torch.cuda.is_available(): decoder_input = decoder_input.cuda() logits = torch.stack(logits, 2) else: decoder_input, _ = utils.convert_position_to_decoder_input( conds_val_pos, token_maxlen=self.token_maxlen ) logits, _ = self.decode_then_output( encoded_used_column, encoded_question, question_mask, decoder_input ) return logits
[docs] def concat_start_and_end_zero_padding(self, question_embed, mask): B, Q_L, embed_D = list(question_embed.size()) zero_padding = torch.zeros(B, 1, embed_D) mask_with_start_end = torch.zeros(B, Q_L + 2) if torch.cuda.is_available(): zero_padding = zero_padding.cuda(torch.cuda.current_device()) mask_with_start_end = mask_with_start_end.cuda(torch.cuda.current_device()) question_embed_with_start_end = torch.cat( [zero_padding, question_embed, zero_padding], dim=1 ) # add <BEG> and <END> mask_with_start_end[:, 0] = 1 # <BEG> mask_with_start_end[:, 1 : Q_L + 1] = mask question_lengths = torch.sum(mask, dim=-1).byte() for i in range(B): mask_with_start_end[i, question_lengths[i].item() + 1] = 1 # <END> return question_embed_with_start_end, mask_with_start_end
[docs] def decode_then_output( self, encoded_used_column, encoded_question, question_mask, decoder_input, decoder_hidden=None, ): B = encoded_used_column.size(0) decoder_output, decoder_hidden = self.decoder( decoder_input.view(B * self.column_maxlen, -1, self.token_maxlen), decoder_hidden ) decoder_output = decoder_output.contiguous().view(B, self.column_maxlen, -1, self.model_dim) decoder_output = decoder_output.unsqueeze(3) logits = self.mlp( self.linear_column(encoded_used_column) + self.linear_conds(decoder_output) + self.linear_question(encoded_question) ).squeeze() logits = f.add_masked_value(logits, question_mask.unsqueeze(1).unsqueeze(1), value=-1e7) return logits, decoder_hidden
================================================ FILE: docs/_build/html/_modules/claf/model/semantic_parsing/utils.html ================================================ claf.model.semantic_parsing.utils — CLaF 0.2.0 documentation

Source code for claf.model.semantic_parsing.utils


import numpy as np
import torch


[docs]def encode_column(column_embed, column_name_mask, rnn_module): B, C_L, N_L, embed_D = list(column_embed.size()) column_lengths = get_column_lengths(column_embed, column_name_mask) column_last_index = column_lengths - column_lengths.gt(0).long() # NOTE: hard-code column_reshape = [-1] + [N_L, embed_D] column_embed = column_embed.view(*column_reshape) encoded_column, _ = rnn_module(column_embed) encoded_D = encoded_column.size(-1) encoded_output_column = torch.cat( [ torch.index_select(encoded_column[i], 0, column_last_index[i]) for i in range(column_last_index.size(0)) ], dim=0, ) encoded_output_column = encoded_output_column.view([B, C_L, encoded_D]) return encoded_output_column
[docs]def get_column_lengths(column_embed, column_name_mask): _, _, N_L, embed_D = list(column_embed.size()) column_reshape = [-1] + [N_L, embed_D] return torch.sum(column_name_mask.view(*column_reshape[:-1]), dim=-1).long()
[docs]def filter_used_column(encoded_columns, col_idx, padding_count=4): B, C_L, D = list(encoded_columns.size()) zero_padding = torch.zeros(D) if torch.cuda.is_available(): zero_padding = zero_padding.cuda(torch.cuda.current_device()) encoded_used_columns = [] for i in range(B): encoded_used_column = torch.stack( [encoded_columns[i][j] for j in col_idx[i]] + [zero_padding] * (padding_count - len(col_idx[i])) ) encoded_used_columns.append(encoded_used_column) return torch.stack(encoded_used_columns)
[docs]def convert_position_to_decoder_input(conds_val_pos, token_maxlen=200): B = len(conds_val_pos) max_len = ( max([max([len(tok) for tok in tok_seq] + [0]) for tok_seq in conds_val_pos]) - 1 ) # The max seq len in the batch. if max_len < 1: max_len = 1 ret_array = np.zeros((B, 4, max_len, token_maxlen), dtype=np.float32) ret_len = np.zeros((B, 4)) for b, tok_seq in enumerate(conds_val_pos): idx = 0 for idx, one_tok_seq in enumerate(tok_seq): out_one_tok_seq = one_tok_seq[:-1] ret_len[b, idx] = len(out_one_tok_seq) for t, tok_id in enumerate(out_one_tok_seq): ret_array[b, idx, t, tok_id] = 1 if idx < 3: ret_array[b, idx + 1 :, 0, 1] = 1 ret_len[b, idx + 1 :] = 1 ret_inp = torch.from_numpy(ret_array) if torch.cuda.is_available(): ret_inp = ret_inp.cuda(torch.cuda.current_device()) return ret_inp, ret_len # [B, IDX, max_len, token_maxlen]
================================================ FILE: docs/_build/html/_modules/claf/model/sequence_classification/bert.html ================================================ claf.model.sequence_classification.bert — CLaF 0.2.0 documentation

Source code for claf.model.sequence_classification.bert


from overrides import overrides
from pytorch_transformers import BertModel
import torch.nn as nn

from claf.data.data_handler import CachePath
from claf.decorator import register
from claf.model.base import ModelWithoutTokenEmbedder
from claf.model.sequence_classification.mixin import SequenceClassification


[docs]@register("model:bert_for_seq_cls") class BertForSeqCls(SequenceClassification, ModelWithoutTokenEmbedder): """ Implementation of Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_classes: number of classified classes * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__(self, token_makers, num_classes, pretrained_model_name=None, dropout=0.2): super(BertForSeqCls, self).__init__(token_makers) self.use_pytorch_transformers = True # for optimizer's model parameters self.num_classes = num_classes self._model = BertModel.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.classifier = nn.Sequential( nn.Dropout(dropout), nn.Linear(self._model.config.hidden_size, num_classes) ) self.classifier.apply(self._model.init_weights) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [3, 4, 1, 0, 0, 0, ...], ..., ] }, "token_type": { "feature": [ [0, 0, 0, 0, 0, 0, ...], ..., ], } } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities of the class. - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self._model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) pooled_output = outputs[1] logits = self.classifier(pooled_output) output_dict = {"sequence_embed": pooled_output, "logits": logits} if labels: class_idx = labels["class_idx"] data_idx = labels["data_idx"] output_dict["class_idx"] = class_idx output_dict["data_idx"] = data_idx # Loss loss = self.criterion( logits.view(-1, self.num_classes), class_idx.view(-1) ) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs] @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence_a = helper["examples"][data_id]["sequence_a"] sequence_a_tokens = helper["examples"][data_id]["sequence_a_tokens"] sequence_b = helper["examples"][data_id]["sequence_b"] sequence_b_tokens = helper["examples"][data_id]["sequence_b_tokens"] target_class_text = helper["examples"][data_id]["class_text"] pred_class_idx = predictions[data_id]["class_idx"] pred_class_text = self._dataset.get_class_text_with_idx(pred_class_idx) print() print("- Sequence a:", sequence_a) print("- Sequence a Tokens:", sequence_a_tokens) if sequence_b: print("- Sequence b:", sequence_b) print("- Sequence b Tokens:", sequence_b_tokens) print("- Target:") print(" Class:", target_class_text) print("- Predict:") print(" Class:", pred_class_text) print()
================================================ FILE: docs/_build/html/_modules/claf/model/sequence_classification/bert_for_seq_cls.html ================================================ claf.model.sequence_classification.bert_for_seq_cls — CLaF 0.1.6 documentation
  • Docs »
  • Module code »
  • claf.model.sequence_classification.bert_for_seq_cls

Source code for claf.model.sequence_classification.bert_for_seq_cls


from overrides import overrides
from pytorch_transformers import BertModel
import torch.nn as nn

from claf.data.data_handler import CachePath
from claf.decorator import register
from claf.model.base import ModelWithoutTokenEmbedder
from claf.model.sequence_classification.mixin import SequenceClassification


[docs]@register("model:bert_for_seq_cls") class BertForSeqCls(SequenceClassification, ModelWithoutTokenEmbedder): """ Implementation of Single Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_classes: number of classified classes * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__(self, token_makers, num_classes, pretrained_model_name=None, dropout=0.2): super(BertForSeqCls, self).__init__(token_makers) self.bert = True # for optimizer's model parameters self.num_classes = num_classes self._model = BertModel.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.classifier = nn.Sequential( nn.Dropout(dropout), nn.Linear(self._model.config.hidden_size, num_classes) ) self.classifier.apply(self._model.init_weights) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [3, 4, 1, 0, 0, 0, ...], ..., ] }, "token_type": { "feature": [ [0, 0, 0, 0, 0, 0, ...], ..., ], } } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - class_logits: representing unnormalized log probabilities of the class. - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self._model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) pooled_output = outputs[1] class_logits = self.classifier(pooled_output) output_dict = {"sequence_embed": pooled_output, "class_logits": class_logits} if labels: class_idx = labels["class_idx"] data_idx = labels["data_idx"] output_dict["class_idx"] = class_idx output_dict["data_idx"] = data_idx # Loss loss = self.criterion(class_logits, class_idx) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs] @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence_a = helper["examples"][data_id]["sequence_a"] sequence_a_tokens = helper["examples"][data_id]["sequence_a_sub_tokens"] sequence_b = helper["examples"][data_id]["sequence_b"] sequence_b_tokens = helper["examples"][data_id]["sequence_b_sub_tokens"] target_class_text = helper["examples"][data_id]["class_text"] pred_class_idx = predictions[data_id]["class_idx"] pred_class_text = self._dataset.get_class_text_with_idx(pred_class_idx) print() print("- Sequence a:", sequence_a) print("- Sequence a Tokens:", sequence_a_tokens) if sequence_b: print("- Sequence b:", sequence_b) print("- Sequence b Tokens:", sequence_b_tokens) print("- Target:") print(" Class:", target_class_text) print("- Predict:") print(" Class:", pred_class_text) print()
================================================ FILE: docs/_build/html/_modules/claf/model/sequence_classification/mixin.html ================================================ claf.model.sequence_classification.mixin — CLaF 0.2.0 documentation

Source code for claf.model.sequence_classification.mixin


from pathlib import Path
import logging

import torch
import pycm
from pycm.pycm_obj import pycmVectorError

from claf.model import cls_utils
from claf.model.base import ModelBase
from claf.metric.classification import macro_f1, macro_precision, macro_recall
from claf.metric.glue import simple_accuracy, f1, matthews_corr

logger = logging.getLogger(__name__)


[docs]class SequenceClassification: """ Sequence Classification Mixin Class """
[docs] def make_predictions(self, output_dict): """ Make predictions with model's output_dict * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities of the class - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized * Returns: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx """ data_indices = output_dict["data_idx"] pred_logits = output_dict["logits"] pred_class_idxs = torch.argmax(pred_logits, dim=-1) predictions = { self._dataset.get_id(data_idx.item()): {"class_idx": pred_class_idx.item()} for data_idx, pred_class_idx in zip(list(data_indices.data), list(pred_class_idxs.data)) } return predictions
[docs] def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities of the class. arguments: arguments dictionary consisting of user_input helper: dictionary to get the classification result, consisting of - class_idx2text: dictionary converting class_idx to class_text * Returns: output dict (dict) consisting of - logits: representing unnormalized log probabilities of the class - class_idx: predicted class idx - class_text: predicted class text """ logits = output_dict["logits"] class_idx = logits.argmax(dim=-1) return { "logits": logits, "class_idx": class_idx, "class_text": helper["class_idx2text"][class_idx.item()], }
[docs] def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: metrics: metric dictionary consisting of - 'macro_f1': class prediction macro(unweighted mean) f1 - 'macro_precision': class prediction macro(unweighted mean) precision - 'macro_recall': class prediction macro(unweighted mean) recall - 'accuracy': class prediction accuracy """ pred_idx = [] pred_classes = [] target_idx = [] target_classes = [] target_count = len(self._dataset.class_idx2text) for data_id, pred in predictions.items(): target = self._dataset.get_ground_truth(data_id) pred_idx.append(pred["class_idx"]) pred_classes.append(self._dataset.class_idx2text[pred["class_idx"]]) target_idx.append(target["class_idx"]) target_classes.append(target["class_text"]) metrics = { "accuracy": simple_accuracy(pred_idx, target_idx), } if target_count == 2: # binary class f1_metric = f1(pred_idx, target_idx) metrics.update(f1_metric) matthews_corr_metric = matthews_corr(pred_idx, target_idx) metrics.update(matthews_corr_metric) return metrics
[docs] def write_predictions(self, predictions, file_path=None, is_dict=True, pycm_obj=None): """ Override write_predictions() in ModelBase to log confusion matrix """ try: super(SequenceClassification, self).write_predictions( predictions, file_path=file_path, is_dict=is_dict ) except AttributeError: # TODO: Need to Fix model_base = ModelBase() model_base._log_dir = self._log_dir model_base._train_counter = self._train_counter model_base.training = self.training model_base.write_predictions(predictions, file_path=file_path, is_dict=is_dict) data_type = "train" if self.training else "valid" if pycm_obj is not None: stats_file_path = f"predictions-{data_type}-{self._train_counter.get_display()}-stats" pycm_obj.save_csv(str(Path(self._log_dir) / "predictions" / stats_file_path)) confusion_matrix_file_path = ( f"predictions-{data_type}-{self._train_counter.get_display()}-confusion_matrix" ) cls_utils.write_confusion_matrix_to_csv( str(Path(self._log_dir) / "predictions" / confusion_matrix_file_path), pycm_obj )
[docs] def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence = helper["examples"][data_id]["sequence"] target_class_text = helper["examples"][data_id]["class_text"] pred_class_idx = predictions[data_id]["class_idx"] pred_class_text = self._dataset.get_class_text_with_idx(pred_class_idx) print() print("- Sequence:", sequence) print("- Target:") print(" Class:", target_class_text) print("- Predict:") print(" Class:", pred_class_text) print()
================================================ FILE: docs/_build/html/_modules/claf/model/sequence_classification/roberta.html ================================================ claf.model.sequence_classification.roberta — CLaF 0.2.0 documentation

Source code for claf.model.sequence_classification.roberta


from overrides import overrides
from pytorch_transformers import RobertaModel
import torch.nn as nn

from claf.data.data_handler import CachePath
from claf.decorator import register
from claf.model.base import ModelWithoutTokenEmbedder
from claf.model.sequence_classification.mixin import SequenceClassification


[docs]@register("model:roberta_for_seq_cls") class RobertaForSeqCls(SequenceClassification, ModelWithoutTokenEmbedder): """ Implementation of Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_classes: number of classified classes * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__(self, token_makers, num_classes, pretrained_model_name=None, dropout=0.2): super(RobertaForSeqCls, self).__init__(token_makers) self.use_pytorch_transformers = True # for optimizer's model parameters self.num_classes = num_classes self._model = RobertaModel.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.classifier = nn.Sequential( nn.Linear(self._model.config.hidden_size, self._model.config.hidden_size), nn.Dropout(dropout), nn.Linear(self._model.config.hidden_size, num_classes) ) self.classifier.apply(self._model.init_weights) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [3, 4, 1, 0, 0, 0, ...], ..., ] }, } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities of the class. - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self._model( bert_inputs, token_type_ids=None, attention_mask=attention_mask ) sequence_output = outputs[0] pooled_output = sequence_output[:, 0, :] # take <s> token (equiv. to [CLS]) logits = self.classifier(pooled_output) output_dict = {"sequence_embed": pooled_output, "logits": logits} if labels: class_idx = labels["class_idx"] data_idx = labels["data_idx"] output_dict["class_idx"] = class_idx output_dict["data_idx"] = data_idx # Loss loss = self.criterion( logits.view(-1, self.num_classes), class_idx.view(-1) ) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs] @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Class, Predicted Class) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence_a = helper["examples"][data_id]["sequence_a"] sequence_a_tokens = helper["examples"][data_id]["sequence_a_tokens"] sequence_b = helper["examples"][data_id]["sequence_b"] sequence_b_tokens = helper["examples"][data_id]["sequence_b_tokens"] target_class_text = helper["examples"][data_id]["class_text"] pred_class_idx = predictions[data_id]["class_idx"] pred_class_text = self._dataset.get_class_text_with_idx(pred_class_idx) print() print("- Sequence a:", sequence_a) print("- Sequence a Tokens:", sequence_a_tokens) if sequence_b: print("- Sequence b:", sequence_b) print("- Sequence b Tokens:", sequence_b_tokens) print("- Target:") print(" Class:", target_class_text) print("- Predict:") print(" Class:", pred_class_text) print()
================================================ FILE: docs/_build/html/_modules/claf/model/sequence_classification/structured_self_attention.html ================================================ claf.model.sequence_classification.structured_self_attention — CLaF 0.2.0 documentation
  • Docs »
  • Module code »
  • claf.model.sequence_classification.structured_self_attention

Source code for claf.model.sequence_classification.structured_self_attention


from overrides import overrides

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F

from claf.decorator import register
from claf.model.base import ModelWithTokenEmbedder
from claf.model.sequence_classification.mixin import SequenceClassification
from claf.modules import functional as f


[docs]@register("model:structured_self_attention") class StructuredSelfAttention(SequenceClassification, ModelWithTokenEmbedder): """ Implementation of model presented in A Structured Self-attentive Sentence Embedding (https://arxiv.org/abs/1703.03130) * Args: token_embedder: used to embed the sequence num_classes: number of classified classes * Kwargs: encoding_rnn_hidden_dim: hidden dimension of rnn (unidirectional) encoding_rnn_num_layer: the number of rnn layers encoding_rnn_dropout: rnn dropout probability attention_dim: attention dimension # d_a in the paper num_attention_heads: number of attention heads # r in the paper sequence_embed_dim: dimension of sequence embedding dropout: classification layer dropout penalization_coefficient: penalty coefficient for frobenius norm """ def __init__( self, token_embedder, num_classes, encoding_rnn_hidden_dim=300, encoding_rnn_num_layer=2, encoding_rnn_dropout=0., attention_dim=350, num_attention_heads=30, sequence_embed_dim=2000, dropout=0.5, penalization_coefficient=1., ): super(StructuredSelfAttention, self).__init__(token_embedder) rnn_input_dim = token_embedder.get_embed_dim() self.num_classes = num_classes self.encoding_rnn_hidden_dim = encoding_rnn_hidden_dim * 2 # bidirectional self.attention_dim = attention_dim self.num_attention_heads = num_attention_heads self.project_dim = sequence_embed_dim self.dropout = dropout self.penalization_coefficient = penalization_coefficient self.encoder = nn.LSTM( input_size=rnn_input_dim, hidden_size=encoding_rnn_hidden_dim, num_layers=encoding_rnn_num_layer, dropout=encoding_rnn_dropout, bidirectional=True, batch_first=True, ) self.A = nn.Sequential( nn.Linear(self.encoding_rnn_hidden_dim, attention_dim, bias=False), nn.Tanh(), nn.Linear(attention_dim, num_attention_heads, bias=False), ) self.fully_connected = nn.Sequential( nn.Linear(self.encoding_rnn_hidden_dim * num_attention_heads, sequence_embed_dim), nn.ReLU(), nn.Dropout(dropout), ) self.classifier = nn.Linear(sequence_embed_dim, num_classes) self.criterion = nn.CrossEntropyLoss()
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. {"sequence": [0, 3, 4, 1]} * Kwargs: label: label dictionary like below. {"class_idx": 2, "data_idx": 0} Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - logits: representing unnormalized log probabilities of the class. - class_idx: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ sequence = features["sequence"] # Sorted Sequence config (seq_lengths, perm_idx, unperm_idx) for RNN pack_forward sequence_config = f.get_sorted_seq_config(sequence) token_embed = self.token_embedder(sequence) token_encodings = f.forward_rnn_with_pack( self.encoder, token_embed, sequence_config ) # [B, L, encoding_rnn_hidden_dim] attention = self.A(token_encodings).transpose(1, 2) # [B, num_attention_heads, L] sequence_mask = f.get_mask_from_tokens(sequence).float() # [B, L] sequence_mask = sequence_mask.unsqueeze(1).expand_as(attention) attention = F.softmax(f.add_masked_value(attention, sequence_mask) + 1e-13, dim=2) attended_encodings = torch.bmm( attention, token_encodings ) # [B, num_attention_heads, sequence_embed_dim] sequence_embed = self.fully_connected( attended_encodings.view(attended_encodings.size(0), -1) ) # [B, sequence_embed_dim] logits = self.classifier(sequence_embed) # [B, num_classes] output_dict = {"sequence_embed": sequence_embed, "logits": logits} if labels: class_idx = labels["class_idx"] data_idx = labels["data_idx"] output_dict["class_idx"] = class_idx output_dict["data_idx"] = data_idx # Loss loss = self.criterion(logits, class_idx) loss += self.penalty(attention) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs] def penalty(self, attention): aa = torch.bmm( attention, attention.transpose(1, 2) ) # [B, num_attention_heads, num_attention_heads] penalization_term = ((aa - aa.new_tensor(np.eye(aa.size(1)))) ** 2).sum() ** 0.5 return penalization_term * self.penalization_coefficient
================================================ FILE: docs/_build/html/_modules/claf/model/token_classification/bert.html ================================================ claf.model.token_classification.bert — CLaF 0.2.0 documentation

Source code for claf.model.token_classification.bert


from overrides import overrides
from pytorch_transformers import BertModel
import torch.nn as nn

from claf.data.data_handler import CachePath
from claf.decorator import register
from claf.model.base import ModelWithoutTokenEmbedder
from claf.model.token_classification.mixin import TokenClassification

from claf.model import cls_utils


[docs]@register("model:bert_for_tok_cls") class BertForTokCls(TokenClassification, ModelWithoutTokenEmbedder): """ Implementation of Single Sentence Tagging model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_tags: number of classified tags ignore_tag_idx: index of the tag to ignore when calculating loss (tag pad value) * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__( self, token_makers, num_tags, ignore_tag_idx, pretrained_model_name=None, dropout=0.2 ): super(BertForTokCls, self).__init__(token_makers) self.use_pytorch_transformers = True # for optimizer's model parameters self.ignore_tag_idx = ignore_tag_idx self.num_tags = num_tags self._model = BertModel.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.classifier = nn.Sequential( nn.Dropout(dropout), nn.Linear(self._model.config.hidden_size, num_tags) ) self.classifier.apply(self._model.init_weights) self.criterion = nn.CrossEntropyLoss(ignore_index=ignore_tag_idx)
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [100, 576, 21, 45, 7, 91, 101, 0, 0, ...], ..., ] } "token_type": { "feature": [ [0, 0, 0, 0, 0, 0, 0, 0, 0, ...], ..., ] }, "tagged_sub_token_idxs": { [ [1, 3, 4, 0, 0, 0, 0, 0, 0, ...], ..., ] } } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - tag_logits: representing unnormalized log probabilities of the tags. - tag_idxs: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] tagged_sub_token_idxs = features["tagged_sub_token_idxs"]["feature"] num_tokens = features["num_tokens"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self._model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) token_encodings = outputs[0] pooled_output = outputs[1] tag_logits = self.classifier(token_encodings) # [B, L, num_tags] # gather the logits of the tagged token positions. gather_token_pos_idxs = tagged_sub_token_idxs.unsqueeze(-1).repeat(1, 1, self.num_tags) token_tag_logits = tag_logits.gather(1, gather_token_pos_idxs) # [B, num_tokens, num_tags] sliced_token_tag_logits = [token_tag_logits[idx, :n, :] for idx, n in enumerate(num_tokens)] output_dict = {"sequence_embed": pooled_output, "tag_logits": sliced_token_tag_logits} if labels: tag_idxs = labels["tag_idxs"] data_idx = labels["data_idx"] output_dict["tag_idxs"] = tag_idxs output_dict["data_idx"] = data_idx # Loss loss = self.criterion(token_tag_logits.view(-1, self.num_tags), tag_idxs.view(-1)) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs] @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Tags, Target Slots, Predicted Tags, Predicted Slots) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence = helper["examples"][data_id]["sequence"] target_tag_texts = helper["examples"][data_id]["tag_texts"] pred_tag_idxs = predictions[data_id]["tag_idxs"] pred_tag_texts = self._dataset.get_tag_texts_with_idxs(pred_tag_idxs) sequence_tokens = helper["examples"][data_id]["sequence_sub_tokens"] print() print("- Sequence:", sequence) print("- Sequence Tokens:", sequence_tokens) print("- Target:") print(" Tags:", target_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, target_tag_texts)) print("- Predict:") print(" Tags:", pred_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, pred_tag_texts)) print()
================================================ FILE: docs/_build/html/_modules/claf/model/token_classification/bert_for_tok_cls.html ================================================ claf.model.token_classification.bert_for_tok_cls — CLaF 0.1.6 documentation

Source code for claf.model.token_classification.bert_for_tok_cls


from overrides import overrides
from pytorch_transformers import BertModel
import torch.nn as nn

from claf.data.data_handler import CachePath
from claf.decorator import register
from claf.model.base import ModelWithoutTokenEmbedder
from claf.model.token_classification.mixin import TokenClassification

from claf.model import cls_utils


[docs]@register("model:bert_for_tok_cls") class BertForTokCls(TokenClassification, ModelWithoutTokenEmbedder): """ Implementation of Single Sentence Tagging model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: token_embedder: used to embed the sequence num_tags: number of classified tags ignore_tag_idx: index of the tag to ignore when calculating loss (tag pad value) * Kwargs: pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout """ def __init__( self, token_makers, num_tags, ignore_tag_idx, pretrained_model_name=None, dropout=0.2 ): super(BertForTokCls, self).__init__(token_makers) self.bert = True # for optimizer's model parameters self.ignore_tag_idx = ignore_tag_idx self.num_tags = num_tags self._model = BertModel.from_pretrained( pretrained_model_name, cache_dir=str(CachePath.ROOT) ) self.classifier = nn.Sequential( nn.Dropout(dropout), nn.Linear(self._model.config.hidden_size, num_tags) ) self.classifier.apply(self._model.init_weights) self.criterion = nn.CrossEntropyLoss(ignore_index=ignore_tag_idx)
[docs] @overrides def forward(self, features, labels=None): """ * Args: features: feature dictionary like below. { "bert_input": { "feature": [ [100, 576, 21, 45, 7, 91, 101, 0, 0, ...], ..., ] } "token_type": { "feature": [ [0, 0, 0, 0, 0, 0, 0, 0, 0, ...], ..., ] }, "tagged_sub_token_idxs": { [ [1, 3, 4, 0, 0, 0, 0, 0, 0, ...], ..., ] } } * Kwargs: label: label dictionary like below. { "class_idx": [2, 1, 0, 4, 5, ...] "data_idx": [2, 4, 5, 7, 2, 1, ...] } Do not calculate loss when there is no label. (inference/predict mode) * Returns: output_dict (dict) consisting of - sequence_embed: embedding vector of the sequence - tag_logits: representing unnormalized log probabilities of the tags. - tag_idxs: target class idx - data_idx: data idx - loss: a scalar loss to be optimized """ bert_inputs = features["bert_input"]["feature"] token_type_ids = features["token_type"]["feature"] tagged_sub_token_idxs = features["tagged_sub_token_idxs"]["feature"] num_tokens = features["num_tokens"]["feature"] attention_mask = (bert_inputs > 0).long() outputs = self._model( bert_inputs, token_type_ids=token_type_ids, attention_mask=attention_mask ) token_encodings = outputs[0] pooled_output = outputs[1] tag_logits = self.classifier(token_encodings) # [B, L, num_tags] # gather the logits of the tagged token positions. gather_token_pos_idxs = tagged_sub_token_idxs.unsqueeze(-1).repeat(1, 1, self.num_tags) token_tag_logits = tag_logits.gather(1, gather_token_pos_idxs) # [B, num_tokens, num_tags] sliced_token_tag_logits = [token_tag_logits[idx, :n, :] for idx, n in enumerate(num_tokens)] output_dict = {"sequence_embed": pooled_output, "tag_logits": sliced_token_tag_logits} if labels: tag_idxs = labels["tag_idxs"] data_idx = labels["data_idx"] output_dict["tag_idxs"] = tag_idxs output_dict["data_idx"] = data_idx # Loss loss = self.criterion(token_tag_logits.view(-1, self.num_tags), tag_idxs.view(-1)) output_dict["loss"] = loss.unsqueeze(0) # NOTE: DataParallel concat Error return output_dict
[docs] @overrides def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Sequence Tokens, Target Tags, Target Slots, Predicted Tags, Predicted Slots) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence = helper["examples"][data_id]["sequence"] target_tag_texts = helper["examples"][data_id]["tag_texts"] pred_tag_idxs = predictions[data_id]["tag_idxs"] pred_tag_texts = self._dataset.get_tag_texts_with_idxs(pred_tag_idxs) sequence_tokens = helper["examples"][data_id]["sequence_sub_tokens"] print() print("- Sequence:", sequence) print("- Sequence Tokens:", sequence_tokens) print("- Target:") print(" Tags:", target_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, target_tag_texts)) print("- Predict:") print(" Tags:", pred_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, pred_tag_texts)) print()
================================================ FILE: docs/_build/html/_modules/claf/model/token_classification/mixin.html ================================================ claf.model.token_classification.mixin — CLaF 0.2.0 documentation

Source code for claf.model.token_classification.mixin


from pathlib import Path
import logging

import numpy as np
import torch
import pycm
from pycm.pycm_obj import pycmVectorError

from claf.decorator import arguments_required
import claf.utils as common_utils
from claf.model import cls_utils
from claf.metric.classification import macro_f1, macro_precision, macro_recall
from seqeval.metrics import accuracy_score as conlleval_accuracy
from seqeval.metrics import f1_score as conlleval_f1

logger = logging.getLogger(__name__)


[docs]class TokenClassification: """ Token Classification Mixin Class """
[docs] def make_predictions(self, output_dict): """ Make predictions with model's output_dict * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - tag_logits: representing unnormalized log probabilities of the tag - tag_idxs: target tag idxs - data_idx: data idx - loss: a scalar loss to be optimized * Returns: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - tag_idxs """ data_indices = output_dict["data_idx"] pred_tag_logits = output_dict["tag_logits"] pred_tag_idxs = [ torch.argmax(pred_tag_logit, dim=-1).tolist() for pred_tag_logit in pred_tag_logits ] predictions = { self._dataset.get_id(data_idx.item()): {"tag_idxs": pred_tag_idx} for data_idx, pred_tag_idx in zip(list(data_indices.data), pred_tag_idxs) } return predictions
@arguments_required(["sequence"]) def predict(self, output_dict, arguments, helper): """ Inference by raw_feature * Args: output_dict: model's output dictionary consisting of - sequence_embed: embedding vector of the sequence - tag_logits: representing unnormalized log probabilities of the tags. arguments: arguments dictionary consisting of user_input helper: dictionary to get the classification result, consisting of - tag_idx2text: dictionary converting tag_idx to tag_text * Returns: output dict (dict) consisting of - tag_logits: representing unnormalized log probabilities of the tags - tag_idxs: predicted tag idxs - tag_texts: predicted tag texts - tag_slots: predicted tag slots """ sequence = arguments["sequence"] tag_logits = output_dict["tag_logits"][0] tag_idxs = [tag_logit.argmax(dim=-1) for tag_logit in tag_logits] tag_texts = [helper["tag_idx2text"][tag_idx.item()] for tag_idx in tag_idxs] return { "tag_logits": tag_logits, "tag_idxs": tag_idxs, "tag_texts": tag_texts, "tag_dict": cls_utils.get_tag_dict(sequence, tag_texts), }
[docs] def make_metrics(self, predictions): """ Make metrics with prediction dictionary * Args: predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - tag_idxs * Returns: metrics: metric dictionary consisting of - 'accuracy': sequence level accuracy - 'tag_accuracy': tag level accuracy - 'macro_f1': tag prediction macro(unweighted mean) f1 - 'macro_precision': tag prediction macro(unweighted mean) precision - 'macro_recall': tag prediction macro(unweighted mean) recall """ pred_tag_idxs_list = [] target_tag_idxs_list = [] accurate_sequence = [] for data_idx, pred in predictions.items(): target = self._dataset.get_ground_truth(data_idx) pred_tag_idxs_list.append(pred["tag_idxs"]) target_tag_idxs_list.append(target["tag_idxs"]) accurate_sequence.append( 1 if (np.asarray(target["tag_idxs"]) == np.asarray(pred["tag_idxs"])).all() else 0 ) pred_tags = [ [self._dataset.tag_idx2text[tag_idx] for tag_idx in tag_idxs] for tag_idxs in pred_tag_idxs_list ] target_tags = [ [self._dataset.tag_idx2text[tag_idx] for tag_idx in tag_idxs] for tag_idxs in target_tag_idxs_list ] flat_pred_tags = list(common_utils.flatten(pred_tags)) flat_target_tags = list(common_utils.flatten(target_tags)) # confusion matrix try: pycm_obj = pycm.ConfusionMatrix(actual_vector=flat_target_tags, predict_vector=flat_pred_tags) except pycmVectorError as e: if str(e) == "Number of the classes is lower than 2": logger.warning("Number of tags in the batch is 1. Sanity check is highly recommended.") return { "accuracy": 1., "tag_accuracy": 1., "macro_f1": 1., "macro_precision": 1., "macro_recall": 1., "conlleval_accuracy": 1., "conlleval_f1": 1., } raise self.write_predictions( {"target": flat_target_tags, "predict": flat_pred_tags}, pycm_obj=pycm_obj ) sequence_accuracy = sum(accurate_sequence) / len(accurate_sequence) metrics = { "accuracy": sequence_accuracy, "tag_accuracy": pycm_obj.Overall_ACC, "macro_f1": macro_f1(pycm_obj), "macro_precision": macro_precision(pycm_obj), "macro_recall": macro_recall(pycm_obj), "conlleval_accuracy": conlleval_accuracy(target_tags, pred_tags), "conlleval_f1": conlleval_f1(target_tags, pred_tags), } return metrics
[docs] def write_predictions(self, predictions, file_path=None, is_dict=True, pycm_obj=None): """ Override write_predictions() in ModelBase to log confusion matrix """ super(TokenClassification, self).write_predictions( predictions, file_path=file_path, is_dict=is_dict ) data_type = "train" if self.training else "valid" if pycm_obj is not None: stats_file_path = f"predictions-{data_type}-{self._train_counter.get_display()}-stats" pycm_obj.save_csv(str(Path(self._log_dir) / "predictions" / stats_file_path)) confusion_matrix_file_path = ( f"predictions-{data_type}-{self._train_counter.get_display()}-confusion_matrix" ) cls_utils.write_confusion_matrix_to_csv( str(Path(self._log_dir) / "predictions" / confusion_matrix_file_path), pycm_obj )
[docs] def print_examples(self, index, inputs, predictions): """ Print evaluation examples * Args: index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of - key: 'id' (sequence id) - value: dictionary consisting of - class_idx * Returns: print(Sequence, Target Tags, Target Slots, Predicted Tags, Predicted Slots) """ data_idx = inputs["labels"]["data_idx"][index].item() data_id = self._dataset.get_id(data_idx) helper = self._dataset.helper sequence = helper["examples"][data_id]["sequence"] target_tag_texts = helper["examples"][data_id]["tag_texts"] pred_tag_idxs = predictions[data_id]["tag_idxs"] pred_tag_texts = self._dataset.get_tag_texts_with_idxs(pred_tag_idxs) print() print("- Sequence:", sequence) print("- Target:") print(" Tags:", target_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, target_tag_texts)) print("- Predict:") print(" Tags:", pred_tag_texts) print(" (Slots)", cls_utils.get_tag_dict(sequence, pred_tag_texts)) print()
================================================ FILE: docs/_build/html/_modules/claf/modules/activation.html ================================================ claf.modules.activation — CLaF 0.2.0 documentation

Source code for claf.modules.activation


import torch.nn as nn


[docs]def get_activation_fn(name): """ PyTorch built-in activation functions """ activation_functions = { "linear": lambda: lambda x: x, "relu": nn.ReLU, "relu6": nn.ReLU6, "elu": nn.ELU, "prelu": nn.PReLU, "leaky_relu": nn.LeakyReLU, "threshold": nn.Threshold, "hardtanh": nn.Hardtanh, "sigmoid": nn.Sigmoid, "tanh": nn.Tanh, "log_sigmoid": nn.LogSigmoid, "softplus": nn.Softplus, "softshrink": nn.Softshrink, "softsign": nn.Softsign, "tanhshrink": nn.Tanhshrink, } if name not in activation_functions: raise ValueError( f"'{name}' is not included in activation_functions. use below one. \n {activation_functions.keys()}" ) return activation_functions[name]
================================================ FILE: docs/_build/html/_modules/claf/modules/attention/bi_attention.html ================================================ claf.modules.attention.bi_attention — CLaF 0.2.0 documentation

Source code for claf.modules.attention.bi_attention


import torch
import torch.nn as nn

import claf.modules.functional as f


[docs]class BiAttention(nn.Module): """ Attention Flow Layer in BiDAF (https://arxiv.org/pdf/1611.01603.pdf) The Similarity matrix Context-to-query Attention (C2Q) Query-to-context Attention (Q2C) * Args: model_dim: The number of module dimension """ def __init__(self, model_dim): super(BiAttention, self).__init__() self.model_dim = model_dim self.W = nn.Linear(6 * model_dim, 1, bias=False)
[docs] def forward(self, context, context_mask, query, query_mask): c, c_mask, q, q_mask = context, context_mask, query, query_mask S = self._make_similiarity_matrix(c, q) # (B, C_L, Q_L) masked_S = f.add_masked_value(S, query_mask.unsqueeze(1), value=-1e7) c2q = self._context2query(S, q, q_mask) q2c = self._query2context(masked_S.max(dim=-1)[0], c, c_mask) # [h; u˜; h◦u˜; h◦h˜] ~ (B, C_L, 8d) G = torch.cat((c, c2q, c * c2q, c * q2c), dim=-1) return G
def _make_similiarity_matrix(self, c, q): # B: batch_size, C_L: context_maxlen, Q_L: query_maxlen B, C_L, Q_L = c.size(0), c.size(1), q.size(1) matrix_shape = (B, C_L, Q_L, self.model_dim * 2) c_aug = c.unsqueeze(2).expand(matrix_shape) # (B, C_L, Q_L, 2d) q_aug = q.unsqueeze(1).expand(matrix_shape) # (B, C_L, Q_L, 2d) c_q = torch.mul(c_aug, q_aug) # element-wise multiplication concated_vector = torch.cat((c_aug, q_aug, c_q), dim=3) # [h; u; h◦u] return self.W(concated_vector).view(c.size(0), C_L, Q_L) def _context2query(self, S, q, q_mask): attention = f.last_dim_masked_softmax(S, q_mask) # (B, C_L, Q_L) c2q = f.weighted_sum(attention=attention, matrix=q) # (B, C_L, 2d) return c2q def _query2context(self, S, c, c_mask): attention = f.masked_softmax(S, c_mask) # (B, C_L) q2c = f.weighted_sum(attention=attention, matrix=c) return q2c.unsqueeze(1).expand(c.size()) # (B, C_L, 2d)
================================================ FILE: docs/_build/html/_modules/claf/modules/attention/co_attention.html ================================================ claf.modules.attention.co_attention — CLaF 0.2.0 documentation

Source code for claf.modules.attention.co_attention


import torch
import torch.nn as nn
import torch.nn.functional as F

import claf.modules.functional as f


[docs]class CoAttention(nn.Module): """ CoAttention encoder in Dynamic Coattention Networks For Question Answering (https://arxiv.org/abs/1611.01604) check the Figure 2 in paper * Args: embed_dim: the number of input embedding dimension """ def __init__(self, embed_dim): super(CoAttention, self).__init__() self.W_0 = nn.Linear(embed_dim * 3, 1, bias=False)
[docs] def forward(self, context_embed, question_embed, context_mask=None, question_mask=None): C, Q = context_embed, question_embed B, C_L, Q_L, D = C.size(0), C.size(1), Q.size(1), Q.size(2) similarity_matrix_shape = torch.zeros(B, C_L, Q_L, D) # (B, C_L, Q_L, D) C_ = C.unsqueeze(2).expand_as(similarity_matrix_shape) Q_ = Q.unsqueeze(1).expand_as(similarity_matrix_shape) C_Q = torch.mul(C_, Q_) S = self.W_0(torch.cat([C_, Q_, C_Q], 3)).squeeze(3) # (B, C_L, Q_L) S_question = S if question_mask is not None: S_question = f.add_masked_value(S_question, question_mask.unsqueeze(1), value=-1e7) S_q = F.softmax(S_question, 2) # (B, C_L, Q_L) S_context = S.transpose(1, 2) if context_mask is not None: S_context = f.add_masked_value(S_context, context_mask.unsqueeze(1), value=-1e7) S_c = F.softmax(S_context, 2) # (B, Q_L, C_L) A = torch.bmm(S_q, Q) # context2query (B, C_L, D) B = torch.bmm(S_q, S_c).bmm(C) # query2context (B, Q_L, D) out = torch.cat([C, A, C * A, C * B], dim=-1) return out
================================================ FILE: docs/_build/html/_modules/claf/modules/attention/docqa_attention.html ================================================ claf.modules.attention.docqa_attention — CLaF 0.2.0 documentation

Source code for claf.modules.attention.docqa_attention

import torch
import torch.nn as nn
import torch.nn.functional as F

from claf.modules import initializer
import claf.modules.functional as f


[docs]class DocQAAttention(nn.Module): """ Bi-Attention Layer + (Self-Attention) in DocumentQA (https://arxiv.org/abs/1710.10723) * Args: rnn_dim: the number of GRU cell hidden size linear_dim: the number of linear hidden size * Kwargs: self_attn: (bool) self-attention weight_init: (bool) weight initialization """ def __init__(self, rnn_dim, linear_dim, self_attn=False, weight_init=True): super(DocQAAttention, self).__init__() self.self_attn = self_attn self.input_w = nn.Linear(2 * rnn_dim, 1, bias=False) self.key_w = nn.Linear(2 * rnn_dim, 1, bias=False) self.dot_w = nn.Parameter(torch.randn(1, 1, rnn_dim * 2)) torch.nn.init.xavier_uniform_(self.dot_w) self.bias = nn.Parameter(torch.FloatTensor([[1]])) self.diag_mask = nn.Parameter(torch.eye(5000)) # NOTE: (hard-code) max_sequence_length if weight_init: initializer.weight(self.input_w) initializer.weight(self.key_w)
[docs] def forward(self, x, x_mask, key, key_mask): S = self._trilinear(x, key) if self.self_attn: seq_length = x.size(1) diag_mask = self.diag_mask.narrow(0, 0, seq_length).narrow(1, 0, seq_length) joint_mask = 1 - self._compute_attention_mask(x_mask, key_mask) mask = torch.clamp(diag_mask + joint_mask, 0, 1) masked_S = S + mask * (-1e7) x2key = self._x2key(masked_S, key, key_mask) return torch.cat((x, x2key, x * x2key), dim=-1) else: joint_mask = 1 - self._compute_attention_mask(x_mask, key_mask) masked_S = S + joint_mask * (-1e7) x2key = self._x2key(masked_S, key, key_mask) masked_S = f.add_masked_value(S, key_mask.unsqueeze(1), value=-1e7) key2x = self._key2x(masked_S.max(dim=-1)[0], x, x_mask) return torch.cat((x, x2key, x * x2key, x * key2x), dim=-1)
def _compute_attention_mask(self, x_mask, key_mask): x_mask = x_mask.unsqueeze(2) key_mask = key_mask.unsqueeze(1) joint_mask = torch.mul(x_mask, key_mask) return joint_mask def _trilinear(self, x, key): B, X_L, K_L = x.size(0), x.size(1), key.size(1) matrix_shape = (B, X_L, K_L) x_logits = self.input_w(x).expand(matrix_shape) key_logits = self.key_w(key).transpose(1, 2).expand(matrix_shape) x_dots = torch.mul(x, self.dot_w) x_key = torch.matmul(x_dots, key.transpose(1, 2)) return x_logits + key_logits + x_key def _x2key(self, S, key, key_mask): if self.self_attn: bias = torch.exp(self.bias) S = torch.exp(S) attention = S / (S.sum(dim=-1, keepdim=True).expand(S.size()) + bias.expand(S.size())) else: attention = F.softmax(S, dim=-1) # (B, C_L, Q_L) x2key = f.weighted_sum(attention=attention, matrix=key) # (B, C_L, 2d) return x2key def _key2x(self, S, x, x_mask): attention = f.masked_softmax(S, x_mask) # (B, C_L) key2x = f.weighted_sum(attention=attention, matrix=x) return key2x.unsqueeze(1).expand(x.size()) # (B, C_L, 2d)
================================================ FILE: docs/_build/html/_modules/claf/modules/attention/multi_head_attention.html ================================================ claf.modules.attention.multi_head_attention — CLaF 0.2.0 documentation

Source code for claf.modules.attention.multi_head_attention


import math
import torch
import torch.nn as nn
import torch.nn.functional as F

import claf.modules.functional as f


[docs]class MultiHeadAttention(nn.Module): """ Transformer's Multi-Head Attention in "Attention is All You Need" (https://arxiv.org/abs/1706.03762) * Kwargs: num_head: the number of Head model_dim: the number of model dimension linear_key_dim: the number of linear key dimemsion linear_value_dim: the number of linear value dimension """ def __init__( self, num_head=8, model_dim=100, dropout=0.1, linear_key_dim=None, linear_value_dim=None ): super(MultiHeadAttention, self).__init__() if linear_key_dim is None: linear_key_dim = model_dim if linear_value_dim is None: linear_value_dim = model_dim assert linear_key_dim % num_head == 0 assert linear_value_dim % num_head == 0 self.model_dim = model_dim self.num_head = num_head self.projection = nn.ModuleList( [ nn.Linear(model_dim, linear_key_dim, bias=False), # query nn.Linear(model_dim, linear_key_dim, bias=False), # key nn.Linear(model_dim, linear_value_dim, bias=False), # value ] ) self.out_linear = nn.Linear(linear_value_dim, model_dim) if dropout > 0: self.dropout = nn.Dropout(dropout) else: self.dropout = lambda x: x
[docs] def forward(self, q, k, v, mask=None): q, k, v = self._linear_projection(q, k, v) qs, ks, vs = self._split_heads(q, k, v) outputs = self._scaled_dot_product(qs, ks, vs, mask=mask) output = self._concat_heads(outputs) return self.out_linear(output)
def _linear_projection(self, query, key, value): q = self.projection[0](query) k = self.projection[1](key) v = self.projection[2](value) return q, k, v def _split_heads(self, query, key, value): B = query.size(0) qs, ks, vs = [ x.view(B, -1, self.num_head, x.size(-1) // self.num_head).transpose(1, 2) for x in [query, key, value] ] return qs, ks, vs def _scaled_dot_product(self, query, key, value, mask=None): K_D = query.size(-1) scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(K_D) if mask is not None: mask = mask.unsqueeze(1).unsqueeze(1) # [B, #H, C_L, D] scores = f.add_masked_value(scores, mask, value=-1e7) attn = F.softmax(scores, dim=-1) attn = self.dropout(attn) return torch.matmul(attn, value) def _concat_heads(self, outputs): B = outputs.size(0) num_head, dim = outputs.size()[-2:] return outputs.transpose(1, 2).contiguous().view(B, -1, self.num_head * dim)
================================================ FILE: docs/_build/html/_modules/claf/modules/attention/seq_attention.html ================================================ claf.modules.attention.seq_attention — CLaF 0.2.0 documentation

Source code for claf.modules.attention.seq_attention

#!/usr/bin/env python3
# Copyright 2017-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree.

"""
original code from: https://github.com/facebookresearch/DrQA/blob/master/drqa/reader/layers.py
"""

import torch.nn as nn
import torch.nn.functional as F


[docs]class SeqAttnMatch(nn.Module): """ Given sequences X and Y, match sequence Y to each element in X. * o_i = sum(alpha_j * y_j) for i in X * alpha_j = softmax(y_j * x_i) """ def __init__(self, embed_dim, identity=False): super(SeqAttnMatch, self).__init__() if not identity: self.linear = nn.Linear(embed_dim, embed_dim) else: self.linear = None
[docs] def forward(self, x, y, y_mask): if self.linear: x_proj = self.linear(x.view(-1, x.size(2))).view(x.size()) x_proj = F.relu(x_proj) y_proj = self.linear(y.view(-1, y.size(2))).view(y.size()) y_proj = F.relu(y_proj) else: x_proj = x y_proj = y scores = x_proj.bmm(y_proj.transpose(2, 1)) y_mask = y_mask.unsqueeze(1).expand(scores.size()) scores = scores.masked_fill((y_mask == 0), -1e30) alpha_flat = F.softmax(scores.view(-1, y.size(1)), -1) alpha = alpha_flat.view(-1, x.size(1), y.size(1)) matched_seq = alpha.bmm(y) return matched_seq
[docs]class LinearSeqAttn(nn.Module): """ Self attention over a sequence: * o_i = softmax(Wx_i) for x_i in X. """ def __init__(self, input_size): super(LinearSeqAttn, self).__init__() self.linear = nn.Linear(input_size, 1)
[docs] def forward(self, x, x_mask): x_flat = x.contiguous().view(-1, x.size(-1)) scores = self.linear(x_flat).view(x.size(0), x.size(1)) scores.data.masked_fill_((x_mask == 0), -1e30) alpha = F.softmax(scores, dim=-1) return alpha
[docs]class BilinearSeqAttn(nn.Module): """ A bilinear attention layer over a sequence X w.r.t y: * o_i = softmax(x_i'Wy) for x_i in X. Optionally don't normalize output weights. """ def __init__(self, x_size, y_size, identity=False, normalize=True): super(BilinearSeqAttn, self).__init__() self.normalize = normalize if not identity: self.linear = nn.Linear(y_size, x_size) else: self.linear = None
[docs] def forward(self, x, y, x_mask): Wy = self.linear(y) if self.linear is not None else y xWy = x.bmm(Wy.unsqueeze(2)).squeeze(2) xWy.data.masked_fill_((x_mask == 0), -1e30) if self.normalize: if self.training: alpha = F.log_softmax(xWy, dim=-1) else: alpha = F.softmax(xWy, dim=-1) else: alpha = xWy.exp() return alpha
================================================ FILE: docs/_build/html/_modules/claf/modules/conv/depthwise_separable_conv.html ================================================ claf.modules.conv.depthwise_separable_conv — CLaF 0.2.0 documentation

Source code for claf.modules.conv.depthwise_separable_conv


import torch.nn as nn
import torch.nn.functional as F

from .pointwise_conv import PointwiseConv


[docs]class DepSepConv(nn.Module): """ Depthwise Separable Convolutions in Xception: Deep Learning with Depthwise Separable Convolutions (https://arxiv.org/abs/1610.02357) depthwise -> pointwise (1x1 conv) * Args: input_size: the number of input tensor's dimension num_filters: the number of convolution filter kernel_size: the number of convolution kernel size """ def __init__(self, input_size=None, num_filters=None, kernel_size=None): super(DepSepConv, self).__init__() self.depthwise = nn.Conv1d( in_channels=input_size, out_channels=input_size, kernel_size=kernel_size, groups=input_size, padding=kernel_size // 2, ) nn.init.kaiming_normal_(self.depthwise.weight) self.pointwise = PointwiseConv(input_size=input_size, num_filters=num_filters) self.activation_fn = F.relu
[docs] def forward(self, x): x = self.depthwise(x.transpose(1, 2)) x = self.pointwise(x.transpose(1, 2)) x = self.activation_fn(x) return x
================================================ FILE: docs/_build/html/_modules/claf/modules/conv/pointwise_conv.html ================================================ claf.modules.conv.pointwise_conv — CLaF 0.2.0 documentation

Source code for claf.modules.conv.pointwise_conv


import torch
import torch.nn as nn


[docs]class PointwiseConv(nn.Module): """ Pointwise Convolution (1x1 Conv) Convolution 1 Dimension (Faster version) (cf. https://github.com/huggingface/pytorch-openai-transformer-lm/blob/\ eafc28abdfadfa0732f03a0fc65805c5bfb2ffe7/model_pytorch.py#L45) * Args: input_size: the number of input tensor's dimension num_filters: the number of convolution filter """ # nf: num_filters, rf: kernel_size, nx: in_channels def __init__(self, input_size, num_filters): super(PointwiseConv, self).__init__() self.kernel_size = 1 self.num_filters = num_filters weight = torch.empty(input_size, num_filters) nn.init.normal_(weight, std=0.02) self.weight = nn.Parameter(weight) self.bias = nn.Parameter(torch.zeros(num_filters))
[docs] def forward(self, x): size_out = x.size()[:-1] + (self.num_filters,) x = torch.addmm(self.bias, x.contiguous().view(-1, x.size(-1)), self.weight) x = x.view(*size_out) return x
================================================ FILE: docs/_build/html/_modules/claf/modules/encoder/lstm_cell_with_projection.html ================================================ claf.modules.encoder.lstm_cell_with_projection — CLaF 0.2.0 documentation

Source code for claf.modules.encoder.lstm_cell_with_projection

"""
This code is from allenai/allennlp
(https://github.com/allenai/allennlp/blob/master/allennlp/modules/lstm_cell_with_projection.py)
"""

import itertools

from typing import Callable, List, Tuple, Union, Optional
import torch
from torch.nn.utils.rnn import pack_padded_sequence, PackedSequence


[docs]class LstmCellWithProjection(torch.nn.Module): # pragma: no cover """ An LSTM with Recurrent Dropout and a projected and clipped hidden state and memory. Note: this implementation is slower than the native Pytorch LSTM because it cannot make use of CUDNN optimizations for stacked RNNs due to and variational dropout and the custom nature of the cell state. Parameters ---------- input_size : ``int``, required. The dimension of the inputs to the LSTM. hidden_size : ``int``, required. The dimension of the outputs of the LSTM. cell_size : ``int``, required. The dimension of the memory cell used for the LSTM. go_forward: ``bool``, optional (default = True) The direction in which the LSTM is applied to the sequence. Forwards by default, or backwards if False. recurrent_dropout_probability: ``float``, optional (default = 0.0) The dropout probability to be used in a dropout scheme as stated in `A Theoretically Grounded Application of Dropout in Recurrent Neural Networks <https://arxiv.org/abs/1512.05287>`_ . Implementation wise, this simply applies a fixed dropout mask per sequence to the recurrent connection of the LSTM. state_projection_clip_value: ``float``, optional, (default = None) The magnitude with which to clip the hidden_state after projecting it. memory_cell_clip_value: ``float``, optional, (default = None) The magnitude with which to clip the memory cell. Returns ------- output_accumulator : ``torch.FloatTensor`` The outputs of the LSTM for each timestep. A tensor of shape (batch_size, max_timesteps, hidden_size) where for a given batch element, all outputs past the sequence length for that batch are zero tensors. final_state: ``Tuple[torch.FloatTensor, torch.FloatTensor]`` The final (state, memory) states of the LSTM, with shape (1, batch_size, hidden_size) and (1, batch_size, cell_size) respectively. The first dimension is 1 in order to match the Pytorch API for returning stacked LSTM states. """ def __init__( self, input_size: int, hidden_size: int, cell_size: int, go_forward: bool = True, recurrent_dropout_probability: float = 0.0, memory_cell_clip_value: Optional[float] = None, state_projection_clip_value: Optional[float] = None, ) -> None: super(LstmCellWithProjection, self).__init__() # Required to be wrapped with a :class:`PytorchSeq2SeqWrapper`. self.input_size = input_size self.hidden_size = hidden_size self.cell_size = cell_size self.go_forward = go_forward self.state_projection_clip_value = state_projection_clip_value self.memory_cell_clip_value = memory_cell_clip_value self.recurrent_dropout_probability = recurrent_dropout_probability # We do the projections for all the gates all at once. self.input_linearity = torch.nn.Linear(input_size, 4 * cell_size, bias=False) self.state_linearity = torch.nn.Linear(hidden_size, 4 * cell_size, bias=True) # Additional projection matrix for making the hidden state smaller. self.state_projection = torch.nn.Linear(cell_size, hidden_size, bias=False) self.reset_parameters()
[docs] def reset_parameters(self): # Use sensible default initializations for parameters. block_orthogonal(self.input_linearity.weight.data, [self.cell_size, self.input_size]) block_orthogonal(self.state_linearity.weight.data, [self.cell_size, self.hidden_size]) self.state_linearity.bias.data.fill_(0.0) # Initialize forget gate biases to 1.0 as per An Empirical # Exploration of Recurrent Network Architectures, (Jozefowicz, 2015). self.state_linearity.bias.data[self.cell_size : 2 * self.cell_size].fill_(1.0)
[docs] def forward( self, # pylint: disable=arguments-differ inputs: torch.FloatTensor, batch_lengths: List[int], initial_state: Optional[Tuple[torch.Tensor, torch.Tensor]] = None, ): """ Parameters ---------- inputs : ``torch.FloatTensor``, required. A tensor of shape (batch_size, num_timesteps, input_size) to apply the LSTM over. batch_lengths : ``List[int]``, required. A list of length batch_size containing the lengths of the sequences in batch. initial_state : ``Tuple[torch.Tensor, torch.Tensor]``, optional, (default = None) A tuple (state, memory) representing the initial hidden state and memory of the LSTM. The ``state`` has shape (1, batch_size, hidden_size) and the ``memory`` has shape (1, batch_size, cell_size). Returns ------- output_accumulator : ``torch.FloatTensor`` The outputs of the LSTM for each timestep. A tensor of shape (batch_size, max_timesteps, hidden_size) where for a given batch element, all outputs past the sequence length for that batch are zero tensors. final_state : ``Tuple[``torch.FloatTensor, torch.FloatTensor]`` A tuple (state, memory) representing the initial hidden state and memory of the LSTM. The ``state`` has shape (1, batch_size, hidden_size) and the ``memory`` has shape (1, batch_size, cell_size). """ batch_size = inputs.size()[0] total_timesteps = inputs.size()[1] output_accumulator = inputs.new_zeros(batch_size, total_timesteps, self.hidden_size) if initial_state is None: full_batch_previous_memory = inputs.new_zeros(batch_size, self.cell_size) full_batch_previous_state = inputs.new_zeros(batch_size, self.hidden_size) else: full_batch_previous_state = initial_state[0].squeeze(0) full_batch_previous_memory = initial_state[1].squeeze(0) current_length_index = batch_size - 1 if self.go_forward else 0 if self.recurrent_dropout_probability > 0.0 and self.training: dropout_mask = get_dropout_mask( self.recurrent_dropout_probability, full_batch_previous_state ) else: dropout_mask = None for timestep in range(total_timesteps): # The index depends on which end we start. index = timestep if self.go_forward else total_timesteps - timestep - 1 # What we are doing here is finding the index into the batch dimension # which we need to use for this timestep, because the sequences have # variable length, so once the index is greater than the length of this # particular batch sequence, we no longer need to do the computation for # this sequence. The key thing to recognise here is that the batch inputs # must be _ordered_ by length from longest (first in batch) to shortest # (last) so initially, we are going forwards with every sequence and as we # pass the index at which the shortest elements of the batch finish, # we stop picking them up for the computation. if self.go_forward: while batch_lengths[current_length_index] <= index: current_length_index -= 1 # If we're going backwards, we are _picking up_ more indices. else: # First conditional: Are we already at the maximum number of elements in the batch? # Second conditional: Does the next shortest sequence beyond the current batch # index require computation use this timestep? while ( current_length_index < (len(batch_lengths) - 1) and batch_lengths[current_length_index + 1] > index ): current_length_index += 1 # Actually get the slices of the batch which we # need for the computation at this timestep. # shape (batch_size, cell_size) previous_memory = full_batch_previous_memory[0 : current_length_index + 1].clone() # Shape (batch_size, hidden_size) previous_state = full_batch_previous_state[0 : current_length_index + 1].clone() # Shape (batch_size, input_size) timestep_input = inputs[0 : current_length_index + 1, index] # Do the projections for all the gates all at once. # Both have shape (batch_size, 4 * cell_size) projected_input = self.input_linearity(timestep_input) projected_state = self.state_linearity(previous_state) # Main LSTM equations using relevant chunks of the big linear # projections of the hidden state and inputs. input_gate = torch.sigmoid( projected_input[:, (0 * self.cell_size) : (1 * self.cell_size)] + projected_state[:, (0 * self.cell_size) : (1 * self.cell_size)] ) forget_gate = torch.sigmoid( projected_input[:, (1 * self.cell_size) : (2 * self.cell_size)] + projected_state[:, (1 * self.cell_size) : (2 * self.cell_size)] ) memory_init = torch.tanh( projected_input[:, (2 * self.cell_size) : (3 * self.cell_size)] + projected_state[:, (2 * self.cell_size) : (3 * self.cell_size)] ) output_gate = torch.sigmoid( projected_input[:, (3 * self.cell_size) : (4 * self.cell_size)] + projected_state[:, (3 * self.cell_size) : (4 * self.cell_size)] ) memory = input_gate * memory_init + forget_gate * previous_memory # Here is the non-standard part of this LSTM cell; first, we clip the # memory cell, then we project the output of the timestep to a smaller size # and again clip it. if self.memory_cell_clip_value: # pylint: disable=invalid-unary-operand-type memory = torch.clamp( memory, -self.memory_cell_clip_value, self.memory_cell_clip_value ) # shape (current_length_index, cell_size) pre_projection_timestep_output = output_gate * torch.tanh(memory) # shape (current_length_index, hidden_size) timestep_output = self.state_projection(pre_projection_timestep_output) if self.state_projection_clip_value: # pylint: disable=invalid-unary-operand-type timestep_output = torch.clamp( timestep_output, -self.state_projection_clip_value, self.state_projection_clip_value, ) # Only do dropout if the dropout prob is > 0.0 and we are in training mode. if dropout_mask is not None: timestep_output = timestep_output * dropout_mask[0 : current_length_index + 1] # We've been doing computation with less than the full batch, so here we create a new # variable for the the whole batch at this timestep and insert the result for the # relevant elements of the batch into it. full_batch_previous_memory = full_batch_previous_memory.clone() full_batch_previous_state = full_batch_previous_state.clone() full_batch_previous_memory[0 : current_length_index + 1] = memory full_batch_previous_state[0 : current_length_index + 1] = timestep_output output_accumulator[0 : current_length_index + 1, index] = timestep_output # Mimic the pytorch API by returning state in the following shape: # (num_layers * num_directions, batch_size, ...). As this # LSTM cell cannot be stacked, the first dimension here is just 1. final_state = ( full_batch_previous_state.unsqueeze(0), full_batch_previous_memory.unsqueeze(0), ) return output_accumulator, final_state
[docs]def get_dropout_mask( dropout_probability: float, tensor_for_masking: torch.Tensor ): # pragma: no cover """ Computes and returns an element-wise dropout mask for a given tensor, where each element in the mask is dropped out with probability dropout_probability. Note that the mask is NOT applied to the tensor - the tensor is passed to retain the correct CUDA tensor type for the mask. Parameters ---------- dropout_probability : float, required. Probability of dropping a dimension of the input. tensor_for_masking : torch.Tensor, required. Returns ------- A torch.FloatTensor consisting of the binary mask scaled by 1/ (1 - dropout_probability). This scaling ensures expected values and variances of the output of applying this mask and the original tensor are the same. """ binary_mask = tensor_for_masking.new_tensor( torch.rand(tensor_for_masking.size()) > dropout_probability ) # Scale mask by 1/keep_prob to preserve output statistics. dropout_mask = binary_mask.float().div(1.0 - dropout_probability) return dropout_mask
[docs]def block_orthogonal( tensor: torch.Tensor, split_sizes: List[int], gain: float = 1.0 ) -> None: # pragma: no cover """ An initializer which allows initializing model parameters in "blocks". This is helpful in the case of recurrent models which use multiple gates applied to linear projections, which can be computed efficiently if they are concatenated together. However, they are separate parameters which should be initialized independently. Parameters ---------- tensor : ``torch.Tensor``, required. A tensor to initialize. split_sizes : List[int], required. A list of length ``tensor.ndim()`` specifying the size of the blocks along that particular dimension. E.g. ``[10, 20]`` would result in the tensor being split into chunks of size 10 along the first dimension and 20 along the second. gain : float, optional (default = 1.0) The gain (scaling) applied to the orthogonal initialization. """ data = tensor.data sizes = list(tensor.size()) if any([a % b != 0 for a, b in zip(sizes, split_sizes)]): raise ValueError( "tensor dimensions must be divisible by their respective " "split_sizes. Found size: {} and split_sizes: {}".format(sizes, split_sizes) ) indexes = [list(range(0, max_size, split)) for max_size, split in zip(sizes, split_sizes)] # Iterate over all possible blocks within the tensor. for block_start_indices in itertools.product(*indexes): # A list of tuples containing the index to start at for this block # and the appropriate step size (i.e split_size[i] for dimension i). index_and_step_tuples = zip(block_start_indices, split_sizes) # This is a tuple of slices corresponding to: # tensor[index: index + step_size, ...]. This is # required because we could have an arbitrary number # of dimensions. The actual slices we need are the # start_index: start_index + step for each dimension in the tensor. block_slice = tuple( [slice(start_index, start_index + step) for start_index, step in index_and_step_tuples] ) data[block_slice] = torch.nn.init.orthogonal_(tensor[block_slice].contiguous(), gain=gain)
[docs]def sort_batch_by_length(tensor: torch.Tensor, sequence_lengths: torch.Tensor): # pragma: no cover """ Sort a batch first tensor by some specified lengths. Parameters ---------- tensor : torch.FloatTensor, required. A batch first Pytorch tensor. sequence_lengths : torch.LongTensor, required. A tensor representing the lengths of some dimension of the tensor which we want to sort by. Returns ------- sorted_tensor : torch.FloatTensor The original tensor sorted along the batch dimension with respect to sequence_lengths. sorted_sequence_lengths : torch.LongTensor The original sequence_lengths sorted by decreasing size. restoration_indices : torch.LongTensor Indices into the sorted_tensor such that ``sorted_tensor.index_select(0, restoration_indices) == original_tensor`` permuation_index : torch.LongTensor The indices used to sort the tensor. This is useful if you want to sort many tensors using the same ordering. """ if not isinstance(tensor, torch.Tensor) or not isinstance(sequence_lengths, torch.Tensor): raise ValueError("Both the tensor and sequence lengths must be torch.Tensors.") sorted_sequence_lengths, permutation_index = sequence_lengths.sort(0, descending=True) sorted_tensor = tensor.index_select(0, permutation_index) index_range = sequence_lengths.new_tensor(torch.arange(0, len(sequence_lengths))) # This is the equivalent of zipping with index, sorting by the original # sequence lengths and returning the now sorted indices. _, reverse_mapping = permutation_index.sort(0, descending=False) restoration_indices = index_range.index_select(0, reverse_mapping) return sorted_tensor, sorted_sequence_lengths, restoration_indices, permutation_index
# We have two types here for the state, because storing the state in something # which is Iterable (like a tuple, below), is helpful for internal manipulation # - however, the states are consumed as either Tensors or a Tuple of Tensors, so # returning them in this format is unhelpful. RnnState = Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]] # pylint: disable=invalid-name RnnStateStorage = Tuple[torch.Tensor, ...] # pylint: disable=invalid-name class _EncoderBase(torch.nn.Module): # pragma: no cover # pylint: disable=abstract-method """ This abstract class serves as a base for the 3 ``Encoder`` abstractions in AllenNLP. - :class:`~allennlp.modules.seq2seq_encoders.Seq2SeqEncoders` - :class:`~allennlp.modules.seq2vec_encoders.Seq2VecEncoders` Additionally, this class provides functionality for sorting sequences by length so they can be consumed by Pytorch RNN classes, which require their inputs to be sorted by length. Finally, it also provides optional statefulness to all of it's subclasses by allowing the caching and retrieving of the hidden states of RNNs. """ def __init__(self, stateful: bool = False) -> None: super(_EncoderBase, self).__init__() self.stateful = stateful self._states: Optional[RnnStateStorage] = None def sort_and_run_forward( self, module: Callable[ [PackedSequence, Optional[RnnState]], Tuple[Union[PackedSequence, torch.Tensor], RnnState], ], inputs: torch.Tensor, mask: torch.Tensor, hidden_state: Optional[RnnState] = None, ): """ This function exists because Pytorch RNNs require that their inputs be sorted before being passed as input. As all of our Seq2xxxEncoders use this functionality, it is provided in a base class. This method can be called on any module which takes as input a ``PackedSequence`` and some ``hidden_state``, which can either be a tuple of tensors or a tensor. As all of our Seq2xxxEncoders have different return types, we return `sorted` outputs from the module, which is called directly. Additionally, we return the indices into the batch dimension required to restore the tensor to it's correct, unsorted order and the number of valid batch elements (i.e the number of elements in the batch which are not completely masked). This un-sorting and re-padding of the module outputs is left to the subclasses because their outputs have different types and handling them smoothly here is difficult. Parameters ---------- module : ``Callable[[PackedSequence, Optional[RnnState]], Tuple[Union[PackedSequence, torch.Tensor], RnnState]]``, required. A function to run on the inputs. In most cases, this is a ``torch.nn.Module``. inputs : ``torch.Tensor``, required. A tensor of shape ``(batch_size, sequence_length, embedding_size)`` representing the inputs to the Encoder. mask : ``torch.Tensor``, required. A tensor of shape ``(batch_size, sequence_length)``, representing masked and non-masked elements of the sequence for each element in the batch. hidden_state : ``Optional[RnnState]``, (default = None). A single tensor of shape (num_layers, batch_size, hidden_size) representing the state of an RNN with or a tuple of tensors of shapes (num_layers, batch_size, hidden_size) and (num_layers, batch_size, memory_size), representing the hidden state and memory state of an LSTM-like RNN. Returns ------- module_output : ``Union[torch.Tensor, PackedSequence]``. A Tensor or PackedSequence representing the output of the Pytorch Module. The batch size dimension will be equal to ``num_valid``, as sequences of zero length are clipped off before the module is called, as Pytorch cannot handle zero length sequences. final_states : ``Optional[RnnState]`` A Tensor representing the hidden state of the Pytorch Module. This can either be a single tensor of shape (num_layers, num_valid, hidden_size), for instance in the case of a GRU, or a tuple of tensors, such as those required for an LSTM. restoration_indices : ``torch.LongTensor`` A tensor of shape ``(batch_size,)``, describing the re-indexing required to transform the outputs back to their original batch order. """ # In some circumstances you may have sequences of zero length. ``pack_padded_sequence`` # requires all sequence lengths to be > 0, so remove sequences of zero length before # calling self._module, then fill with zeros. # First count how many sequences are empty. batch_size = mask.size(0) num_valid = torch.sum(mask[:, 0]).int().item() sequence_lengths = mask.long().sum(-1) sorted_inputs, sorted_sequence_lengths, restoration_indices, sorting_indices = sort_batch_by_length( inputs, sequence_lengths ) # Now create a PackedSequence with only the non-empty, sorted sequences. packed_sequence_input = pack_padded_sequence( sorted_inputs[:num_valid, :, :], sorted_sequence_lengths[:num_valid].data.tolist(), batch_first=True, ) # Prepare the initial states. if not self.stateful: if hidden_state is None: initial_states = hidden_state elif isinstance(hidden_state, tuple): initial_states = [ state.index_select(1, sorting_indices)[:, :num_valid, :].contiguous() for state in hidden_state ] else: initial_states = hidden_state.index_select(1, sorting_indices)[ :, :num_valid, : ].contiguous() else: initial_states = self._get_initial_states(batch_size, num_valid, sorting_indices) # Actually call the module on the sorted PackedSequence. module_output, final_states = module(packed_sequence_input, initial_states) return module_output, final_states, restoration_indices def _get_initial_states( self, batch_size: int, num_valid: int, sorting_indices: torch.LongTensor ) -> Optional[RnnState]: """ Returns an initial state for use in an RNN. Additionally, this method handles the batch size changing across calls by mutating the state to append initial states for new elements in the batch. Finally, it also handles sorting the states with respect to the sequence lengths of elements in the batch and removing rows which are completely padded. Importantly, this `mutates` the state if the current batch size is larger than when it was previously called. Parameters ---------- batch_size : ``int``, required. The batch size can change size across calls to stateful RNNs, so we need to know if we need to expand or shrink the states before returning them. Expanded states will be set to zero. num_valid : ``int``, required. The batch may contain completely padded sequences which get removed before the sequence is passed through the encoder. We also need to clip these off of the state too. sorting_indices ``torch.LongTensor``, required. Pytorch RNNs take sequences sorted by length. When we return the states to be used for a given call to ``module.forward``, we need the states to match up to the sorted sequences, so before returning them, we sort the states using the same indices used to sort the sequences. Returns ------- This method has a complex return type because it has to deal with the first time it is called, when it has no state, and the fact that types of RNN have heterogeneous states. If it is the first time the module has been called, it returns ``None``, regardless of the type of the ``Module``. Otherwise, for LSTMs, it returns a tuple of ``torch.Tensors`` with shape ``(num_layers, num_valid, state_size)`` and ``(num_layers, num_valid, memory_size)`` respectively, or for GRUs, it returns a single ``torch.Tensor`` of shape ``(num_layers, num_valid, state_size)``. """ # We don't know the state sizes the first time calling forward, # so we let the module define what it's initial hidden state looks like. if self._states is None: return None # Otherwise, we have some previous states. if batch_size > self._states[0].size(1): # This batch is larger than the all previous states. # If so, resize the states. num_states_to_concat = batch_size - self._states[0].size(1) resized_states = [] # state has shape (num_layers, batch_size, hidden_size) for state in self._states: # This _must_ be inside the loop because some # RNNs have states with different last dimension sizes. zeros = state.new_zeros(state.size(0), num_states_to_concat, state.size(2)) resized_states.append(torch.cat([state, zeros], 1)) self._states = tuple(resized_states) correctly_shaped_states = self._states elif batch_size < self._states[0].size(1): # This batch is smaller than the previous one. correctly_shaped_states = tuple(state[:, :batch_size, :] for state in self._states) else: correctly_shaped_states = self._states # At this point, our states are of shape (num_layers, batch_size, hidden_size). # However, the encoder uses sorted sequences and additionally removes elements # of the batch which are fully padded. We need the states to match up to these # sorted and filtered sequences, so we do that in the next two blocks before # returning the state/s. if len(self._states) == 1: # GRUs only have a single state. This `unpacks` it from the # tuple and returns the tensor directly. correctly_shaped_state = correctly_shaped_states[0] sorted_state = correctly_shaped_state.index_select(1, sorting_indices) return sorted_state[:, :num_valid, :] else: # LSTMs have a state tuple of (state, memory). sorted_states = [ state.index_select(1, sorting_indices) for state in correctly_shaped_states ] return tuple(state[:, :num_valid, :] for state in sorted_states) def _update_states( self, final_states: RnnStateStorage, restoration_indices: torch.LongTensor ) -> None: """ After the RNN has run forward, the states need to be updated. This method just sets the state to the updated new state, performing several pieces of book-keeping along the way - namely, unsorting the states and ensuring that the states of completely padded sequences are not updated. Finally, it also detaches the state variable from the computational graph, such that the graph can be garbage collected after each batch iteration. Parameters ---------- final_states : ``RnnStateStorage``, required. The hidden states returned as output from the RNN. restoration_indices : ``torch.LongTensor``, required. The indices that invert the sorting used in ``sort_and_run_forward`` to order the states with respect to the lengths of the sequences in the batch. """ # TODO(Mark): seems weird to sort here, but append zeros in the subclasses. # which way around is best? new_unsorted_states = [state.index_select(1, restoration_indices) for state in final_states] if self._states is None: # We don't already have states, so just set the # ones we receive to be the current state. self._states = tuple(state.data for state in new_unsorted_states) else: # Now we've sorted the states back so that they correspond to the original # indices, we need to figure out what states we need to update, because if we # didn't use a state for a particular row, we want to preserve its state. # Thankfully, the rows which are all zero in the state correspond exactly # to those which aren't used, so we create masks of shape (new_batch_size,), # denoting which states were used in the RNN computation. current_state_batch_size = self._states[0].size(1) new_state_batch_size = final_states[0].size(1) # Masks for the unused states of shape (1, new_batch_size, 1) used_new_rows_mask = [ (state[0, :, :].sum(-1) != 0.0).float().view(1, new_state_batch_size, 1) for state in new_unsorted_states ] new_states = [] if current_state_batch_size > new_state_batch_size: # The new state is smaller than the old one, # so just update the indices which we used. for old_state, new_state, used_mask in zip( self._states, new_unsorted_states, used_new_rows_mask ): # zero out all rows in the previous state # which _were_ used in the current state. masked_old_state = old_state[:, :new_state_batch_size, :] * (1 - used_mask) # The old state is larger, so update the relevant parts of it. old_state[:, :new_state_batch_size, :] = new_state + masked_old_state new_states.append(old_state.detach()) else: # The states are the same size, so we just have to # deal with the possibility that some rows weren't used. new_states = [] for old_state, new_state, used_mask in zip( self._states, new_unsorted_states, used_new_rows_mask ): # zero out all rows which _were_ used in the current state. masked_old_state = old_state * (1 - used_mask) # The old state is larger, so update the relevant parts of it. new_state += masked_old_state new_states.append(new_state.detach()) # It looks like there should be another case handled here - when # the current_state_batch_size < new_state_batch_size. However, # this never happens, because the states themeselves are mutated # by appending zeros when calling _get_inital_states, meaning that # the new states are either of equal size, or smaller, in the case # that there are some unused elements (zero-length) for the RNN computation. self._states = tuple(new_states) def reset_states(self): self._states = None
================================================ FILE: docs/_build/html/_modules/claf/modules/encoder/positional.html ================================================ claf.modules.encoder.positional — CLaF 0.2.0 documentation

Source code for claf.modules.encoder.positional


import math
import numpy as np
import torch
import torch.nn as nn


[docs]class PositionalEncoding(nn.Module): """ Positional Encoding in "Attention is All You Need" (https://arxiv.org/abs/1706.03762) The use of relative position is possible because sin(x+y) and cos(x+y) can be expressed in terms of y, sin(x) and cos(x). (cf. https://github.com/tensorflow/tensor2tensor/blob/42c3f377f441e5a0f431127d63e71414ead291c4/\ tensor2tensor/layers/common_attention.py#L388) * Args: embed_dim: the number of embedding dimension * Kwargs: max_len: the number of maximum sequence length """ def __init__(self, embed_dim, max_length=2000): super(PositionalEncoding, self).__init__() signal_sinusoid = self._get_timing_signal(max_length, embed_dim) self.register_buffer("position_encoding", signal_sinusoid) def _get_timing_signal(self, length, channels, min_timescale=1.0, max_timescale=1.0e4): position = np.arange(length) num_timescales = channels // 2 log_timescale_increment = math.log( float(max_timescale) / float(min_timescale) / (float(num_timescales) - 1) ) inv_timescales = min_timescale * np.exp( np.arange(num_timescales).astype(np.float) * -log_timescale_increment ) scaled_time = np.expand_dims(position, 1) * np.expand_dims(inv_timescales, 0) signal = np.concatenate([np.sin(scaled_time), np.cos(scaled_time)], axis=1) signal = np.pad(signal, [[0, 0], [0, channels % 2]], "constant", constant_values=[0.0, 0.0]) signal = signal.reshape([1, length, channels]) return torch.from_numpy(signal).type(torch.FloatTensor)
[docs] def forward(self, x): x = x + self.position_encoding[:, : x.size(1)] return x
================================================ FILE: docs/_build/html/_modules/claf/modules/functional.html ================================================ claf.modules.functional — CLaF 0.2.0 documentation

Source code for claf.modules.functional

"""
    some functional codes from allennlp: https://github.com/allenai/allennlp

    - add_masked_value : replace_masked_values (allennlp)
    - get_mask_from_tokens : get_mask_from_tokens (allennlp)
    - last_dim_masked_softmax : last_dim_masked_softmax (allennlp)
    - masked_softmax : masked_softmax (allennlp)
    - weighted_sum : weighted_sum (allennlp)
"""

import torch
import torch.nn.functional as F
from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence


[docs]def add_masked_value(tensor, mask, value=-1e7): mask = mask.float() one_minus_mask = 1.0 - mask values_to_add = value * one_minus_mask return tensor * mask + values_to_add
[docs]def get_mask_from_tokens(tokens): tensor_dims = [(tensor.dim(), tensor) for tensor in tokens.values()] tensor_dims.sort(key=lambda x: x[0]) smallest_dim = tensor_dims[0][0] if smallest_dim == 2: token_tensor = tensor_dims[0][1] return (token_tensor != 0).long() elif smallest_dim == 3: character_tensor = tensor_dims[0][1] return ((character_tensor > 0).long().sum(dim=-1) > 0).long() else: raise ValueError("Expected a tensor with dimension 2 or 3, found {}".format(smallest_dim))
[docs]def last_dim_masked_softmax(x, mask): x_shape = x.size() reshaped_x = x.view(-1, x.size()[-1]) while mask.dim() < x.dim(): mask = mask.unsqueeze(1) mask = mask.expand_as(x).contiguous().float() mask = mask.view(-1, mask.size()[-1]) reshaped_result = masked_softmax(reshaped_x, mask) return reshaped_result.view(*x_shape)
[docs]def masked_softmax(x, mask): if mask is None: raise ValueError("mask can't be None.") output = F.softmax(x * mask, dim=-1) output = output * mask output = output / (output.sum(dim=1, keepdim=True) + 1e-13) return output
[docs]def weighted_sum(attention, matrix): # pragma: no cover if attention.dim() == 2 and matrix.dim() == 3: return attention.unsqueeze(1).bmm(matrix).squeeze(1) elif attention.dim() == 3 and matrix.dim() == 3: return attention.bmm(matrix) else: raise ValueError( f"attention dim {attention.dim()} and matrix dim {matrix.dim()} operation not support. (2, 3) and (3, 3) are available dimemsion." )
[docs]def masked_zero(tensor, mask): """ Tensor masking operation """ while mask.dim() < tensor.dim(): mask = mask.unsqueeze(-1) if isinstance(tensor, torch.FloatTensor): mask = mask.float() elif isinstance(tensor, torch.ByteTensor): mask = mask.byte() elif isinstance(tensor, torch.LongTensor): mask = mask.long() return tensor * mask
[docs]def masked_log_softmax(vector, mask): # pragma: no cover if mask is not None: vector = vector + mask.float().log() return torch.nn.functional.log_softmax(vector, dim=1)
[docs]def get_sorted_seq_config(features, pad_index=0): tensor_dims = [(tensor.dim(), tensor) for tensor in features.values()] tensor_dims.sort(key=lambda x: x[0]) smallest_dim = tensor_dims[0][0] if smallest_dim == 2: token_tensor = tensor_dims[0][1] else: raise ValueError("features smallest_dim must be `2` ([B, S_L]) ") seq_lengths = torch.sum(token_tensor > pad_index, dim=-1) seq_lengths, perm_idx = seq_lengths.sort(0, descending=True) _, unperm_idx = perm_idx.sort(0) return {"seq_lengths": seq_lengths, "perm_idx": perm_idx, "unperm_idx": unperm_idx}
[docs]def forward_rnn_with_pack(rnn_module, tensor, seq_config): sorted_tensor = tensor[seq_config["perm_idx"]] packed_input = pack_padded_sequence(sorted_tensor, seq_config["seq_lengths"], batch_first=True) packed_output, _ = rnn_module(packed_input) output, _ = pad_packed_sequence(packed_output, batch_first=True) output = output[seq_config["unperm_idx"]] # restore origin order return output
================================================ FILE: docs/_build/html/_modules/claf/modules/initializer.html ================================================ claf.modules.initializer — CLaF 0.2.0 documentation

Source code for claf.modules.initializer


import logging

import torch
import torch.nn as nn

logger = logging.getLogger(__name__)


[docs]def weight(module): """ weight initialization (according to module type) * Args: module: torch.nn.Module """ if type(module) == list: for m in module: weight(m) if isinstance(module, nn.Conv2d): logger.info("initializing Conv Layer") torch.nn.init.uniform_(module.weight) elif isinstance(module, nn.Linear): torch.nn.init.xavier_uniform_(module.weight) logger.info("Initializing Linear Layer") elif isinstance(module, nn.GRU): torch.nn.init.normal_(module.weight_hh_l0, std=0.05) logger.info("Initializing GRU Layer")
================================================ FILE: docs/_build/html/_modules/claf/modules/layer/highway.html ================================================ claf.modules.layer.highway — CLaF 0.2.0 documentation

Source code for claf.modules.layer.highway


import torch
import torch.nn as nn

from claf.modules.activation import get_activation_fn


[docs]class Highway(nn.Module): """ Highway Networks (https://arxiv.org/abs/1505.00387) https://github.com/allenai/allennlp/blob/master/allennlp/modules/highway.py * Args: input_size: The number of expected features in the input `x` num_layers: The number of Highway layers. activation: Activation Function (ReLU is default) """ def __init__(self, input_size, num_layers=2, activation="relu"): super(Highway, self).__init__() self.activation_fn = activation if type(activation) == str: self.activation_fn = get_activation_fn(activation)() self._layers = torch.nn.ModuleList( [nn.Linear(input_size, input_size * 2) for _ in range(num_layers)] ) for layer in self._layers: layer.bias[input_size:].data.fill_( 1 ) # should bias the highway layer to just carry its input forward.
[docs] def forward(self, x): current_input = x for layer in self._layers: projected_input = layer(current_input) linear_part = current_input nonlinear_part, gate = projected_input.chunk(2, dim=-1) nonlinear_part = self.activation_fn(nonlinear_part) gate = torch.sigmoid(gate) current_input = gate * linear_part + (1 - gate) * nonlinear_part return current_input
================================================ FILE: docs/_build/html/_modules/claf/modules/layer/normalization.html ================================================ claf.modules.layer.normalization — CLaF 0.2.0 documentation

Source code for claf.modules.layer.normalization


import torch
import torch.nn as nn


[docs]class LayerNorm(nn.Module): """ Layer Normalization (https://arxiv.org/abs/1607.06450) """ def __init__(self, normalized_shape, eps=1e-5): super(LayerNorm, self).__init__() self.gamma = nn.Parameter(torch.ones(normalized_shape)) self.beta = nn.Parameter(torch.zeros(normalized_shape)) self.eps = eps
[docs] def forward(self, x): mean = x.mean(-1, keepdim=True) std = x.std(-1, keepdim=True) return self.gamma * (x - mean) / (std + self.eps) + self.beta
================================================ FILE: docs/_build/html/_modules/claf/modules/layer/positionwise.html ================================================ claf.modules.layer.positionwise — CLaF 0.2.0 documentation

Source code for claf.modules.layer.positionwise


import torch.nn as nn
import torch.nn.functional as F

from claf.modules.conv import PointwiseConv


[docs]class PositionwiseFeedForward(nn.Module): """ Pointwise Feed-Forward Layer * Args: input_size: the number of input size hidden_size: the number of hidden size * Kwargs: dropout: the probability of dropout """ def __init__(self, input_size, hidden_size, dropout=0.1): super(PositionwiseFeedForward, self).__init__() self.pointwise_conv1 = PointwiseConv(input_size=input_size, num_filters=hidden_size) self.pointwise_conv2 = PointwiseConv(input_size=hidden_size, num_filters=input_size) self.activation_fn = F.relu self.dropout = nn.Dropout(p=dropout)
[docs] def forward(self, x): x = self.pointwise_conv1(x) x = self.activation_fn(x) x = self.pointwise_conv2(x) x = self.dropout(x) return x
================================================ FILE: docs/_build/html/_modules/claf/modules/layer/residual.html ================================================ claf.modules.layer.residual — CLaF 0.2.0 documentation

Source code for claf.modules.layer.residual

import torch
import torch.nn as nn

from claf.modules.layer.normalization import LayerNorm


[docs]class ResidualConnection(nn.Module): """ ResidualConnection in Deep Residual Learning for Image Recognition (https://arxiv.org/abs/1512.03385) => f(x) + x * Args: dim: the number of dimension * Kwargs: layer_dropout: layer dropout probability (stochastic depth) dropout: dropout probability """ def __init__(self, dim, layer_dropout=None, layernorm=False): super(ResidualConnection, self).__init__() self.survival = None if layer_dropout < 1: self.survival = torch.FloatTensor([layer_dropout]) if layernorm: self.norm = LayerNorm(dim) else: self.norm = lambda x: x
[docs] def forward(self, x, sub_layer_fn): # implementation of stochastic depth if self.training and self.survival is not None: survival_prob = torch.bernoulli(self.survival).item() if survival_prob == 1: return x + sub_layer_fn(self.norm(x)) else: return x else: return x + sub_layer_fn(self.norm(x))
================================================ FILE: docs/_build/html/_modules/claf/modules/layer/scalar_mix.html ================================================ claf.modules.layer.scalar_mix — CLaF 0.2.0 documentation

Source code for claf.modules.layer.scalar_mix

"""
This code is from allenai/allennlp
(https://github.com/allenai/allennlp/blob/master/allennlp/modules/scalar_mix.py)
"""

from typing import List

import torch
from torch.nn import ParameterList, Parameter


[docs]class ScalarMix(torch.nn.Module): # pragma: no cover """ Computes a parameterised scalar mixture of N tensors, ``mixture = gamma * sum(s_k * tensor_k)`` where ``s = softmax(w)``, with ``w`` and ``gamma`` scalar parameters. In addition, if ``do_layer_norm=True`` then apply layer normalization to each tensor before weighting. """ def __init__( self, mixture_size: int, do_layer_norm: bool = False, initial_scalar_parameters: List[float] = None, trainable: bool = True, ) -> None: super(ScalarMix, self).__init__() self.mixture_size = mixture_size self.do_layer_norm = do_layer_norm if initial_scalar_parameters is None: initial_scalar_parameters = [0.0] * mixture_size elif len(initial_scalar_parameters) != mixture_size: raise ValueError( "Length of initial_scalar_parameters {} differs " "from mixture_size {}".format(initial_scalar_parameters, mixture_size) ) self.scalar_parameters = ParameterList( [ Parameter( torch.FloatTensor([initial_scalar_parameters[i]]), requires_grad=trainable ) for i in range(mixture_size) ] ) self.gamma = Parameter(torch.FloatTensor([1.0]), requires_grad=trainable)
[docs] def forward( self, tensors: List[torch.Tensor], # pylint: disable=arguments-differ mask: torch.Tensor = None, ) -> torch.Tensor: """ Compute a weighted average of the ``tensors``. The input tensors an be any shape with at least two dimensions, but must all be the same shape. When ``do_layer_norm=True``, the ``mask`` is required input. If the ``tensors`` are dimensioned ``(dim_0, ..., dim_{n-1}, dim_n)``, then the ``mask`` is dimensioned ``(dim_0, ..., dim_{n-1})``, as in the typical case with ``tensors`` of shape ``(batch_size, timesteps, dim)`` and ``mask`` of shape ``(batch_size, timesteps)``. When ``do_layer_norm=False`` the ``mask`` is ignored. """ if len(tensors) != self.mixture_size: raise ValueError( "{} tensors were passed, but the module was initialized to " "mix {} tensors.".format(len(tensors), self.mixture_size) ) def _do_layer_norm(tensor, broadcast_mask, num_elements_not_masked): tensor_masked = tensor * broadcast_mask mean = torch.sum(tensor_masked) / num_elements_not_masked variance = ( torch.sum(((tensor_masked - mean) * broadcast_mask) ** 2) / num_elements_not_masked ) return (tensor - mean) / torch.sqrt(variance + 1E-12) normed_weights = torch.nn.functional.softmax( torch.cat([parameter for parameter in self.scalar_parameters]), dim=0 ) normed_weights = torch.split(normed_weights, split_size_or_sections=1) if not self.do_layer_norm: pieces = [] for weight, tensor in zip(normed_weights, tensors): pieces.append(weight * tensor) return self.gamma * sum(pieces) else: mask_float = mask.float() broadcast_mask = mask_float.unsqueeze(-1) input_dim = tensors[0].size(-1) num_elements_not_masked = torch.sum(mask_float) * input_dim pieces = [] for weight, tensor in zip(normed_weights, tensors): pieces.append( weight * _do_layer_norm(tensor, broadcast_mask, num_elements_not_masked) ) return self.gamma * sum(pieces)
================================================ FILE: docs/_build/html/_modules/claf/tokens/cove.html ================================================ claf.tokens.cove — CLaF 0.2.0 documentation

Source code for claf.tokens.cove

"""
This code is from salesforce/cove
(https://github.com/salesforce/cove/blob/master/cove/encoder.py)
"""

import torch
from torch import nn

from claf.data.data_handler import CachePath, DataHandler


[docs]class MTLSTM(nn.Module): def __init__( self, word_embedding, pretrained_path=None, requires_grad=False, residual_embeddings=False ): """Initialize an MTLSTM. Arguments: n_vocab (bool): If not None, initialize MTLSTM with an embedding matrix with n_vocab vectors vectors (Float Tensor): If not None, initiapize embedding matrix with specified vectors residual_embedding (bool): If True, concatenate the input embeddings with MTLSTM outputs during forward """ super(MTLSTM, self).__init__() self.word_embedding = word_embedding self.rnn = nn.LSTM(300, 300, num_layers=2, bidirectional=True, batch_first=True) data_handler = DataHandler(cache_path=CachePath.PRETRAINED_VECTOR) cove_weight_path = data_handler.read(pretrained_path, return_path=True) if torch.cuda.is_available(): checkpoint = torch.load(cove_weight_path) else: checkpoint = torch.load(cove_weight_path, map_location="cpu") self.rnn.load_state_dict(checkpoint) self.residual_embeddings = residual_embeddings self.requires_grad = requires_grad
[docs] def forward(self, inputs): """A pretrained MT-LSTM (McCann et. al. 2017). This LSTM was trained with 300d 840B GloVe on the WMT 2017 machine translation dataset. Arguments: inputs (Tensor): If MTLSTM handles embedding, a Long Tensor of size (batch_size, timesteps). Otherwise, a Float Tensor of size (batch_size, timesteps, features). lengths (Long Tensor): (batch_size, lengths) lenghts of each sequence for handling padding hidden (Float Tensor): initial hidden state of the LSTM """ embedded_inputs = self.word_embedding(inputs) encoded_inputs, _ = self.rnn(embedded_inputs) if not self.requires_grad: encoded_inputs.detach() outputs = encoded_inputs if self.residual_embeddings: outputs = torch.cat([embedded_inputs, encoded_inputs], 2) return outputs
================================================ FILE: docs/_build/html/_modules/claf/tokens/elmo.html ================================================ claf.tokens.elmo — CLaF 0.2.0 documentation

Source code for claf.tokens.elmo

"""
This code is from allenai/allennlp
(https://github.com/allenai/allennlp/blob/master/allennlp/modules/elmo.py)
"""

import json
import logging
from typing import Union, List, Dict, Any, Optional, Tuple
import warnings

import numpy
from overrides import overrides
import torch
from torch.nn.utils.rnn import PackedSequence, pad_packed_sequence
from torch.nn.modules import Dropout


with warnings.catch_warnings():  # pragma: no cover
    warnings.filterwarnings("ignore", category=FutureWarning)
    import h5py

from claf.modules.layer import Highway, ScalarMix
from claf.modules.encoder import _EncoderBase, LstmCellWithProjection


logger = logging.getLogger(__name__)  # pylint: disable=invalid-name

# pylint: disable=attribute-defined-outside-init


[docs]class Elmo(torch.nn.Module): # pragma: no cover """ Compute ELMo representations using a pre-trained bidirectional language model. See "Deep contextualized word representations", Peters et al. for details. This module takes character id input and computes ``num_output_representations`` different layers of ELMo representations. Typically ``num_output_representations`` is 1 or 2. For example, in the case of the SRL model in the above paper, ``num_output_representations=1`` where ELMo was included at the input token representation layer. In the case of the SQuAD model, ``num_output_representations=2`` as ELMo was also included at the GRU output layer. In the implementation below, we learn separate scalar weights for each output layer, but only run the biLM once on each input sequence for efficiency. Parameters ---------- options_file : ``str``, required. ELMo JSON options file weight_file : ``str``, required. ELMo hdf5 weight file num_output_representations: ``int``, required. The number of ELMo representation layers to output. requires_grad: ``bool``, optional If True, compute gradient of ELMo parameters for fine tuning. do_layer_norm : ``bool``, optional, (default=False). Should we apply layer normalization (passed to ``ScalarMix``)? dropout : ``float``, optional, (default = 0.5). The dropout to be applied to the ELMo representations. vocab_to_cache : ``List[str]``, optional, (default = 0.5). A list of words to pre-compute and cache character convolutions for. If you use this option, Elmo expects that you pass word indices of shape (batch_size, timesteps) to forward, instead of character indices. If you use this option and pass a word which wasn't pre-cached, this will break. module : ``torch.nn.Module``, optional, (default = None). If provided, then use this module instead of the pre-trained ELMo biLM. If using this option, then pass ``None`` for both ``options_file`` and ``weight_file``. The module must provide a public attribute ``num_layers`` with the number of internal layers and its ``forward`` method must return a ``dict`` with ``activations`` and ``mask`` keys (see `_ElmoBilm`` for an example). Note that ``requires_grad`` is also ignored with this option. """ def __init__( self, options_file: str, weight_file: str, num_output_representations: int, requires_grad: bool = False, do_layer_norm: bool = False, dropout: float = 0.5, vocab_to_cache: List[str] = None, module: torch.nn.Module = None, ) -> None: super(Elmo, self).__init__() logging.info("Initializing ELMo") if module is not None: if options_file is not None or weight_file is not None: raise ValueError("Don't provide options_file or weight_file with module") self._elmo_lstm = module else: self._elmo_lstm = _ElmoBiLm( options_file, weight_file, requires_grad=requires_grad, vocab_to_cache=vocab_to_cache, ) self._has_cached_vocab = vocab_to_cache is not None self._dropout = Dropout(p=dropout) self._scalar_mixes: Any = [] for k in range(num_output_representations): scalar_mix = ScalarMix(self._elmo_lstm.num_layers, do_layer_norm=do_layer_norm) self.add_module("scalar_mix_{}".format(k), scalar_mix) self._scalar_mixes.append(scalar_mix)
[docs] def get_output_dim(self): return self._elmo_lstm.get_output_dim()
[docs] def forward( self, inputs: torch.Tensor, word_inputs: torch.Tensor = None, # pylint: disable=arguments-differ ) -> Dict[str, Union[torch.Tensor, List[torch.Tensor]]]: """ Parameters ---------- inputs: ``torch.Tensor``, required. Shape ``(batch_size, timesteps, 50)`` of character ids representing the current batch. word_inputs : ``torch.Tensor``, required. If you passed a cached vocab, you can in addition pass a tensor of shape ``(batch_size, timesteps)``, which represent word ids which have been pre-cached. Returns ------- Dict with keys: ``'elmo_representations'``: ``List[torch.Tensor]`` A ``num_output_representations`` list of ELMo representations for the input sequence. Each representation is shape ``(batch_size, timesteps, embedding_dim)`` ``'mask'``: ``torch.Tensor`` Shape ``(batch_size, timesteps)`` long tensor with sequence mask. """ # reshape the input if needed original_shape = inputs.size() if len(original_shape) > 3: timesteps, num_characters = original_shape[-2:] reshaped_inputs = inputs.view(-1, timesteps, num_characters) else: reshaped_inputs = inputs if word_inputs is not None: original_word_size = word_inputs.size() if self._has_cached_vocab and len(original_word_size) > 2: reshaped_word_inputs = word_inputs.view(-1, original_word_size[-1]) logger.warning( "Word inputs were passed to ELMo but it does not have a cached vocab." ) reshaped_word_inputs = None else: reshaped_word_inputs = word_inputs else: reshaped_word_inputs = word_inputs # run the biLM bilm_output = self._elmo_lstm(reshaped_inputs, reshaped_word_inputs) layer_activations = bilm_output["activations"] mask_with_bos_eos = bilm_output["mask"] # compute the elmo representations representations = [] for i in range(len(self._scalar_mixes)): scalar_mix = getattr(self, "scalar_mix_{}".format(i)) representation_with_bos_eos = scalar_mix(layer_activations, mask_with_bos_eos) representation_without_bos_eos, mask_without_bos_eos = remove_sentence_boundaries( representation_with_bos_eos, mask_with_bos_eos ) representations.append(self._dropout(representation_without_bos_eos)) # reshape if necessary if word_inputs is not None and len(original_word_size) > 2: mask = mask_without_bos_eos.view(original_word_size) elmo_representations = [ representation.view(original_word_size + (-1,)) for representation in representations ] elif len(original_shape) > 3: mask = mask_without_bos_eos.view(original_shape[:-1]) elmo_representations = [ representation.view(original_shape[:-1] + (-1,)) for representation in representations ] else: mask = mask_without_bos_eos elmo_representations = representations return {"elmo_representations": elmo_representations, "mask": mask}
[docs] @classmethod def from_params(cls, params) -> "Elmo": # Add files to archive params.add_file_to_archive("options_file") params.add_file_to_archive("weight_file") options_file = params.pop("options_file") weight_file = params.pop("weight_file") requires_grad = params.pop("requires_grad", False) num_output_representations = params.pop("num_output_representations") do_layer_norm = params.pop_bool("do_layer_norm", False) dropout = params.pop_float("dropout", 0.5) params.assert_empty(cls.__name__) return cls( options_file=options_file, weight_file=weight_file, num_output_representations=num_output_representations, requires_grad=requires_grad, do_layer_norm=do_layer_norm, dropout=dropout, )
[docs]def remove_sentence_boundaries( tensor: torch.Tensor, mask: torch.Tensor ) -> Tuple[torch.Tensor, torch.Tensor]: # pragma: no cover """ Remove begin/end of sentence embeddings from the batch of sentences. Given a batch of sentences with size ``(batch_size, timesteps, dim)`` this returns a tensor of shape ``(batch_size, timesteps - 2, dim)`` after removing the beginning and end sentence markers. The sentences are assumed to be padded on the right, with the beginning of each sentence assumed to occur at index 0 (i.e., ``mask[:, 0]`` is assumed to be 1). Returns both the new tensor and updated mask. This function is the inverse of ``add_sentence_boundary_token_ids``. Parameters ---------- tensor : ``torch.Tensor`` A tensor of shape ``(batch_size, timesteps, dim)`` mask : ``torch.Tensor`` A tensor of shape ``(batch_size, timesteps)`` Returns ------- tensor_without_boundary_tokens : ``torch.Tensor`` The tensor after removing the boundary tokens of shape ``(batch_size, timesteps - 2, dim)`` new_mask : ``torch.Tensor`` The new mask for the tensor of shape ``(batch_size, timesteps - 2)``. """ # TODO: matthewp, profile this transfer sequence_lengths = mask.sum(dim=1).detach().cpu().numpy() tensor_shape = list(tensor.data.shape) new_shape = list(tensor_shape) new_shape[1] = tensor_shape[1] - 2 tensor_without_boundary_tokens = tensor.new_zeros(*new_shape) new_mask = tensor.new_zeros((new_shape[0], new_shape[1]), dtype=torch.long) for i, j in enumerate(sequence_lengths): if j > 2: tensor_without_boundary_tokens[i, : (j - 2), :] = tensor[i, 1 : (j - 1), :] new_mask[i, : (j - 2)] = 1 return tensor_without_boundary_tokens, new_mask
class _ElmoBiLm(torch.nn.Module): # pragma: no cover """ Run a pre-trained bidirectional language model, outputing the activations at each layer for weighting together into an ELMo representation (with ``allennlp.modules.seq2seq_encoders.Elmo``). This is a lower level class, useful for advanced uses, but most users should use ``allennlp.modules.seq2seq_encoders.Elmo`` directly. Parameters ---------- options_file : ``str`` ELMo JSON options file weight_file : ``str`` ELMo hdf5 weight file requires_grad: ``bool``, optional If True, compute gradient of ELMo parameters for fine tuning. vocab_to_cache : ``List[str]``, optional, (default = 0.5). A list of words to pre-compute and cache character convolutions for. If you use this option, _ElmoBiLm expects that you pass word indices of shape (batch_size, timesteps) to forward, instead of character indices. If you use this option and pass a word which wasn't pre-cached, this will break. """ def __init__( self, options_file: str, weight_file: str, requires_grad: bool = False, vocab_to_cache: List[str] = None, ) -> None: super(_ElmoBiLm, self).__init__() self._token_embedder = _ElmoCharacterEncoder( options_file, weight_file, requires_grad=requires_grad ) self._requires_grad = requires_grad if requires_grad and vocab_to_cache: logging.warning( "You are fine tuning ELMo and caching char CNN word vectors. " "This behaviour is not guaranteed to be well defined, particularly. " "if not all of your inputs will occur in the vocabulary cache." ) # This is an embedding, used to look up cached # word vectors built from character level cnn embeddings. self._word_embedding = None self._bos_embedding: torch.Tensor = None self._eos_embedding: torch.Tensor = None with open(options_file, "r") as fin: options = json.load(fin) if not options["lstm"].get("use_skip_connections"): raise ValueError("We only support pretrained biLMs with residual connections") self._elmo_lstm = ElmoLstm( input_size=options["lstm"]["projection_dim"], hidden_size=options["lstm"]["projection_dim"], cell_size=options["lstm"]["dim"], num_layers=options["lstm"]["n_layers"], memory_cell_clip_value=options["lstm"]["cell_clip"], state_projection_clip_value=options["lstm"]["proj_clip"], requires_grad=requires_grad, ) self._elmo_lstm.load_weights(weight_file) # Number of representation layers including context independent layer self.num_layers = options["lstm"]["n_layers"] + 1 def get_output_dim(self): return 2 * self._token_embedder.get_output_dim() def forward( self, inputs: torch.Tensor, word_inputs: torch.Tensor = None, # pylint: disable=arguments-differ ) -> Dict[str, Union[torch.Tensor, List[torch.Tensor]]]: """ Parameters ---------- inputs: ``torch.Tensor``, required. Shape ``(batch_size, timesteps, 50)`` of character ids representing the current batch. word_inputs : ``torch.Tensor``, required. If you passed a cached vocab, you can in addition pass a tensor of shape ``(batch_size, timesteps)``, which represent word ids which have been pre-cached. Returns ------- Dict with keys: ``'activations'``: ``List[torch.Tensor]`` A list of activations at each layer of the network, each of shape ``(batch_size, timesteps + 2, embedding_dim)`` ``'mask'``: ``torch.Tensor`` Shape ``(batch_size, timesteps + 2)`` long tensor with sequence mask. Note that the output tensors all include additional special begin and end of sequence markers. """ if self._word_embedding is not None and word_inputs is not None: try: mask_without_bos_eos = (word_inputs > 0).long() # The character cnn part is cached - just look it up. embedded_inputs = self._word_embedding(word_inputs) # type: ignore # shape (batch_size, timesteps + 2, embedding_dim) type_representation, mask = add_sentence_boundary_token_ids( embedded_inputs, mask_without_bos_eos, self._bos_embedding, self._eos_embedding ) except RuntimeError: # Back off to running the character convolutions, # as we might not have the words in the cache. token_embedding = self._token_embedder(inputs) mask = token_embedding["mask"] type_representation = token_embedding["token_embedding"] else: token_embedding = self._token_embedder(inputs) mask = token_embedding["mask"] type_representation = token_embedding["token_embedding"] lstm_outputs = self._elmo_lstm(type_representation, mask) # Prepare the output. The first layer is duplicated. # Because of minor differences in how masking is applied depending # on whether the char cnn layers are cached, we'll be defensive and # multiply by the mask here. It's not strictly necessary, as the # mask passed on is correct, but the values in the padded areas # of the char cnn representations can change. output_tensors = [ torch.cat([type_representation, type_representation], dim=-1) * mask.float().unsqueeze(-1) ] for layer_activations in torch.chunk(lstm_outputs, lstm_outputs.size(0), dim=0): output_tensors.append(layer_activations.squeeze(0)) return {"activations": output_tensors, "mask": mask}
[docs]def add_sentence_boundary_token_ids( tensor: torch.Tensor, mask: torch.Tensor, sentence_begin_token: Any, sentence_end_token: Any ) -> Tuple[torch.Tensor, torch.Tensor]: # pragma: no cover """ Add begin/end of sentence tokens to the batch of sentences. Given a batch of sentences with size ``(batch_size, timesteps)`` or ``(batch_size, timesteps, dim)`` this returns a tensor of shape ``(batch_size, timesteps + 2)`` or ``(batch_size, timesteps + 2, dim)`` respectively. Returns both the new tensor and updated mask. Parameters ---------- tensor : ``torch.Tensor`` A tensor of shape ``(batch_size, timesteps)`` or ``(batch_size, timesteps, dim)`` mask : ``torch.Tensor`` A tensor of shape ``(batch_size, timesteps)`` sentence_begin_token: Any (anything that can be broadcast in torch for assignment) For 2D input, a scalar with the <S> id. For 3D input, a tensor with length dim. sentence_end_token: Any (anything that can be broadcast in torch for assignment) For 2D input, a scalar with the </S> id. For 3D input, a tensor with length dim. Returns ------- tensor_with_boundary_tokens : ``torch.Tensor`` The tensor with the appended and prepended boundary tokens. If the input was 2D, it has shape (batch_size, timesteps + 2) and if the input was 3D, it has shape (batch_size, timesteps + 2, dim). new_mask : ``torch.Tensor`` The new mask for the tensor, taking into account the appended tokens marking the beginning and end of the sentence. """ # TODO: matthewp, profile this transfer sequence_lengths = mask.sum(dim=1).detach().cpu().numpy() tensor_shape = list(tensor.data.shape) new_shape = list(tensor_shape) new_shape[1] = tensor_shape[1] + 2 tensor_with_boundary_tokens = tensor.new_zeros(*new_shape) if len(tensor_shape) == 2: tensor_with_boundary_tokens[:, 1:-1] = tensor tensor_with_boundary_tokens[:, 0] = sentence_begin_token for i, j in enumerate(sequence_lengths): tensor_with_boundary_tokens[i, j + 1] = sentence_end_token new_mask = (tensor_with_boundary_tokens != 0).long() elif len(tensor_shape) == 3: tensor_with_boundary_tokens[:, 1:-1, :] = tensor for i, j in enumerate(sequence_lengths): tensor_with_boundary_tokens[i, 0, :] = sentence_begin_token tensor_with_boundary_tokens[i, j + 1, :] = sentence_end_token new_mask = ((tensor_with_boundary_tokens > 0).long().sum(dim=-1) > 0).long() else: raise ValueError("add_sentence_boundary_token_ids only accepts 2D and 3D input") return tensor_with_boundary_tokens, new_mask
def _make_bos_eos( character: int, padding_character: int, beginning_of_word_character: int, end_of_word_character: int, max_word_length: int, ): # pragma: no cover char_ids = [padding_character] * max_word_length char_ids[0] = beginning_of_word_character char_ids[1] = character char_ids[2] = end_of_word_character return char_ids class _ElmoCharacterEncoder(torch.nn.Module): # pragma: no cover """ Compute context sensitive token representation using pretrained biLM. This embedder has input character ids of size (batch_size, sequence_length, 50) and returns (batch_size, sequence_length + 2, embedding_dim), where embedding_dim is specified in the options file (typically 512). We add special entries at the beginning and end of each sequence corresponding to <S> and </S>, the beginning and end of sentence tokens. Note: this is a lower level class useful for advanced usage. Most users should use ``ElmoTokenEmbedder`` or ``allennlp.modules.Elmo`` instead. Parameters ---------- options_file : ``str`` ELMo JSON options file weight_file : ``str`` ELMo hdf5 weight file requires_grad: ``bool``, optional If True, compute gradient of ELMo parameters for fine tuning. The relevant section of the options file is something like: .. example-code:: .. code-block:: python {'char_cnn': { 'activation': 'relu', 'embedding': {'dim': 4}, 'filters': [[1, 4], [2, 8], [3, 16], [4, 32], [5, 64]], 'max_characters_per_token': 50, 'n_characters': 262, 'n_highway': 2 } } """ def __init__(self, options_file: str, weight_file: str, requires_grad: bool = False) -> None: super(_ElmoCharacterEncoder, self).__init__() with open(options_file, "r") as fin: self._options = json.load(fin) self._weight_file = weight_file self.output_dim = self._options["lstm"]["projection_dim"] self.requires_grad = requires_grad self._load_weights() max_word_length = 50 # char ids 0-255 come from utf-8 encoding bytes # assign 256-300 to special chars beginning_of_sentence_character = 256 # <begin sentence> end_of_sentence_character = 257 # <end sentence> beginning_of_word_character = 258 # <begin word> end_of_word_character = 259 # <end word> padding_character = 260 # <padding> beginning_of_sentence_characters = _make_bos_eos( beginning_of_sentence_character, padding_character, beginning_of_word_character, end_of_word_character, max_word_length, ) end_of_sentence_characters = _make_bos_eos( end_of_sentence_character, padding_character, beginning_of_word_character, end_of_word_character, max_word_length, ) # Cache the arrays for use in forward -- +1 due to masking. self._beginning_of_sentence_characters = torch.from_numpy( numpy.array(beginning_of_sentence_characters) + 1 ) self._end_of_sentence_characters = torch.from_numpy( numpy.array(end_of_sentence_characters) + 1 ) def get_output_dim(self): return self.output_dim @overrides def forward( self, inputs: torch.Tensor ) -> Dict[str, torch.Tensor]: # pylint: disable=arguments-differ """ Compute context insensitive token embeddings for ELMo representations. Parameters ---------- inputs: ``torch.Tensor`` Shape ``(batch_size, sequence_length, 50)`` of character ids representing the current batch. Returns ------- Dict with keys: ``'token_embedding'``: ``torch.Tensor`` Shape ``(batch_size, sequence_length + 2, embedding_dim)`` tensor with context insensitive token representations. ``'mask'``: ``torch.Tensor`` Shape ``(batch_size, sequence_length + 2)`` long tensor with sequence mask. """ # Add BOS/EOS mask = ((inputs > 0).long().sum(dim=-1) > 0).long() character_ids_with_bos_eos, mask_with_bos_eos = add_sentence_boundary_token_ids( inputs, mask, self._beginning_of_sentence_characters, self._end_of_sentence_characters ) # the character id embedding max_chars_per_token = self._options["char_cnn"]["max_characters_per_token"] # (batch_size * sequence_length, max_chars_per_token, embed_dim) character_embedding = torch.nn.functional.embedding( character_ids_with_bos_eos.view(-1, max_chars_per_token), self._char_embedding_weights ) # run convolutions cnn_options = self._options["char_cnn"] if cnn_options["activation"] == "tanh": activation = torch.nn.functional.tanh elif cnn_options["activation"] == "relu": activation = torch.nn.functional.relu else: raise ValueError("Unknown activation") # (batch_size * sequence_length, embed_dim, max_chars_per_token) character_embedding = torch.transpose(character_embedding, 1, 2) convs = [] for i in range(len(self._convolutions)): conv = getattr(self, "char_conv_{}".format(i)) convolved = conv(character_embedding) # (batch_size * sequence_length, n_filters for this width) convolved, _ = torch.max(convolved, dim=-1) convolved = activation(convolved) convs.append(convolved) # (batch_size * sequence_length, n_filters) token_embedding = torch.cat(convs, dim=-1) # apply the highway layers (batch_size * sequence_length, n_filters) token_embedding = self._highways(token_embedding) # final projection (batch_size * sequence_length, embedding_dim) token_embedding = self._projection(token_embedding) # reshape to (batch_size, sequence_length, embedding_dim) batch_size, sequence_length, _ = character_ids_with_bos_eos.size() return { "mask": mask_with_bos_eos, "token_embedding": token_embedding.view(batch_size, sequence_length, -1), } def _load_weights(self): self._load_char_embedding() self._load_cnn_weights() self._load_highway() self._load_projection() def _load_char_embedding(self): with h5py.File(self._weight_file, "r") as fin: char_embed_weights = fin["char_embed"][...] weights = numpy.zeros( (char_embed_weights.shape[0] + 1, char_embed_weights.shape[1]), dtype="float32" ) weights[1:, :] = char_embed_weights self._char_embedding_weights = torch.nn.Parameter( torch.FloatTensor(weights), requires_grad=self.requires_grad ) def _load_cnn_weights(self): cnn_options = self._options["char_cnn"] filters = cnn_options["filters"] char_embed_dim = cnn_options["embedding"]["dim"] convolutions = [] for i, (width, num) in enumerate(filters): conv = torch.nn.Conv1d( in_channels=char_embed_dim, out_channels=num, kernel_size=width, bias=True ) # load the weights with h5py.File(self._weight_file, "r") as fin: weight = fin["CNN"]["W_cnn_{}".format(i)][...] bias = fin["CNN"]["b_cnn_{}".format(i)][...] w_reshaped = numpy.transpose(weight.squeeze(axis=0), axes=(2, 1, 0)) if w_reshaped.shape != tuple(conv.weight.data.shape): raise ValueError("Invalid weight file") conv.weight.data.copy_(torch.FloatTensor(w_reshaped)) conv.bias.data.copy_(torch.FloatTensor(bias)) conv.weight.requires_grad = self.requires_grad conv.bias.requires_grad = self.requires_grad convolutions.append(conv) self.add_module("char_conv_{}".format(i), conv) self._convolutions = convolutions def _load_highway(self): # pylint: disable=protected-access # the highway layers have same dimensionality as the number of cnn filters cnn_options = self._options["char_cnn"] filters = cnn_options["filters"] n_filters = sum(f[1] for f in filters) n_highway = cnn_options["n_highway"] # create the layers, and load the weights self._highways = Highway(n_filters, n_highway, activation=torch.nn.functional.relu) for k in range(n_highway): # The AllenNLP highway is one matrix multplication with concatenation of # transform and carry weights. with h5py.File(self._weight_file, "r") as fin: # The weights are transposed due to multiplication order assumptions in tf # vs pytorch (tf.matmul(X, W) vs pytorch.matmul(W, X)) w_transform = numpy.transpose(fin["CNN_high_{}".format(k)]["W_transform"][...]) # -1.0 since AllenNLP is g * x + (1 - g) * f(x) but tf is (1 - g) * x + g * f(x) w_carry = -1.0 * numpy.transpose(fin["CNN_high_{}".format(k)]["W_carry"][...]) weight = numpy.concatenate([w_transform, w_carry], axis=0) self._highways._layers[k].weight.data.copy_(torch.FloatTensor(weight)) self._highways._layers[k].weight.requires_grad = self.requires_grad b_transform = fin["CNN_high_{}".format(k)]["b_transform"][...] b_carry = -1.0 * fin["CNN_high_{}".format(k)]["b_carry"][...] bias = numpy.concatenate([b_transform, b_carry], axis=0) self._highways._layers[k].bias.data.copy_(torch.FloatTensor(bias)) self._highways._layers[k].bias.requires_grad = self.requires_grad def _load_projection(self): cnn_options = self._options["char_cnn"] filters = cnn_options["filters"] n_filters = sum(f[1] for f in filters) self._projection = torch.nn.Linear(n_filters, self.output_dim, bias=True) with h5py.File(self._weight_file, "r") as fin: weight = fin["CNN_proj"]["W_proj"][...] bias = fin["CNN_proj"]["b_proj"][...] self._projection.weight.data.copy_(torch.FloatTensor(numpy.transpose(weight))) self._projection.bias.data.copy_(torch.FloatTensor(bias)) self._projection.weight.requires_grad = self.requires_grad self._projection.bias.requires_grad = self.requires_grad
[docs]class ElmoLstm(_EncoderBase): # pragma: no cover """ A stacked, bidirectional LSTM which uses :class:`~allennlp.modules.lstm_cell_with_projection.LstmCellWithProjection`'s with highway layers between the inputs to layers. The inputs to the forward and backward directions are independent - forward and backward states are not concatenated between layers. Additionally, this LSTM maintains its `own` state, which is updated every time ``forward`` is called. It is dynamically resized for different batch sizes and is designed for use with non-continuous inputs (i.e inputs which aren't formatted as a stream, such as text used for a language modelling task, which is how stateful RNNs are typically used). This is non-standard, but can be thought of as having an "end of sentence" state, which is carried across different sentences. Parameters ---------- input_size : ``int``, required The dimension of the inputs to the LSTM. hidden_size : ``int``, required The dimension of the outputs of the LSTM. cell_size : ``int``, required. The dimension of the memory cell of the :class:`~allennlp.modules.lstm_cell_with_projection.LstmCellWithProjection`. num_layers : ``int``, required The number of bidirectional LSTMs to use. requires_grad: ``bool``, optional If True, compute gradient of ELMo parameters for fine tuning. recurrent_dropout_probability: ``float``, optional (default = 0.0) The dropout probability to be used in a dropout scheme as stated in `A Theoretically Grounded Application of Dropout in Recurrent Neural Networks <https://arxiv.org/abs/1512.05287>`_ . state_projection_clip_value: ``float``, optional, (default = None) The magnitude with which to clip the hidden_state after projecting it. memory_cell_clip_value: ``float``, optional, (default = None) The magnitude with which to clip the memory cell. """ def __init__( self, input_size: int, hidden_size: int, cell_size: int, num_layers: int, requires_grad: bool = False, recurrent_dropout_probability: float = 0.0, memory_cell_clip_value: Optional[float] = None, state_projection_clip_value: Optional[float] = None, ) -> None: super(ElmoLstm, self).__init__(stateful=True) # Required to be wrapped with a :class:`PytorchSeq2SeqWrapper`. self.input_size = input_size self.hidden_size = hidden_size self.num_layers = num_layers self.cell_size = cell_size self.requires_grad = requires_grad forward_layers = [] backward_layers = [] lstm_input_size = input_size go_forward = True for layer_index in range(num_layers): forward_layer = LstmCellWithProjection( lstm_input_size, hidden_size, cell_size, go_forward, recurrent_dropout_probability, memory_cell_clip_value, state_projection_clip_value, ) backward_layer = LstmCellWithProjection( lstm_input_size, hidden_size, cell_size, not go_forward, recurrent_dropout_probability, memory_cell_clip_value, state_projection_clip_value, ) lstm_input_size = hidden_size self.add_module("forward_layer_{}".format(layer_index), forward_layer) self.add_module("backward_layer_{}".format(layer_index), backward_layer) forward_layers.append(forward_layer) backward_layers.append(backward_layer) self.forward_layers = forward_layers self.backward_layers = backward_layers
[docs] def forward( self, inputs: torch.Tensor, mask: torch.LongTensor # pylint: disable=arguments-differ ) -> torch.Tensor: """ Parameters ---------- inputs : ``torch.Tensor``, required. A Tensor of shape ``(batch_size, sequence_length, hidden_size)``. mask : ``torch.LongTensor``, required. A binary mask of shape ``(batch_size, sequence_length)`` representing the non-padded elements in each sequence in the batch. Returns ------- A ``torch.Tensor`` of shape (num_layers, batch_size, sequence_length, hidden_size), where the num_layers dimension represents the LSTM output from that layer. """ batch_size, total_sequence_length = mask.size() stacked_sequence_output, final_states, restoration_indices = self.sort_and_run_forward( self._lstm_forward, inputs, mask ) num_layers, num_valid, returned_timesteps, encoder_dim = stacked_sequence_output.size() # Add back invalid rows which were removed in the call to sort_and_run_forward. if num_valid < batch_size: zeros = stacked_sequence_output.new_zeros( num_layers, batch_size - num_valid, returned_timesteps, encoder_dim ) stacked_sequence_output = torch.cat([stacked_sequence_output, zeros], 1) # The states also need to have invalid rows added back. new_states = [] for state in final_states: state_dim = state.size(-1) zeros = state.new_zeros(num_layers, batch_size - num_valid, state_dim) new_states.append(torch.cat([state, zeros], 1)) final_states = new_states # It's possible to need to pass sequences which are padded to longer than the # max length of the sequence to a Seq2StackEncoder. However, packing and unpacking # the sequences mean that the returned tensor won't include these dimensions, because # the RNN did not need to process them. We add them back on in the form of zeros here. sequence_length_difference = total_sequence_length - returned_timesteps if sequence_length_difference > 0: zeros = stacked_sequence_output.new_zeros( num_layers, batch_size, sequence_length_difference, stacked_sequence_output[0].size(-1), ) stacked_sequence_output = torch.cat([stacked_sequence_output, zeros], 2) self._update_states(final_states, restoration_indices) # Restore the original indices and return the sequence. # Has shape (num_layers, batch_size, sequence_length, hidden_size) return stacked_sequence_output.index_select(1, restoration_indices)
def _lstm_forward( self, inputs: PackedSequence, initial_state: Optional[Tuple[torch.Tensor, torch.Tensor]] = None, ) -> Tuple[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: """ Parameters ---------- inputs : ``PackedSequence``, required. A batch first ``PackedSequence`` to run the stacked LSTM over. initial_state : ``Tuple[torch.Tensor, torch.Tensor]``, optional, (default = None) A tuple (state, memory) representing the initial hidden state and memory of the LSTM, with shape (num_layers, batch_size, 2 * hidden_size) and (num_layers, batch_size, 2 * cell_size) respectively. Returns ------- output_sequence : ``torch.FloatTensor`` The encoded sequence of shape (num_layers, batch_size, sequence_length, hidden_size) final_states: ``Tuple[torch.FloatTensor, torch.FloatTensor]`` The per-layer final (state, memory) states of the LSTM, with shape (num_layers, batch_size, 2 * hidden_size) and (num_layers, batch_size, 2 * cell_size) respectively. The last dimension is duplicated because it contains the state/memory for both the forward and backward layers. """ if initial_state is None: hidden_states: List[Optional[Tuple[torch.Tensor, torch.Tensor]]] = [None] * len( self.forward_layers ) elif initial_state[0].size()[0] != len(self.forward_layers): raise ValueError( "Initial states were passed to forward() but the number of " "initial states does not match the number of layers." ) else: hidden_states = list(zip(initial_state[0].split(1, 0), initial_state[1].split(1, 0))) inputs, batch_lengths = pad_packed_sequence(inputs, batch_first=True) forward_output_sequence = inputs backward_output_sequence = inputs final_states = [] sequence_outputs = [] for layer_index, state in enumerate(hidden_states): forward_layer = getattr(self, "forward_layer_{}".format(layer_index)) backward_layer = getattr(self, "backward_layer_{}".format(layer_index)) forward_cache = forward_output_sequence backward_cache = backward_output_sequence if state is not None: forward_hidden_state, backward_hidden_state = state[0].split(self.hidden_size, 2) forward_memory_state, backward_memory_state = state[1].split(self.cell_size, 2) forward_state = (forward_hidden_state, forward_memory_state) backward_state = (backward_hidden_state, backward_memory_state) else: forward_state = None backward_state = None forward_output_sequence, forward_state = forward_layer( forward_output_sequence, batch_lengths, forward_state ) backward_output_sequence, backward_state = backward_layer( backward_output_sequence, batch_lengths, backward_state ) # Skip connections, just adding the input to the output. if layer_index != 0: forward_output_sequence += forward_cache backward_output_sequence += backward_cache sequence_outputs.append( torch.cat([forward_output_sequence, backward_output_sequence], -1) ) # Append the state tuples in a list, so that we can return # the final states for all the layers. final_states.append( ( torch.cat([forward_state[0], backward_state[0]], -1), torch.cat([forward_state[1], backward_state[1]], -1), ) ) stacked_sequence_outputs: torch.FloatTensor = torch.stack(sequence_outputs) # Stack the hidden state and memory for each layer into 2 tensors of shape # (num_layers, batch_size, hidden_size) and (num_layers, batch_size, cell_size) # respectively. final_hidden_states, final_memory_states = zip(*final_states) final_state_tuple: Tuple[torch.FloatTensor, torch.FloatTensor] = ( torch.cat(final_hidden_states, 0), torch.cat(final_memory_states, 0), ) return stacked_sequence_outputs, final_state_tuple
[docs] def load_weights(self, weight_file: str) -> None: """ Load the pre-trained weights from the file. """ requires_grad = self.requires_grad with h5py.File(weight_file, "r") as fin: for i_layer, lstms in enumerate(zip(self.forward_layers, self.backward_layers)): for j_direction, lstm in enumerate(lstms): # lstm is an instance of LSTMCellWithProjection cell_size = lstm.cell_size dataset = fin["RNN_%s" % j_direction]["RNN"]["MultiRNNCell"][ "Cell%s" % i_layer ]["LSTMCell"] # tensorflow packs together both W and U matrices into one matrix, # but pytorch maintains individual matrices. In addition, tensorflow # packs the gates as input, memory, forget, output but pytorch # uses input, forget, memory, output. So we need to modify the weights. tf_weights = numpy.transpose(dataset["W_0"][...]) torch_weights = tf_weights.copy() # split the W from U matrices input_size = lstm.input_size input_weights = torch_weights[:, :input_size] recurrent_weights = torch_weights[:, input_size:] tf_input_weights = tf_weights[:, :input_size] tf_recurrent_weights = tf_weights[:, input_size:] # handle the different gate order convention for torch_w, tf_w in [ [input_weights, tf_input_weights], [recurrent_weights, tf_recurrent_weights], ]: torch_w[(1 * cell_size) : (2 * cell_size), :] = tf_w[ (2 * cell_size) : (3 * cell_size), : ] torch_w[(2 * cell_size) : (3 * cell_size), :] = tf_w[ (1 * cell_size) : (2 * cell_size), : ] lstm.input_linearity.weight.data.copy_(torch.FloatTensor(input_weights)) lstm.state_linearity.weight.data.copy_(torch.FloatTensor(recurrent_weights)) lstm.input_linearity.weight.requires_grad = requires_grad lstm.state_linearity.weight.requires_grad = requires_grad # the bias weights tf_bias = dataset["B"][...] # tensorflow adds 1.0 to forget gate bias instead of modifying the # parameters... tf_bias[(2 * cell_size) : (3 * cell_size)] += 1 torch_bias = tf_bias.copy() torch_bias[(1 * cell_size) : (2 * cell_size)] = tf_bias[ (2 * cell_size) : (3 * cell_size) ] torch_bias[(2 * cell_size) : (3 * cell_size)] = tf_bias[ (1 * cell_size) : (2 * cell_size) ] lstm.state_linearity.bias.data.copy_(torch.FloatTensor(torch_bias)) lstm.state_linearity.bias.requires_grad = requires_grad # the projection weights proj_weights = numpy.transpose(dataset["W_P_0"][...]) lstm.state_projection.weight.data.copy_(torch.FloatTensor(proj_weights)) lstm.state_projection.weight.requires_grad = requires_grad
================================================ FILE: docs/_build/html/_modules/claf/tokens/embedding/base.html ================================================ claf.tokens.embedding.base — CLaF 0.2.0 documentation

Source code for claf.tokens.embedding.base


import torch


[docs]class TokenEmbedding(torch.nn.Module): """ Token Embedding It can be embedding matrix, language model (ELMo), neural machine translation model (CoVe) and features. * Args: vocab: Vocab (rqa.tokens.vocab) """ def __init__(self, vocab): super(TokenEmbedding, self).__init__() self.vocab = vocab
[docs] def forward(self, tokens): """ embedding look-up """ raise NotImplementedError
[docs] def get_output_dim(self): """ get embedding dimension """ raise NotImplementedError
[docs] def get_vocab_size(self): return len(self.vocab)
================================================ FILE: docs/_build/html/_modules/claf/tokens/embedding/bert_embedding.html ================================================ claf.tokens.embedding.bert_embedding — CLaF 0.2.0 documentation

Source code for claf.tokens.embedding.bert_embedding


from overrides import overrides

from pytorch_transformers import BertModel

import claf.modules.functional as f

from .base import TokenEmbedding


[docs]class BertEmbedding(TokenEmbedding): """ BERT Embedding(Encoder) BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805) * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: pretrained_model_name: ... use_as_embedding: ... trainable: Finetune or fixed """ def __init__(self, vocab, pretrained_model_name=None, trainable=False, unit="subword"): super(BertEmbedding, self).__init__(vocab) self.trainable = trainable self.pad_index = vocab.get_index(vocab.pad_token) self.sep_index = vocab.get_index(vocab.sep_token) if unit != "subword": raise NotImplementedError("BertEmbedding is only available 'subword' unit, right now.") self.bert_model = BertModel.from_pretrained(pretrained_model_name) # BertModel with config
[docs] @overrides def forward(self, inputs): if inputs.size(1) > self.bert_model.config.max_position_embeddings: raise ValueError( f"max_seq_length in this bert_model is '{self.bert_model.config.max_position_embeddings}'. (input seq_length: {inputs.size(1)})" ) # TODO: add text_unit option # current: sub_word (default) / later: sub_words --(average)--> word attention_mask = (inputs != self.pad_index).long() sequence_output, pooled_output = self.bert_model( inputs, attention_mask=attention_mask, output_all_encoded_layers=False ) sequence_output = f.masked_zero(sequence_output, attention_mask) if not self.trainable: sequence_output = sequence_output.detach() pooled_output = pooled_output.detach() sequence_output = self.remove_cls_sep_token(inputs, sequence_output) return sequence_output
[docs] @overrides def get_output_dim(self): return self.bert_model.config.hidden_size
[docs] def remove_cls_sep_token(self, inputs, outputs): seq_mask = inputs.eq(self.sep_index).eq(0) outputs = f.masked_zero(outputs, seq_mask) return outputs[:, 1:-1, :] # B, S_L, D
================================================ FILE: docs/_build/html/_modules/claf/tokens/embedding/char_embedding.html ================================================ claf.tokens.embedding.char_embedding — CLaF 0.2.0 documentation

Source code for claf.tokens.embedding.char_embedding


from overrides import overrides
import torch
import torch.nn as nn
import torch.nn.functional as F

from claf.modules.activation import get_activation_fn

from .base import TokenEmbedding


[docs]class CharEmbedding(TokenEmbedding): """ Character Embedding (CharCNN) (https://arxiv.org/abs/1509.01626) * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: dropout: The number of dropout probability embed_dim: The number of embedding dimension kernel_sizes: The list of kernel size (n-gram) num_filter: The number of cnn filter activation: Activation Function (eg. ReLU) """ def __init__( self, vocab, dropout=0.2, embed_dim=16, kernel_sizes=[5], num_filter=100, activation="relu" ): super(CharEmbedding, self).__init__(vocab) self.embed_dim = embed_dim self.num_filter = num_filter self.weight = self._init_weight(trainable=True) self.convs = [ nn.Conv1d( in_channels=1, out_channels=num_filter, kernel_size=embed_dim * kernel_size, stride=embed_dim, ) for kernel_size in kernel_sizes ] # kernel_size = n-gram for i, conv in enumerate(self.convs): self.add_module(f"conv_{i}", conv) self.activation_fn = get_activation_fn(activation)() self.dropout = nn.Dropout(p=dropout) self.projection = None if len(kernel_sizes) > 1: maxpool_output_dim = len(kernel_sizes) * num_filter self.projection = nn.Linear(maxpool_output_dim, num_filter) def _init_weight(self, trainable=False): weight = torch.FloatTensor(self.get_vocab_size(), self.embed_dim) weight = torch.nn.Parameter(weight, requires_grad=trainable) torch.nn.init.xavier_uniform_(weight) return weight
[docs] @overrides def forward(self, chars): mask_chars = (chars != 0).long() B, W_L, C_L = chars.size() # (batch_size, word_maxlen, char_maxlen) chars = chars.view(B, W_L * C_L) char_embedds = F.embedding(chars, self.weight) char_embedds = char_embedds.view(B, W_L, C_L, -1) # Masking char_embedds = char_embedds * mask_chars.unsqueeze(-1).float() char_embedds = char_embedds.view(B * W_L, 1, -1) conv_outputs = [] for i in range(len(self.convs)): conv = getattr(self, f"conv_{i}") output = self.activation_fn(conv(char_embedds)) pooled = F.max_pool1d(output, output.size(2)).squeeze(2) conv_outputs.append(pooled) encoded = conv_outputs[0] if len(conv_outputs) > 1: encoded = torch.cat(conv_outputs, dim=1) encoded = encoded.view(B, W_L, -1) if self.projection: encoded = self.projection(encoded) return self.dropout(encoded)
[docs] @overrides def get_output_dim(self): return self.num_filter
================================================ FILE: docs/_build/html/_modules/claf/tokens/embedding/cove_embedding.html ================================================ claf.tokens.embedding.cove_embedding — CLaF 0.2.0 documentation

Source code for claf.tokens.embedding.cove_embedding



from overrides import overrides

import torch.nn as nn

from claf.tokens.cove import MTLSTM

from .base import TokenEmbedding
from .word_embedding import WordEmbedding


[docs]class CoveEmbedding(TokenEmbedding): """ Cove Embedding Learned in Translation: Contextualized Word Vectors (http://papers.nips.cc/paper/7209-learned-in-translation-contextualized-word-vectors.pdf) * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: dropout: The number of dropout probability pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed project_dim: The number of project (linear) dimension """ def __init__( self, vocab, glove_pretrained_path=None, model_pretrained_path=None, dropout=0.2, trainable=False, project_dim=None, ): super(CoveEmbedding, self).__init__(vocab) self.embed_dim = 600 # MTLSTM (hidden_size=300 + bidirectional => 600) word_embedding = WordEmbedding( vocab, dropout=0, embed_dim=300, pretrained_path=glove_pretrained_path ) self.cove = MTLSTM( word_embedding, pretrained_path=model_pretrained_path, requires_grad=trainable ) if dropout and dropout > 0: self.dropout = nn.Dropout(p=dropout) else: self.dropout = lambda x: x self.project_dim = project_dim self.project_linear = None if project_dim: self.project_linear = nn.Linear(self.elmo.get_output_dim(), project_dim)
[docs] @overrides def forward(self, words): embedded_words = self.cove(words) return self.dropout(embedded_words)
[docs] @overrides def get_output_dim(self): if self.project_linear: return self.project_dim return self.embed_dim
================================================ FILE: docs/_build/html/_modules/claf/tokens/embedding/elmo_embedding.html ================================================ claf.tokens.embedding.elmo_embedding — CLaF 0.2.0 documentation

Source code for claf.tokens.embedding.elmo_embedding


from overrides import overrides

import torch.nn as nn

from claf.data.data_handler import CachePath, DataHandler
from claf.tokens.elmo import Elmo

from .base import TokenEmbedding


DEFAULT_OPTIONS_FILE = "elmo_2x4096_512_2048cnn_2xhighway_options.json"
DEFAULT_WEIGHT_FILE = "elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5"
HIDDEN_SIZE = 1024


[docs]class ELMoEmbedding(TokenEmbedding): """ ELMo Embedding Embedding From Language Model Deep contextualized word representations (https://arxiv.org/abs/1802.0536) * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: options_file: ELMo model config file path weight_file: ELMo model weight file path do_layer_norm: Should we apply layer normalization (passed to ``ScalarMix``)? default is False dropout: The number of dropout probability trainable: Finetune or fixed project_dim: The number of project (linear) dimension """ def __init__( self, vocab, options_file=DEFAULT_OPTIONS_FILE, weight_file=DEFAULT_WEIGHT_FILE, do_layer_norm=False, dropout=0.5, trainable=False, project_dim=None, ): super(ELMoEmbedding, self).__init__(vocab) data_handler = DataHandler(cache_path=CachePath.PRETRAINED_VECTOR) option_path = data_handler.read(options_file, return_path=True) weight_path = data_handler.read(weight_file, return_path=True) self.elmo = Elmo(option_path, weight_path, 1, requires_grad=trainable, dropout=dropout) self.project_dim = project_dim self.project_linear = None if project_dim: self.project_linear = nn.Linear(self.elmo.get_output_dim(), project_dim)
[docs] @overrides def forward(self, chars): elmo_output = self.elmo(chars) elmo_representations = elmo_output["elmo_representations"][0] if self.project_linear: elmo_representations = self.project_linear(elmo_representations) return elmo_representations
[docs] @overrides def get_output_dim(self): if self.project_linear: return self.project_dim return self.elmo.get_output_dim()
================================================ FILE: docs/_build/html/_modules/claf/tokens/embedding/frequent_word_embedding.html ================================================ claf.tokens.embedding.frequent_word_embedding — CLaF 0.2.0 documentation

Source code for claf.tokens.embedding.frequent_word_embedding


from overrides import overrides
import torch
import torch.nn as nn

import claf.modules.functional as f

from .base import TokenEmbedding
from .word_embedding import WordEmbedding


[docs]class FrequentTuningWordEmbedding(TokenEmbedding): """ Frequent Word Finetuning Embedding Finetuning embedding matrix, according to 'threshold_index' * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx (initialized to zeros) whenever it encounters the index. max_norm: If given, will renormalize the embedding vectors to have a norm lesser than this before extracting. Note: this will modify weight in-place. norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of frequency of the words in the mini-batch. Default False. sparse: if True, gradient w.r.t. weight will be a sparse tensor. See Notes under torch.nn.Embedding for more details regarding sparse gradients. pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed """ def __init__( self, vocab, dropout=0.2, embed_dim=100, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, pretrained_path=None, ): super(FrequentTuningWordEmbedding, self).__init__(vocab) self.threshold_index = vocab.threshold_index self.embed_dim = embed_dim self.fine_tune_word_embedding = WordEmbedding( vocab, dropout=0, embed_dim=embed_dim, padding_idx=padding_idx, max_norm=max_norm, norm_type=norm_type, scale_grad_by_freq=scale_grad_by_freq, sparse=sparse, pretrained_path=pretrained_path, ) self.fixed_word_embedding = WordEmbedding( vocab, dropout=0, embed_dim=embed_dim, padding_idx=padding_idx, max_norm=max_norm, norm_type=norm_type, scale_grad_by_freq=scale_grad_by_freq, sparse=sparse, pretrained_path=pretrained_path, ) if dropout > 0: self.dropout = nn.Dropout(p=dropout) else: self.dropout = lambda x: x
[docs] @overrides def forward(self, words, frequent_tuning=False): if frequent_tuning and self.training: padding_mask = words.eq(0).long() # Fine-tuning - N the most frequent fine_tune_mask = torch.lt(words, self.threshold_index) * padding_mask.eq( 0 ) # < threshold_index fine_tune_words = words * fine_tune_mask.long() fine_tune_embedded = self.fine_tune_word_embedding(fine_tune_words) fine_tune_embedded = f.masked_zero(fine_tune_embedded, fine_tune_mask) # Fixed - under N frequent fixed_mask = torch.ge(words, self.threshold_index) # >= threshold_index fixed_embedeed = self.fixed_word_embedding(words).detach() # Fixed fixed_embedeed = f.masked_zero(fixed_embedeed, fixed_mask) embedded_words = fine_tune_embedded + fixed_embedeed else: embedded_words = self.fixed_word_embedding(words) return self.dropout(embedded_words)
[docs] @overrides def get_output_dim(self): return self.embed_dim
================================================ FILE: docs/_build/html/_modules/claf/tokens/embedding/sparse_feature.html ================================================ claf.tokens.embedding.sparse_feature — CLaF 0.2.0 documentation

Source code for claf.tokens.embedding.sparse_feature


from overrides import overrides
import torch
import torch.nn as nn
import torch.nn.functional as F

from claf.tokens.vocabulary import Vocab

from .base import TokenEmbedding
from .word_embedding import WordEmbedding


[docs]class SparseFeature(TokenEmbedding): """ Sparse Feature 1. Sparse to Embedding 2. One Hot Encoding * Args: vocab: Vocab (claf.tokens.vocab) embed_type: The type of embedding [one_hot|embedding] feature_count: The number of feature count * Kwargs: params: additional parameters for embedding module """ def __init__(self, vocab, embed_type, feature_count, params={}): super(SparseFeature, self).__init__(vocab) self.feature_count = feature_count if embed_type == "embedding": embed_module = SparseToEmbedding else: embed_module = OneHotEncoding self.embed_modules = nn.ModuleList( [embed_module(i, vocab.token_name, **params) for i in range(feature_count)] ) indexs = torch.arange(feature_count).long() indexs = indexs.view(feature_count, 1) self.indexs = nn.Parameter(indexs, requires_grad=False)
[docs] @overrides def forward(self, inputs): embedded_inputs = [] for i in range(len(self.embed_modules)): tensors = torch.index_select(inputs, -1, self.indexs[i]).squeeze(-1) embedded = self.embed_modules[i](tensors) embedded_inputs.append(embedded) return torch.cat(embedded_inputs, dim=-1)
[docs] @overrides def get_output_dim(self): return sum(e.get_output_dim() for e in self.embed_modules)
[docs]class SparseToEmbedding(nn.Module): """ Sparse to Embedding * Args: token_name: token_name * Kwargs: dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx (initialized to zeros) whenever it encounters the index. max_norm: If given, will renormalize the embedding vectors to have a norm lesser than this before extracting. Note: this will modify weight in-place. norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of frequency of the words in the mini-batch. Default False. sparse: if True, gradient w.r.t. weight will be a sparse tensor. See Notes under torch.nn.Embedding for more details regarding sparse gradients. pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed """ def __init__( self, index, token_name, classes, dropout=0, embed_dim=15, trainable=True, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, ): super(SparseToEmbedding, self).__init__() self.embed_dim = embed_dim vocab = Vocab(token_name) vocab.init() for c in classes[index]: vocab.add(c) embedding_params = { "vocab": vocab, "dropout": dropout, "embed_dim": embed_dim, "trainable": trainable, "padding_idx": padding_idx, "max_norm": max_norm, "norm_type": norm_type, "scale_grad_by_freq": scale_grad_by_freq, "sparse": sparse, } self.embedding = WordEmbedding(**embedding_params)
[docs] @overrides def forward(self, inputs): return self.embedding(inputs)
[docs] def get_output_dim(self): return self.embed_dim
[docs]class OneHotEncoding(nn.Module): """ Sparse to one-hot encoding * Args: vocab: Vocab (claf.tokens.vocab) """ def __init__(self, index, token_name, classes): super(OneHotEncoding, self).__init__() vocab = Vocab(token_name) vocab.init() for c in classes[index]: vocab.add(c) num_class = len(vocab) self.num_class = num_class one_hot_encoding = torch.eye(num_class) self.one_hots = nn.Parameter(one_hot_encoding, requires_grad=False)
[docs] @overrides def forward(self, inputs): if self.num_class == 4: inputs = inputs - 2 # make 0, 1 binary_feature return inputs.float().unsqueeze(-1) return F.embedding(inputs, self.one_hots)
[docs] def get_output_dim(self): if self.num_class == 4: # binary_feature return 1 # 0 or 1 return self.num_class
================================================ FILE: docs/_build/html/_modules/claf/tokens/embedding/word_embedding.html ================================================ claf.tokens.embedding.word_embedding — CLaF 0.2.0 documentation

Source code for claf.tokens.embedding.word_embedding


import logging
from overrides import overrides
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F

from claf.data.data_handler import CachePath, DataHandler

from .base import TokenEmbedding

logger = logging.getLogger(__name__)


[docs]class WordEmbedding(TokenEmbedding): """ Word Embedding Default Token Embedding * Args: vocab: Vocab (claf.tokens.vocab) * Kwargs: dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx (initialized to zeros) whenever it encounters the index. max_norm: If given, will renormalize the embedding vectors to have a norm lesser than this before extracting. Note: this will modify weight in-place. norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of frequency of the words in the mini-batch. Default False. sparse: if True, gradient w.r.t. weight will be a sparse tensor. See Notes under torch.nn.Embedding for more details regarding sparse gradients. pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed """ def __init__( self, vocab, dropout=0.2, embed_dim=100, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, pretrained_path=None, trainable=True, ): super(WordEmbedding, self).__init__(vocab) self.data_handler = DataHandler(cache_path=CachePath.PRETRAINED_VECTOR) self.embed_dim = embed_dim if dropout and dropout > 0: self.dropout = nn.Dropout(p=dropout) else: self.dropout = lambda x: x if pretrained_path: weight = self._read_pretrained_file(pretrained_path) self.weight = torch.nn.Parameter(weight, requires_grad=trainable) else: self.weight = self._init_weight(trainable=trainable) # nn.functional.embedding = optional paramters # (padding_idx, max_norm, norm_type, scale_grad_by_freq, sparse) # check - https://pytorch.org/docs/master/nn.html#torch.nn.functional.embeddin\ # ://pytorch.org/docs/master/nn.html#torch.nn.functional.embedding self.padding_idx = padding_idx self.max_norm = max_norm self.norm_type = norm_type self.scale_grad_by_freq = scale_grad_by_freq self.sparse = sparse def _init_weight(self, trainable=True): weight = torch.FloatTensor(self.get_vocab_size(), self.embed_dim) weight = torch.nn.Parameter(weight, requires_grad=trainable) torch.nn.init.xavier_uniform_(weight) return weight
[docs] @overrides def forward(self, words): input_size = words.size() if len(input_size) > 2: words = words.view(-1, input_size[-1]) embedded_words = F.embedding( words, self.weight, padding_idx=self.padding_idx, max_norm=self.max_norm, norm_type=self.norm_type, scale_grad_by_freq=self.scale_grad_by_freq, sparse=self.sparse, ) if len(input_size) > 2: embedded_size = list(input_size) + [embedded_words.size(-1)] embedded_words = embedded_words.view(*embedded_size) return self.dropout(embedded_words)
def _read_pretrained_file(self, file_path): words_to_keep = set(self.vocab.get_all_tokens()) vocab_size = self.get_vocab_size() embeddings = {} # First we read the embeddings from the file, only keeping vectors for the words we need. logger.info("Reading embeddings from file") file_path = self.data_handler.read(file_path, return_path=True) with open(file_path, "rb") as embeddings_file: for line in embeddings_file: fields = line.decode("utf-8").rstrip().split(" ") if len(fields) - 1 != self.embed_dim: logger.info( f"Found line with wrong number of dimensions (expected {self.embed_dim}, was {len(fields)}): {line}" ) continue word = fields[0] if word in words_to_keep: vector = np.asarray(fields[1:], dtype="float32") embeddings[word] = vector if not embeddings: raise ValueError( "No embeddings of correct dimension found. check input dimension value" ) all_embeddings = np.asarray(list(embeddings.values())) embeddings_mean = float(np.mean(all_embeddings)) embeddings_std = float(np.std(all_embeddings)) # Now we initialize the weight matrix for an embedding layer, starting with random vectors, # then filling in the word vectors we just read. logger.info("Initializing pre-trained embedding layer") embedding_matrix = torch.FloatTensor(vocab_size, self.embed_dim).normal_( embeddings_mean, embeddings_std ) match_count = 0 for i in range(0, vocab_size): word = self.vocab.get_token(i) if word in embeddings: embedding_matrix[i] = torch.FloatTensor(embeddings[word]) match_count += 1 else: # f"Word {word} was not found in the embedding file. Initialising randomly." pass logger.info(f"Match embedding vocab size: {match_count}. [{match_count}/{vocab_size}]") return embedding_matrix
[docs] @overrides def get_output_dim(self): return self.embed_dim
================================================ FILE: docs/_build/html/_modules/claf/tokens/hangul.html ================================================ claf.tokens.hangul — CLaF 0.2.0 documentation

Source code for claf.tokens.hangul

#!/usr/bin/env python
# encoding: utf-8

"""
Hangulpy.py
Copyright (C) 2012 Ryan Rho, Hyunwoo Cho
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

import string
import re

################################################################################
# Hangul Unicode Variables
################################################################################

# Code = 0xAC00 + (Chosung_index * NUM_JOONGSUNGS * NUM_JONGSUNGS) + (Joongsung_index * NUM_JONGSUNGS) + (Jongsung_index)
CHOSUNGS = [
    "ㄱ",
    "ㄲ",
    "ㄴ",
    "ㄷ",
    "ㄸ",
    "ㄹ",
    "ㅁ",
    "ㅂ",
    "ㅃ",
    "ㅅ",
    "ㅆ",
    "ㅇ",
    "ㅈ",
    "ㅉ",
    "ㅊ",
    "ㅋ",
    "ㅌ",
    "ㅍ",
    "ㅎ",
]
JOONGSUNGS = [
    "ㅏ",
    "ㅐ",
    "ㅑ",
    "ㅒ",
    "ㅓ",
    "ㅔ",
    "ㅕ",
    "ㅖ",
    "ㅗ",
    "ㅘ",
    "ㅙ",
    "ㅚ",
    "ㅛ",
    "ㅜ",
    "ㅝ",
    "ㅞ",
    "ㅟ",
    "ㅠ",
    "ㅡ",
    "ㅢ",
    "ㅣ",
]
JONGSUNGS = [
    "",
    "ㄱ",
    "ㄲ",
    "ㄳ",
    "ㄴ",
    "ㄵ",
    "ㄶ",
    "ㄷ",
    "ㄹ",
    "ㄺ",
    "ㄻ",
    "ㄼ",
    "ㄽ",
    "ㄾ",
    "ㄿ",
    "ㅀ",
    "ㅁ",
    "ㅂ",
    "ㅄ",
    "ㅅ",
    "ㅆ",
    "ㅇ",
    "ㅈ",
    "ㅊ",
    "ㅋ",
    "ㅌ",
    "ㅍ",
    "ㅎ",
]

NUM_CHOSUNGS = 19
NUM_JOONGSUNGS = 21
NUM_JONGSUNGS = 28

FIRST_HANGUL_UNICODE = 0xAC00  # '가'
LAST_HANGUL_UNICODE = 0xD7A3  # '힣'

################################################################################
# Boolean Hangul functions
################################################################################


[docs]def is_hangul(phrase): # pragma: no cover """Check whether the phrase is Hangul. This method ignores white spaces, punctuations, and numbers. @param phrase a target string @return True if the phrase is Hangul. False otherwise.""" # If the input is only one character, test whether the character is Hangul. if len(phrase) == 1: return is_all_hangul(phrase) # Remove all white spaces, punctuations, numbers. exclude = set(string.whitespace + string.punctuation + "0123456789") phrase = "".join(ch for ch in phrase if ch not in exclude) return is_all_hangul(phrase)
[docs]def is_all_hangul(phrase): # pragma: no cover """Check whether the phrase contains all Hangul letters @param phrase a target string @return True if the phrase only consists of Hangul. False otherwise.""" for unicode_value in map(lambda letter: ord(letter), phrase): if unicode_value < FIRST_HANGUL_UNICODE or unicode_value > LAST_HANGUL_UNICODE: # Check whether the letter is chosungs, joongsungs, or jongsungs. if unicode_value not in map(lambda v: ord(v), CHOSUNGS + JOONGSUNGS + JONGSUNGS[1:]): return False return True
[docs]def has_jongsung(letter): # pragma: no cover """Check whether this letter contains Jongsung""" if len(letter) != 1: raise Exception("The target string must be one letter.") if not is_hangul(letter): raise NotHangulException("The target string must be Hangul") unicode_value = ord(letter) return (unicode_value - FIRST_HANGUL_UNICODE) % NUM_JONGSUNGS > 0
[docs]def has_batchim(letter): # pragma: no cover """This method is the same as has_jongsung()""" return has_jongsung(letter)
[docs]def has_approximant(letter): # pragma: no cover """Approximant makes complex vowels, such as ones starting with y or w. In Korean there is a unique approximant euㅡ making uiㅢ, but ㅢ does not make many irregularities.""" if len(letter) != 1: raise Exception("The target string must be one letter.") if not is_hangul(letter): raise NotHangulException("The target string must be Hangul") jaso = decompose(letter) diphthong = (2, 3, 6, 7, 9, 10, 12, 14, 15, 17) # [u'ㅑ',u'ㅒ',',u'ㅕ',u'ㅖ',u'ㅘ',u'ㅙ',u'ㅛ',u'ㅝ',u'ㅞ',u'ㅠ'] # excluded 'ㅢ' because y- and w-based complex vowels are irregular. # vowels with umlauts (ㅐ, ㅔ, ㅚ, ㅟ) are not considered complex vowels. return jaso[1] in diphthong
################################################################################ # Decomposition & Combination ################################################################################
[docs]def compose(chosung, joongsung, jongsung=""): # pragma: no cover """This function returns a Hangul letter by composing the specified chosung, joongsung, and jongsung. @param chosung @param joongsung @param jongsung the terminal Hangul letter. This is optional if you do not need a jongsung.""" if jongsung is None: jongsung = "" try: chosung_index = CHOSUNGS.index(chosung) joongsung_index = JOONGSUNGS.index(joongsung) jongsung_index = JONGSUNGS.index(jongsung) except Exception as e: raise NotHangulException( "No valid Hangul character can be generated using given combination of chosung, joongsung, and jongsung." ) return chr( 0xAC00 + chosung_index * NUM_JOONGSUNGS * NUM_JONGSUNGS + joongsung_index * NUM_JONGSUNGS + jongsung_index )
[docs]def decompose(hangul_letter): # pragma: no cover """This function returns letters by decomposing the specified Hangul letter.""" if len(hangul_letter) < 1: raise NotLetterException("") elif not is_hangul(hangul_letter): raise NotHangulException("") code = ord(hangul_letter) - FIRST_HANGUL_UNICODE jongsung_index = int(code % NUM_JONGSUNGS) code /= NUM_JONGSUNGS joongsung_index = int(code % NUM_JOONGSUNGS) code /= NUM_JOONGSUNGS chosung_index = int(code) return (CHOSUNGS[chosung_index], JOONGSUNGS[joongsung_index], JONGSUNGS[jongsung_index])
################################################################################ # Josa functions ################################################################################
[docs]def josa_en(word): # pragma: no cover """add josa either '은' or '는' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "은" if has_jongsung(last_letter) else "는" return word + josa
[docs]def josa_eg(word): # pragma: no cover """add josa either '이' or '가' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "이" if has_jongsung(last_letter) else "가" return word + josa
[docs]def josa_el(word): # pragma: no cover """add josa either '을' or '를' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "을" if has_jongsung(last_letter) else "를" return word + josa
[docs]def josa_ro(word): # pragma: no cover """add josa either '으로' or '로' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] if not has_jongsung(last_letter): josa = "로" elif (ord(last_letter) - FIRST_HANGUL_UNICODE) % NUM_JONGSUNGS == 9: # ㄹ josa = "로" else: josa = "으로" return word + josa
[docs]def josa_gwa(word): # pragma: no cover """add josa either '과' or '와' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "과" if has_jongsung(last_letter) else "와" return word + josa
[docs]def josa_ida(word): # pragma: no cover """add josa either '이다' or '다' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] josa = "이다" if has_jongsung(last_letter) else "다" return word + josa
################################################################################ # Prefixes and suffixes # Practice area; need more organization ################################################################################
[docs]def add_ryul(word): # pragma: no cover """add suffix either '률' or '율' at the end of this word""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[-1] if not has_jongsung(last_letter): ryul = "율" elif (ord(last_letter) - FIRST_HANGUL_UNICODE) % NUM_JONGSUNGS == 4: # ㄴ ryul = "율" else: ryul = "률" return word + ryul
################################################################################ # The formatter, or ultimately, a template system # Practice area; need more organization ################################################################################
[docs]def ili(word): # pragma: no cover """convert {가} or {이} to their correct respective particles automagically.""" word = word.strip() if not is_hangul(word): raise NotHangulException("") last_letter = word[word.find("{가}") - 1] word = word.replace("{가}", ("이" if has_jongsung(last_letter) else "가")) last_letter = word[word.find("{이}") - 1] word = word.replace("{이}", ("이" if has_jongsung(last_letter) else "가")) return word
################################################################################ # Exceptions ################################################################################
[docs]class NotHangulException(Exception): # pragma: no cover pass
[docs]class NotLetterException(Exception): # pragma: no cover pass
[docs]class NotWordException(Exception): # pragma: no cover pass
================================================ FILE: docs/_build/html/_modules/claf/tokens/indexer/base.html ================================================ claf.tokens.indexer.base — CLaF 0.2.0 documentation

Source code for claf.tokens.indexer.base

[docs]class TokenIndexer: """ Token Indexer indexing tokens (eg. 'hi' -> 4) """ def __init__(self, tokenizer): self.param_key = None self.tokenizer = tokenizer
[docs] def index(self, token): """ indexing function """ raise NotImplementedError
[docs] def set_vocab(self, vocab): self.vocab = vocab
================================================ FILE: docs/_build/html/_modules/claf/tokens/indexer/bert_indexer.html ================================================ claf.tokens.indexer.bert_indexer — CLaF 0.2.0 documentation

Source code for claf.tokens.indexer.bert_indexer


from overrides import overrides

from .base import TokenIndexer


[docs]class BertIndexer(TokenIndexer): """ Bert Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: SubwordTokenizer * Kwargs: lowercase: word token to lowercase insert_start: insert start_token to first insert_end: append end_token """ def __init__(self, tokenizer, do_tokenize=True): super(BertIndexer, self).__init__(tokenizer) self.do_tokenize = do_tokenize
[docs] @overrides def index(self, text): input_type = type(text) if input_type == str: return self._index_text(text) elif input_type == list: texts = text # List of text case return [self._index_text(text) for text in texts] else: raise ValueError(f"Not supported type: {type(text)}")
def _index_text(self, text): if self.do_tokenize: tokens = self.tokenizer.tokenize(text) else: tokens = [text] indexed_tokens = [self.vocab.get_index(token) for token in tokens] # Insert CLS_TOKEN ans SEP_TOKEN insert_start = self.vocab.get_index(self.vocab.cls_token) indexed_tokens.insert(0, insert_start) insert_end = self.vocab.get_index(self.vocab.sep_token) indexed_tokens.append(insert_end) return indexed_tokens
================================================ FILE: docs/_build/html/_modules/claf/tokens/indexer/char_indexer.html ================================================ claf.tokens.indexer.char_indexer — CLaF 0.2.0 documentation

Source code for claf.tokens.indexer.char_indexer


from overrides import overrides

from .base import TokenIndexer


[docs]class CharIndexer(TokenIndexer): """ Character Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: CharTokenizer * Kwargs: insert_char_start: insert start index (eg. ['h', 'i'] -> ['<s>', 'h', 'i'] ) default is None insert_char_end: insert end index (eg. ['h', 'i'] -> ['h', 'i', '</s>'] ) default is None """ def __init__(self, tokenizer, insert_char_start=None, insert_char_end=None): super(CharIndexer, self).__init__(tokenizer) self.insert_char_start = insert_char_start self.insert_char_end = insert_char_end
[docs] @overrides def index(self, text): indexed_tokens = [self.index_token(token) for token in self.tokenizer.tokenize(text)] return indexed_tokens
[docs] def index_token(self, chars): char_ids = [self.vocab.get_index(char) for char in chars] if self.insert_char_start is not None: char_ids.insert(0, self.vocab.get_index(self.vocab.start_token)) if self.insert_char_end is not None: char_ids.append(self.vocab.get_index(self.vocab.end_token)) return char_ids
================================================ FILE: docs/_build/html/_modules/claf/tokens/indexer/elmo_indexer.html ================================================ claf.tokens.indexer.elmo_indexer — CLaF 0.2.0 documentation

Source code for claf.tokens.indexer.elmo_indexer

"""
This code is from allenai/allennlp
(https://github.com/allenai/allennlp/blob/master/allennlp/data/token_indexers/elmo_indexer.py)
"""

from overrides import overrides

from .base import TokenIndexer


def _make_bos_eos(
    character: int,
    padding_character: int,
    beginning_of_word_character: int,
    end_of_word_character: int,
    max_word_length: int,
):
    char_ids = [padding_character] * max_word_length
    char_ids[0] = beginning_of_word_character
    char_ids[1] = character
    char_ids[2] = end_of_word_character
    return char_ids


[docs]class ELMoIndexer(TokenIndexer): """ Maps individual tokens to sequences of character ids, compatible with ELMo. To be consistent with previously trained models, we include it here as special of existing character indexers. """ max_word_length = 50 # char ids 0-255 come from utf-8 encoding bytes # assign 256-300 to special chars beginning_of_sentence_character = 256 # <begin sentence> end_of_sentence_character = 257 # <end sentence> beginning_of_word_character = 258 # <begin word> end_of_word_character = 259 # <end word> padding_character = 260 # <padding><Paste> beginning_of_sentence_characters = _make_bos_eos( beginning_of_sentence_character, padding_character, beginning_of_word_character, end_of_word_character, max_word_length, ) end_of_sentence_characters = _make_bos_eos( end_of_sentence_character, padding_character, beginning_of_word_character, end_of_word_character, max_word_length, ) BOS_TOKEN = "<S>" EOS_TOKEN = "</S>" def __init__(self, tokenizer): super(ELMoIndexer, self).__init__(tokenizer)
[docs] @overrides def index(self, text): indexed_tokens = [self.index_token(token) for token in self.tokenizer.tokenize(text)] return indexed_tokens
[docs] def index_token(self, word): if word == self.BOS_TOKEN: char_ids = self.beginning_of_sentence_characters elif word == self.EOS_TOKEN: char_ids = self.end_of_sentence_characters else: word_encodeds = word.encode("utf-8", "ignore")[: (self.max_word_length - 2)] char_ids = [char_id for char_id in word_encodeds] char_ids = [self.beginning_of_word_character] + char_ids + [self.end_of_word_character] return [c + 1 for c in char_ids]
================================================ FILE: docs/_build/html/_modules/claf/tokens/indexer/exact_match_indexer.html ================================================ claf.tokens.indexer.exact_match_indexer — CLaF 0.2.0 documentation

Source code for claf.tokens.indexer.exact_match_indexer



from overrides import overrides
from nltk.stem import WordNetLemmatizer

from .base import TokenIndexer


[docs]class ExactMatchIndexer(TokenIndexer): """ Exact Match Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: WordTokenizer * Kwargs: lower: add lower feature. default is True (0 or 1) lemma: add lemma case feature. feature is True (0 or 1) """ def __init__(self, tokenizer, lower=True, lemma=True): super(ExactMatchIndexer, self).__init__(tokenizer) self.param_key = "question" self.lemmatizer = WordNetLemmatizer() self.lower = lower self.lemma = lemma
[docs] @overrides def index(self, text, query_text): tokenized_query_text = self.tokenizer.tokenize(query_text) query_tokens = { "origin": set(tokenized_query_text), "lower": set([token.lower() for token in tokenized_query_text]), "lemma": set( [self.lemmatizer.lemmatize(token.lower()) for token in tokenized_query_text] ), } indexed_tokens = [ self.index_token(token, query_tokens) for token in self.tokenizer.tokenize(text) ] return indexed_tokens
[docs] def index_token(self, token, query_tokens): em_feature = [] # 1. origin origin_case = 1 if token in query_tokens["origin"] else 0 em_feature.append(origin_case + 2) # 2. lower if self.lower: lower_case = 1 if token.lower() in query_tokens["lower"] else 0 em_feature.append(lower_case + 2) # 3. lemma if self.lemma: lemma_case = ( 1 if self.lemmatizer.lemmatize(token.lower()) in query_tokens["lemma"] else 0 ) em_feature.append(lemma_case + 2) return em_feature
================================================ FILE: docs/_build/html/_modules/claf/tokens/indexer/linguistic_indexer.html ================================================ claf.tokens.indexer.linguistic_indexer — CLaF 0.2.0 documentation

Source code for claf.tokens.indexer.linguistic_indexer


from overrides import overrides
import spacy

from claf.tokens.linguistic import POSTag, NER

from .base import TokenIndexer


[docs]class LinguisticIndexer(TokenIndexer): """ Linguistic Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: WordTokenizer * Kwargs: pos_tag: POS Tagging ner: Named Entity Recognition dep: Dependency Parser """ def __init__(self, tokenizer, pos_tag=None, ner=None, dep=None): super(LinguisticIndexer, self).__init__(tokenizer) self.spacy_model = None # Features self.use_pos_tag = pos_tag self.pos_to_index = {t: i for i, t in enumerate(POSTag.classes)} self.use_ner = ner self.ner_to_index = {t: i for i, t in enumerate(NER.classes)} self.use_dep = dep if dep: raise NotImplementedError("Dependency Parser feature")
[docs] @overrides def index(self, text): package = self.tokenizer.name return getattr(self, f"_{package}")(text)
""" Need to match with Tokenizer's package """ def _mecab_ko(self, text): raise NotImplementedError("Linguistic Feature with mecab package") def _nltk_en(self, text): raise NotImplementedError("Linguistic Feature with nltk package") def _spacy_en(self, text): if self.spacy_model is None: from claf.tokens.tokenizer.utils import load_spacy_model_for_tokenizer disables = ["vectors", "textcat", "parser"] if not self.use_pos_tag: disables.apppend("tagger") if not self.use_ner: disables.apppend("ner") self.spacy_model = spacy.load("en_core_web_sm", disable=disables) self.spacy_model.tokenizer = load_spacy_model_for_tokenizer( self.tokenizer.extra_split_chars_re ) sent_tokenizer = self.tokenizer.sent_tokenizer sentences = sent_tokenizer.tokenize(text) ner_entities = {} docs = [] for sentence in sentences: doc = self.spacy_model(sentence) docs.append(doc) if self.use_ner: for e in doc.ents: ner_entities[e.text] = e.label_ linguistic_features = [] for doc in docs: for token in doc: if token.is_space: continue feature = [] if self.use_pos_tag: feature.append(self.pos_to_index[token.pos_]) if self.use_ner: feature.append(self.ner_to_index[ner_entities.get(token.text, "NONE")]) linguistic_features.append(feature) return linguistic_features
================================================ FILE: docs/_build/html/_modules/claf/tokens/indexer/word_indexer.html ================================================ claf.tokens.indexer.word_indexer — CLaF 0.2.0 documentation

Source code for claf.tokens.indexer.word_indexer


from overrides import overrides

from .base import TokenIndexer


[docs]class WordIndexer(TokenIndexer): """ Word Token Indexer * Property vocab: Vocab (claf.tokens.vocabulary) * Args: tokenizer: WordTokenizer * Kwargs: lowercase: word token to lowercase insert_start: insert start_token to first insert_end: append end_token """ def __init__( self, tokenizer, do_tokenize=True, lowercase=False, insert_start=None, insert_end=None ): super(WordIndexer, self).__init__(tokenizer) self.do_tokenize = do_tokenize self.lowercase = lowercase self.insert_start = insert_start self.insert_end = insert_end
[docs] @overrides def index(self, text): input_type = type(text) if input_type == str: indexed_tokens = self._index_text(text) elif input_type == list: indexed_tokens = self._index_list_of_text(text) else: raise ValueError(f"Not supported type: {type(text)}") if self.insert_start is not None: insert_start = self.vocab.get_index(self.vocab.start_token) indexed_tokens.insert(0, insert_start) if self.insert_end is not None: insert_end = self.vocab.get_index(self.vocab.end_token) indexed_tokens.append(insert_end) return indexed_tokens
def _index_text(self, text): if not self.do_tokenize: raise ValueError("input text type is 'str'. 'do_tokenize' is required.") return [self._index_token(token) for token in self.tokenizer.tokenize(text)] def _index_list_of_text(self, list_of_text): if self.do_tokenize: indexed_tokens = [ [self._index_token(token) for token in self.tokenizer.tokenize(text)] for text in list_of_text ] else: indexed_tokens = [self._index_token(text) for text in list_of_text] return indexed_tokens def _index_token(self, token): if self.lowercase: token = token.lower() return self.vocab.get_index(token)
================================================ FILE: docs/_build/html/_modules/claf/tokens/linguistic.html ================================================ claf.tokens.linguistic — CLaF 0.2.0 documentation

Source code for claf.tokens.linguistic

[docs]class POSTag: """ Universal POS tags expends by spacy (https://spacy.io/api/annotation#section-pos-tagging) """ classes = [ "ADJ", # adjectives "ADP", # adpositions (prepositions and postpositions) "ADV", # adverbs "AUX", # auxiliary (spacy) "CONJ", # conjunctions "CCONJ", # coordinating conjunction (spacy) "DET", # determiners "INTJ", # interjection (spacy) "NOUN", # nouns (common and proper) "NUM", # cardinal numbers "PART", # particles or other function words (spacy) "PRON", # pronouns "PROPN", # proper noun "PUNCT", # punctuation "SCONJ", # subordinating conjunction "SYM", # symbol "VERB", # verbs (all tenses and modes) "X", # other: foreign words, typos, abbreviations "SPACE", # space ]
[docs]class NER: """ Named Entity Recognition Models trained on the OntoNotes 5 corpus support the following entity types: (https://spacy.io/api/annotation#section-dependency-parsing) """ classes = [ "NONE", # None "PERSON", # People, including fictional. "NORP", # Nationalities or religious or political groups. "FAC", # Buildings, airports, highways, bridges, etc. "ORG", # Companies, agencies, institutions, etc. "GPE", # Countries, cities, states. "LOC", # Non-GPE locations, mountain ranges, bodies of water. "PRODUCT", # Objects, vehicles, foods, etc. (Not services.) "EVENT", # Named hurricanes, battles, wars, sports events, etc. "WORK_OF_ART", # Titles of books, songs, etc. "LAW", # Named documents made into laws. "LANGUAGE", # Any named language. "DATE", # Absolute or relative dates or periods. "TIME", # Times smaller than a day. "PERCENT", # Percentage, including "%". "MONEY", # Monetary values, including unit. "QUANTITY", # Measurements, as of weight or distance. "ORDINAL", # "first", "second", etc. "CARDINAL", # Numerals that do not fall under another type. ]
================================================ FILE: docs/_build/html/_modules/claf/tokens/text_handler.html ================================================ claf.tokens.text_handler — CLaF 0.2.0 documentation

Source code for claf.tokens.text_handler


from collections import Counter
import logging
import time

from tqdm import tqdm

from claf.data.data_handler import CachePath, DataHandler
from claf.data.utils import padding_tokens, transpose
from claf.tokens.token_maker import TokenMaker
from claf.tokens.vocabulary import Vocab
from claf import utils as common_utils

logger = logging.getLogger(__name__)


[docs]class TextHandler: """ Text Handler - voacb and token_counter - raw_features -> indexed_features - raw_features -> tensor * Args: token_makers: Dictionary consisting of - key: token_name - value: TokenMaker (claf.tokens.token_maker) * Kwargs: lazy_indexing: Apply `Lazy Evaluation` to text indexing """ def __init__(self, token_makers, lazy_indexing=True): self.token_makers = token_makers self.lazy_indexing = lazy_indexing self.data_handler = DataHandler(cache_path=CachePath.TOKEN_COUNTER)
[docs] def build_vocabs(self, token_counters): logger.info("Start build vocab") vocab_start_time = time.time() vocabs = {} for token_name, token_maker in self.token_makers.items(): is_defined_config = type(token_maker.vocab_config) == dict if is_defined_config: token_counter = token_counters[token_name] vocab = self._build_vocab_with_config(token_name, token_maker, token_counter) else: vocab = Vocab(token_name) vocab.init() vocabs[token_name] = vocab logger.info( f" => {token_name} vocab size: {len(vocab)} (use predefine vocab: {vocab.pretrained_path is not None})" ) vocab_elapased_time = time.time() - vocab_start_time logger.info(f"Complete build vocab... elapsed_time: {vocab_elapased_time}\n") # Setting Indexer (vocab) for token_name, token_maker in self.token_makers.items(): token_maker.set_vocab(vocabs[token_name]) return vocabs
def _build_vocab_with_config(self, token_name, token_maker, token_counter): token_maker.vocab_config["token_name"] = token_name vocab = Vocab(**token_maker.vocab_config) if vocab.pretrained_path is not None: vocab.build_with_pretrained_file(token_counter) else: vocab.build(token_counter) return vocab
[docs] def is_all_vocab_use_pretrained(self): for token_name, token_maker in self.token_makers.items(): if token_maker.vocab_config.get("pretrained_path", None) is None: return False if token_maker.vocab_config.get("pretrained_token", "") != Vocab.PRETRAINED_ALL: return False return True
[docs] def make_token_counters(self, texts, config=None): token_counters = {} for token_name, token_maker in self.token_makers.items(): token_vocab_config = token_maker.vocab_config if type(token_vocab_config) == dict: if token_vocab_config.get("pretrained_token", None) == Vocab.PRETRAINED_ALL: texts = [ "" ] # do not use token_counter from dataset -> make empty token_counter token_counter = self._make_token_counter( texts, token_maker.tokenizer, config=config, desc=f"{token_name}-vocab" ) logger.info(f" * {token_name} token_counter size: {len(token_counter)}") token_counters[token_name] = token_counter return token_counters
def _make_token_counter(self, texts, tokenizer, config=None, desc=None): tokenizer_name = tokenizer.name cache_token_counter = None if config is not None: data_reader_config = config.data_reader cache_token_counter = self.data_handler.cache_token_counter( data_reader_config, tokenizer_name ) if cache_token_counter: return cache_token_counter else: tokens = [ token for text in tqdm(texts, desc=desc) for token in tokenizer.tokenize(text) ] flatten_list = list(common_utils.flatten(tokens)) token_counter = Counter(flatten_list) if config is not None: # Cache TokenCounter self.data_handler.cache_token_counter( data_reader_config, tokenizer_name, obj=token_counter ) return token_counter
[docs] def index(self, datas, text_columns): logger.info(f"Start token indexing, Lazy: {self.lazy_indexing}") indexing_start_time = time.time() for data_type, data in datas.items(): if type(data) == list: # Multi-Data Indexing for d in data: self._index_features( d.features, text_columns, desc=f"indexing features ({data_type})" ) else: self._index_features( data.features, text_columns, desc=f"indexing features ({data_type})" ) indexing_elapased_time = time.time() - indexing_start_time logger.info(f"Complete token indexing... elapsed_time: {indexing_elapased_time} \n")
def _index_features(self, features, text_columns, desc=None, suppress_tqdm=False): for feature in tqdm(features, desc=desc, disable=suppress_tqdm): for key, text in feature.items(): if key not in text_columns: continue # Set data_type (text => {"text": ..., "token1": ..., ...}) if type(feature[key]) != dict: feature[key] = {"text": text} if type(text) == dict: text = text["text"] for token_name, token_maker in self.token_makers.items(): param_key = token_maker.indexer.param_key if param_key == key: continue feature[key][token_name] = self._index_token(token_maker, text, feature) def _index_token(self, token_maker, text, data): def index(): indexer = token_maker.indexer params = {} if token_maker.type_name == TokenMaker.EXACT_MATCH_TYPE: param_text = data[indexer.param_key] if type(param_text) == dict: param_text = param_text["text"] params["query_text"] = param_text return indexer.index(text, **params) if self.lazy_indexing: return index else: return index()
[docs] def raw_to_tensor_fn(self, data_reader, cuda_device=None, helper={}): def raw_to_tensor(inputs): is_one = True # batch_size 1 flag feature, _helper = data_reader.read_one_example(inputs) nonlocal helper helper.update(_helper) if type(feature) == list: is_one = False features = feature else: features = [feature] self._index_features(features, data_reader.text_columns, suppress_tqdm=True) if is_one: indexed_features = features[0] else: # when features > 1, need to transpose (dict_of_list -> list_of_dict) indexed_features = {} for key in features[0]: feature_with_key = [feature[key] for feature in features] indexed_features[key] = transpose(feature_with_key, skip_keys=["text"]) for key in indexed_features: for token_name in self.token_makers: if token_name not in indexed_features[key]: continue indexed_values = indexed_features[key][token_name] if is_one: indexed_values = [indexed_values] tensor = padding_tokens(indexed_values, token_name=token_name) if cuda_device is not None and type(tensor) != list: tensor = tensor.cuda(cuda_device) indexed_features[key][token_name] = tensor for key in indexed_features: if "text" in indexed_features[key]: del indexed_features[key]["text"] return indexed_features, helper return raw_to_tensor
================================================ FILE: docs/_build/html/_modules/claf/tokens/token_embedder/base.html ================================================ claf.tokens.token_embedder.base — CLaF 0.2.0 documentation

Source code for claf.tokens.token_embedder.base



import torch


[docs]class TokenEmbedder(torch.nn.Module): """ Token Embedder Take a tensor(indexed token) look up Embedding modules. * Args: token_makers: dictionary of TokenMaker (claf.token_makers.token) """ def __init__(self, token_makers): super(TokenEmbedder, self).__init__() self.embed_dims = {} self.vocabs = { token_name: token_maker.vocab for token_name, token_maker in token_makers.items() } self.add_embedding_modules(token_makers)
[docs] def add_embedding_modules(self, token_makers): """ add embedding module to TokenEmbedder """ self.token_names = [] for token_name, token_maker in token_makers.items(): self.token_names.append(token_name) vocab = token_maker.vocab embedding = token_maker.embedding_fn(vocab) self.add_module(token_name, embedding) self.embed_dims[token_name] = embedding.get_output_dim()
[docs] def get_embed_dim(self): raise NotImplementedError
[docs] def forward(self, inputs, params={}): raise NotImplementedError
================================================ FILE: docs/_build/html/_modules/claf/tokens/token_embedder/basic_embedder.html ================================================ claf.tokens.token_embedder.basic_embedder — CLaF 0.2.0 documentation

Source code for claf.tokens.token_embedder.basic_embedder


from overrides import overrides

import torch

from .base import TokenEmbedder


[docs]class BasicTokenEmbedder(TokenEmbedder): """ Basic Token Embedder Take a tensor(indexed token) look up Embedding modules. Output is concatenating all embedded tensors. * Args: token_makers: dictionary of TokenMaker (claf.tokens.token_maker) """ def __init__(self, token_makers): super(BasicTokenEmbedder, self).__init__(token_makers)
[docs] @overrides def get_embed_dim(self, except_keys=[]): return sum(self.embed_dims.values())
[docs] @overrides def forward(self, inputs, except_keys=[], params={}): token_names = [name for name in self.token_names if name not in except_keys] if set(token_names) != set(inputs.keys()): raise ValueError( f"Mismatch token_names inputs: {inputs.keys()}, embeddings: {self.token_names}" ) embedded_tokens = [] for token_name, tensors in inputs.items(): embedding = getattr(self, token_name) embedded_token = embedding(tensors, **params) embedded_tokens.append(embedded_token) output = torch.cat(embedded_tokens, dim=-1) return output
================================================ FILE: docs/_build/html/_modules/claf/tokens/token_embedder/reading_comprehension_embedder.html ================================================ claf.tokens.token_embedder.reading_comprehension_embedder — CLaF 0.2.0 documentation

Source code for claf.tokens.token_embedder.reading_comprehension_embedder


from overrides import overrides
import torch

import claf.modules.functional as f
import claf.modules.attention as attention

from .base import TokenEmbedder


[docs]class RCTokenEmbedder(TokenEmbedder): """ Reading Comprehension Token Embedder Take a tensor(indexed token) look up Embedding modules. Inputs are seperated context and query for individual token setting. * Args: token_makers: dictionary of TokenMaker (claf.tokens.token_maker) vocabs: dictionary of vocab {"token_name": Vocab (claf.token_makers.vocaburary), ...} """ EXCLUSIVE_TOKENS = ["exact_match"] # only context def __init__(self, token_makers): super(RCTokenEmbedder, self).__init__(token_makers) self.context_embed_dim = sum(self.embed_dims.values()) self.query_embed_dim = sum(self._filter(self.embed_dims, exclusive=False).values()) self.align_attention = attention.SeqAttnMatch(self.query_embed_dim)
[docs] @overrides def get_embed_dim(self): return self.context_embed_dim, self.query_embed_dim
[docs] @overrides def forward(self, context, query, context_params={}, query_params={}, query_align=False): """ * Args: context: context inputs (eg. {"token_name1": tensor, "token_name2": tensor, ...}) query: query inputs (eg. {"token_name1": tensor, "token_name2": tensor, ...}) * Kwargs: context_params: custom context parameters query_params: query context parameters query_align: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to 'context_embed'. """ if set(self.token_names) != set(context.keys()): raise ValueError( f"Mismatch token_names inputs: {context.keys()}, embeddings: {self.token_names}" ) context_tokens, query_tokens = {}, {} for token_name, context_tensors in context.items(): embedding = getattr(self, token_name) context_tokens[token_name] = embedding( context_tensors, **context_params.get(token_name, {}) ) if token_name in query: query_tokens[token_name] = embedding( query[token_name], **query_params.get(token_name, {}) ) # query_align_embedding if query_align: common_context = self._filter(context_tokens, exclusive=False) embedded_common_context = torch.cat(list(common_context.values()), dim=-1) exclusive_context = self._filter(context_tokens, exclusive=True) embedded_exclusive_context = None if exclusive_context != {}: embedded_exclusive_context = torch.cat(list(exclusive_context.values()), dim=-1) query_mask = f.get_mask_from_tokens(query_tokens) embedded_query = torch.cat(list(query_tokens.values()), dim=-1) embedded_aligned_query = self.align_attention( embedded_common_context, embedded_query, query_mask ) # Merge context embedded embedded_context = [embedded_common_context, embedded_aligned_query] if embedded_exclusive_context is not None: embedded_context.append(embedded_exclusive_context) context_output = torch.cat(embedded_context, dim=-1) query_output = embedded_query else: context_output = torch.cat(list(context_tokens.values()), dim=-1) query_output = torch.cat(list(query_tokens.values()), dim=-1) return context_output, query_output
def _filter(self, token_data, exclusive=False): if exclusive: return {k: v for k, v in token_data.items() if k in self.EXCLUSIVE_TOKENS} else: return {k: v for k, v in token_data.items() if k not in self.EXCLUSIVE_TOKENS}
================================================ FILE: docs/_build/html/_modules/claf/tokens/token_maker.html ================================================ claf.tokens.token_maker — CLaF 0.2.0 documentation

Source code for claf.tokens.token_maker

[docs]class TokenMaker: """ Token Maker (Data Transfer Object) Token Maker consists of Tokenizer, Indexer, Embedding and Vocab * Kwargs: tokenizer: Tokenizer (claf.tokens.tokenizer.base) indexer: TokenIndexer (claf.tokens.indexer.base) embedding_fn: wrapper function of TokenEmbedding (claf.tokens.embedding.base) vocab_config: config dict of Vocab (claf.tokens.vocaburary) """ # Token Type List FEATURE_TYPE = "feature" # Do not use embedding, pass indexed_feature BERT_TYPE = "bert" CHAR_TYPE = "char" COVE_TYPE = "cove" ELMO_TYPE = "elmo" EXACT_MATCH_TYPE = "exact_match" WORD_TYPE = "word" FREQUENT_WORD_TYPE = "frequent_word" LINGUISTIC_TYPE = "linguistic" def __init__( self, token_type, tokenizer=None, indexer=None, embedding_fn=None, vocab_config=None ): self.type_name = token_type self._tokenizer = tokenizer self._indexer = indexer self._embedding_fn = embedding_fn self._vocab_config = vocab_config @property def tokenizer(self): return self._tokenizer @tokenizer.setter def tokenizer(self, tokenizer): self._tokenizer = tokenizer @property def indexer(self): return self._indexer @indexer.setter def indexer(self, indexer): self._indexer = indexer @property def embedding_fn(self): return self._embedding_fn @embedding_fn.setter def embedding_fn(self, embedding_fn): self._embedding_fn = embedding_fn @property def vocab_config(self): return self._vocab_config @vocab_config.setter def vocab_config(self, vocab_config): self._vocab_config = vocab_config @property def vocab(self): return self._vocab @vocab.setter def vocab(self, vocab): self._vocab = vocab
[docs] def set_vocab(self, vocab): self._indexer.set_vocab(vocab) self._vocab = vocab
================================================ FILE: docs/_build/html/_modules/claf/tokens/tokenizer/base.html ================================================ claf.tokens.tokenizer.base — CLaF 0.2.0 documentation

Source code for claf.tokens.tokenizer.base

[docs]class Tokenizer: """ Tokenizer Base Class """ MAX_TO_KEEP_CACHE = 3 def __init__(self, name, cache_name): self.cache = {} # dict: {text: tokenized_tokens} self.name = name self.cache_name = cache_name
[docs] def tokenize(self, text, unit="text"): if type(text) == str and text in self.cache: return self.cache[text] tokenized_tokens = self._tokenize(text, unit="text") # Cache if len(self.cache) <= self.MAX_TO_KEEP_CACHE: self.cache[text] = tokenized_tokens else: first_key = next(iter(self.cache.keys())) del self.cache[first_key] return tokenized_tokens
def _tokenize(self, text, unit="text"): """ splitting text into tokens. """ if type(text) != str: raise ValueError(f"text type is must be str. not {type(text)}") return getattr(self, f"_{self.name}")(text, unit=unit)
================================================ FILE: docs/_build/html/_modules/claf/tokens/tokenizer/bpe.html ================================================ claf.tokens.tokenizer.bpe — CLaF 0.2.0 documentation

Source code for claf.tokens.tokenizer.bpe


from pytorch_transformers import RobertaTokenizer

from claf.data.data_handler import CachePath, DataHandler

from .base import Tokenizer


[docs]class BPETokenizer(Tokenizer): """ BPTE(Byte-Pair Encoding) Tokenizer text -> ... * Args: name: tokenizer name [roberta] """ def __init__(self, name, config={}): super(BPETokenizer, self).__init__(name, f"bpe-{name}") self.data_handler = DataHandler(CachePath.VOCAB) self.config = config self.bpe_tokenizer = None """ Tokenizers """ def _roberta(self, text, unit="text"): """ ex) """ if self.bpe_tokenizer is None: vocab_path = self.data_handler.read(self.config["vocab_path"], return_path=True) merges_path = self.data_handler.read(self.config["merges_path"], return_path=True) del self.config["vocab_path"] del self.config["merges_path"] self.bpe_tokenizer = RobertaTokenizer(vocab_path, merges_path, **self.config) return self.bpe_tokenizer._tokenize(text)
================================================ FILE: docs/_build/html/_modules/claf/tokens/tokenizer/char.html ================================================ claf.tokens.tokenizer.char — CLaF 0.2.0 documentation

Source code for claf.tokens.tokenizer.char


from claf.tokens import hangul as hg

from .base import Tokenizer


[docs]class CharTokenizer(Tokenizer): """ Character Tokenizer text -> word tokens -> [char tokens] * Args: name: tokenizer name [character|decompose_ko] word_tokenizer: word tokenizer object """ def __init__(self, name, word_tokenizer, config={}): super(CharTokenizer, self).__init__(name, f"char-{name}+{word_tokenizer.cache_name}") self.config = config self.word_tokenizer = word_tokenizer """ Tokenizers """ def _character(self, text, unit="text"): """ ex) Hello World -> ['Hello', 'World'] -> [['H', 'e', 'l', 'l', 'o'], ['W', 'o', 'r', 'l', 'd']] """ if unit == "word": return [char for char in text] else: return [[char for char in word] for word in self.word_tokenizer.tokenize(text)] def _jamo_ko(self, text, unit="text"): """ ex) 안녕 세상 -> ['안녕', '세상'] -> [['ㅇ', 'ㅏ', 'ㄴ', 'ㄴ', 'ㅕ', 'ㅇ'], ['ㅅ', 'ㅔ', 'ㅅ', 'ㅏ', 'ㅇ']] """ def decompose(char): if hg.is_hangul(char): try: return [c for c in hg.decompose(char) if c != ""] except IndexError: # Case: ㅋㅋㅋㅋ return [char] else: return [char] tokens = [] if unit == "word": chars = [] for char in text: chars.extend(decompose(char)) tokens.append(chars) else: for word in self.word_tokenizer.tokenize(text): chars = [] for char in word: chars.extend(decompose(char)) tokens.append(chars) return tokens
================================================ FILE: docs/_build/html/_modules/claf/tokens/tokenizer/pass_text.html ================================================ claf.tokens.tokenizer.pass_text — CLaF 0.2.0 documentation

Source code for claf.tokens.tokenizer.pass_text

[docs]class PassText: """ Pass text without tokenize """ def __init__(self): self.name = "pass" self.cache_name = "pass"
[docs] def tokenize(self, text): return text
================================================ FILE: docs/_build/html/_modules/claf/tokens/tokenizer/sent.html ================================================ claf.tokens.tokenizer.sent — CLaF 0.2.0 documentation

Source code for claf.tokens.tokenizer.sent


import nltk.data

from .base import Tokenizer


[docs]class SentTokenizer(Tokenizer): """ Sentence Tokenizer text -> [sent tokens] * Args: name: tokenizer name [punkt] """ def __init__(self, name, config={}): super(SentTokenizer, self).__init__(name, f"sent-{name}") self.config = config """ Tokenizers """ def _punkt(self, text, unit="text"): """ ex) Hello World. This is punkt tokenizer -> ['Hello World', 'This is punkt tokenizer'] """ sent_tokenizer = nltk.data.load("tokenizers/punkt/english.pickle") return sent_tokenizer.tokenize(text)
================================================ FILE: docs/_build/html/_modules/claf/tokens/tokenizer/subword.html ================================================ claf.tokens.tokenizer.subword — CLaF 0.2.0 documentation

Source code for claf.tokens.tokenizer.subword


from pytorch_transformers import WordpieceTokenizer
from pytorch_transformers.tokenization_bert import load_vocab


from claf.data.data_handler import CachePath, DataHandler

from .base import Tokenizer


[docs]class SubwordTokenizer(Tokenizer): """ Subword Tokenizer text -> [word tokens] -> [[sub word tokens], ...] * Args: name: tokenizer name [wordpiece] """ def __init__(self, name, word_tokenizer, config={}): super(SubwordTokenizer, self).__init__(name, f"subword-{name}+{word_tokenizer.cache_name}") self.data_handler = DataHandler(CachePath.VOCAB) self.config = config self.word_tokenizer = word_tokenizer self.subword_tokenizer = None """ Tokenizers """ def _wordpiece(self, text, unit="text"): """ ex) Hello World -> ['Hello', 'World'] -> ['He', '##llo', 'Wo', '##rld'] """ if self.subword_tokenizer is None: vocab_path = self.data_handler.read(self.config["vocab_path"], return_path=True) vocab = load_vocab(vocab_path) self.subword_tokenizer = WordpieceTokenizer( vocab, unk_token=self.config.get("unk_token", "[UNK]")) tokens = [] if unit == "word": for sub_token in self.subword_tokenizer.tokenize(text): tokens.append(sub_token) else: for token in self.word_tokenizer.tokenize(text): for sub_token in self.subword_tokenizer.tokenize(token): tokens.append(sub_token) return tokens
================================================ FILE: docs/_build/html/_modules/claf/tokens/tokenizer/utils.html ================================================ claf.tokens.tokenizer.utils — CLaF 0.2.0 documentation

Source code for claf.tokens.tokenizer.utils


import spacy


[docs]def create_tokenizer_with_regex(nlp, split_regex): prefixes_re = spacy.util.compile_prefix_regex(nlp.Defaults.prefixes) infix_re = split_regex suffix_re = spacy.util.compile_suffix_regex(nlp.Defaults.suffixes) return spacy.tokenizer.Tokenizer( nlp.vocab, nlp.Defaults.tokenizer_exceptions, prefix_search=prefixes_re.search, infix_finditer=infix_re.finditer, suffix_search=suffix_re.search, token_match=None, )
[docs]def load_spacy_model_for_tokenizer(split_regex): model = spacy.load("en_core_web_sm", disable=["vectors", "textcat", "tagger", "parser", "ner"]) if split_regex is not None: spacy_tokenizer = create_tokenizer_with_regex(model, split_regex) model.tokenizer = spacy_tokenizer return model
================================================ FILE: docs/_build/html/_modules/claf/tokens/tokenizer/word.html ================================================ claf.tokens.tokenizer.word — CLaF 0.2.0 documentation

Source code for claf.tokens.tokenizer.word



import re

from overrides import overrides

from claf import utils as common_utils

from .base import Tokenizer


[docs]class WordTokenizer(Tokenizer): """ Word Tokenizer * Args: name: tokenizer name [treebank_en|spacy_en|mecab_ko|bert_basic] * Kwargs: flatten: return type as flatten list split_with_regex: post split action. Split tokens that the tokenizer cannot split. """ def __init__(self, name, sent_tokenizer, config={}, split_with_regex=True): super(WordTokenizer, self).__init__(name, f"word-{name}+{sent_tokenizer.cache_name}") self.config = config self.sent_tokenizer = sent_tokenizer self.word_tokenizer = None self.split_with_regex = split_with_regex if split_with_regex: self.extra_split_chars_re = self.make_split_regex_expression()
[docs] def make_split_regex_expression(self): """ Apply a small amount of extra splitting to the given tokens, this is in particular to avoid UNK tokens due to contraction, quotation, or other forms of puncutation. I haven't really done tests to see if/how much difference this makes, but it does avoid some common UNKs I noticed in SQuAD/TriviaQA """ extra_split_chars = ( "-", "£", "€", "¥", "¢", "₹", "*", "\u2212", "\u2014", "\u2013", "/", "~", '"', "'", "\ud01C", "\u2019", "\u201D", "\u2018", "\u00B0", ".", ":", ) extra_split_tokens = ( "``", "(?<=[^_])_(?=[^_])", # dashes w/o a preceeding or following dash, so __wow___ -> ___ wow ___ "''", "[" + "".join(extra_split_chars) + "]", ) return re.compile("(" + "|".join(extra_split_tokens) + ")")
@overrides def _tokenize(self, text, unit="text"): """ Text -> word tokens """ if type(text) != str: raise ValueError(f"text type is must be str. not {type(text)}") if unit == "sentence": tokens = getattr(self, f"_{self.name}")(text) else: sentences = self.sent_tokenizer.tokenize(text) tokens = [getattr(self, f"_{self.name}")(sentence) for sentence in sentences] if self.split_with_regex and self.name != "spacy_en": tokens = self._split_with_regex(tokens) return list(common_utils.flatten(tokens)) def _split_with_regex(self, sentences): for i, sentence in enumerate(sentences): sentences[i] = [token for token in self._post_split_tokens(sentence)] return sentences def _post_split_tokens(self, tokens): return [[x for x in self.extra_split_chars_re.split(token) if x != ""] for token in tokens] """ Tokenizers """ def _space_all(self, text): def is_whitespace(c): if c == " " or c == "\t" or c == "\r" or c == "\n" or ord(c) == 0x202F: return True return False prev_is_whitespace = True tokens = [] for char in text: if is_whitespace(char): prev_is_whitespace = True else: if prev_is_whitespace: tokens.append(char) else: tokens[-1] += char prev_is_whitespace = False return tokens def _treebank_en(self, text): if self.word_tokenizer is None: import nltk self.word_tokenizer = nltk.TreebankWordTokenizer() return [ token.replace("''", '"').replace("``", '"') for token in self.word_tokenizer.tokenize(text) ] def _spacy_en(self, text): if self.word_tokenizer is None: from claf.tokens.tokenizer.utils import load_spacy_model_for_tokenizer self.word_tokenizer = load_spacy_model_for_tokenizer(self.extra_split_chars_re) def _remove_spaces(tokens): return [token.text for token in tokens if not token.is_space] return _remove_spaces(self.word_tokenizer(text)) def _bert_basic(self, text): if self.word_tokenizer is None: from pytorch_transformers import BasicTokenizer self.word_tokenizer = BasicTokenizer(**self.config) return self.word_tokenizer.tokenize(text) def _mecab_ko(self, text): if self.word_tokenizer is None: from konlpy.tag import Mecab self.word_tokenizer = Mecab() return self.word_tokenizer.morphs(text)
================================================ FILE: docs/_build/html/_modules/claf/tokens/vocabulary.html ================================================ claf.tokens.vocabulary — CLaF 0.2.0 documentation

Source code for claf.tokens.vocabulary


from collections import defaultdict
import json

from claf.data.data_handler import CachePath, DataHandler


[docs]class VocabDict(defaultdict): """ Vocab DefaultDict Class * Kwargs: oov_value: out-of-vocaburary token value (eg. <unk>) """ def __init__(self, oov_value): self.oov_value = oov_value def __missing__(self, key): return self.oov_value
[docs]class Vocab: """ Vocaburary Class Vocab consists of token_to_index and index_to_token. * Args: token_name: Token name (Token and Vocab is one-to-one relationship) * Kwargs: pad_token: padding token value (eg. <pad>) oov_token: out-of-vocaburary token value (eg. <unk>) start_token: start token value (eg. <s>, <bos>) end_token: end token value (eg. </s>, <eos>) cls_token: CLS token value for BERT (eg. [CLS]) sep_token: SEP token value for BERT (eg. [SEP]) min_count: token's minimal frequent count. when you define min_count, tokens remain that bigger than min_count. max_vocab_size: vocaburary's maximun size. when you define max_vocab_size, tokens are selected according to frequent count. frequent_count: get frequent_count threshold_index. (eg. frequent_count = 1000, threshold_index is the tokens that frequent_count is 999 index number.) pretrained_path: pretrained vocab file path (format: A\nB\nC\nD\n...) """ DEFAULT_PAD_INDEX, DEFAULT_PAD_TOKEN = 0, "[PAD]" DEFAULT_OOV_INDEX, DEFAULT_OOV_TOKEN = 1, "[UNK]" # pretrained_vocab handle methods PRETRAINED_ALL = "all" # Case. embedding matrix - predefine_vocab fixed PRETRAINED_INTERSECT = "intersect" # add token that included in predefine_vocab, else UNK_token def __init__( self, token_name, pad_token=None, oov_token=None, start_token=None, end_token=None, cls_token=None, sep_token=None, min_count=None, max_vocab_size=None, frequent_count=None, pretrained_path=None, pretrained_token=None, ): self.token_name = token_name # basic token (pad and oov) self.pad_index = self.DEFAULT_PAD_INDEX self.pad_token = pad_token if pad_token is None: self.pad_token = self.DEFAULT_PAD_TOKEN self.oov_index = self.DEFAULT_OOV_INDEX self.oov_token = oov_token if oov_token is None: self.oov_token = self.DEFAULT_OOV_TOKEN # special_tokens self.start_token = start_token self.end_token = end_token self.cls_token = cls_token self.sep_token = sep_token self.min_count = min_count self.max_vocab_size = max_vocab_size self.token_counter = None self.frequent_count = frequent_count self.threshold_index = None self.pretrained_path = pretrained_path self.pretrained_token = pretrained_token self.pretrained_token_methods = [self.PRETRAINED_ALL, self.PRETRAINED_INTERSECT]
[docs] def init(self): self.token_to_index = VocabDict(self.oov_index) self.index_to_token = VocabDict(self.oov_token) # add default token (pad, oov) self.add(self.pad_token) self.add(self.oov_token) special_tokens = [self.start_token, self.end_token, self.cls_token, self.sep_token] for token in special_tokens: if token is not None: self.add(token)
[docs] def build(self, token_counter, predefine_vocab=None): """ build token with token_counter * Args: token_counter: (collections.Counter) token's frequent_count Counter. """ if predefine_vocab is not None: if ( self.pretrained_token is None or self.pretrained_token not in self.pretrained_token_methods ): raise ValueError( f"When use 'predefine_vocab', need to set 'pretrained_token' {self.pretrained_token_methods}" ) if predefine_vocab: if self.pretrained_token == self.PRETRAINED_ALL: self.from_texts(predefine_vocab) return else: predefine_vocab = set(predefine_vocab) self.token_counter = token_counter self.init() token_counts = list(token_counter.items()) token_counts.sort(key=lambda x: x[1], reverse=True) # order: DESC if self.max_vocab_size is not None: token_counts = token_counts[: self.max_vocab_size] for token, count in token_counts: if self.min_count is not None: if count >= self.min_count: self.add(token, predefine_vocab=predefine_vocab) else: self.add(token, predefine_vocab=predefine_vocab) if self.threshold_index is None and self.frequent_count is not None: if count < self.frequent_count: self.threshold_index = len(self.token_to_index)
[docs] def build_with_pretrained_file(self, token_counter): data_handler = DataHandler(CachePath.VOCAB) vocab_texts = data_handler.read(self.pretrained_path) if self.pretrained_path.endswith(".txt"): predefine_vocab = vocab_texts.split("\n") elif self.pretrained_path.endswith(".json"): vocab_texts = json.loads(vocab_texts) # {token: id} predefine_vocab = [item[0] for item in sorted(vocab_texts.items(), key=lambda x: x[1])] else: raise ValueError(f"support vocab extention. .txt or .json") self.build(token_counter, predefine_vocab=predefine_vocab)
def __len__(self): return len(self.token_to_index)
[docs] def add(self, token, predefine_vocab=None): if token in self.token_to_index: return # already added if predefine_vocab: if self.pretrained_token == self.PRETRAINED_INTERSECT and token not in predefine_vocab: return index = len(self.token_to_index) self.token_to_index[token] = index self.index_to_token[index] = token
[docs] def get_index(self, token): return self.token_to_index[token]
[docs] def get_token(self, index): return self.index_to_token[index]
[docs] def get_all_tokens(self): return list(self.token_to_index.keys())
[docs] def dump(self, path): with open(path, "w", encoding="utf-8") as out_file: out_file.write(self.to_text())
[docs] def load(self, path): with open(path, "r", encoding="utf-8") as in_file: texts = in_file.read() self.from_texts(texts)
[docs] def to_text(self): return "\n".join(self.get_all_tokens())
[docs] def from_texts(self, texts): if type(texts) == list: tokens = texts else: tokens = [token for token in texts.split("\n")] tokens = [token for token in tokens if token] # filtering empty string # basic token (pad and oov) if self.pad_token in tokens: self.pad_index = tokens.index(self.pad_token) else: self.pad_index = len(tokens) tokens.append(self.pad_token) if self.oov_token in tokens: self.oov_index = tokens.index(self.oov_token) else: self.oov_index = len(tokens) tokens.append(self.oov_token) self.token_to_index = VocabDict(self.oov_index) self.index_to_token = VocabDict(self.oov_token) for token in tokens: self.add(token) return self
================================================ FILE: docs/_build/html/_modules/claf/tokens.html ================================================ claf.tokens — CLaF 0.2.0 documentation

Source code for claf.tokens


from claf.decorator import register
from claf.tokens import indexer, embedding
from claf.tokens.linguistic import POSTag, NER
from claf.tokens.token_maker import TokenMaker
from claf.tokens.tokenizer import PassText


[docs]def basic_embedding_fn(embedding_config, module): def wrapper(vocab): embedding_config["vocab"] = vocab return module(**embedding_config) return wrapper
[docs]@register(f"token:{TokenMaker.FEATURE_TYPE}") class FeatureTokenMaker(TokenMaker): """ Feature Token Do not use Embedding function. Just pass indexed_feature example. hello -> ['hello', 'world'] -> [3, 5] -> tensor consisting of - tokenizer: Tokenizer (need to define unit) - indexer: WordIndexer - embedding: None - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): tokenizer = PassText() do_tokenize = indexer_config.get("do_tokenize", False) if do_tokenize: text_unit = indexer_config.get("unit", None) if text_unit is None: raise ValueError("When use 'do_tokenize', 'unit' is required. ") del indexer_config["unit"] tokenizer = tokenizers[text_unit] super(FeatureTokenMaker, self).__init__( TokenMaker.FEATURE_TYPE, tokenizer=tokenizer, indexer=indexer.WordIndexer(tokenizer, **indexer_config), embedding_fn=None, vocab_config=vocab_config, )
[docs]@register(f"token:{TokenMaker.BERT_TYPE}") class BertTokenMaker(TokenMaker): """ BERT Token Pre-training of Deep Bidirectional Transformers for Language Understanding example. hello -> ['[CLS]', 'he', '##llo', [SEP]] -> [1, 4, 7, 2] -> BERT -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: ELMoEmbedding (Language Modeling BiLSTM) - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): tokenizer = tokenizers["subword"] super(BertTokenMaker, self).__init__( TokenMaker.BERT_TYPE, tokenizer=tokenizer, indexer=indexer.BertIndexer(tokenizer, **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.BertEmbedding), vocab_config=vocab_config, )
[docs]@register(f"token:{TokenMaker.CHAR_TYPE}") class CharTokenMaker(TokenMaker): """ Character Token Character-level Convolutional Networks for Text Classification (https://arxiv.org/abs/1509.01626) example. hello -> ['h', 'e', 'l', 'l', 'o'] -> [2, 3, 4, 4, 5] -> CharCNN -> tensor consisting of - tokenizer: CharTokenizer - indexer: CharIndexer - embedding: CharEmbedding (CharCNN) - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(CharTokenMaker, self).__init__( TokenMaker.CHAR_TYPE, tokenizer=tokenizers["char"], indexer=indexer.CharIndexer(tokenizers["char"], **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.CharEmbedding), vocab_config=vocab_config, )
[docs]@register(f"token:{TokenMaker.COVE_TYPE}") class CoveTokenMaker(TokenMaker): """ CoVe Token Learned in Translation: Contextualized Word Vectors (McCann et. al. 2017) (https://github.com/salesforce/cove) example. hello -> ['hello'] -> [2] -> CoVe -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: CoveEmbedding (Machine Translation LSTM) - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(CoveTokenMaker, self).__init__( TokenMaker.CHAR_TYPE, tokenizer=tokenizers["word"], indexer=indexer.WordIndexer(tokenizers["word"], **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.CoveEmbedding), vocab_config=vocab_config, )
[docs]@register(f"token:{TokenMaker.ELMO_TYPE}") class ElmoTokenMaker(TokenMaker): """ ELMo Token Embedding from Language Modeling Deep contextualized word representations (https://github.com/allenai/allennlp/blob/master/allennlp/modules/elmo.py) example. hello -> ['h', 'e', 'l', 'l', 'o'] -> [2, 3, 4, 4, 5] -> ELMo -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: ELMoEmbedding (Language Modeling BiLSTM) - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(ElmoTokenMaker, self).__init__( TokenMaker.WORD_TYPE, tokenizer=tokenizers["word"], indexer=indexer.ELMoIndexer(tokenizers["word"], **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.ELMoEmbedding), vocab_config="elmo", )
[docs]@register(f"token:{TokenMaker.EXACT_MATCH_TYPE}") class ExactMatchTokenMaker(TokenMaker): """ Exact Match Token (Sparse Feature) Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form. example. c: i do, q: i -> ['i', 'do'] -> [1, 0] -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: SparseFeature - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(ExactMatchTokenMaker, self).__init__( TokenMaker.EXACT_MATCH_TYPE, tokenizer=tokenizers["word"], indexer=indexer.ExactMatchIndexer(tokenizers["word"], **indexer_config), embedding_fn=self._embedding_fn(embedding_config, indexer_config), vocab_config=vocab_config, ) def _embedding_fn(self, embedding_config, indexer_config): def wrapper(vocab): embed_type = embedding_config.get("type", "sparse") if "type" in embedding_config: del embedding_config["type"] binary_classes = ["False", "True"] feature_count = 1 # origin embedding_config["classes"] = [binary_classes] if indexer_config.get("lower", False): feature_count += 1 embedding_config["classes"].append(binary_classes) if indexer_config.get("lemma", False): feature_count += 1 embedding_config["classes"].append(binary_classes) return embedding.SparseFeature( vocab, embed_type, feature_count, params=embedding_config ) return wrapper
[docs]@register(f"token:{TokenMaker.WORD_TYPE}") class WordTokenMaker(TokenMaker): """ Word Token (default) i do -> ['i', 'do'] -> [1, 2] -> Embedding Matrix -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: WordEmbedding - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(WordTokenMaker, self).__init__( TokenMaker.WORD_TYPE, tokenizer=tokenizers["word"], indexer=indexer.WordIndexer(tokenizers["word"], **indexer_config), embedding_fn=basic_embedding_fn(embedding_config, embedding.WordEmbedding), vocab_config=vocab_config, )
[docs]@register(f"token:{TokenMaker.FREQUENT_WORD_TYPE}") class FrequentWordTokenMaker(TokenMaker): """ Frequent-Tuning Word Token word token + pre-trained word embeddings fixed and only fine-tune the N most frequent example. i do -> ['i', 'do'] -> [1, 2] -> Embedding Matrix -> tensor finetuning only 'do' consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: FrequentTuningWordEmbedding - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(FrequentWordTokenMaker, self).__init__( TokenMaker.FREQUENT_WORD_TYPE, tokenizer=tokenizers["word"], indexer=indexer.WordIndexer(tokenizers["word"], **indexer_config), embedding_fn=basic_embedding_fn( embedding_config, embedding.FrequentTuningWordEmbedding ), vocab_config=vocab_config, )
[docs]@register(f"token:{TokenMaker.LINGUISTIC_TYPE}") class LinguisticTokenMaker(TokenMaker): """ Exact Match Token (Sparse Feature) Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form. example. c: i do, q: i -> ['i', 'do'] -> [1, 0] -> tensor consisting of - tokenizer: WordTokenizer - indexer: WordIndexer - embedding: SparseFeature - vocab: Vocab """ def __init__(self, tokenizers, indexer_config, embedding_config, vocab_config): super(LinguisticTokenMaker, self).__init__( TokenMaker.LINGUISTIC_TYPE, tokenizer=tokenizers["word"], indexer=indexer.LinguisticIndexer(tokenizers["word"], **indexer_config), embedding_fn=self._embedding_fn(embedding_config, indexer_config), vocab_config=vocab_config, ) def _embedding_fn(self, embedding_config, indexer_config): def wrapper(vocab): embed_type = embedding_config.get("type", "sparse") if "type" in embedding_config: del embedding_config["type"] feature_count = 0 embedding_config["classes"] = [] if indexer_config.get("pos_tag", False): feature_count += 1 embedding_config["classes"].append(POSTag.classes) if indexer_config.get("ner", False): feature_count += 1 embedding_config["classes"].append(NER.classes) return embedding.SparseFeature( vocab, embed_type, feature_count, params=embedding_config ) return wrapper
================================================ FILE: docs/_build/html/_modules/claf/utils.html ================================================ claf.utils — CLaF 0.2.0 documentation

Source code for claf.utils


import logging
import os
import sys

from claf.learn.mode import Mode


""" Interface """


[docs]def get_user_input(category): print(f"{category.capitalize()} > ", end="") sys.stdout.flush() user_input = sys.stdin.readline() try: return eval(user_input) except BaseException: return str(user_input)
[docs]def flatten(l): for item in l: if isinstance(item, list): for in_item in flatten(item): yield in_item else: yield item
""" Logging """
[docs]def set_logging_config(mode, config): stdout_handler = logging.StreamHandler(sys.stdout) logging_handlers = [stdout_handler] logging_level = logging.INFO if mode == Mode.TRAIN: log_path = os.path.join( config.trainer.log_dir, f"{config.data_reader.dataset}_{config.model.name}.log" ) os.makedirs(os.path.dirname(log_path), exist_ok=True) file_handler = logging.FileHandler(log_path) logging_handlers.append(file_handler) elif mode == Mode.PREDICT: logging_level = logging.WARNING logging.basicConfig( format="%(asctime)s (%(filename)s:%(lineno)d): [%(levelname)s] - %(message)s", handlers=logging_handlers, level=logging_level, )
================================================ FILE: docs/_build/html/_modules/index.html ================================================ Overview: module code — CLaF 0.2.0 documentation
  • Docs »
  • Overview: module code

All modules for which code is available

================================================ FILE: docs/_build/html/_modules/logging.html ================================================ logging — CLaF 0.2.0 documentation

Source code for logging

# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""
Logging package for Python. Based on PEP 282 and comments thereto in
comp.lang.python.

Copyright (C) 2001-2016 Vinay Sajip. All Rights Reserved.

To use, simply 'import logging' and log away!
"""

import sys, os, time, io, traceback, warnings, weakref, collections

from string import Template

__all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
           'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
           'LogRecord', 'Logger', 'LoggerAdapter', 'NOTSET', 'NullHandler',
           'StreamHandler', 'WARN', 'WARNING', 'addLevelName', 'basicConfig',
           'captureWarnings', 'critical', 'debug', 'disable', 'error',
           'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
           'info', 'log', 'makeLogRecord', 'setLoggerClass', 'shutdown',
           'warn', 'warning', 'getLogRecordFactory', 'setLogRecordFactory',
           'lastResort', 'raiseExceptions']

try:
    import threading
except ImportError: #pragma: no cover
    threading = None

__author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
__status__  = "production"
# The following module attributes are no longer updated.
__version__ = "0.5.1.2"
__date__    = "07 February 2010"

#---------------------------------------------------------------------------
#   Miscellaneous module data
#---------------------------------------------------------------------------

#
#_startTime is used as the base when calculating the relative time of events
#
_startTime = time.time()

#
#raiseExceptions is used to see if exceptions during handling should be
#propagated
#
raiseExceptions = True

#
# If you don't want threading information in the log, set this to zero
#
logThreads = True

#
# If you don't want multiprocessing information in the log, set this to zero
#
logMultiprocessing = True

#
# If you don't want process information in the log, set this to zero
#
logProcesses = True

#---------------------------------------------------------------------------
#   Level related stuff
#---------------------------------------------------------------------------
#
# Default levels and level names, these can be replaced with any positive set
# of values having corresponding names. There is a pseudo-level, NOTSET, which
# is only really there as a lower limit for user-defined levels. Handlers and
# loggers are initialized with NOTSET so that they will log all messages, even
# at user-defined levels.
#

CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

_levelToName = {
    CRITICAL: 'CRITICAL',
    ERROR: 'ERROR',
    WARNING: 'WARNING',
    INFO: 'INFO',
    DEBUG: 'DEBUG',
    NOTSET: 'NOTSET',
}
_nameToLevel = {
    'CRITICAL': CRITICAL,
    'FATAL': FATAL,
    'ERROR': ERROR,
    'WARN': WARNING,
    'WARNING': WARNING,
    'INFO': INFO,
    'DEBUG': DEBUG,
    'NOTSET': NOTSET,
}

def getLevelName(level):
    """
    Return the textual representation of logging level 'level'.

    If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
    INFO, DEBUG) then you get the corresponding string. If you have
    associated levels with names using addLevelName then the name you have
    associated with 'level' is returned.

    If a numeric value corresponding to one of the defined levels is passed
    in, the corresponding string representation is returned.

    Otherwise, the string "Level %s" % level is returned.
    """
    # See Issues #22386, #27937 and #29220 for why it's this way
    result = _levelToName.get(level)
    if result is not None:
        return result
    result = _nameToLevel.get(level)
    if result is not None:
        return result
    return "Level %s" % level

def addLevelName(level, levelName):
    """
    Associate 'levelName' with 'level'.

    This is used when converting levels to text during message formatting.
    """
    _acquireLock()
    try:    #unlikely to cause an exception, but you never know...
        _levelToName[level] = levelName
        _nameToLevel[levelName] = level
    finally:
        _releaseLock()

if hasattr(sys, '_getframe'):
    currentframe = lambda: sys._getframe(3)
else: #pragma: no cover
    def currentframe():
        """Return the frame object for the caller's stack frame."""
        try:
            raise Exception
        except Exception:
            return sys.exc_info()[2].tb_frame.f_back

#
# _srcfile is used when walking the stack to check when we've got the first
# caller stack frame, by skipping frames whose filename is that of this
# module's source. It therefore should contain the filename of this module's
# source file.
#
# Ordinarily we would use __file__ for this, but frozen modules don't always
# have __file__ set, for some reason (see Issue #21736). Thus, we get the
# filename from a handy code object from a function defined in this module.
# (There's no particular reason for picking addLevelName.)
#

_srcfile = os.path.normcase(addLevelName.__code__.co_filename)

# _srcfile is only used in conjunction with sys._getframe().
# To provide compatibility with older versions of Python, set _srcfile
# to None if _getframe() is not available; this value will prevent
# findCaller() from being called. You can also do this if you want to avoid
# the overhead of fetching caller information, even when _getframe() is
# available.
#if not hasattr(sys, '_getframe'):
#    _srcfile = None


def _checkLevel(level):
    if isinstance(level, int):
        rv = level
    elif str(level) == level:
        if level not in _nameToLevel:
            raise ValueError("Unknown level: %r" % level)
        rv = _nameToLevel[level]
    else:
        raise TypeError("Level not an integer or a valid string: %r" % level)
    return rv

#---------------------------------------------------------------------------
#   Thread-related stuff
#---------------------------------------------------------------------------

#
#_lock is used to serialize access to shared data structures in this module.
#This needs to be an RLock because fileConfig() creates and configures
#Handlers, and so might arbitrary user threads. Since Handler code updates the
#shared dictionary _handlers, it needs to acquire the lock. But if configuring,
#the lock would already have been acquired - so we need an RLock.
#The same argument applies to Loggers and Manager.loggerDict.
#
if threading:
    _lock = threading.RLock()
else: #pragma: no cover
    _lock = None


def _acquireLock():
    """
    Acquire the module-level lock for serializing access to shared data.

    This should be released with _releaseLock().
    """
    if _lock:
        _lock.acquire()

def _releaseLock():
    """
    Release the module-level lock acquired by calling _acquireLock().
    """
    if _lock:
        _lock.release()

#---------------------------------------------------------------------------
#   The logging record
#---------------------------------------------------------------------------

class LogRecord(object):
    """
    A LogRecord instance represents an event being logged.

    LogRecord instances are created every time something is logged. They
    contain all the information pertinent to the event being logged. The
    main information passed in is in msg and args, which are combined
    using str(msg) % args to create the message field of the record. The
    record also includes information such as when the record was created,
    the source line where the logging call was made, and any exception
    information to be logged.
    """
    def __init__(self, name, level, pathname, lineno,
                 msg, args, exc_info, func=None, sinfo=None, **kwargs):
        """
        Initialize a logging record with interesting information.
        """
        ct = time.time()
        self.name = name
        self.msg = msg
        #
        # The following statement allows passing of a dictionary as a sole
        # argument, so that you can do something like
        #  logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
        # Suggested by Stefan Behnel.
        # Note that without the test for args[0], we get a problem because
        # during formatting, we test to see if the arg is present using
        # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
        # and if the passed arg fails 'if self.args:' then no formatting
        # is done. For example, logger.warning('Value is %d', 0) would log
        # 'Value is %d' instead of 'Value is 0'.
        # For the use case of passing a dictionary, this should not be a
        # problem.
        # Issue #21172: a request was made to relax the isinstance check
        # to hasattr(args[0], '__getitem__'). However, the docs on string
        # formatting still seem to suggest a mapping object is required.
        # Thus, while not removing the isinstance check, it does now look
        # for collections.Mapping rather than, as before, dict.
        if (args and len(args) == 1 and isinstance(args[0], collections.Mapping)
            and args[0]):
            args = args[0]
        self.args = args
        self.levelname = getLevelName(level)
        self.levelno = level
        self.pathname = pathname
        try:
            self.filename = os.path.basename(pathname)
            self.module = os.path.splitext(self.filename)[0]
        except (TypeError, ValueError, AttributeError):
            self.filename = pathname
            self.module = "Unknown module"
        self.exc_info = exc_info
        self.exc_text = None      # used to cache the traceback text
        self.stack_info = sinfo
        self.lineno = lineno
        self.funcName = func
        self.created = ct
        self.msecs = (ct - int(ct)) * 1000
        self.relativeCreated = (self.created - _startTime) * 1000
        if logThreads and threading:
            self.thread = threading.get_ident()
            self.threadName = threading.current_thread().name
        else: # pragma: no cover
            self.thread = None
            self.threadName = None
        if not logMultiprocessing: # pragma: no cover
            self.processName = None
        else:
            self.processName = 'MainProcess'
            mp = sys.modules.get('multiprocessing')
            if mp is not None:
                # Errors may occur if multiprocessing has not finished loading
                # yet - e.g. if a custom import hook causes third-party code
                # to run when multiprocessing calls import. See issue 8200
                # for an example
                try:
                    self.processName = mp.current_process().name
                except Exception: #pragma: no cover
                    pass
        if logProcesses and hasattr(os, 'getpid'):
            self.process = os.getpid()
        else:
            self.process = None

    def __str__(self):
        return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
            self.pathname, self.lineno, self.msg)

    __repr__ = __str__

    def getMessage(self):
        """
        Return the message for this LogRecord.

        Return the message for this LogRecord after merging any user-supplied
        arguments with the message.
        """
        msg = str(self.msg)
        if self.args:
            msg = msg % self.args
        return msg

#
#   Determine which class to use when instantiating log records.
#
_logRecordFactory = LogRecord

def setLogRecordFactory(factory):
    """
    Set the factory to be used when instantiating a log record.

    :param factory: A callable which will be called to instantiate
    a log record.
    """
    global _logRecordFactory
    _logRecordFactory = factory

def getLogRecordFactory():
    """
    Return the factory to be used when instantiating a log record.
    """

    return _logRecordFactory

def makeLogRecord(dict):
    """
    Make a LogRecord whose attributes are defined by the specified dictionary,
    This function is useful for converting a logging event received over
    a socket connection (which is sent as a dictionary) into a LogRecord
    instance.
    """
    rv = _logRecordFactory(None, None, "", 0, "", (), None, None)
    rv.__dict__.update(dict)
    return rv

#---------------------------------------------------------------------------
#   Formatter classes and functions
#---------------------------------------------------------------------------

class PercentStyle(object):

    default_format = '%(message)s'
    asctime_format = '%(asctime)s'
    asctime_search = '%(asctime)'

    def __init__(self, fmt):
        self._fmt = fmt or self.default_format

    def usesTime(self):
        return self._fmt.find(self.asctime_search) >= 0

    def format(self, record):
        return self._fmt % record.__dict__

class StrFormatStyle(PercentStyle):
    default_format = '{message}'
    asctime_format = '{asctime}'
    asctime_search = '{asctime'

    def format(self, record):
        return self._fmt.format(**record.__dict__)


class StringTemplateStyle(PercentStyle):
    default_format = '${message}'
    asctime_format = '${asctime}'
    asctime_search = '${asctime}'

    def __init__(self, fmt):
        self._fmt = fmt or self.default_format
        self._tpl = Template(self._fmt)

    def usesTime(self):
        fmt = self._fmt
        return fmt.find('$asctime') >= 0 or fmt.find(self.asctime_format) >= 0

    def format(self, record):
        return self._tpl.substitute(**record.__dict__)

BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"

_STYLES = {
    '%': (PercentStyle, BASIC_FORMAT),
    '{': (StrFormatStyle, '{levelname}:{name}:{message}'),
    '$': (StringTemplateStyle, '${levelname}:${name}:${message}'),
}

class Formatter(object):
    """
    Formatter instances are used to convert a LogRecord to text.

    Formatters need to know how a LogRecord is constructed. They are
    responsible for converting a LogRecord to (usually) a string which can
    be interpreted by either a human or an external system. The base Formatter
    allows a formatting string to be specified. If none is supplied, the
    the style-dependent default value, "%(message)s", "{message}", or
    "${message}", is used.

    The Formatter can be initialized with a format string which makes use of
    knowledge of the LogRecord attributes - e.g. the default value mentioned
    above makes use of the fact that the user's message and arguments are pre-
    formatted into a LogRecord's message attribute. Currently, the useful
    attributes in a LogRecord are described by:

    %(name)s            Name of the logger (logging channel)
    %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
                        WARNING, ERROR, CRITICAL)
    %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
                        "WARNING", "ERROR", "CRITICAL")
    %(pathname)s        Full pathname of the source file where the logging
                        call was issued (if available)
    %(filename)s        Filename portion of pathname
    %(module)s          Module (name portion of filename)
    %(lineno)d          Source line number where the logging call was issued
                        (if available)
    %(funcName)s        Function name
    %(created)f         Time when the LogRecord was created (time.time()
                        return value)
    %(asctime)s         Textual time when the LogRecord was created
    %(msecs)d           Millisecond portion of the creation time
    %(relativeCreated)d Time in milliseconds when the LogRecord was created,
                        relative to the time the logging module was loaded
                        (typically at application startup time)
    %(thread)d          Thread ID (if available)
    %(threadName)s      Thread name (if available)
    %(process)d         Process ID (if available)
    %(message)s         The result of record.getMessage(), computed just as
                        the record is emitted
    """

    converter = time.localtime

    def __init__(self, fmt=None, datefmt=None, style='%'):
        """
        Initialize the formatter with specified format strings.

        Initialize the formatter either with the specified format string, or a
        default as described above. Allow for specialized date formatting with
        the optional datefmt argument. If datefmt is omitted, you get an
        ISO8601-like (or RFC 3339-like) format.

        Use a style parameter of '%', '{' or '$' to specify that you want to
        use one of %-formatting, :meth:`str.format` (``{}``) formatting or
        :class:`string.Template` formatting in your format string.

        .. versionchanged:: 3.2
           Added the ``style`` parameter.
        """
        if style not in _STYLES:
            raise ValueError('Style must be one of: %s' % ','.join(
                             _STYLES.keys()))
        self._style = _STYLES[style][0](fmt)
        self._fmt = self._style._fmt
        self.datefmt = datefmt

    default_time_format = '%Y-%m-%d %H:%M:%S'
    default_msec_format = '%s,%03d'

    def formatTime(self, record, datefmt=None):
        """
        Return the creation time of the specified LogRecord as formatted text.

        This method should be called from format() by a formatter which
        wants to make use of a formatted time. This method can be overridden
        in formatters to provide for any specific requirement, but the
        basic behaviour is as follows: if datefmt (a string) is specified,
        it is used with time.strftime() to format the creation time of the
        record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used.
        The resulting string is returned. This function uses a user-configurable
        function to convert the creation time to a tuple. By default,
        time.localtime() is used; to change this for a particular formatter
        instance, set the 'converter' attribute to a function with the same
        signature as time.localtime() or time.gmtime(). To change it for all
        formatters, for example if you want all logging times to be shown in GMT,
        set the 'converter' attribute in the Formatter class.
        """
        ct = self.converter(record.created)
        if datefmt:
            s = time.strftime(datefmt, ct)
        else:
            t = time.strftime(self.default_time_format, ct)
            s = self.default_msec_format % (t, record.msecs)
        return s

    def formatException(self, ei):
        """
        Format and return the specified exception information as a string.

        This default implementation just uses
        traceback.print_exception()
        """
        sio = io.StringIO()
        tb = ei[2]
        # See issues #9427, #1553375. Commented out for now.
        #if getattr(self, 'fullstack', False):
        #    traceback.print_stack(tb.tb_frame.f_back, file=sio)
        traceback.print_exception(ei[0], ei[1], tb, None, sio)
        s = sio.getvalue()
        sio.close()
        if s[-1:] == "\n":
            s = s[:-1]
        return s

    def usesTime(self):
        """
        Check if the format uses the creation time of the record.
        """
        return self._style.usesTime()

    def formatMessage(self, record):
        return self._style.format(record)

    def formatStack(self, stack_info):
        """
        This method is provided as an extension point for specialized
        formatting of stack information.

        The input data is a string as returned from a call to
        :func:`traceback.print_stack`, but with the last trailing newline
        removed.

        The base implementation just returns the value passed in.
        """
        return stack_info

    def format(self, record):
        """
        Format the specified record as text.

        The record's attribute dictionary is used as the operand to a
        string formatting operation which yields the returned string.
        Before formatting the dictionary, a couple of preparatory steps
        are carried out. The message attribute of the record is computed
        using LogRecord.getMessage(). If the formatting string uses the
        time (as determined by a call to usesTime(), formatTime() is
        called to format the event time. If there is exception information,
        it is formatted using formatException() and appended to the message.
        """
        record.message = record.getMessage()
        if self.usesTime():
            record.asctime = self.formatTime(record, self.datefmt)
        s = self.formatMessage(record)
        if record.exc_info:
            # Cache the traceback text to avoid converting it multiple times
            # (it's constant anyway)
            if not record.exc_text:
                record.exc_text = self.formatException(record.exc_info)
        if record.exc_text:
            if s[-1:] != "\n":
                s = s + "\n"
            s = s + record.exc_text
        if record.stack_info:
            if s[-1:] != "\n":
                s = s + "\n"
            s = s + self.formatStack(record.stack_info)
        return s

#
#   The default formatter to use when no other is specified
#
_defaultFormatter = Formatter()

class BufferingFormatter(object):
    """
    A formatter suitable for formatting a number of records.
    """
    def __init__(self, linefmt=None):
        """
        Optionally specify a formatter which will be used to format each
        individual record.
        """
        if linefmt:
            self.linefmt = linefmt
        else:
            self.linefmt = _defaultFormatter

    def formatHeader(self, records):
        """
        Return the header string for the specified records.
        """
        return ""

    def formatFooter(self, records):
        """
        Return the footer string for the specified records.
        """
        return ""

    def format(self, records):
        """
        Format the specified records and return the result as a string.
        """
        rv = ""
        if len(records) > 0:
            rv = rv + self.formatHeader(records)
            for record in records:
                rv = rv + self.linefmt.format(record)
            rv = rv + self.formatFooter(records)
        return rv

#---------------------------------------------------------------------------
#   Filter classes and functions
#---------------------------------------------------------------------------

class Filter(object):
    """
    Filter instances are used to perform arbitrary filtering of LogRecords.

    Loggers and Handlers can optionally use Filter instances to filter
    records as desired. The base filter class only allows events which are
    below a certain point in the logger hierarchy. For example, a filter
    initialized with "A.B" will allow events logged by loggers "A.B",
    "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
    initialized with the empty string, all events are passed.
    """
    def __init__(self, name=''):
        """
        Initialize a filter.

        Initialize with the name of the logger which, together with its
        children, will have its events allowed through the filter. If no
        name is specified, allow every event.
        """
        self.name = name
        self.nlen = len(name)

    def filter(self, record):
        """
        Determine if the specified record is to be logged.

        Is the specified record to be logged? Returns 0 for no, nonzero for
        yes. If deemed appropriate, the record may be modified in-place.
        """
        if self.nlen == 0:
            return True
        elif self.name == record.name:
            return True
        elif record.name.find(self.name, 0, self.nlen) != 0:
            return False
        return (record.name[self.nlen] == ".")

class Filterer(object):
    """
    A base class for loggers and handlers which allows them to share
    common code.
    """
    def __init__(self):
        """
        Initialize the list of filters to be an empty list.
        """
        self.filters = []

    def addFilter(self, filter):
        """
        Add the specified filter to this handler.
        """
        if not (filter in self.filters):
            self.filters.append(filter)

    def removeFilter(self, filter):
        """
        Remove the specified filter from this handler.
        """
        if filter in self.filters:
            self.filters.remove(filter)

    def filter(self, record):
        """
        Determine if a record is loggable by consulting all the filters.

        The default is to allow the record to be logged; any filter can veto
        this and the record is then dropped. Returns a zero value if a record
        is to be dropped, else non-zero.

        .. versionchanged:: 3.2

           Allow filters to be just callables.
        """
        rv = True
        for f in self.filters:
            if hasattr(f, 'filter'):
                result = f.filter(record)
            else:
                result = f(record) # assume callable - will raise if not
            if not result:
                rv = False
                break
        return rv

#---------------------------------------------------------------------------
#   Handler classes and functions
#---------------------------------------------------------------------------

_handlers = weakref.WeakValueDictionary()  #map of handler names to handlers
_handlerList = [] # added to allow handlers to be removed in reverse of order initialized

def _removeHandlerRef(wr):
    """
    Remove a handler reference from the internal cleanup list.
    """
    # This function can be called during module teardown, when globals are
    # set to None. It can also be called from another thread. So we need to
    # pre-emptively grab the necessary globals and check if they're None,
    # to prevent race conditions and failures during interpreter shutdown.
    acquire, release, handlers = _acquireLock, _releaseLock, _handlerList
    if acquire and release and handlers:
        acquire()
        try:
            if wr in handlers:
                handlers.remove(wr)
        finally:
            release()

def _addHandlerRef(handler):
    """
    Add a handler to the internal cleanup list using a weak reference.
    """
    _acquireLock()
    try:
        _handlerList.append(weakref.ref(handler, _removeHandlerRef))
    finally:
        _releaseLock()

class Handler(Filterer):
    """
    Handler instances dispatch logging events to specific destinations.

    The base handler class. Acts as a placeholder which defines the Handler
    interface. Handlers can optionally use Formatter instances to format
    records as desired. By default, no formatter is specified; in this case,
    the 'raw' message as determined by record.message is logged.
    """
    def __init__(self, level=NOTSET):
        """
        Initializes the instance - basically setting the formatter to None
        and the filter list to empty.
        """
        Filterer.__init__(self)
        self._name = None
        self.level = _checkLevel(level)
        self.formatter = None
        # Add the handler to the global _handlerList (for cleanup on shutdown)
        _addHandlerRef(self)
        self.createLock()

    def get_name(self):
        return self._name

    def set_name(self, name):
        _acquireLock()
        try:
            if self._name in _handlers:
                del _handlers[self._name]
            self._name = name
            if name:
                _handlers[name] = self
        finally:
            _releaseLock()

    name = property(get_name, set_name)

    def createLock(self):
        """
        Acquire a thread lock for serializing access to the underlying I/O.
        """
        if threading:
            self.lock = threading.RLock()
        else: #pragma: no cover
            self.lock = None

    def acquire(self):
        """
        Acquire the I/O thread lock.
        """
        if self.lock:
            self.lock.acquire()

    def release(self):
        """
        Release the I/O thread lock.
        """
        if self.lock:
            self.lock.release()

    def setLevel(self, level):
        """
        Set the logging level of this handler.  level must be an int or a str.
        """
        self.level = _checkLevel(level)

    def format(self, record):
        """
        Format the specified record.

        If a formatter is set, use it. Otherwise, use the default formatter
        for the module.
        """
        if self.formatter:
            fmt = self.formatter
        else:
            fmt = _defaultFormatter
        return fmt.format(record)

    def emit(self, record):
        """
        Do whatever it takes to actually log the specified logging record.

        This version is intended to be implemented by subclasses and so
        raises a NotImplementedError.
        """
        raise NotImplementedError('emit must be implemented '
                                  'by Handler subclasses')

    def handle(self, record):
        """
        Conditionally emit the specified logging record.

        Emission depends on filters which may have been added to the handler.
        Wrap the actual emission of the record with acquisition/release of
        the I/O thread lock. Returns whether the filter passed the record for
        emission.
        """
        rv = self.filter(record)
        if rv:
            self.acquire()
            try:
                self.emit(record)
            finally:
                self.release()
        return rv

    def setFormatter(self, fmt):
        """
        Set the formatter for this handler.
        """
        self.formatter = fmt

    def flush(self):
        """
        Ensure all logging output has been flushed.

        This version does nothing and is intended to be implemented by
        subclasses.
        """
        pass

    def close(self):
        """
        Tidy up any resources used by the handler.

        This version removes the handler from an internal map of handlers,
        _handlers, which is used for handler lookup by name. Subclasses
        should ensure that this gets called from overridden close()
        methods.
        """
        #get the module data lock, as we're updating a shared structure.
        _acquireLock()
        try:    #unlikely to raise an exception, but you never know...
            if self._name and self._name in _handlers:
                del _handlers[self._name]
        finally:
            _releaseLock()

    def handleError(self, record):
        """
        Handle errors which occur during an emit() call.

        This method should be called from handlers when an exception is
        encountered during an emit() call. If raiseExceptions is false,
        exceptions get silently ignored. This is what is mostly wanted
        for a logging system - most users will not care about errors in
        the logging system, they are more interested in application errors.
        You could, however, replace this with a custom handler if you wish.
        The record which was being processed is passed in to this method.
        """
        if raiseExceptions and sys.stderr:  # see issue 13807
            t, v, tb = sys.exc_info()
            try:
                sys.stderr.write('--- Logging error ---\n')
                traceback.print_exception(t, v, tb, None, sys.stderr)
                sys.stderr.write('Call stack:\n')
                # Walk the stack frame up until we're out of logging,
                # so as to print the calling context.
                frame = tb.tb_frame
                while (frame and os.path.dirname(frame.f_code.co_filename) ==
                       __path__[0]):
                    frame = frame.f_back
                if frame:
                    traceback.print_stack(frame, file=sys.stderr)
                else:
                    # couldn't find the right stack frame, for some reason
                    sys.stderr.write('Logged from file %s, line %s\n' % (
                                     record.filename, record.lineno))
                # Issue 18671: output logging message and arguments
                try:
                    sys.stderr.write('Message: %r\n'
                                     'Arguments: %s\n' % (record.msg,
                                                          record.args))
                except Exception:
                    sys.stderr.write('Unable to print the message and arguments'
                                     ' - possible formatting error.\nUse the'
                                     ' traceback above to help find the error.\n'
                                    )
            except OSError: #pragma: no cover
                pass    # see issue 5971
            finally:
                del t, v, tb

    def __repr__(self):
        level = getLevelName(self.level)
        return '<%s (%s)>' % (self.__class__.__name__, level)

class StreamHandler(Handler):
    """
    A handler class which writes logging records, appropriately formatted,
    to a stream. Note that this class does not close the stream, as
    sys.stdout or sys.stderr may be used.
    """

    terminator = '\n'

    def __init__(self, stream=None):
        """
        Initialize the handler.

        If stream is not specified, sys.stderr is used.
        """
        Handler.__init__(self)
        if stream is None:
            stream = sys.stderr
        self.stream = stream

    def flush(self):
        """
        Flushes the stream.
        """
        self.acquire()
        try:
            if self.stream and hasattr(self.stream, "flush"):
                self.stream.flush()
        finally:
            self.release()

    def emit(self, record):
        """
        Emit a record.

        If a formatter is specified, it is used to format the record.
        The record is then written to the stream with a trailing newline.  If
        exception information is present, it is formatted using
        traceback.print_exception and appended to the stream.  If the stream
        has an 'encoding' attribute, it is used to determine how to do the
        output to the stream.
        """
        try:
            msg = self.format(record)
            stream = self.stream
            stream.write(msg)
            stream.write(self.terminator)
            self.flush()
        except Exception:
            self.handleError(record)

    def __repr__(self):
        level = getLevelName(self.level)
        name = getattr(self.stream, 'name', '')
        if name:
            name += ' '
        return '<%s %s(%s)>' % (self.__class__.__name__, name, level)


class FileHandler(StreamHandler):
    """
    A handler class which writes formatted logging records to disk files.
    """
    def __init__(self, filename, mode='a', encoding=None, delay=False):
        """
        Open the specified file and use it as the stream for logging.
        """
        # Issue #27493: add support for Path objects to be passed in
        filename = os.fspath(filename)
        #keep the absolute path, otherwise derived classes which use this
        #may come a cropper when the current directory changes
        self.baseFilename = os.path.abspath(filename)
        self.mode = mode
        self.encoding = encoding
        self.delay = delay
        if delay:
            #We don't open the stream, but we still need to call the
            #Handler constructor to set level, formatter, lock etc.
            Handler.__init__(self)
            self.stream = None
        else:
            StreamHandler.__init__(self, self._open())

    def close(self):
        """
        Closes the stream.
        """
        self.acquire()
        try:
            try:
                if self.stream:
                    try:
                        self.flush()
                    finally:
                        stream = self.stream
                        self.stream = None
                        if hasattr(stream, "close"):
                            stream.close()
            finally:
                # Issue #19523: call unconditionally to
                # prevent a handler leak when delay is set
                StreamHandler.close(self)
        finally:
            self.release()

    def _open(self):
        """
        Open the current base file with the (original) mode and encoding.
        Return the resulting stream.
        """
        return open(self.baseFilename, self.mode, encoding=self.encoding)

    def emit(self, record):
        """
        Emit a record.

        If the stream was not opened because 'delay' was specified in the
        constructor, open it before calling the superclass's emit.
        """
        if self.stream is None:
            self.stream = self._open()
        StreamHandler.emit(self, record)

    def __repr__(self):
        level = getLevelName(self.level)
        return '<%s %s (%s)>' % (self.__class__.__name__, self.baseFilename, level)


class _StderrHandler(StreamHandler):
    """
    This class is like a StreamHandler using sys.stderr, but always uses
    whatever sys.stderr is currently set to rather than the value of
    sys.stderr at handler construction time.
    """
    def __init__(self, level=NOTSET):
        """
        Initialize the handler.
        """
        Handler.__init__(self, level)

    @property
    def stream(self):
        return sys.stderr


_defaultLastResort = _StderrHandler(WARNING)
lastResort = _defaultLastResort

#---------------------------------------------------------------------------
#   Manager classes and functions
#---------------------------------------------------------------------------

class PlaceHolder(object):
    """
    PlaceHolder instances are used in the Manager logger hierarchy to take
    the place of nodes for which no loggers have been defined. This class is
    intended for internal use only and not as part of the public API.
    """
    def __init__(self, alogger):
        """
        Initialize with the specified logger being a child of this placeholder.
        """
        self.loggerMap = { alogger : None }

    def append(self, alogger):
        """
        Add the specified logger as a child of this placeholder.
        """
        if alogger not in self.loggerMap:
            self.loggerMap[alogger] = None

#
#   Determine which class to use when instantiating loggers.
#

def setLoggerClass(klass):
    """
    Set the class to be used when instantiating a logger. The class should
    define __init__() such that only a name argument is required, and the
    __init__() should call Logger.__init__()
    """
    if klass != Logger:
        if not issubclass(klass, Logger):
            raise TypeError("logger not derived from logging.Logger: "
                            + klass.__name__)
    global _loggerClass
    _loggerClass = klass

def getLoggerClass():
    """
    Return the class to be used when instantiating a logger.
    """
    return _loggerClass

class Manager(object):
    """
    There is [under normal circumstances] just one Manager instance, which
    holds the hierarchy of loggers.
    """
    def __init__(self, rootnode):
        """
        Initialize the manager with the root node of the logger hierarchy.
        """
        self.root = rootnode
        self.disable = 0
        self.emittedNoHandlerWarning = False
        self.loggerDict = {}
        self.loggerClass = None
        self.logRecordFactory = None

    def getLogger(self, name):
        """
        Get a logger with the specified name (channel name), creating it
        if it doesn't yet exist. This name is a dot-separated hierarchical
        name, such as "a", "a.b", "a.b.c" or similar.

        If a PlaceHolder existed for the specified name [i.e. the logger
        didn't exist but a child of it did], replace it with the created
        logger and fix up the parent/child references which pointed to the
        placeholder to now point to the logger.
        """
        rv = None
        if not isinstance(name, str):
            raise TypeError('A logger name must be a string')
        _acquireLock()
        try:
            if name in self.loggerDict:
                rv = self.loggerDict[name]
                if isinstance(rv, PlaceHolder):
                    ph = rv
                    rv = (self.loggerClass or _loggerClass)(name)
                    rv.manager = self
                    self.loggerDict[name] = rv
                    self._fixupChildren(ph, rv)
                    self._fixupParents(rv)
            else:
                rv = (self.loggerClass or _loggerClass)(name)
                rv.manager = self
                self.loggerDict[name] = rv
                self._fixupParents(rv)
        finally:
            _releaseLock()
        return rv

    def setLoggerClass(self, klass):
        """
        Set the class to be used when instantiating a logger with this Manager.
        """
        if klass != Logger:
            if not issubclass(klass, Logger):
                raise TypeError("logger not derived from logging.Logger: "
                                + klass.__name__)
        self.loggerClass = klass

    def setLogRecordFactory(self, factory):
        """
        Set the factory to be used when instantiating a log record with this
        Manager.
        """
        self.logRecordFactory = factory

    def _fixupParents(self, alogger):
        """
        Ensure that there are either loggers or placeholders all the way
        from the specified logger to the root of the logger hierarchy.
        """
        name = alogger.name
        i = name.rfind(".")
        rv = None
        while (i > 0) and not rv:
            substr = name[:i]
            if substr not in self.loggerDict:
                self.loggerDict[substr] = PlaceHolder(alogger)
            else:
                obj = self.loggerDict[substr]
                if isinstance(obj, Logger):
                    rv = obj
                else:
                    assert isinstance(obj, PlaceHolder)
                    obj.append(alogger)
            i = name.rfind(".", 0, i - 1)
        if not rv:
            rv = self.root
        alogger.parent = rv

    def _fixupChildren(self, ph, alogger):
        """
        Ensure that children of the placeholder ph are connected to the
        specified logger.
        """
        name = alogger.name
        namelen = len(name)
        for c in ph.loggerMap.keys():
            #The if means ... if not c.parent.name.startswith(nm)
            if c.parent.name[:namelen] != name:
                alogger.parent = c.parent
                c.parent = alogger

#---------------------------------------------------------------------------
#   Logger classes and functions
#---------------------------------------------------------------------------

class Logger(Filterer):
    """
    Instances of the Logger class represent a single logging channel. A
    "logging channel" indicates an area of an application. Exactly how an
    "area" is defined is up to the application developer. Since an
    application can have any number of areas, logging channels are identified
    by a unique string. Application areas can be nested (e.g. an area
    of "input processing" might include sub-areas "read CSV files", "read
    XLS files" and "read Gnumeric files"). To cater for this natural nesting,
    channel names are organized into a namespace hierarchy where levels are
    separated by periods, much like the Java or Python package namespace. So
    in the instance given above, channel names might be "input" for the upper
    level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
    There is no arbitrary limit to the depth of nesting.
    """
    def __init__(self, name, level=NOTSET):
        """
        Initialize the logger with a name and an optional level.
        """
        Filterer.__init__(self)
        self.name = name
        self.level = _checkLevel(level)
        self.parent = None
        self.propagate = True
        self.handlers = []
        self.disabled = False

    def setLevel(self, level):
        """
        Set the logging level of this logger.  level must be an int or a str.
        """
        self.level = _checkLevel(level)

    def debug(self, msg, *args, **kwargs):
        """
        Log 'msg % args' with severity 'DEBUG'.

        To pass exception information, use the keyword argument exc_info with
        a true value, e.g.

        logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
        """
        if self.isEnabledFor(DEBUG):
            self._log(DEBUG, msg, args, **kwargs)

    def info(self, msg, *args, **kwargs):
        """
        Log 'msg % args' with severity 'INFO'.

        To pass exception information, use the keyword argument exc_info with
        a true value, e.g.

        logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
        """
        if self.isEnabledFor(INFO):
            self._log(INFO, msg, args, **kwargs)

    def warning(self, msg, *args, **kwargs):
        """
        Log 'msg % args' with severity 'WARNING'.

        To pass exception information, use the keyword argument exc_info with
        a true value, e.g.

        logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
        """
        if self.isEnabledFor(WARNING):
            self._log(WARNING, msg, args, **kwargs)

    def warn(self, msg, *args, **kwargs):
        warnings.warn("The 'warn' method is deprecated, "
            "use 'warning' instead", DeprecationWarning, 2)
        self.warning(msg, *args, **kwargs)

    def error(self, msg, *args, **kwargs):
        """
        Log 'msg % args' with severity 'ERROR'.

        To pass exception information, use the keyword argument exc_info with
        a true value, e.g.

        logger.error("Houston, we have a %s", "major problem", exc_info=1)
        """
        if self.isEnabledFor(ERROR):
            self._log(ERROR, msg, args, **kwargs)

    def exception(self, msg, *args, exc_info=True, **kwargs):
        """
        Convenience method for logging an ERROR with exception information.
        """
        self.error(msg, *args, exc_info=exc_info, **kwargs)

    def critical(self, msg, *args, **kwargs):
        """
        Log 'msg % args' with severity 'CRITICAL'.

        To pass exception information, use the keyword argument exc_info with
        a true value, e.g.

        logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
        """
        if self.isEnabledFor(CRITICAL):
            self._log(CRITICAL, msg, args, **kwargs)

    fatal = critical

    def log(self, level, msg, *args, **kwargs):
        """
        Log 'msg % args' with the integer severity 'level'.

        To pass exception information, use the keyword argument exc_info with
        a true value, e.g.

        logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
        """
        if not isinstance(level, int):
            if raiseExceptions:
                raise TypeError("level must be an integer")
            else:
                return
        if self.isEnabledFor(level):
            self._log(level, msg, args, **kwargs)

    def findCaller(self, stack_info=False):
        """
        Find the stack frame of the caller so that we can note the source
        file name, line number and function name.
        """
        f = currentframe()
        #On some versions of IronPython, currentframe() returns None if
        #IronPython isn't run with -X:Frames.
        if f is not None:
            f = f.f_back
        rv = "(unknown file)", 0, "(unknown function)", None
        while hasattr(f, "f_code"):
            co = f.f_code
            filename = os.path.normcase(co.co_filename)
            if filename == _srcfile:
                f = f.f_back
                continue
            sinfo = None
            if stack_info:
                sio = io.StringIO()
                sio.write('Stack (most recent call last):\n')
                traceback.print_stack(f, file=sio)
                sinfo = sio.getvalue()
                if sinfo[-1] == '\n':
                    sinfo = sinfo[:-1]
                sio.close()
            rv = (co.co_filename, f.f_lineno, co.co_name, sinfo)
            break
        return rv

    def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
                   func=None, extra=None, sinfo=None):
        """
        A factory method which can be overridden in subclasses to create
        specialized LogRecords.
        """
        rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
                             sinfo)
        if extra is not None:
            for key in extra:
                if (key in ["message", "asctime"]) or (key in rv.__dict__):
                    raise KeyError("Attempt to overwrite %r in LogRecord" % key)
                rv.__dict__[key] = extra[key]
        return rv

    def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False):
        """
        Low-level logging routine which creates a LogRecord and then calls
        all the handlers of this logger to handle the record.
        """
        sinfo = None
        if _srcfile:
            #IronPython doesn't track Python frames, so findCaller raises an
            #exception on some versions of IronPython. We trap it here so that
            #IronPython can use logging.
            try:
                fn, lno, func, sinfo = self.findCaller(stack_info)
            except ValueError: # pragma: no cover
                fn, lno, func = "(unknown file)", 0, "(unknown function)"
        else: # pragma: no cover
            fn, lno, func = "(unknown file)", 0, "(unknown function)"
        if exc_info:
            if isinstance(exc_info, BaseException):
                exc_info = (type(exc_info), exc_info, exc_info.__traceback__)
            elif not isinstance(exc_info, tuple):
                exc_info = sys.exc_info()
        record = self.makeRecord(self.name, level, fn, lno, msg, args,
                                 exc_info, func, extra, sinfo)
        self.handle(record)

    def handle(self, record):
        """
        Call the handlers for the specified record.

        This method is used for unpickled records received from a socket, as
        well as those created locally. Logger-level filtering is applied.
        """
        if (not self.disabled) and self.filter(record):
            self.callHandlers(record)

    def addHandler(self, hdlr):
        """
        Add the specified handler to this logger.
        """
        _acquireLock()
        try:
            if not (hdlr in self.handlers):
                self.handlers.append(hdlr)
        finally:
            _releaseLock()

    def removeHandler(self, hdlr):
        """
        Remove the specified handler from this logger.
        """
        _acquireLock()
        try:
            if hdlr in self.handlers:
                self.handlers.remove(hdlr)
        finally:
            _releaseLock()

    def hasHandlers(self):
        """
        See if this logger has any handlers configured.

        Loop through all handlers for this logger and its parents in the
        logger hierarchy. Return True if a handler was found, else False.
        Stop searching up the hierarchy whenever a logger with the "propagate"
        attribute set to zero is found - that will be the last logger which
        is checked for the existence of handlers.
        """
        c = self
        rv = False
        while c:
            if c.handlers:
                rv = True
                break
            if not c.propagate:
                break
            else:
                c = c.parent
        return rv

    def callHandlers(self, record):
        """
        Pass a record to all relevant handlers.

        Loop through all handlers for this logger and its parents in the
        logger hierarchy. If no handler was found, output a one-off error
        message to sys.stderr. Stop searching up the hierarchy whenever a
        logger with the "propagate" attribute set to zero is found - that
        will be the last logger whose handlers are called.
        """
        c = self
        found = 0
        while c:
            for hdlr in c.handlers:
                found = found + 1
                if record.levelno >= hdlr.level:
                    hdlr.handle(record)
            if not c.propagate:
                c = None    #break out
            else:
                c = c.parent
        if (found == 0):
            if lastResort:
                if record.levelno >= lastResort.level:
                    lastResort.handle(record)
            elif raiseExceptions and not self.manager.emittedNoHandlerWarning:
                sys.stderr.write("No handlers could be found for logger"
                                 " \"%s\"\n" % self.name)
                self.manager.emittedNoHandlerWarning = True

    def getEffectiveLevel(self):
        """
        Get the effective level for this logger.

        Loop through this logger and its parents in the logger hierarchy,
        looking for a non-zero logging level. Return the first one found.
        """
        logger = self
        while logger:
            if logger.level:
                return logger.level
            logger = logger.parent
        return NOTSET

    def isEnabledFor(self, level):
        """
        Is this logger enabled for level 'level'?
        """
        if self.manager.disable >= level:
            return False
        return level >= self.getEffectiveLevel()

    def getChild(self, suffix):
        """
        Get a logger which is a descendant to this one.

        This is a convenience method, such that

        logging.getLogger('abc').getChild('def.ghi')

        is the same as

        logging.getLogger('abc.def.ghi')

        It's useful, for example, when the parent logger is named using
        __name__ rather than a literal string.
        """
        if self.root is not self:
            suffix = '.'.join((self.name, suffix))
        return self.manager.getLogger(suffix)

    def __repr__(self):
        level = getLevelName(self.getEffectiveLevel())
        return '<%s %s (%s)>' % (self.__class__.__name__, self.name, level)


class RootLogger(Logger):
    """
    A root logger is not that different to any other logger, except that
    it must have a logging level and there is only one instance of it in
    the hierarchy.
    """
    def __init__(self, level):
        """
        Initialize the logger with the name "root".
        """
        Logger.__init__(self, "root", level)

_loggerClass = Logger

class LoggerAdapter(object):
    """
    An adapter for loggers which makes it easier to specify contextual
    information in logging output.
    """

    def __init__(self, logger, extra):
        """
        Initialize the adapter with a logger and a dict-like object which
        provides contextual information. This constructor signature allows
        easy stacking of LoggerAdapters, if so desired.

        You can effectively pass keyword arguments as shown in the
        following example:

        adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
        """
        self.logger = logger
        self.extra = extra

    def process(self, msg, kwargs):
        """
        Process the logging message and keyword arguments passed in to
        a logging call to insert contextual information. You can either
        manipulate the message itself, the keyword args or both. Return
        the message and kwargs modified (or not) to suit your needs.

        Normally, you'll only need to override this one method in a
        LoggerAdapter subclass for your specific needs.
        """
        kwargs["extra"] = self.extra
        return msg, kwargs

    #
    # Boilerplate convenience methods
    #
    def debug(self, msg, *args, **kwargs):
        """
        Delegate a debug call to the underlying logger.
        """
        self.log(DEBUG, msg, *args, **kwargs)

    def info(self, msg, *args, **kwargs):
        """
        Delegate an info call to the underlying logger.
        """
        self.log(INFO, msg, *args, **kwargs)

    def warning(self, msg, *args, **kwargs):
        """
        Delegate a warning call to the underlying logger.
        """
        self.log(WARNING, msg, *args, **kwargs)

    def warn(self, msg, *args, **kwargs):
        warnings.warn("The 'warn' method is deprecated, "
            "use 'warning' instead", DeprecationWarning, 2)
        self.warning(msg, *args, **kwargs)

    def error(self, msg, *args, **kwargs):
        """
        Delegate an error call to the underlying logger.
        """
        self.log(ERROR, msg, *args, **kwargs)

    def exception(self, msg, *args, exc_info=True, **kwargs):
        """
        Delegate an exception call to the underlying logger.
        """
        self.log(ERROR, msg, *args, exc_info=exc_info, **kwargs)

    def critical(self, msg, *args, **kwargs):
        """
        Delegate a critical call to the underlying logger.
        """
        self.log(CRITICAL, msg, *args, **kwargs)

    def log(self, level, msg, *args, **kwargs):
        """
        Delegate a log call to the underlying logger, after adding
        contextual information from this adapter instance.
        """
        if self.isEnabledFor(level):
            msg, kwargs = self.process(msg, kwargs)
            self.logger.log(level, msg, *args, **kwargs)

    def isEnabledFor(self, level):
        """
        Is this logger enabled for level 'level'?
        """
        if self.logger.manager.disable >= level:
            return False
        return level >= self.getEffectiveLevel()

    def setLevel(self, level):
        """
        Set the specified level on the underlying logger.
        """
        self.logger.setLevel(level)

    def getEffectiveLevel(self):
        """
        Get the effective level for the underlying logger.
        """
        return self.logger.getEffectiveLevel()

    def hasHandlers(self):
        """
        See if the underlying logger has any handlers.
        """
        return self.logger.hasHandlers()

    def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False):
        """
        Low-level log implementation, proxied to allow nested logger adapters.
        """
        return self.logger._log(
            level,
            msg,
            args,
            exc_info=exc_info,
            extra=extra,
            stack_info=stack_info,
        )

    @property
    def manager(self):
        return self.logger.manager

    @manager.setter
    def manager(self, value):
        self.logger.manager = value

    @property
    def name(self):
        return self.logger.name

    def __repr__(self):
        logger = self.logger
        level = getLevelName(logger.getEffectiveLevel())
        return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level)

root = RootLogger(WARNING)
Logger.root = root
Logger.manager = Manager(Logger.root)

#---------------------------------------------------------------------------
# Configuration classes and functions
#---------------------------------------------------------------------------

def basicConfig(**kwargs):
    """
    Do basic configuration for the logging system.

    This function does nothing if the root logger already has handlers
    configured. It is a convenience method intended for use by simple scripts
    to do one-shot configuration of the logging package.

    The default behaviour is to create a StreamHandler which writes to
    sys.stderr, set a formatter using the BASIC_FORMAT format string, and
    add the handler to the root logger.

    A number of optional keyword arguments may be specified, which can alter
    the default behaviour.

    filename  Specifies that a FileHandler be created, using the specified
              filename, rather than a StreamHandler.
    filemode  Specifies the mode to open the file, if filename is specified
              (if filemode is unspecified, it defaults to 'a').
    format    Use the specified format string for the handler.
    datefmt   Use the specified date/time format.
    style     If a format string is specified, use this to specify the
              type of format string (possible values '%', '{', '$', for
              %-formatting, :meth:`str.format` and :class:`string.Template`
              - defaults to '%').
    level     Set the root logger level to the specified level.
    stream    Use the specified stream to initialize the StreamHandler. Note
              that this argument is incompatible with 'filename' - if both
              are present, 'stream' is ignored.
    handlers  If specified, this should be an iterable of already created
              handlers, which will be added to the root handler. Any handler
              in the list which does not have a formatter assigned will be
              assigned the formatter created in this function.

    Note that you could specify a stream created using open(filename, mode)
    rather than passing the filename and mode in. However, it should be
    remembered that StreamHandler does not close its stream (since it may be
    using sys.stdout or sys.stderr), whereas FileHandler closes its stream
    when the handler is closed.

    .. versionchanged:: 3.2
       Added the ``style`` parameter.

    .. versionchanged:: 3.3
       Added the ``handlers`` parameter. A ``ValueError`` is now thrown for
       incompatible arguments (e.g. ``handlers`` specified together with
       ``filename``/``filemode``, or ``filename``/``filemode`` specified
       together with ``stream``, or ``handlers`` specified together with
       ``stream``.
    """
    # Add thread safety in case someone mistakenly calls
    # basicConfig() from multiple threads
    _acquireLock()
    try:
        if len(root.handlers) == 0:
            handlers = kwargs.pop("handlers", None)
            if handlers is None:
                if "stream" in kwargs and "filename" in kwargs:
                    raise ValueError("'stream' and 'filename' should not be "
                                     "specified together")
            else:
                if "stream" in kwargs or "filename" in kwargs:
                    raise ValueError("'stream' or 'filename' should not be "
                                     "specified together with 'handlers'")
            if handlers is None:
                filename = kwargs.pop("filename", None)
                mode = kwargs.pop("filemode", 'a')
                if filename:
                    h = FileHandler(filename, mode)
                else:
                    stream = kwargs.pop("stream", None)
                    h = StreamHandler(stream)
                handlers = [h]
            dfs = kwargs.pop("datefmt", None)
            style = kwargs.pop("style", '%')
            if style not in _STYLES:
                raise ValueError('Style must be one of: %s' % ','.join(
                                 _STYLES.keys()))
            fs = kwargs.pop("format", _STYLES[style][1])
            fmt = Formatter(fs, dfs, style)
            for h in handlers:
                if h.formatter is None:
                    h.setFormatter(fmt)
                root.addHandler(h)
            level = kwargs.pop("level", None)
            if level is not None:
                root.setLevel(level)
            if kwargs:
                keys = ', '.join(kwargs.keys())
                raise ValueError('Unrecognised argument(s): %s' % keys)
    finally:
        _releaseLock()

#---------------------------------------------------------------------------
# Utility functions at module level.
# Basically delegate everything to the root logger.
#---------------------------------------------------------------------------

def getLogger(name=None):
    """
    Return a logger with the specified name, creating it if necessary.

    If no name is specified, return the root logger.
    """
    if name:
        return Logger.manager.getLogger(name)
    else:
        return root

def critical(msg, *args, **kwargs):
    """
    Log a message with severity 'CRITICAL' on the root logger. If the logger
    has no handlers, call basicConfig() to add a console handler with a
    pre-defined format.
    """
    if len(root.handlers) == 0:
        basicConfig()
    root.critical(msg, *args, **kwargs)

fatal = critical

def error(msg, *args, **kwargs):
    """
    Log a message with severity 'ERROR' on the root logger. If the logger has
    no handlers, call basicConfig() to add a console handler with a pre-defined
    format.
    """
    if len(root.handlers) == 0:
        basicConfig()
    root.error(msg, *args, **kwargs)

def exception(msg, *args, exc_info=True, **kwargs):
    """
    Log a message with severity 'ERROR' on the root logger, with exception
    information. If the logger has no handlers, basicConfig() is called to add
    a console handler with a pre-defined format.
    """
    error(msg, *args, exc_info=exc_info, **kwargs)

def warning(msg, *args, **kwargs):
    """
    Log a message with severity 'WARNING' on the root logger. If the logger has
    no handlers, call basicConfig() to add a console handler with a pre-defined
    format.
    """
    if len(root.handlers) == 0:
        basicConfig()
    root.warning(msg, *args, **kwargs)

def warn(msg, *args, **kwargs):
    warnings.warn("The 'warn' function is deprecated, "
        "use 'warning' instead", DeprecationWarning, 2)
    warning(msg, *args, **kwargs)

def info(msg, *args, **kwargs):
    """
    Log a message with severity 'INFO' on the root logger. If the logger has
    no handlers, call basicConfig() to add a console handler with a pre-defined
    format.
    """
    if len(root.handlers) == 0:
        basicConfig()
    root.info(msg, *args, **kwargs)

def debug(msg, *args, **kwargs):
    """
    Log a message with severity 'DEBUG' on the root logger. If the logger has
    no handlers, call basicConfig() to add a console handler with a pre-defined
    format.
    """
    if len(root.handlers) == 0:
        basicConfig()
    root.debug(msg, *args, **kwargs)

def log(level, msg, *args, **kwargs):
    """
    Log 'msg % args' with the integer severity 'level' on the root logger. If
    the logger has no handlers, call basicConfig() to add a console handler
    with a pre-defined format.
    """
    if len(root.handlers) == 0:
        basicConfig()
    root.log(level, msg, *args, **kwargs)

def disable(level):
    """
    Disable all logging calls of severity 'level' and below.
    """
    root.manager.disable = level

def shutdown(handlerList=_handlerList):
    """
    Perform any cleanup actions in the logging system (e.g. flushing
    buffers).

    Should be called at application exit.
    """
    for wr in reversed(handlerList[:]):
        #errors might occur, for example, if files are locked
        #we just ignore them if raiseExceptions is not set
        try:
            h = wr()
            if h:
                try:
                    h.acquire()
                    h.flush()
                    h.close()
                except (OSError, ValueError):
                    # Ignore errors which might be caused
                    # because handlers have been closed but
                    # references to them are still around at
                    # application exit.
                    pass
                finally:
                    h.release()
        except: # ignore everything, as we're shutting down
            if raiseExceptions:
                raise
            #else, swallow

#Let's try and shutdown automatically on application exit...
import atexit
atexit.register(shutdown)

# Null handler

class NullHandler(Handler):
    """
    This handler does nothing. It's intended to be used to avoid the
    "No handlers could be found for logger XXX" one-off warning. This is
    important for library code, which may contain code to log events. If a user
    of the library does not configure logging, the one-off warning might be
    produced; to avoid this, the library developer simply needs to instantiate
    a NullHandler and add it to the top-level logger of the library module or
    package.
    """
    def handle(self, record):
        """Stub."""

    def emit(self, record):
        """Stub."""

    def createLock(self):
        self.lock = None

# Warnings integration

_warnings_showwarning = None

def _showwarning(message, category, filename, lineno, file=None, line=None):
    """
    Implementation of showwarnings which redirects to logging, which will first
    check to see if the file parameter is None. If a file is specified, it will
    delegate to the original warnings implementation of showwarning. Otherwise,
    it will call warnings.formatwarning and will log the resulting string to a
    warnings logger named "py.warnings" with level logging.WARNING.
    """
    if file is not None:
        if _warnings_showwarning is not None:
            _warnings_showwarning(message, category, filename, lineno, file, line)
    else:
        s = warnings.formatwarning(message, category, filename, lineno, line)
        logger = getLogger("py.warnings")
        if not logger.handlers:
            logger.addHandler(NullHandler())
        logger.warning("%s", s)

def captureWarnings(capture):
    """
    If capture is true, redirect all warnings to the logging package.
    If capture is False, ensure that warnings are not redirected to logging
    but to their original destinations.
    """
    global _warnings_showwarning
    if capture:
        if _warnings_showwarning is None:
            _warnings_showwarning = warnings.showwarning
            warnings.showwarning = _showwarning
    else:
        if _warnings_showwarning is not None:
            warnings.showwarning = _warnings_showwarning
            _warnings_showwarning = None
================================================ FILE: docs/_build/html/_modules/pathlib.html ================================================ pathlib — CLaF 0.2.0 documentation

Source code for pathlib

import fnmatch
import functools
import io
import ntpath
import os
import posixpath
import re
import sys
from collections import Sequence
from contextlib import contextmanager
from errno import EINVAL, ENOENT, ENOTDIR
from operator import attrgetter
from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
from urllib.parse import quote_from_bytes as urlquote_from_bytes


supports_symlinks = True
if os.name == 'nt':
    import nt
    if sys.getwindowsversion()[:2] >= (6, 0):
        from nt import _getfinalpathname
    else:
        supports_symlinks = False
        _getfinalpathname = None
else:
    nt = None


__all__ = [
    "PurePath", "PurePosixPath", "PureWindowsPath",
    "Path", "PosixPath", "WindowsPath",
    ]

#
# Internals
#

def _is_wildcard_pattern(pat):
    # Whether this pattern needs actual matching using fnmatch, or can
    # be looked up directly as a file.
    return "*" in pat or "?" in pat or "[" in pat


class _Flavour(object):
    """A flavour implements a particular (platform-specific) set of path
    semantics."""

    def __init__(self):
        self.join = self.sep.join

    def parse_parts(self, parts):
        parsed = []
        sep = self.sep
        altsep = self.altsep
        drv = root = ''
        it = reversed(parts)
        for part in it:
            if not part:
                continue
            if altsep:
                part = part.replace(altsep, sep)
            drv, root, rel = self.splitroot(part)
            if sep in rel:
                for x in reversed(rel.split(sep)):
                    if x and x != '.':
                        parsed.append(sys.intern(x))
            else:
                if rel and rel != '.':
                    parsed.append(sys.intern(rel))
            if drv or root:
                if not drv:
                    # If no drive is present, try to find one in the previous
                    # parts. This makes the result of parsing e.g.
                    # ("C:", "/", "a") reasonably intuitive.
                    for part in it:
                        if not part:
                            continue
                        if altsep:
                            part = part.replace(altsep, sep)
                        drv = self.splitroot(part)[0]
                        if drv:
                            break
                break
        if drv or root:
            parsed.append(drv + root)
        parsed.reverse()
        return drv, root, parsed

    def join_parsed_parts(self, drv, root, parts, drv2, root2, parts2):
        """
        Join the two paths represented by the respective
        (drive, root, parts) tuples.  Return a new (drive, root, parts) tuple.
        """
        if root2:
            if not drv2 and drv:
                return drv, root2, [drv + root2] + parts2[1:]
        elif drv2:
            if drv2 == drv or self.casefold(drv2) == self.casefold(drv):
                # Same drive => second path is relative to the first
                return drv, root, parts + parts2[1:]
        else:
            # Second path is non-anchored (common case)
            return drv, root, parts + parts2
        return drv2, root2, parts2


class _WindowsFlavour(_Flavour):
    # Reference for Windows paths can be found at
    # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx

    sep = '\\'
    altsep = '/'
    has_drv = True
    pathmod = ntpath

    is_supported = (os.name == 'nt')

    drive_letters = (
        set(chr(x) for x in range(ord('a'), ord('z') + 1)) |
        set(chr(x) for x in range(ord('A'), ord('Z') + 1))
    )
    ext_namespace_prefix = '\\\\?\\'

    reserved_names = (
        {'CON', 'PRN', 'AUX', 'NUL'} |
        {'COM%d' % i for i in range(1, 10)} |
        {'LPT%d' % i for i in range(1, 10)}
        )

    # Interesting findings about extended paths:
    # - '\\?\c:\a', '//?/c:\a' and '//?/c:/a' are all supported
    #   but '\\?\c:/a' is not
    # - extended paths are always absolute; "relative" extended paths will
    #   fail.

    def splitroot(self, part, sep=sep):
        first = part[0:1]
        second = part[1:2]
        if (second == sep and first == sep):
            # XXX extended paths should also disable the collapsing of "."
            # components (according to MSDN docs).
            prefix, part = self._split_extended_path(part)
            first = part[0:1]
            second = part[1:2]
        else:
            prefix = ''
        third = part[2:3]
        if (second == sep and first == sep and third != sep):
            # is a UNC path:
            # vvvvvvvvvvvvvvvvvvvvv root
            # \\machine\mountpoint\directory\etc\...
            #            directory ^^^^^^^^^^^^^^
            index = part.find(sep, 2)
            if index != -1:
                index2 = part.find(sep, index + 1)
                # a UNC path can't have two slashes in a row
                # (after the initial two)
                if index2 != index + 1:
                    if index2 == -1:
                        index2 = len(part)
                    if prefix:
                        return prefix + part[1:index2], sep, part[index2+1:]
                    else:
                        return part[:index2], sep, part[index2+1:]
        drv = root = ''
        if second == ':' and first in self.drive_letters:
            drv = part[:2]
            part = part[2:]
            first = third
        if first == sep:
            root = first
            part = part.lstrip(sep)
        return prefix + drv, root, part

    def casefold(self, s):
        return s.lower()

    def casefold_parts(self, parts):
        return [p.lower() for p in parts]

    def resolve(self, path, strict=False):
        s = str(path)
        if not s:
            return os.getcwd()
        previous_s = None
        if _getfinalpathname is not None:
            if strict:
                return self._ext_to_normal(_getfinalpathname(s))
            else:
                tail_parts = []  # End of the path after the first one not found
                while True:
                    try:
                        s = self._ext_to_normal(_getfinalpathname(s))
                    except FileNotFoundError:
                        previous_s = s
                        s, tail = os.path.split(s)
                        tail_parts.append(tail)
                        if previous_s == s:
                            return path
                    else:
                        return os.path.join(s, *reversed(tail_parts))
        # Means fallback on absolute
        return None

    def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix):
        prefix = ''
        if s.startswith(ext_prefix):
            prefix = s[:4]
            s = s[4:]
            if s.startswith('UNC\\'):
                prefix += s[:3]
                s = '\\' + s[3:]
        return prefix, s

    def _ext_to_normal(self, s):
        # Turn back an extended path into a normal DOS-like path
        return self._split_extended_path(s)[1]

    def is_reserved(self, parts):
        # NOTE: the rules for reserved names seem somewhat complicated
        # (e.g. r"..\NUL" is reserved but not r"foo\NUL").
        # We err on the side of caution and return True for paths which are
        # not considered reserved by Windows.
        if not parts:
            return False
        if parts[0].startswith('\\\\'):
            # UNC paths are never reserved
            return False
        return parts[-1].partition('.')[0].upper() in self.reserved_names

    def make_uri(self, path):
        # Under Windows, file URIs use the UTF-8 encoding.
        drive = path.drive
        if len(drive) == 2 and drive[1] == ':':
            # It's a path on a local drive => 'file:///c:/a/b'
            rest = path.as_posix()[2:].lstrip('/')
            return 'file:///%s/%s' % (
                drive, urlquote_from_bytes(rest.encode('utf-8')))
        else:
            # It's a path on a network drive => 'file://host/share/a/b'
            return 'file:' + urlquote_from_bytes(path.as_posix().encode('utf-8'))

    def gethomedir(self, username):
        if 'HOME' in os.environ:
            userhome = os.environ['HOME']
        elif 'USERPROFILE' in os.environ:
            userhome = os.environ['USERPROFILE']
        elif 'HOMEPATH' in os.environ:
            try:
                drv = os.environ['HOMEDRIVE']
            except KeyError:
                drv = ''
            userhome = drv + os.environ['HOMEPATH']
        else:
            raise RuntimeError("Can't determine home directory")

        if username:
            # Try to guess user home directory.  By default all users
            # directories are located in the same place and are named by
            # corresponding usernames.  If current user home directory points
            # to nonstandard place, this guess is likely wrong.
            if os.environ['USERNAME'] != username:
                drv, root, parts = self.parse_parts((userhome,))
                if parts[-1] != os.environ['USERNAME']:
                    raise RuntimeError("Can't determine home directory "
                                       "for %r" % username)
                parts[-1] = username
                if drv or root:
                    userhome = drv + root + self.join(parts[1:])
                else:
                    userhome = self.join(parts)
        return userhome

class _PosixFlavour(_Flavour):
    sep = '/'
    altsep = ''
    has_drv = False
    pathmod = posixpath

    is_supported = (os.name != 'nt')

    def splitroot(self, part, sep=sep):
        if part and part[0] == sep:
            stripped_part = part.lstrip(sep)
            # According to POSIX path resolution:
            # http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04_11
            # "A pathname that begins with two successive slashes may be
            # interpreted in an implementation-defined manner, although more
            # than two leading slashes shall be treated as a single slash".
            if len(part) - len(stripped_part) == 2:
                return '', sep * 2, stripped_part
            else:
                return '', sep, stripped_part
        else:
            return '', '', part

    def casefold(self, s):
        return s

    def casefold_parts(self, parts):
        return parts

    def resolve(self, path, strict=False):
        sep = self.sep
        accessor = path._accessor
        seen = {}
        def _resolve(path, rest):
            if rest.startswith(sep):
                path = ''

            for name in rest.split(sep):
                if not name or name == '.':
                    # current dir
                    continue
                if name == '..':
                    # parent dir
                    path, _, _ = path.rpartition(sep)
                    continue
                newpath = path + sep + name
                if newpath in seen:
                    # Already seen this path
                    path = seen[newpath]
                    if path is not None:
                        # use cached value
                        continue
                    # The symlink is not resolved, so we must have a symlink loop.
                    raise RuntimeError("Symlink loop from %r" % newpath)
                # Resolve the symbolic link
                try:
                    target = accessor.readlink(newpath)
                except OSError as e:
                    if e.errno != EINVAL and strict:
                        raise
                    # Not a symlink, or non-strict mode. We just leave the path
                    # untouched.
                    path = newpath
                else:
                    seen[newpath] = None # not resolved symlink
                    path = _resolve(path, target)
                    seen[newpath] = path # resolved symlink

            return path
        # NOTE: according to POSIX, getcwd() cannot contain path components
        # which are symlinks.
        base = '' if path.is_absolute() else os.getcwd()
        return _resolve(base, str(path)) or sep

    def is_reserved(self, parts):
        return False

    def make_uri(self, path):
        # We represent the path using the local filesystem encoding,
        # for portability to other applications.
        bpath = bytes(path)
        return 'file://' + urlquote_from_bytes(bpath)

    def gethomedir(self, username):
        if not username:
            try:
                return os.environ['HOME']
            except KeyError:
                import pwd
                return pwd.getpwuid(os.getuid()).pw_dir
        else:
            import pwd
            try:
                return pwd.getpwnam(username).pw_dir
            except KeyError:
                raise RuntimeError("Can't determine home directory "
                                   "for %r" % username)


_windows_flavour = _WindowsFlavour()
_posix_flavour = _PosixFlavour()


class _Accessor:
    """An accessor implements a particular (system-specific or not) way of
    accessing paths on the filesystem."""


class _NormalAccessor(_Accessor):

    def _wrap_strfunc(strfunc):
        @functools.wraps(strfunc)
        def wrapped(pathobj, *args):
            return strfunc(str(pathobj), *args)
        return staticmethod(wrapped)

    def _wrap_binary_strfunc(strfunc):
        @functools.wraps(strfunc)
        def wrapped(pathobjA, pathobjB, *args):
            return strfunc(str(pathobjA), str(pathobjB), *args)
        return staticmethod(wrapped)

    stat = _wrap_strfunc(os.stat)

    lstat = _wrap_strfunc(os.lstat)

    open = _wrap_strfunc(os.open)

    listdir = _wrap_strfunc(os.listdir)

    scandir = _wrap_strfunc(os.scandir)

    chmod = _wrap_strfunc(os.chmod)

    if hasattr(os, "lchmod"):
        lchmod = _wrap_strfunc(os.lchmod)
    else:
        def lchmod(self, pathobj, mode):
            raise NotImplementedError("lchmod() not available on this system")

    mkdir = _wrap_strfunc(os.mkdir)

    unlink = _wrap_strfunc(os.unlink)

    rmdir = _wrap_strfunc(os.rmdir)

    rename = _wrap_binary_strfunc(os.rename)

    replace = _wrap_binary_strfunc(os.replace)

    if nt:
        if supports_symlinks:
            symlink = _wrap_binary_strfunc(os.symlink)
        else:
            def symlink(a, b, target_is_directory):
                raise NotImplementedError("symlink() not available on this system")
    else:
        # Under POSIX, os.symlink() takes two args
        @staticmethod
        def symlink(a, b, target_is_directory):
            return os.symlink(str(a), str(b))

    utime = _wrap_strfunc(os.utime)

    # Helper for resolve()
    def readlink(self, path):
        return os.readlink(path)


_normal_accessor = _NormalAccessor()


#
# Globbing helpers
#

def _make_selector(pattern_parts):
    pat = pattern_parts[0]
    child_parts = pattern_parts[1:]
    if pat == '**':
        cls = _RecursiveWildcardSelector
    elif '**' in pat:
        raise ValueError("Invalid pattern: '**' can only be an entire path component")
    elif _is_wildcard_pattern(pat):
        cls = _WildcardSelector
    else:
        cls = _PreciseSelector
    return cls(pat, child_parts)

if hasattr(functools, "lru_cache"):
    _make_selector = functools.lru_cache()(_make_selector)


class _Selector:
    """A selector matches a specific glob pattern part against the children
    of a given path."""

    def __init__(self, child_parts):
        self.child_parts = child_parts
        if child_parts:
            self.successor = _make_selector(child_parts)
            self.dironly = True
        else:
            self.successor = _TerminatingSelector()
            self.dironly = False

    def select_from(self, parent_path):
        """Iterate over all child paths of `parent_path` matched by this
        selector.  This can contain parent_path itself."""
        path_cls = type(parent_path)
        is_dir = path_cls.is_dir
        exists = path_cls.exists
        scandir = parent_path._accessor.scandir
        if not is_dir(parent_path):
            return iter([])
        return self._select_from(parent_path, is_dir, exists, scandir)


class _TerminatingSelector:

    def _select_from(self, parent_path, is_dir, exists, scandir):
        yield parent_path


class _PreciseSelector(_Selector):

    def __init__(self, name, child_parts):
        self.name = name
        _Selector.__init__(self, child_parts)

    def _select_from(self, parent_path, is_dir, exists, scandir):
        try:
            path = parent_path._make_child_relpath(self.name)
            if (is_dir if self.dironly else exists)(path):
                for p in self.successor._select_from(path, is_dir, exists, scandir):
                    yield p
        except PermissionError:
            return


class _WildcardSelector(_Selector):

    def __init__(self, pat, child_parts):
        self.pat = re.compile(fnmatch.translate(pat))
        _Selector.__init__(self, child_parts)

    def _select_from(self, parent_path, is_dir, exists, scandir):
        try:
            cf = parent_path._flavour.casefold
            entries = list(scandir(parent_path))
            for entry in entries:
                if not self.dironly or entry.is_dir():
                    name = entry.name
                    casefolded = cf(name)
                    if self.pat.match(casefolded):
                        path = parent_path._make_child_relpath(name)
                        for p in self.successor._select_from(path, is_dir, exists, scandir):
                            yield p
        except PermissionError:
            return



class _RecursiveWildcardSelector(_Selector):

    def __init__(self, pat, child_parts):
        _Selector.__init__(self, child_parts)

    def _iterate_directories(self, parent_path, is_dir, scandir):
        yield parent_path
        try:
            entries = list(scandir(parent_path))
            for entry in entries:
                if entry.is_dir() and not entry.is_symlink():
                    path = parent_path._make_child_relpath(entry.name)
                    for p in self._iterate_directories(path, is_dir, scandir):
                        yield p
        except PermissionError:
            return

    def _select_from(self, parent_path, is_dir, exists, scandir):
        try:
            yielded = set()
            try:
                successor_select = self.successor._select_from
                for starting_point in self._iterate_directories(parent_path, is_dir, scandir):
                    for p in successor_select(starting_point, is_dir, exists, scandir):
                        if p not in yielded:
                            yield p
                            yielded.add(p)
            finally:
                yielded.clear()
        except PermissionError:
            return


#
# Public API
#

class _PathParents(Sequence):
    """This object provides sequence-like access to the logical ancestors
    of a path.  Don't try to construct it yourself."""
    __slots__ = ('_pathcls', '_drv', '_root', '_parts')

    def __init__(self, path):
        # We don't store the instance to avoid reference cycles
        self._pathcls = type(path)
        self._drv = path._drv
        self._root = path._root
        self._parts = path._parts

    def __len__(self):
        if self._drv or self._root:
            return len(self._parts) - 1
        else:
            return len(self._parts)

    def __getitem__(self, idx):
        if idx < 0 or idx >= len(self):
            raise IndexError(idx)
        return self._pathcls._from_parsed_parts(self._drv, self._root,
                                                self._parts[:-idx - 1])

    def __repr__(self):
        return "<{}.parents>".format(self._pathcls.__name__)


class PurePath(object):
    """Base class for manipulating paths without I/O.

    PurePath represents a filesystem path and offers operations which
    don't imply any actual filesystem I/O.  Depending on your system,
    instantiating a PurePath will return either a PurePosixPath or a
    PureWindowsPath object.  You can also instantiate either of these classes
    directly, regardless of your system.
    """
    __slots__ = (
        '_drv', '_root', '_parts',
        '_str', '_hash', '_pparts', '_cached_cparts',
    )

    def __new__(cls, *args):
        """Construct a PurePath from one or several strings and or existing
        PurePath objects.  The strings and path objects are combined so as
        to yield a canonicalized path, which is incorporated into the
        new PurePath object.
        """
        if cls is PurePath:
            cls = PureWindowsPath if os.name == 'nt' else PurePosixPath
        return cls._from_parts(args)

    def __reduce__(self):
        # Using the parts tuple helps share interned path parts
        # when pickling related paths.
        return (self.__class__, tuple(self._parts))

    @classmethod
    def _parse_args(cls, args):
        # This is useful when you don't want to create an instance, just
        # canonicalize some constructor arguments.
        parts = []
        for a in args:
            if isinstance(a, PurePath):
                parts += a._parts
            else:
                a = os.fspath(a)
                if isinstance(a, str):
                    # Force-cast str subclasses to str (issue #21127)
                    parts.append(str(a))
                else:
                    raise TypeError(
                        "argument should be a str object or an os.PathLike "
                        "object returning str, not %r"
                        % type(a))
        return cls._flavour.parse_parts(parts)

    @classmethod
    def _from_parts(cls, args, init=True):
        # We need to call _parse_args on the instance, so as to get the
        # right flavour.
        self = object.__new__(cls)
        drv, root, parts = self._parse_args(args)
        self._drv = drv
        self._root = root
        self._parts = parts
        if init:
            self._init()
        return self

    @classmethod
    def _from_parsed_parts(cls, drv, root, parts, init=True):
        self = object.__new__(cls)
        self._drv = drv
        self._root = root
        self._parts = parts
        if init:
            self._init()
        return self

    @classmethod
    def _format_parsed_parts(cls, drv, root, parts):
        if drv or root:
            return drv + root + cls._flavour.join(parts[1:])
        else:
            return cls._flavour.join(parts)

    def _init(self):
        # Overridden in concrete Path
        pass

    def _make_child(self, args):
        drv, root, parts = self._parse_args(args)
        drv, root, parts = self._flavour.join_parsed_parts(
            self._drv, self._root, self._parts, drv, root, parts)
        return self._from_parsed_parts(drv, root, parts)

    def __str__(self):
        """Return the string representation of the path, suitable for
        passing to system calls."""
        try:
            return self._str
        except AttributeError:
            self._str = self._format_parsed_parts(self._drv, self._root,
                                                  self._parts) or '.'
            return self._str

    def __fspath__(self):
        return str(self)

    def as_posix(self):
        """Return the string representation of the path with forward (/)
        slashes."""
        f = self._flavour
        return str(self).replace(f.sep, '/')

    def __bytes__(self):
        """Return the bytes representation of the path.  This is only
        recommended to use under Unix."""
        return os.fsencode(str(self))

    def __repr__(self):
        return "{}({!r})".format(self.__class__.__name__, self.as_posix())

    def as_uri(self):
        """Return the path as a 'file' URI."""
        if not self.is_absolute():
            raise ValueError("relative path can't be expressed as a file URI")
        return self._flavour.make_uri(self)

    @property
    def _cparts(self):
        # Cached casefolded parts, for hashing and comparison
        try:
            return self._cached_cparts
        except AttributeError:
            self._cached_cparts = self._flavour.casefold_parts(self._parts)
            return self._cached_cparts

    def __eq__(self, other):
        if not isinstance(other, PurePath):
            return NotImplemented
        return self._cparts == other._cparts and self._flavour is other._flavour

    def __hash__(self):
        try:
            return self._hash
        except AttributeError:
            self._hash = hash(tuple(self._cparts))
            return self._hash

    def __lt__(self, other):
        if not isinstance(other, PurePath) or self._flavour is not other._flavour:
            return NotImplemented
        return self._cparts < other._cparts

    def __le__(self, other):
        if not isinstance(other, PurePath) or self._flavour is not other._flavour:
            return NotImplemented
        return self._cparts <= other._cparts

    def __gt__(self, other):
        if not isinstance(other, PurePath) or self._flavour is not other._flavour:
            return NotImplemented
        return self._cparts > other._cparts

    def __ge__(self, other):
        if not isinstance(other, PurePath) or self._flavour is not other._flavour:
            return NotImplemented
        return self._cparts >= other._cparts

    drive = property(attrgetter('_drv'),
                     doc="""The drive prefix (letter or UNC path), if any.""")

    root = property(attrgetter('_root'),
                    doc="""The root of the path, if any.""")

    @property
    def anchor(self):
        """The concatenation of the drive and root, or ''."""
        anchor = self._drv + self._root
        return anchor

    @property
    def name(self):
        """The final path component, if any."""
        parts = self._parts
        if len(parts) == (1 if (self._drv or self._root) else 0):
            return ''
        return parts[-1]

    @property
    def suffix(self):
        """The final component's last suffix, if any."""
        name = self.name
        i = name.rfind('.')
        if 0 < i < len(name) - 1:
            return name[i:]
        else:
            return ''

    @property
    def suffixes(self):
        """A list of the final component's suffixes, if any."""
        name = self.name
        if name.endswith('.'):
            return []
        name = name.lstrip('.')
        return ['.' + suffix for suffix in name.split('.')[1:]]

    @property
    def stem(self):
        """The final path component, minus its last suffix."""
        name = self.name
        i = name.rfind('.')
        if 0 < i < len(name) - 1:
            return name[:i]
        else:
            return name

    def with_name(self, name):
        """Return a new path with the file name changed."""
        if not self.name:
            raise ValueError("%r has an empty name" % (self,))
        drv, root, parts = self._flavour.parse_parts((name,))
        if (not name or name[-1] in [self._flavour.sep, self._flavour.altsep]
            or drv or root or len(parts) != 1):
            raise ValueError("Invalid name %r" % (name))
        return self._from_parsed_parts(self._drv, self._root,
                                       self._parts[:-1] + [name])

    def with_suffix(self, suffix):
        """Return a new path with the file suffix changed.  If the path
        has no suffix, add given suffix.  If the given suffix is an empty
        string, remove the suffix from the path.
        """
        f = self._flavour
        if f.sep in suffix or f.altsep and f.altsep in suffix:
            raise ValueError("Invalid suffix %r" % (suffix))
        if suffix and not suffix.startswith('.') or suffix == '.':
            raise ValueError("Invalid suffix %r" % (suffix))
        name = self.name
        if not name:
            raise ValueError("%r has an empty name" % (self,))
        old_suffix = self.suffix
        if not old_suffix:
            name = name + suffix
        else:
            name = name[:-len(old_suffix)] + suffix
        return self._from_parsed_parts(self._drv, self._root,
                                       self._parts[:-1] + [name])

    def relative_to(self, *other):
        """Return the relative path to another path identified by the passed
        arguments.  If the operation is not possible (because this is not
        a subpath of the other path), raise ValueError.
        """
        # For the purpose of this method, drive and root are considered
        # separate parts, i.e.:
        #   Path('c:/').relative_to('c:')  gives Path('/')
        #   Path('c:/').relative_to('/')   raise ValueError
        if not other:
            raise TypeError("need at least one argument")
        parts = self._parts
        drv = self._drv
        root = self._root
        if root:
            abs_parts = [drv, root] + parts[1:]
        else:
            abs_parts = parts
        to_drv, to_root, to_parts = self._parse_args(other)
        if to_root:
            to_abs_parts = [to_drv, to_root] + to_parts[1:]
        else:
            to_abs_parts = to_parts
        n = len(to_abs_parts)
        cf = self._flavour.casefold_parts
        if (root or drv) if n == 0 else cf(abs_parts[:n]) != cf(to_abs_parts):
            formatted = self._format_parsed_parts(to_drv, to_root, to_parts)
            raise ValueError("{!r} does not start with {!r}"
                             .format(str(self), str(formatted)))
        return self._from_parsed_parts('', root if n == 1 else '',
                                       abs_parts[n:])

    @property
    def parts(self):
        """An object providing sequence-like access to the
        components in the filesystem path."""
        # We cache the tuple to avoid building a new one each time .parts
        # is accessed.  XXX is this necessary?
        try:
            return self._pparts
        except AttributeError:
            self._pparts = tuple(self._parts)
            return self._pparts

    def joinpath(self, *args):
        """Combine this path with one or several arguments, and return a
        new path representing either a subpath (if all arguments are relative
        paths) or a totally different path (if one of the arguments is
        anchored).
        """
        return self._make_child(args)

    def __truediv__(self, key):
        return self._make_child((key,))

    def __rtruediv__(self, key):
        return self._from_parts([key] + self._parts)

    @property
    def parent(self):
        """The logical parent of the path."""
        drv = self._drv
        root = self._root
        parts = self._parts
        if len(parts) == 1 and (drv or root):
            return self
        return self._from_parsed_parts(drv, root, parts[:-1])

    @property
    def parents(self):
        """A sequence of this path's logical parents."""
        return _PathParents(self)

    def is_absolute(self):
        """True if the path is absolute (has both a root and, if applicable,
        a drive)."""
        if not self._root:
            return False
        return not self._flavour.has_drv or bool(self._drv)

    def is_reserved(self):
        """Return True if the path contains one of the special names reserved
        by the system, if any."""
        return self._flavour.is_reserved(self._parts)

    def match(self, path_pattern):
        """
        Return True if this path matches the given pattern.
        """
        cf = self._flavour.casefold
        path_pattern = cf(path_pattern)
        drv, root, pat_parts = self._flavour.parse_parts((path_pattern,))
        if not pat_parts:
            raise ValueError("empty pattern")
        if drv and drv != cf(self._drv):
            return False
        if root and root != cf(self._root):
            return False
        parts = self._cparts
        if drv or root:
            if len(pat_parts) != len(parts):
                return False
            pat_parts = pat_parts[1:]
        elif len(pat_parts) > len(parts):
            return False
        for part, pat in zip(reversed(parts), reversed(pat_parts)):
            if not fnmatch.fnmatchcase(part, pat):
                return False
        return True

# Can't subclass os.PathLike from PurePath and keep the constructor
# optimizations in PurePath._parse_args().
os.PathLike.register(PurePath)


class PurePosixPath(PurePath):
    """PurePath subclass for non-Windows systems.

    On a POSIX system, instantiating a PurePath should return this object.
    However, you can also instantiate it directly on any system.
    """
    _flavour = _posix_flavour
    __slots__ = ()


class PureWindowsPath(PurePath):
    """PurePath subclass for Windows systems.

    On a Windows system, instantiating a PurePath should return this object.
    However, you can also instantiate it directly on any system.
    """
    _flavour = _windows_flavour
    __slots__ = ()


# Filesystem-accessing classes


class Path(PurePath):
    """PurePath subclass that can make system calls.

    Path represents a filesystem path but unlike PurePath, also offers
    methods to do system calls on path objects. Depending on your system,
    instantiating a Path will return either a PosixPath or a WindowsPath
    object. You can also instantiate a PosixPath or WindowsPath directly,
    but cannot instantiate a WindowsPath on a POSIX system or vice versa.
    """
    __slots__ = (
        '_accessor',
        '_closed',
    )

    def __new__(cls, *args, **kwargs):
        if cls is Path:
            cls = WindowsPath if os.name == 'nt' else PosixPath
        self = cls._from_parts(args, init=False)
        if not self._flavour.is_supported:
            raise NotImplementedError("cannot instantiate %r on your system"
                                      % (cls.__name__,))
        self._init()
        return self

    def _init(self,
              # Private non-constructor arguments
              template=None,
              ):
        self._closed = False
        if template is not None:
            self._accessor = template._accessor
        else:
            self._accessor = _normal_accessor

    def _make_child_relpath(self, part):
        # This is an optimization used for dir walking.  `part` must be
        # a single part relative to this path.
        parts = self._parts + [part]
        return self._from_parsed_parts(self._drv, self._root, parts)

    def __enter__(self):
        if self._closed:
            self._raise_closed()
        return self

    def __exit__(self, t, v, tb):
        self._closed = True

    def _raise_closed(self):
        raise ValueError("I/O operation on closed path")

    def _opener(self, name, flags, mode=0o666):
        # A stub for the opener argument to built-in open()
        return self._accessor.open(self, flags, mode)

    def _raw_open(self, flags, mode=0o777):
        """
        Open the file pointed by this path and return a file descriptor,
        as os.open() does.
        """
        if self._closed:
            self._raise_closed()
        return self._accessor.open(self, flags, mode)

    # Public API

    @classmethod
    def cwd(cls):
        """Return a new path pointing to the current working directory
        (as returned by os.getcwd()).
        """
        return cls(os.getcwd())

    @classmethod
    def home(cls):
        """Return a new path pointing to the user's home directory (as
        returned by os.path.expanduser('~')).
        """
        return cls(cls()._flavour.gethomedir(None))

    def samefile(self, other_path):
        """Return whether other_path is the same or not as this file
        (as returned by os.path.samefile()).
        """
        st = self.stat()
        try:
            other_st = other_path.stat()
        except AttributeError:
            other_st = os.stat(other_path)
        return os.path.samestat(st, other_st)

    def iterdir(self):
        """Iterate over the files in this directory.  Does not yield any
        result for the special paths '.' and '..'.
        """
        if self._closed:
            self._raise_closed()
        for name in self._accessor.listdir(self):
            if name in {'.', '..'}:
                # Yielding a path object for these makes little sense
                continue
            yield self._make_child_relpath(name)
            if self._closed:
                self._raise_closed()

    def glob(self, pattern):
        """Iterate over this subtree and yield all existing files (of any
        kind, including directories) matching the given pattern.
        """
        if not pattern:
            raise ValueError("Unacceptable pattern: {!r}".format(pattern))
        pattern = self._flavour.casefold(pattern)
        drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
        if drv or root:
            raise NotImplementedError("Non-relative patterns are unsupported")
        selector = _make_selector(tuple(pattern_parts))
        for p in selector.select_from(self):
            yield p

    def rglob(self, pattern):
        """Recursively yield all existing files (of any kind, including
        directories) matching the given pattern, anywhere in this subtree.
        """
        pattern = self._flavour.casefold(pattern)
        drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
        if drv or root:
            raise NotImplementedError("Non-relative patterns are unsupported")
        selector = _make_selector(("**",) + tuple(pattern_parts))
        for p in selector.select_from(self):
            yield p

    def absolute(self):
        """Return an absolute version of this path.  This function works
        even if the path doesn't point to anything.

        No normalization is done, i.e. all '.' and '..' will be kept along.
        Use resolve() to get the canonical path to a file.
        """
        # XXX untested yet!
        if self._closed:
            self._raise_closed()
        if self.is_absolute():
            return self
        # FIXME this must defer to the specific flavour (and, under Windows,
        # use nt._getfullpathname())
        obj = self._from_parts([os.getcwd()] + self._parts, init=False)
        obj._init(template=self)
        return obj

    def resolve(self, strict=False):
        """
        Make the path absolute, resolving all symlinks on the way and also
        normalizing it (for example turning slashes into backslashes under
        Windows).
        """
        if self._closed:
            self._raise_closed()
        s = self._flavour.resolve(self, strict=strict)
        if s is None:
            # No symlink resolution => for consistency, raise an error if
            # the path doesn't exist or is forbidden
            self.stat()
            s = str(self.absolute())
        # Now we have no symlinks in the path, it's safe to normalize it.
        normed = self._flavour.pathmod.normpath(s)
        obj = self._from_parts((normed,), init=False)
        obj._init(template=self)
        return obj

    def stat(self):
        """
        Return the result of the stat() system call on this path, like
        os.stat() does.
        """
        return self._accessor.stat(self)

    def owner(self):
        """
        Return the login name of the file owner.
        """
        import pwd
        return pwd.getpwuid(self.stat().st_uid).pw_name

    def group(self):
        """
        Return the group name of the file gid.
        """
        import grp
        return grp.getgrgid(self.stat().st_gid).gr_name

    def open(self, mode='r', buffering=-1, encoding=None,
             errors=None, newline=None):
        """
        Open the file pointed by this path and return a file object, as
        the built-in open() function does.
        """
        if self._closed:
            self._raise_closed()
        return io.open(str(self), mode, buffering, encoding, errors, newline,
                       opener=self._opener)

    def read_bytes(self):
        """
        Open the file in bytes mode, read it, and close the file.
        """
        with self.open(mode='rb') as f:
            return f.read()

    def read_text(self, encoding=None, errors=None):
        """
        Open the file in text mode, read it, and close the file.
        """
        with self.open(mode='r', encoding=encoding, errors=errors) as f:
            return f.read()

    def write_bytes(self, data):
        """
        Open the file in bytes mode, write to it, and close the file.
        """
        # type-check for the buffer interface before truncating the file
        view = memoryview(data)
        with self.open(mode='wb') as f:
            return f.write(view)

    def write_text(self, data, encoding=None, errors=None):
        """
        Open the file in text mode, write to it, and close the file.
        """
        if not isinstance(data, str):
            raise TypeError('data must be str, not %s' %
                            data.__class__.__name__)
        with self.open(mode='w', encoding=encoding, errors=errors) as f:
            return f.write(data)

    def touch(self, mode=0o666, exist_ok=True):
        """
        Create this file with the given access mode, if it doesn't exist.
        """
        if self._closed:
            self._raise_closed()
        if exist_ok:
            # First try to bump modification time
            # Implementation note: GNU touch uses the UTIME_NOW option of
            # the utimensat() / futimens() functions.
            try:
                self._accessor.utime(self, None)
            except OSError:
                # Avoid exception chaining
                pass
            else:
                return
        flags = os.O_CREAT | os.O_WRONLY
        if not exist_ok:
            flags |= os.O_EXCL
        fd = self._raw_open(flags, mode)
        os.close(fd)

    def mkdir(self, mode=0o777, parents=False, exist_ok=False):
        """
        Create a new directory at this given path.
        """
        if self._closed:
            self._raise_closed()
        try:
            self._accessor.mkdir(self, mode)
        except FileNotFoundError:
            if not parents or self.parent == self:
                raise
            self.parent.mkdir(parents=True, exist_ok=True)
            self.mkdir(mode, parents=False, exist_ok=exist_ok)
        except OSError:
            # Cannot rely on checking for EEXIST, since the operating system
            # could give priority to other errors like EACCES or EROFS
            if not exist_ok or not self.is_dir():
                raise

    def chmod(self, mode):
        """
        Change the permissions of the path, like os.chmod().
        """
        if self._closed:
            self._raise_closed()
        self._accessor.chmod(self, mode)

    def lchmod(self, mode):
        """
        Like chmod(), except if the path points to a symlink, the symlink's
        permissions are changed, rather than its target's.
        """
        if self._closed:
            self._raise_closed()
        self._accessor.lchmod(self, mode)

    def unlink(self):
        """
        Remove this file or link.
        If the path is a directory, use rmdir() instead.
        """
        if self._closed:
            self._raise_closed()
        self._accessor.unlink(self)

    def rmdir(self):
        """
        Remove this directory.  The directory must be empty.
        """
        if self._closed:
            self._raise_closed()
        self._accessor.rmdir(self)

    def lstat(self):
        """
        Like stat(), except if the path points to a symlink, the symlink's
        status information is returned, rather than its target's.
        """
        if self._closed:
            self._raise_closed()
        return self._accessor.lstat(self)

    def rename(self, target):
        """
        Rename this path to the given path.
        """
        if self._closed:
            self._raise_closed()
        self._accessor.rename(self, target)

    def replace(self, target):
        """
        Rename this path to the given path, clobbering the existing
        destination if it exists.
        """
        if self._closed:
            self._raise_closed()
        self._accessor.replace(self, target)

    def symlink_to(self, target, target_is_directory=False):
        """
        Make this path a symlink pointing to the given path.
        Note the order of arguments (self, target) is the reverse of os.symlink's.
        """
        if self._closed:
            self._raise_closed()
        self._accessor.symlink(target, self, target_is_directory)

    # Convenience functions for querying the stat results

    def exists(self):
        """
        Whether this path exists.
        """
        try:
            self.stat()
        except OSError as e:
            if e.errno not in (ENOENT, ENOTDIR):
                raise
            return False
        return True

    def is_dir(self):
        """
        Whether this path is a directory.
        """
        try:
            return S_ISDIR(self.stat().st_mode)
        except OSError as e:
            if e.errno not in (ENOENT, ENOTDIR):
                raise
            # Path doesn't exist or is a broken symlink
            # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
            return False

    def is_file(self):
        """
        Whether this path is a regular file (also True for symlinks pointing
        to regular files).
        """
        try:
            return S_ISREG(self.stat().st_mode)
        except OSError as e:
            if e.errno not in (ENOENT, ENOTDIR):
                raise
            # Path doesn't exist or is a broken symlink
            # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
            return False

    def is_symlink(self):
        """
        Whether this path is a symbolic link.
        """
        try:
            return S_ISLNK(self.lstat().st_mode)
        except OSError as e:
            if e.errno not in (ENOENT, ENOTDIR):
                raise
            # Path doesn't exist
            return False

    def is_block_device(self):
        """
        Whether this path is a block device.
        """
        try:
            return S_ISBLK(self.stat().st_mode)
        except OSError as e:
            if e.errno not in (ENOENT, ENOTDIR):
                raise
            # Path doesn't exist or is a broken symlink
            # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
            return False

    def is_char_device(self):
        """
        Whether this path is a character device.
        """
        try:
            return S_ISCHR(self.stat().st_mode)
        except OSError as e:
            if e.errno not in (ENOENT, ENOTDIR):
                raise
            # Path doesn't exist or is a broken symlink
            # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
            return False

    def is_fifo(self):
        """
        Whether this path is a FIFO.
        """
        try:
            return S_ISFIFO(self.stat().st_mode)
        except OSError as e:
            if e.errno not in (ENOENT, ENOTDIR):
                raise
            # Path doesn't exist or is a broken symlink
            # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
            return False

    def is_socket(self):
        """
        Whether this path is a socket.
        """
        try:
            return S_ISSOCK(self.stat().st_mode)
        except OSError as e:
            if e.errno not in (ENOENT, ENOTDIR):
                raise
            # Path doesn't exist or is a broken symlink
            # (see https://bitbucket.org/pitrou/pathlib/issue/12/)
            return False

    def expanduser(self):
        """ Return a new path with expanded ~ and ~user constructs
        (as returned by os.path.expanduser)
        """
        if (not (self._drv or self._root) and
            self._parts and self._parts[0][:1] == '~'):
            homedir = self._flavour.gethomedir(self._parts[0][1:])
            return self._from_parts([homedir] + self._parts[1:])

        return self


class PosixPath(Path, PurePosixPath):
    """Path subclass for non-Windows systems.

    On a POSIX system, instantiating a Path should return this object.
    """
    __slots__ = ()

class WindowsPath(Path, PureWindowsPath):
    """Path subclass for Windows systems.

    On a Windows system, instantiating a Path should return this object.
    """
    __slots__ = ()

    def owner(self):
        raise NotImplementedError("Path.owner() is unsupported on this system")

    def group(self):
        raise NotImplementedError("Path.group() is unsupported on this system")
================================================ FILE: docs/_build/html/_sources/claf.config.factory.rst.txt ================================================ claf.config.factory package =========================== Submodules ---------- .. automodule:: claf.config.factory.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.data_loader :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.data_reader :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.model :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.optimizer :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.tokens :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.config.factory :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.config.rst.txt ================================================ claf.config package =================== Subpackages ----------- .. toctree:: claf.config.factory Submodules ---------- .. automodule:: claf.config.args :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.namespace :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.pattern :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.registry :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.config :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.data.dataset.rst.txt ================================================ claf.data.dataset package ========================= Submodules ---------- .. automodule:: claf.data.dataset.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.seq_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.seq_cls_bert :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.squad :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.squad_bert :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.tok_cls_bert :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.wikisql :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.data.dataset :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.data.reader.bert.rst.txt ================================================ claf.data.reader.bert package ============================= Submodules ---------- .. automodule:: claf.data.reader.bert.cola :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.bert.conll2003 :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.bert.seq_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.bert.squad :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.bert.tok_cls :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.data.reader.bert :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.data.reader.rst.txt ================================================ claf.data.reader package ======================== Subpackages ----------- .. toctree:: claf.data.reader.bert Submodules ---------- .. automodule:: claf.data.reader.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.cola :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.seq_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.squad :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.wikisql :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.data.reader :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.data.rst.txt ================================================ claf.data package ================= Subpackages ----------- .. toctree:: claf.data.dataset claf.data.reader Submodules ---------- .. automodule:: claf.data.batch :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.collate :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.data_handler :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.data :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.decorator.rst.txt ================================================ claf.decorator package ====================== Submodules ---------- .. automodule:: claf.decorator.arguments :members: :undoc-members: :show-inheritance: .. automodule:: claf.decorator.register :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.decorator :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.learn.rst.txt ================================================ claf.learn package ================== Submodules ---------- .. automodule:: claf.learn.experiment :members: :undoc-members: :show-inheritance: .. automodule:: claf.learn.mode :members: :undoc-members: :show-inheritance: .. automodule:: claf.learn.tensorboard :members: :undoc-members: :show-inheritance: .. automodule:: claf.learn.trainer :members: :undoc-members: :show-inheritance: .. automodule:: claf.learn.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.learn :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.machine.components.retrieval.rst.txt ================================================ claf.machine.components.retrieval package ========================================= Submodules ---------- .. automodule:: claf.machine.components.retrieval.tfidf :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.machine.components.retrieval :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.machine.components.rst.txt ================================================ claf.machine.components package =============================== Subpackages ----------- .. toctree:: claf.machine.components.retrieval Module contents --------------- .. automodule:: claf.machine.components :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.machine.rst.txt ================================================ claf.machine package ==================== Subpackages ----------- .. toctree:: claf.machine.components Submodules ---------- .. automodule:: claf.machine.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.machine.module :members: :undoc-members: :show-inheritance: .. automodule:: claf.machine.nlu :members: :undoc-members: :show-inheritance: .. automodule:: claf.machine.open_qa :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.machine :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.metric.rst.txt ================================================ claf.metric package =================== Submodules ---------- .. automodule:: claf.metric.classification :members: :undoc-members: :show-inheritance: .. automodule:: claf.metric.squad_v1_official :members: :undoc-members: :show-inheritance: .. automodule:: claf.metric.squad_v2_official :members: :undoc-members: :show-inheritance: .. automodule:: claf.metric.wikisql_official :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.metric :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.model.reading_comprehension.rst.txt ================================================ claf.model.reading\_comprehension package ========================================= Submodules ---------- .. automodule:: claf.model.reading_comprehension.bert_for_qa :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.bidaf :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.bidaf_no_answer :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.docqa :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.docqa_no_answer :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.drqa :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.mixin :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.qanet :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model.reading_comprehension :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.model.rst.txt ================================================ claf.model package ================== Subpackages ----------- .. toctree:: claf.model.reading_comprehension claf.model.semantic_parsing claf.model.sequence_classification claf.model.token_classification Submodules ---------- .. automodule:: claf.model.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.cls_utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.model.semantic_parsing.rst.txt ================================================ claf.model.semantic\_parsing package ==================================== Submodules ---------- .. automodule:: claf.model.semantic_parsing.mixin :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.semantic_parsing.sqlnet :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.semantic_parsing.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model.semantic_parsing :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.model.sequence_classification.rst.txt ================================================ claf.model.sequence\_classification package =========================================== Submodules ---------- .. automodule:: claf.model.sequence_classification.bert_for_seq_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.sequence_classification.mixin :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.sequence_classification.structured_self_attention :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model.sequence_classification :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.model.token_classification.rst.txt ================================================ claf.model.token\_classification package ======================================== Submodules ---------- .. automodule:: claf.model.token_classification.bert_for_tok_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.token_classification.mixin :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model.token_classification :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.modules.attention.rst.txt ================================================ claf.modules.attention package ============================== Submodules ---------- .. automodule:: claf.modules.attention.bi_attention :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.attention.co_attention :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.attention.docqa_attention :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.attention.multi_head_attention :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.attention.seq_attention :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules.attention :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.modules.conv.rst.txt ================================================ claf.modules.conv package ========================= Submodules ---------- .. automodule:: claf.modules.conv.depthwise_separable_conv :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.conv.pointwise_conv :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules.conv :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.modules.encoder.rst.txt ================================================ claf.modules.encoder package ============================ Submodules ---------- .. automodule:: claf.modules.encoder.lstm_cell_with_projection :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.encoder.positional :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules.encoder :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.modules.layer.rst.txt ================================================ claf.modules.layer package ========================== Submodules ---------- .. automodule:: claf.modules.layer.highway :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.layer.normalization :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.layer.positionwise :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.layer.residual :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.layer.scalar_mix :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules.layer :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.modules.rst.txt ================================================ claf.modules package ==================== Subpackages ----------- .. toctree:: claf.modules.attention claf.modules.conv claf.modules.encoder claf.modules.layer Submodules ---------- .. automodule:: claf.modules.activation :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.functional :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.initializer :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.rst.txt ================================================ claf package ============ Subpackages ----------- .. toctree:: claf.config claf.data claf.decorator claf.learn claf.machine claf.metric claf.model claf.modules claf.tokens Submodules ---------- .. automodule:: claf.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.tokens.embedding.rst.txt ================================================ claf.tokens.embedding package ============================= Submodules ---------- .. automodule:: claf.tokens.embedding.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.bert_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.char_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.cove_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.elmo_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.frequent_word_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.sparse_feature :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.word_embedding :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens.embedding :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.tokens.indexer.rst.txt ================================================ claf.tokens.indexer package =========================== Submodules ---------- .. automodule:: claf.tokens.indexer.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.bert_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.char_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.elmo_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.exact_match_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.linguistic_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.word_indexer :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens.indexer :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.tokens.rst.txt ================================================ claf.tokens package =================== Subpackages ----------- .. toctree:: claf.tokens.embedding claf.tokens.indexer claf.tokens.token_embedder claf.tokens.tokenizer Submodules ---------- .. automodule:: claf.tokens.cove :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.elmo :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.hangul :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.linguistic :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.text_handler :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.token_maker :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.vocabulary :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.tokens.token_embedder.rst.txt ================================================ claf.tokens.token\_embedder package =================================== Submodules ---------- .. automodule:: claf.tokens.token_embedder.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.token_embedder.basic_embedder :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.token_embedder.reading_comprehension_embedder :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens.token_embedder :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/claf.tokens.tokenizer.rst.txt ================================================ claf.tokens.tokenizer package ============================= Submodules ---------- .. automodule:: claf.tokens.tokenizer.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.char :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.pass_text :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.sent :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.subword :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.utils :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.word :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens.tokenizer :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_build/html/_sources/contents/dataset_and_model.md.txt ================================================ # Dataset and Model **Table of Contents** - [Multi Task](#multi-task) - [Reading Comprehension](#reading-comprehension) - [Regression](#regression) - [Semantic Parsing](#semantic-parsing) - [Sequence Classification](#sequence-classification) - [Token Classification](#token-classification) --- ## Multi-Task ### Dataset - [GLUE Benchmark](https://gluebenchmark.com/): The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems. - CoLA, MNLI, MRPC, QNLI, QQP, RTE, SST-2, STS-B, WNLI ### Model - [Multi-Task Deep Neural Networks for Natural Language Understanding](https://arxiv.org/abs/1901.11504) ## Reading Comprehension ### Dataset - [HistoryQA](https://oss.navercorp.com/ClovaAI-PJT/HistoryQA): Joseon History Question Answering Dataset (SQuAD Style) - [KorQuAD](https://korquad.github.io/): KorQuAD는 한국어 Machine Reading Comprehension을 위해 만든 데이터셋입니다. 모든 질의에 대한 답변은 해당 Wikipedia 아티클 문단의 일부 하위 영역으로 이루어집니다. Stanford Question Answering Dataset(SQuAD) v1.0과 동일한 방식으로 구성되었습니다. - [SQuAD](https://rajpurkar.github.io/SQuAD-explorer/): **S**tanford **Qu**estion **A**nswering **D**ataset is a reading comprehension dataset, consisting of questions posed by crowdworkers on a set of Wikipedia articles, where the answer to every question is a segment of text, or span, from the corresponding reading passage, or the question might be unanswerable. ### Model - BiDAF: [Birectional Attention Flow for Machine Comprehension](https://arxiv.org/abs/1611.01603) + `No Answer` - [A Structured Self-attentive Sentence Embedding](https://arxiv.org/abs/1703.03130) - DrQA: [Reading Wikipedia to Answer Open-Domain Questions](https://arxiv.org/abs/1704.00051) - DocQA: [Simple and Effective Multi-Paragraph Reading Comprehension](https://arxiv.org/abs/1710.10723) + `No Answer` - [QANet: Combining Local Convolution with Global Self-Attention for Reading Comprehension ](https://arxiv.org/abs/1804.09541) - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) --- ## Regression - [GLUE Benchmark](https://gluebenchmark.com/): The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems. - STS-B ### Model - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) - [RoBERTa: A Robustly Optimized BERT Pretraining Approach](https://arxiv.org/abs/1907.11692) --- ## Semantic Parsing ### Dataset - [WikiSQL](https://github.com/salesforce/WikiSQL): A large crowd-sourced dataset for developing natural language interfaces for relational databases. WikiSQL is the dataset released along with our work [Seq2SQL: Generating Structured Queries from Natural Language using Reinforcement Learning](http://arxiv.org/abs/1709.00103). ### Model - SQLNet: [SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning](https://arxiv.org/abs/1711.04436) --- ## Sequence Classification ### Dataset - [GLUE Benchmark](https://gluebenchmark.com/): The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems. - CoLA, MNLI, MRPC, QNLI, QQP, RTE, SST-2, WNLI ### Model - [A Structured Self-attentive Sentence Embedding](https://arxiv.org/abs/1703.03130) - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) - [RoBERTa: A Robustly Optimized BERT Pretraining Approach](https://arxiv.org/abs/1907.11692) --- ## Token Classification ### Dataset - [NER - CoNLL 2013](https://www.clips.uantwerpen.be/conll2003/ner/): The shared task of CoNLL-2003 concerns language-independent named entity recognition. Named entities are phrases that contain the names of persons, organizations, locations, times and quantities. ### Model - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) ================================================ FILE: docs/_build/html/_sources/contents/pretrained_vector.md.txt ================================================ # Pretrained Vector - List on [DataServer](http://dev-reasoning-qa-data-ncl.nfra.io:7778/) ## English - `Counter Fitting`: [Counter-fitting Word Vectors to Linguistic Constraints](http://mi.eng.cam.ac.uk/~nm480/naaclhlt2016.pdf) - counter\_fitted\_glove.300d.txt - `Cove`: [Learned in Translation: Contextualized Word Vectors (McCann et. al. 2017)](https://github.com/salesforce/cove) - wmtlstm-b142a7f2.pth - `fastText`: [Enriching Word Vectors with Subword Information](https://github.com/facebookresearch/fastText) - fasttext.wiki.en.300d.txt - `GloVe`: [GloVe: Global Vectors for Word Representation](https://nlp.stanford.edu/projects/glove/) - glove.6B.50d.txt - glove.6B.100d.txt - glove.6B.200d.txt - glove.6B.300d.txt - glove.840B.300d.txt - `ELMo`: [Deep contextualized word representations](https://github.com/allenai/allennlp/blob/master/allennlp/modules/elmo.py) - elmo\_2x4096\_512\_2048cnn\_2xhighway\_weights.hdf5 - elmo\_2x4096\_512\_2048cnn\_2xhighway\_options - `Word2Vec`: [Distributed Representations of Words and Phrases and their Compositionality](https://code.google.com/archive/p/word2vec/) - GoogleNews-vectors-negative300.txt ## Korean - `fastText`: [Enriching Word Vectors with Subword Information](https://github.com/facebookresearch/fastText) - fasttext.wiki.ko.300d.txt ================================================ FILE: docs/_build/html/_sources/contents/tokens.md.txt ================================================ # Tokens TokenMakers consists of Tokenizer, Indexer, Vocabulary, and Embedding Modules. `TokenMaker` is responsible for the indexing of text and the generation of the tensors through the embedding module. ## Tokenizers - Tokenizer Design ![images](../../images/tokenizers_design.png) ``` class SentTokenizer(name, config): ... class WordTokenizer(name, sent_tokenizer, config) ... class SubwordTokenizer(name, word_tokenizer, config) ... class CharTokenizer(name, word_tokenizer, config) ... ``` The Tokenizer has a dependency with the other unit's tokenizer and the `tokenize()` function takes the input of text units. (* unit: unit of input e.g. 'text', 'sentence' and 'word') - `tokenizer()` example ``` >>> text = "Hello World.This is tokenizer example code." >>> word_tokenizer.tokenize(text, unit="text") # text -> sentences -> words >>> ['Hello', 'World', '.', 'This', 'is', 'tokenizer', 'example', 'code', '.'] >>> word_tokenizer.tokenize(text, unit="sentence") # text -> words >>> ['Hello', 'World.This', 'is', 'tokenizer', 'example', 'code', '.'] ``` Several tensors in a sub-level text unit can be combined into a single tensor of higher level via a vector operation. For example, subword level tensors can be averaged to represent a word level tensor. e.g.) concatenate \[word; subword\] (subword tokens --average--> word token) * The list of pre-defined `Tokenizers`: | Text Unit | Language | Name | Example | | ---- | ---- | --- | --- | | BPE | All (depend on vocab) | **roberta** | Hello World
-> ["ĠHello", "ĠWorld"] | | Char | All | **character** | Hello World
-> ["Hello", "World"]
-> [["H", "e", "l", "l", "o"], ["W", "o", "r", "l", "d"]] | | Char | Korean | [**jamo_ko**](https://github.com/rhobot/Hangulpy) | "안녕 세상"
-> ["안녕", "세상"]
-> [["ㅇ", "ㅏ", "ㄴ", "ㄴ", "ㅕ", "ㅇ"], ["ㅅ", "ㅔ", "ㅅ", "ㅏ", "ㅇ"]] | | Subword | All (but, need vocab.txt) | [**wordpiece**](https://github.com/huggingface/pytorch-pretrained-BERT/blob/master/pytorch_pretrained_bert/tokenization.py) | "expectancy of anyone"
-> ["expectancy", "of", "anyone"]
-> ["expect", "##ancy", "of", "anyone"] | | Word | English | [**nltk_en**](http://www.nltk.org/api/nltk.tokenize.html) | - | | Word | English | [**spacy_en**](https://spacy.io/api/tokenizer) | - | | Word | Korean | [**mecab_ko**](https://bitbucket.org/eunjeon/mecab-ko) | - | | Word | All | **bert_basic** | - | | Word | All | **space_all** | "Hello World"
-> ["Hello", "World"] | | Sent | All | [**punkt**](http://www.nltk.org/api/nltk.tokenize.html) | "Hello World. This is punkt tokenizer."
-> ["Hello World.", "This is punkt tokenizer."] | ## Token Maker * The list of pre-defined `Token Maker`: | Type | Description | Category | Notes | | ---- | ---- | --- | --- | | **char** | character -> convolution -> maxpool | `CharCNN` | - | | **cove** | Embeddings from Neural Machine Translation | `NMT` | - From [Salesforce](https://github.com/salesforce/cove) | | **feature** | Do not use embedding function, just pass feature | `Feature` | - | | **word** | word -> Embedding (+pretrained) | `Word2Vec` | - | | **frequent_word** | word token + pre-trained word embeddings fixed and only fine-tune the N most frequent | `Word2Vec` + `Fine-tune` | - | | **exact_match** | Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form. | `Feature` | - Sparse or Embedding
- Only for RC| | **elmo** | Embeddings from Language Models | `LM` | From [Allennlp](https://github.com/allenai/allennlp) | | **linguistic** | Linguistic Features like POS Tagging, NER and Dependency Parser | `Feature` | - Sparse or Embedding | - Example of tokens in [BaseConfig](#baseconfig) ``` "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { # Define the tokenizer in each unit. "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { # token_name "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { # token_name "indexer": { "lowercase": true }, "embedding": { "embed_dim": 100, "pretrained_path": ", "trainable": false, "dropout": 0.2 } } }, # Tokens process # Text -> Indexed Featrues -> Tensor -> TokenEmbedder -> Model # Visualization # - Text: Hello World # - Indexed Feature: {'char': [[2, 3, 4, 4, 5], [6, 7, 8, 4, 9]], 'glove': [2, 3]} # - Tensor: {'char': tensor, 'glove': tensor} # - TokenEmbedder: [char; glove] (default: concatenate) # - Model: use embedded_value ``` ================================================ FILE: docs/_build/html/_sources/index.rst.txt ================================================ .. CLaF documentation master file, created by sphinx-quickstart on Wed Aug 22 16:14:25 2018. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. :github_url: https://github.com/naver/claf CLaF documentation =================================== CLaF: Clova Language Framework .. toctree:: :glob: :maxdepth: 1 :caption: Contents contents/* .. toctree:: :maxdepth: 1 :caption: Package Reference config data learn metric model modules tokens .. toctree:: :glob: :maxdepth: 1 :caption: Reports reports/* .. toctree:: :glob: :maxdepth: 1 :caption: Summary summary/* .. toctree:: :maxdepth: 1 :caption: Appendix References Indices and tables ================== * :ref:`genindex` * :ref:`modindex` ================================================ FILE: docs/_build/html/_sources/modules.rst.txt ================================================ claf ==== .. toctree:: :maxdepth: 4 claf ================================================ FILE: docs/_build/html/_sources/references.md.txt ================================================ # References - **Dataset** - Pranav Rajpurkar, Jian Zhang, Konstantin Lopyrev and Percy Liang. 2016, [SQuAD: 100,000+ Questions for Machine Comprehension of Text](https://arxiv.org/abs/1606.05250) - Pranav Rajpurkar, Robin Jia and Percy Liang. 2018, [Know What You Don't Know: Unanswerable Questions for SQuAD](https://arxiv.org/abs/1806.03822) - Victor Zhong, Caiming Xiong, and Richard Socher. 2017, [Seq2SQL: Generating Structured Queries from Natural Language using Reinforcement Learning](http://arxiv.org/abs/1709.00103) - **Model** - Minjoon Seo, Aniruddha Kembhavi, Ali Farhadi and Hannaneh Hajishirzi. 2016, [Bidirectional Attention Flow for Machine Comprehension](https://arxiv.org/abs/1611.01603) - Danqi Chen, Adam Fisch, Jason Weston and Antoine Bordes. 2017, [Reading Wikipedia to Answer Open-Domain Questions](https://arxiv.org/abs/1704.00051) - Christopher Clark and Matt Gardner. 2017, [Simple and Effective Multi-Paragraph Reading Comprehension](https://arxiv.org/abs/1710.10723) - Adams Wei Yu, David Dohan, Minh-Thang Luong, Rui Zhao, Kai Chen, Mohammad Norouzi and Quoc V. Le. 2018, [QANet: Combining Local Convolution with Global Self-Attention for Reading Comprehension](https://arxiv.org/abs/1804.09541) - Jacob Devlin, Ming-Wei Chang, Kenton Lee and Kristina Toutanova. 2018, [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) - Xiaojun Xu, Chang Liu and Dawn Song. 2017, [SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning](https://arxiv.org/abs/1711.04436) - **Token** - Yoon Kim,. 2014, [Convolutional Neural Networks for Sentence Classification](https://arxiv.org/abs/1408.5882) - B. McCann, J. Bradbury, C. Xiong, R. Socher, [Learned in Translation: Contextualized Word Vectors](http://papers.nips.cc/paper/7209-learned-in-translation-contextualized-word-vectors.pdf) - P. Bojanowski, E. Grave, A. Joulin, T. Mikolov, [Enriching Word Vectors with Subword Information](https://arxiv.org/abs/1607.04606) - Matthew E. Peters, Mark Neumann, Mohit Iyyer, Matt Gardner, Christopher Clark, Kenton Lee and Luke Zettlemoyer. 2018, [Deep contextualized word representations](https://arxiv.org/abs/1802.05365) - **Other Framework** - Matt Gardner, Joel Grus, Mark Neumann, Oyvind Tafjord, Pradeep Dasigi, Nelson F. Liu, Matthew Peters, Michael Schmitz and Luke S. Zettlemoyer. 2017, [AllenNLP: A Deep Semantic Natural Language Processing Platform](https://www.semanticscholar.org/paper/AllenNLP%3A-A-Deep-Semantic-Natural-Language-Platform-Gardner-Grus/a5502187140cdd98d76ae711973dbcdaf1fef46d) - Guillaume Klein, Yoon Kim, Yuntian Deng, Vincent Nguyen, Jean Senellart and Alexander M. Rush [OpenNMT: Neural Machine Translation Toolkit](https://arxiv.org/pdf/1805.11462) ================================================ FILE: docs/_build/html/_sources/reports/glue.md.txt ================================================ # GLUE - [`GLUE`](https://gluebenchmark.com/): The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems. --- ## Results ### Dev Set - **Base** Size : 12-layer, 768-hidden, 12-heads, 110M parameters | Task (Metric) | Model | CLaF Result | Official Result | BaseConfig | | ------------- | ----- | ----- | -------- | ---------- | | **CoLA** (**Matthew's Corr**) | BERT-Base | 59.393 | 52.1 (Test set) | glue/cola_bert.json | | | MT-DNN (BERT) Base | 54.658 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 64.828 | 63.6 | glue/cola_roberta.json | | **MNLI m/mm** (**Accuracy**) | BERT-Base | 83.923/84.306 | 84.6/83.4 (Test set) | glue/mnli{m/mm}_bert.json | | | MT-DNN (BERT) Base | 84.452/84.225 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 87.305/87.236 | 87.6/- | glue/mnli{m/mm}_roberta.json | | **MRPC** (**Accuracy/F1**) | BERT-Base | 87.5/91.282 | 88.9 (Test set) | glue/mrpc_bert.json | | | MT-DNN (BERT) Base | 87.5/91.005 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 88.480/91.681 | 90.2 | glue/mrpc_roberta.json | | **QNLI** (**Accuracy**) | BERT-Base | 88.521 | 90.5 (Test set) | glue/qnli_bert.json | | | MT-DNN (BERT) Base | - | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 90.823 | 92.8 | glue/qnli_roberta.json | | **QQP** (**Accuracy/F1**) | BERT-Base | 90.378/87.171 | 71.2 (Test set) | glue/qqp_bert.json | | | MT-DNN (BERT) Base | 91.261/88.219 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 91.541/88.768 | 91.9 | glue/qqp_roberta.json | | **RTE** (**Accuracy**) | BERT-Base | 69.314 | 66.4 (Test set) | glue/rte_bert.json | | | MT-DNN (BERT) Base | 79.422 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 73.646 | 78.7 | glue/rte_roberta.json | | **SST-2** (**Accuracy**) | BERT-Base | 92.546 | 93.5 (Test set) | glue/sst_bert.json | | | MT-DNN (BERT) Base | 93.005 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 94.495 | 94.8 | glue/sst_roberta.json | | **STS-B** (**Pearson/Spearman**) | BERT-Base | 88.070/87.881 | 85.8 (Test set) | glue/stsb_bert.json | | | MT-DNN (BERT) Base | 88.444/88.807 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 89.003/89.094 | 91.2 | glue/stsb_roberta.json | | **WNLI** (**Accuracy**) | BERT-Base | 56.338 | 65.1 (Test set) | glue/wnli_bert.json | | | MT-DNN (BERT) Base | 57.746 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 60.563 | - | glue/wnli_roberta.json | - **Large** Size : 24-layer, 1024-hidden, 16-heads, 340M parameters | Task (Metric) | Model | CLaF Result | Official Result | BaseConfig | | ------------- | ----- | ----- | -------- | ---------- | | **CoLA** (**Matthew's Corr**) | BERT-Large | 61.151 | 60.6 | glue/cola_bert.json | | | MT-DNN (BERT) Large | - | 63.5 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | - | 68.0 | glue/cola_roberta.json | | **MNLI m/mm** (**Accuracy**) | BERT-Large | - | 86.6/- | glue/mnli{m/mm}_bert.json | | | MT-DNN (BERT) Large | - | 87.1/86.7 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | - | 90.2/90.2 | glue/mnli{m/mm}_roberta.json | | **MRPC** (**Accuracy/F1**) | BERT-Large | 87.255/90.845 | 88.0 | glue/mrpc_bert.json | | | MT-DNN (BERT) Large | - | 91.0/87.5 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 90.686/93.214 | 90.9 | glue/mrpc_roberta.json | | **QNLI** (**Accuracy**) | BERT-Large | 90.440 | 92.3 | glue/qnli_bert.json | | | MT-DNN (BERT) Large | - | 87.1/86.7 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | - | 94.7 | glue/qnli_roberta.json | | **QQP** (**Accuracy/F1**) | BERT-Large | 91.640/88.745 | 91.3 | glue/qqp_bert.json | | | MT-DNN (BERT) Large | - | 87.1/86.7 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 91.848/89.031 | 92.2 | glue/qqp_roberta.json | | **RTE** (**Accuracy**) | BERT-Large | 69.675 | 70.4 | glue/rte_bert.json | | | MT-DNN (BERT) Large | - | 83.4 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 84.838 | 86.6 | glue/rte_roberta.json | | **SST-2** (**Accuracy**) | BERT-Large | 93.349 | 93.2 | glue/sst_bert.json | | | MT-DNN (BERT) Large | - | 94.3 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 95.642 | 96.4 | glue/sst_roberta.json | | **STS-B** (**Pearson/Spearman**) | BERT-Large | 90.041/89735 | 90.0 | glue/stsb_bert.json | | | MT-DNN (BERT) Large | - | 90.7/90.6 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 91.980/91.764 | 92.4 | glue/stsb_roberta.json | | **WNLI** (**Accuracy**) | BERT-Large | 59.155 | - | glue/wnli_bert.json | | | MT-DNN (BERT) Large | - | - | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | - | 91.3 | - | ================================================ FILE: docs/_build/html/_sources/reports/historyqa.md.txt ================================================ # HistoryQA `Span Detector` - `HistoryQA`: Joseon History Question Answering Dataset - Train: 31901 / Dev: 3067 --- ## Results - Dev Set | Model | EM | F1 | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 81.709 | 84.743 | history/bidaf.json | - | | **DocQA** | 85.099 | 87.789 | history/docqa.json | - | ================================================ FILE: docs/_build/html/_sources/reports/korquad.md.txt ================================================ # KorQuAD `Span Detector` - [`KorQuAD`](https://korquad.github.io/): KorQuAD는 한국어 Machine Reading Comprehension을 위해 만든 데이터셋입니다. 모든 질의에 대한 답변은 해당 Wikipedia 아티클 문단의 일부 하위 영역으로 이루어집니다. Stanford Question Answering Dataset(SQuAD) v1.0과 동일한 방식으로 구성되었습니다. - v1.0 - Train: 60359 / Dev: 5774 --- ## Results - Dev Set | Model | EM | F1 | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 75.476 | 85.915 | korquad/bidaf.json | - | | **DocQA** | 77.693 | 88.115 | korquad/docqa.json | - | | **BERT**-Base, Multilingual Uncased | 81.573 | 90.679 | korquad/bert_base_multilingual_uncased.json | - | | **BERT**-Base, Multilingual Cased | 82.542 | 91.692 | korquad/bert_base_multilingual_cased.json | - | ================================================ FILE: docs/_build/html/_sources/reports/squad.md.txt ================================================ # SQuAD `Span Detector`, `No Answer` - [`SQuAD`](https://rajpurkar.github.io/SQuAD-explorer/): Stanford Question Answering Dataset (SQuAD), a new reading comprehension dataset consisting of 100,000+ questions posed by crowdworkers on a set of Wikipedia articles, where the answer to each question is a segment of text from the corresponding reading passage. - v1.1 - Train: 87599 / Dev: 10570 / Test: 9533 - v2.0 + no_answer - Train : 130319 / Dev: 11873 / Test: 8862 --- ## Results (v1.1) - Dev Set | Model | EM (official) | F1 (official) | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 68.108 (67.7) | 77.780 (77.3) | squad/bidaf.json | - | | **BiDAF + ELMo** | 74.295 | 82.727 | squad/bidaf+elmo.json | - | | **DrQA** | 68.316 (68.8) | 77.493 (78.0) | squad/drqa.json | - | | **DocQA** | 71.760 (71.513) | 80.635 (80.422) | squad/docqa.json | - | | **DocQA + ELMo** | 76.244 (77.5) | 84.372 (84.5) | squad/docqa+elmo.json | - | | **QANet** | 70.918 (73.6) | 79.800 (82.7) | squad/qanet.json | - | | **BERT**-Base Uncased | 79.508 (80.8) | 87.642 (88.5) | squad/bert_base_uncased.json | - | | **BERT**-Large Uncased | 83.254 (84.1) | 90.440 (90.9) | squad/bert_large_uncased.json | - | | **RoBERTa**-Base | 82.980 | 90.459 | roberta_base.json/bert_base_uncased.json | - | | **RoBERTa**-Large | 88.061 (88.9) | 94.034 (94.6) | squad/roberta_large.json | - | --- ## Results (v2.0) - Dev Set | Model | EM (official) | F1 (official) | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 62.570 | 65.461 | squad/bidaf_no_answer.json | - | | **DocQA** | 61.728 | 64.489 | squad/docqa_no_answer.json | - | ================================================ FILE: docs/_build/html/_sources/reports/wikisql.md.txt ================================================ # WikiSQL `Semantic Parsing`, `NL2SQL` - `WikiSQL`: A large crowd-sourced dataset for developing natural language interfaces for relational databases. --- ## Results - Column details * Agg: Aggregator * Sel: SELECT Column * Cond: Where clause * LF: Logical Form * EX: Execution * (): Paper result | Model | Agg | Sel | Cond | LF | EX | BaseConfig | | --- | --- | --- | --- | --- | --- | --- | | **SQLNet** | (90.1) | (91.1) | (72.1) | - | (69.8) | wikisql/sqlnet.json | ================================================ FILE: docs/_build/html/_sources/summary/reading_comprehension.md.txt ================================================ # Reading Comprehension Focus on Service orientied metrics (eg. 1-example inference latency) - Exists samples in `reports/summary/` directory ## SQuAD v1.1 | Model | Inference Latency
(1-example/ms) | F1 (SQuAD) | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 142.644 `cpu` / 32.545 `gpu` | 77.747 | squad/bidaf.json | - | | **BiDAF + ELMo** | - `cpu` / - `gpu` | 82.288 | squad/bidaf+elmo.json | - | | **DrQA** | - `cpu` / - `gpu` | 77.049 | squad/drqa.json | - | | **DocQA** | - `cpu` / - `gpu` | 80.635 | squad/docqa.json | - | | **DocQA + ELMo** | - `cpu` / - `gpu` | 84.372 | squad/docqa+elmo.json | - | | **QANet** | - `cpu` / - `gpu` | 79.800 | squad/qanet.json | - | | **BERT** | - `cpu` / - `gpu` | 87.130 | squad/bert\_base-_uncased.json | - | ### Plot - Inference Latency (1-example) ![images](../../images/inference_latency_chart-1000.png) ================================================ FILE: docs/_build/html/_static/basic.css ================================================ /* * basic.css * ~~~~~~~~~ * * Sphinx stylesheet -- basic theme. * * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ /* -- main layout ----------------------------------------------------------- */ div.clearer { clear: both; } /* -- relbar ---------------------------------------------------------------- */ div.related { width: 100%; font-size: 90%; } div.related h3 { display: none; } div.related ul { margin: 0; padding: 0 0 0 10px; list-style: none; } div.related li { display: inline; } div.related li.right { float: right; margin-right: 5px; } /* -- sidebar --------------------------------------------------------------- */ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; } div.sphinxsidebar { float: left; width: 230px; margin-left: -100%; font-size: 90%; word-wrap: break-word; overflow-wrap : break-word; } div.sphinxsidebar ul { list-style: none; } div.sphinxsidebar ul ul, div.sphinxsidebar ul.want-points { margin-left: 20px; list-style: square; } div.sphinxsidebar ul ul { margin-top: 0; margin-bottom: 0; } div.sphinxsidebar form { margin-top: 10px; } div.sphinxsidebar input { border: 1px solid #98dbcc; font-family: sans-serif; font-size: 1em; } div.sphinxsidebar #searchbox form.search { overflow: hidden; } div.sphinxsidebar #searchbox input[type="text"] { float: left; width: 80%; padding: 0.25em; box-sizing: border-box; } div.sphinxsidebar #searchbox input[type="submit"] { float: left; width: 20%; border-left: none; padding: 0.25em; box-sizing: border-box; } img { border: 0; max-width: 100%; } /* -- search page ----------------------------------------------------------- */ ul.search { margin: 10px 0 0 20px; padding: 0; } ul.search li { padding: 5px 0 5px 20px; background-image: url(file.png); background-repeat: no-repeat; background-position: 0 7px; } ul.search li a { font-weight: bold; } ul.search li div.context { color: #888; margin: 2px 0 0 30px; text-align: left; } ul.keywordmatches li.goodmatch a { font-weight: bold; } /* -- index page ------------------------------------------------------------ */ table.contentstable { width: 90%; margin-left: auto; margin-right: auto; } table.contentstable p.biglink { line-height: 150%; } a.biglink { font-size: 1.3em; } span.linkdescr { font-style: italic; padding-top: 5px; font-size: 90%; } /* -- general index --------------------------------------------------------- */ table.indextable { width: 100%; } table.indextable td { text-align: left; vertical-align: top; } table.indextable ul { margin-top: 0; margin-bottom: 0; list-style-type: none; } table.indextable > tbody > tr > td > ul { padding-left: 0em; } table.indextable tr.pcap { height: 10px; } table.indextable tr.cap { margin-top: 10px; background-color: #f2f2f2; } img.toggler { margin-right: 3px; margin-top: 3px; cursor: pointer; } div.modindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } div.genindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } /* -- domain module index --------------------------------------------------- */ table.modindextable td { padding: 2px; border-collapse: collapse; } /* -- general body styles --------------------------------------------------- */ div.body { min-width: 450px; max-width: 800px; } div.body p, div.body dd, div.body li, div.body blockquote { -moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto; } a.headerlink { visibility: hidden; } a.brackets:before, span.brackets > a:before{ content: "["; } a.brackets:after, span.brackets > a:after { content: "]"; } h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink, caption:hover > a.headerlink, p.caption:hover > a.headerlink, div.code-block-caption:hover > a.headerlink { visibility: visible; } div.body p.caption { text-align: inherit; } div.body td { text-align: left; } .first { margin-top: 0 !important; } p.rubric { margin-top: 30px; font-weight: bold; } img.align-left, .figure.align-left, object.align-left { clear: left; float: left; margin-right: 1em; } img.align-right, .figure.align-right, object.align-right { clear: right; float: right; margin-left: 1em; } img.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } img.align-default, .figure.align-default { display: block; margin-left: auto; margin-right: auto; } .align-left { text-align: left; } .align-center { text-align: center; } .align-default { text-align: center; } .align-right { text-align: right; } /* -- sidebars -------------------------------------------------------------- */ div.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; padding: 7px 7px 0 7px; background-color: #ffe; width: 40%; float: right; } p.sidebar-title { font-weight: bold; } /* -- topics ---------------------------------------------------------------- */ div.topic { border: 1px solid #ccc; padding: 7px 7px 0 7px; margin: 10px 0 10px 0; } p.topic-title { font-size: 1.1em; font-weight: bold; margin-top: 10px; } /* -- admonitions ----------------------------------------------------------- */ div.admonition { margin-top: 10px; margin-bottom: 10px; padding: 7px; } div.admonition dt { font-weight: bold; } div.admonition dl { margin-bottom: 0; } p.admonition-title { margin: 0px 10px 5px 0px; font-weight: bold; } div.body p.centered { text-align: center; margin-top: 25px; } /* -- tables ---------------------------------------------------------------- */ table.docutils { border: 0; border-collapse: collapse; } table.align-center { margin-left: auto; margin-right: auto; } table.align-default { margin-left: auto; margin-right: auto; } table caption span.caption-number { font-style: italic; } table caption span.caption-text { } table.docutils td, table.docutils th { padding: 1px 8px 1px 5px; border-top: 0; border-left: 0; border-right: 0; border-bottom: 1px solid #aaa; } table.footnote td, table.footnote th { border: 0 !important; } th { text-align: left; padding-right: 5px; } table.citation { border-left: solid 1px gray; margin-left: 1px; } table.citation td { border-bottom: none; } th > p:first-child, td > p:first-child { margin-top: 0px; } th > p:last-child, td > p:last-child { margin-bottom: 0px; } /* -- figures --------------------------------------------------------------- */ div.figure { margin: 0.5em; padding: 0.5em; } div.figure p.caption { padding: 0.3em; } div.figure p.caption span.caption-number { font-style: italic; } div.figure p.caption span.caption-text { } /* -- field list styles ----------------------------------------------------- */ table.field-list td, table.field-list th { border: 0 !important; } .field-list ul { margin: 0; padding-left: 1em; } .field-list p { margin: 0; } .field-name { -moz-hyphens: manual; -ms-hyphens: manual; -webkit-hyphens: manual; hyphens: manual; } /* -- hlist styles ---------------------------------------------------------- */ table.hlist td { vertical-align: top; } /* -- other body styles ----------------------------------------------------- */ ol.arabic { list-style: decimal; } ol.loweralpha { list-style: lower-alpha; } ol.upperalpha { list-style: upper-alpha; } ol.lowerroman { list-style: lower-roman; } ol.upperroman { list-style: upper-roman; } li > p:first-child { margin-top: 0px; } li > p:last-child { margin-bottom: 0px; } dl.footnote > dt, dl.citation > dt { float: left; } dl.footnote > dd, dl.citation > dd { margin-bottom: 0em; } dl.footnote > dd:after, dl.citation > dd:after { content: ""; clear: both; } dl.field-list { display: grid; grid-template-columns: fit-content(30%) auto; } dl.field-list > dt { font-weight: bold; word-break: break-word; padding-left: 0.5em; padding-right: 5px; } dl.field-list > dt:after { content: ":"; } dl.field-list > dd { padding-left: 0.5em; margin-top: 0em; margin-left: 0em; margin-bottom: 0em; } dl { margin-bottom: 15px; } dd > p:first-child { margin-top: 0px; } dd ul, dd table { margin-bottom: 10px; } dd { margin-top: 3px; margin-bottom: 10px; margin-left: 30px; } dt:target, span.highlighted { background-color: #fbe54e; } rect.highlighted { fill: #fbe54e; } dl.glossary dt { font-weight: bold; font-size: 1.1em; } .optional { font-size: 1.3em; } .sig-paren { font-size: larger; } .versionmodified { font-style: italic; } .system-message { background-color: #fda; padding: 5px; border: 3px solid red; } .footnote:target { background-color: #ffa; } .line-block { display: block; margin-top: 1em; margin-bottom: 1em; } .line-block .line-block { margin-top: 0; margin-bottom: 0; margin-left: 1.5em; } .guilabel, .menuselection { font-family: sans-serif; } .accelerator { text-decoration: underline; } .classifier { font-style: oblique; } .classifier:before { font-style: normal; margin: 0.5em; content: ":"; } abbr, acronym { border-bottom: dotted 1px; cursor: help; } /* -- code displays --------------------------------------------------------- */ pre { overflow: auto; overflow-y: hidden; /* fixes display issues on Chrome browsers */ } span.pre { -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; } td.linenos pre { padding: 5px 0px; border: 0; background-color: transparent; color: #aaa; } table.highlighttable { margin-left: 0.5em; } table.highlighttable td { padding: 0 0.5em 0 0.5em; } div.code-block-caption { padding: 2px 5px; font-size: small; } div.code-block-caption code { background-color: transparent; } div.code-block-caption + div > div.highlight > pre { margin-top: 0; } div.code-block-caption span.caption-number { padding: 0.1em 0.3em; font-style: italic; } div.code-block-caption span.caption-text { } div.literal-block-wrapper { padding: 1em 1em 0; } div.literal-block-wrapper div.highlight { margin: 0; } code.descname { background-color: transparent; font-weight: bold; font-size: 1.2em; } code.descclassname { background-color: transparent; } code.xref, a code { background-color: transparent; font-weight: bold; } h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { background-color: transparent; } .viewcode-link { float: right; } .viewcode-back { float: right; font-family: sans-serif; } div.viewcode-block:target { margin: -1px -10px; padding: 0 10px; } /* -- math display ---------------------------------------------------------- */ img.math { vertical-align: middle; } div.body div.math p { text-align: center; } span.eqno { float: right; } span.eqno a.headerlink { position: relative; left: 0px; z-index: 1; } div.math:hover a.headerlink { visibility: visible; } /* -- printout stylesheet --------------------------------------------------- */ @media print { div.document, div.documentwrapper, div.bodywrapper { margin: 0 !important; width: 100%; } div.sphinxsidebar, div.related, div.footer, #top-link { display: none; } } ================================================ FILE: docs/_build/html/_static/css/badge_only.css ================================================ .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} ================================================ FILE: docs/_build/html/_static/css/theme.css ================================================ /* sphinx_rtd_theme version 0.4.2 | MIT license */ /* Built 20181005 13:10 */ *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,.rst-content code,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:.5cm}p,h2,.rst-content .toctree-wrapper p.caption,h3{orphans:3;widows:3}h2,.rst-content .toctree-wrapper p.caption,h3{page-break-after:avoid}}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.rst-content .admonition,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*! * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.7.0");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff2?v=4.7.0") format("woff2"),url("../fonts/fontawesome-webfont.woff?v=4.7.0") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.7.0") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857em;text-align:center}.fa-ul{padding-left:0;margin-left:2.1428571429em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.1428571429em;width:2.1428571429em;top:.1428571429em;text-align:center}.fa-li.fa-lg{left:-1.8571428571em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.wy-menu-vertical li span.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-left.toctree-expand,.wy-menu-vertical li.current>a span.fa-pull-left.toctree-expand,.rst-content .fa-pull-left.admonition-title,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content dl dt .fa-pull-left.headerlink,.rst-content p.caption .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.rst-content code.download span.fa-pull-left:first-child,.fa-pull-left.icon{margin-right:.3em}.fa.fa-pull-right,.wy-menu-vertical li span.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-right.toctree-expand,.wy-menu-vertical li.current>a span.fa-pull-right.toctree-expand,.rst-content .fa-pull-right.admonition-title,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content dl dt .fa-pull-right.headerlink,.rst-content p.caption .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.rst-content code.download span.fa-pull-right:first-child,.fa-pull-right.icon{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-menu-vertical li span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.rst-content code.download span.pull-left:first-child,.pull-left.icon{margin-right:.3em}.fa.pull-right,.wy-menu-vertical li span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.rst-content code.download span.pull-right:first-child,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-hotel:before,.fa-bed:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-yc:before,.fa-y-combinator:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-tv:before,.fa-television:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:""}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-signing:before,.fa-sign-language:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-vcard:before,.fa-address-card:before{content:""}.fa-vcard-o:before,.fa-address-card-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context{font-family:inherit}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before{font-family:"FontAwesome";display:inline-block;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa,a .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink,a .rst-content p.caption .headerlink,.rst-content p.caption a .headerlink,a .rst-content table>caption .headerlink,.rst-content table>caption a .headerlink,a .rst-content tt.download span:first-child,.rst-content tt.download a span:first-child,a .rst-content code.download span:first-child,.rst-content code.download a span:first-child,a .icon{display:inline-block;text-decoration:inherit}.btn .fa,.btn .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .btn span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.btn .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .rst-content p.caption .headerlink,.rst-content p.caption .btn .headerlink,.btn .rst-content table>caption .headerlink,.rst-content table>caption .btn .headerlink,.btn .rst-content tt.download span:first-child,.rst-content tt.download .btn span:first-child,.btn .rst-content code.download span:first-child,.rst-content code.download .btn span:first-child,.btn .icon,.nav .fa,.nav .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand,.nav .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .rst-content p.caption .headerlink,.rst-content p.caption .nav .headerlink,.nav .rst-content table>caption .headerlink,.rst-content table>caption .nav .headerlink,.nav .rst-content tt.download span:first-child,.rst-content tt.download .nav span:first-child,.nav .rst-content code.download span:first-child,.rst-content code.download .nav span:first-child,.nav .icon{display:inline}.btn .fa.fa-large,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .btn span.fa-large:first-child,.btn .rst-content code.download span.fa-large:first-child,.rst-content code.download .btn span.fa-large:first-child,.btn .fa-large.icon,.nav .fa.fa-large,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.nav .rst-content code.download span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.nav .fa-large.icon{line-height:.9em}.btn .fa.fa-spin,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .btn span.fa-spin:first-child,.btn .rst-content code.download span.fa-spin:first-child,.rst-content code.download .btn span.fa-spin:first-child,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.nav .rst-content code.download span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.wy-menu-vertical li span.btn.toctree-expand:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.rst-content code.download span.btn:first-child:before,.btn.icon:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.rst-content code.download span.btn:first-child:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.rst-content tt.download .btn-mini span:first-child:before,.btn-mini .rst-content code.download span:first-child:before,.rst-content code.download .btn-mini span:first-child:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.rst-content .admonition{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:#6ab0de;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.admonition{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso,.rst-content .admonition-todo,.rst-content .wy-alert-warning.admonition{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .admonition-todo .admonition-title,.rst-content .wy-alert-warning.admonition .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.admonition{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.admonition{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.admonition{background:#f3f6f6}.wy-alert.wy-alert-neutral .wy-alert-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition .admonition-title{color:#404040;background:#e1e4e5}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a{color:#FFF}.wy-alert p:last-child,.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0px;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27AE60}.wy-tray-container li.wy-tray-item-info{background:#FFF}.wy-tray-container li.wy-tray-item-warning{background:#E67E22}.wy-tray-container li.wy-tray-item-danger{background:#E74C3C}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width: 768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);background-color:#27AE60;text-decoration:none;font-weight:normal;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset,0px -2px 0px 0px rgba(0,0,0,0.1) inset;outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:0px -1px 0px 0px rgba(0,0,0,0.05) inset,0px 2px 0px 0px rgba(0,0,0,0.1) inset;padding:8px 12px 6px 12px}.btn:visited{color:#fff}.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#FFF !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27AE60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#E74C3C !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#E67E22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f !important}.btn-link{background-color:transparent !important;color:#FFF;box-shadow:none;border-color:transparent !important}.btn-link:hover{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:active{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:visited{color:#9B59B6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#FFF;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#FFF;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 .3125em 0;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#E74C3C}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{float:left;display:block;margin-right:2.3576515979%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.3576515979%;width:48.821174201%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n+1){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.3576515979%;width:31.7615656014%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:6px 0 0 0;font-size:90%}.wy-control-no-input{display:inline-block;margin:6px 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type="datetime-local"]{padding:.34375em .625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129FEA}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#E74C3C;border:1px solid #E74C3C}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#E74C3C}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#E74C3C}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type="radio"][disabled],input[type="checkbox"][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{position:absolute;content:"";display:block;left:0;top:0;width:36px;height:12px;border-radius:4px;background:#ccc;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{position:absolute;content:"";display:block;width:18px;height:18px;border-radius:4px;background:#999;left:-3px;top:-3px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27AE60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#E74C3C}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 1px #E74C3C}.wy-control-group.wy-control-group-error textarea{border:solid 1px #E74C3C}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27AE60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#E74C3C}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#E67E22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#FFF}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:.3em;display:block}.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px}.wy-table td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#448C59;text-decoration:none;cursor:pointer}a:hover{color:#698C44}a:visited{color:#448C89}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#E67E22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#FFF !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27AE60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#E74C3C !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,.rst-content .toctree-wrapper p.caption,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2,.rst-content .toctree-wrapper p.caption{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}code,.rst-content tt,.rst-content code{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;color:#E74C3C;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li p:last-child,.rst-content .section ul li p:last-child,.rst-content .toctree-wrapper ul li p:last-child,article ul li p:last-child{margin-bottom:0}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul,article ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,article ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,article ul li li li{list-style:square}.wy-plain-list-disc li ol li,.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,article ul li ol li{list-style:decimal}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li,article ol li{list-style:decimal;margin-left:24px}.wy-plain-list-decimal li p:last-child,.rst-content .section ol li p:last-child,.rst-content ol.arabic li p:last-child,article ol li p:last-child{margin-bottom:0}.wy-plain-list-decimal li ul,.rst-content .section ol li ul,.rst-content ol.arabic li ul,article ol li ul{margin-bottom:0}.wy-plain-list-decimal li ul li,.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:before,.wy-breadcrumbs:after{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs li code,.wy-breadcrumbs li .rst-content tt,.rst-content .wy-breadcrumbs li tt{padding:5px;border:none;background:none}.wy-breadcrumbs li code.literal,.wy-breadcrumbs li .rst-content tt.literal,.rst-content .wy-breadcrumbs li tt.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;margin-bottom:0;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li code,.wy-menu-vertical li .rst-content tt,.rst-content .wy-menu-vertical li tt{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.on a:hover span.toctree-expand,.wy-menu-vertical li.current>a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand{display:block;font-size:.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a{color:#404040}.wy-menu-vertical li.toctree-l1.current li.toctree-l2>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>ul{display:none}.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current>ul{display:block}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{display:block;background:#c9c9c9;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3{font-size:.9em}.wy-menu-vertical li.toctree-l3.current>a{background:#bdbdbd;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{display:block;background:#bdbdbd;padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#FFF;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#FFF;text-align:center;padding:.809em;display:block;color:#fcfcfc;margin-bottom:.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em auto;height:45px;width:45px;background-color:#FFF;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-side-nav-search>a img.logo,.wy-side-nav-search .wy-dropdown>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search>a.icon img.logo,.wy-side-nav-search .wy-dropdown>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:normal;color:rgba(255,255,255,0.3)}.wy-nav .wy-menu-vertical header{color:#FFF}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#FFF;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#FFF;color:#404040;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#404040;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#FFF;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:gray}footer p{margin-bottom:12px}footer span.commit code,footer span.commit .rst-content tt,.rst-content footer span.commit tt{padding:0px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;font-size:1em;background:none;border:none;color:gray}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{width:100%}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:before,.rst-breadcrumbs-buttons:after{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-side-scroll{width:auto}.wy-side-nav-search{width:auto}.wy-menu.wy-menu-vertical{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1100px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,footer,.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#FFF;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0px}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px 12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;display:block;overflow:auto}.rst-content pre.literal-block,.rst-content div[class^='highlight']{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px 0}.rst-content pre.literal-block div[class^='highlight'],.rst-content div[class^='highlight'] div[class^='highlight']{padding:0px;border:none;margin:0}.rst-content div[class^='highlight'] td.code{width:100%}.rst-content .linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;display:block;overflow:auto}.rst-content div[class^='highlight'] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content pre.literal-block,.rst-content div[class^='highlight'] pre,.rst-content .linenodiv pre{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;font-size:12px;line-height:1.4}@media print{.rst-content .codeblock,.rst-content div[class^='highlight'],.rst-content div[class^='highlight'] pre{white-space:pre-wrap}}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last,.rst-content .admonition-todo .last,.rst-content .admonition .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .section ol p:last-child,.rst-content .section ul p:last-child{margin-bottom:24px}.rst-content .line-block{margin-left:0px;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink{visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after{content:"";font-family:FontAwesome}.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content .toctree-wrapper p.caption:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#F1C40F;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:baseline;position:relative;top:-0.4em;line-height:0;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:gray}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.docutils.citation tt,.rst-content table.docutils.citation code,.rst-content table.docutils.footnote tt,.rst-content table.docutils.footnote code{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}.rst-content table.docutils td .last,.rst-content table.docutils td .last :last-child{margin-bottom:0}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content tt,.rst-content tt,.rst-content code{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;padding:2px 5px}.rst-content tt big,.rst-content tt em,.rst-content tt big,.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100% !important;line-height:normal}.rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal{color:#E74C3C}.rst-content tt.xref,a .rst-content tt,.rst-content tt.xref,.rst-content code.xref,a .rst-content tt,a .rst-content code{font-weight:bold;color:#404040}.rst-content pre,.rst-content kbd,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace}.rst-content a tt,.rst-content a tt,.rst-content a code{color:#FFF}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold;margin-bottom:12px}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#448C59;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:#555}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) code{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27AE60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:bold}.rst-content tt.download,.rst-content code.download{background:inherit;padding:inherit;font-weight:normal;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content tt.download span:first-child,.rst-content code.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .versionmodified{font-style:italic}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.math{text-align:center}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-regular.eot");src:url("../fonts/Lato/lato-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-regular.woff2") format("woff2"),url("../fonts/Lato/lato-regular.woff") format("woff"),url("../fonts/Lato/lato-regular.ttf") format("truetype");font-weight:400;font-style:normal}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-bold.eot");src:url("../fonts/Lato/lato-bold.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-bold.woff2") format("woff2"),url("../fonts/Lato/lato-bold.woff") format("woff"),url("../fonts/Lato/lato-bold.ttf") format("truetype");font-weight:700;font-style:normal}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-bolditalic.eot");src:url("../fonts/Lato/lato-bolditalic.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-bolditalic.woff2") format("woff2"),url("../fonts/Lato/lato-bolditalic.woff") format("woff"),url("../fonts/Lato/lato-bolditalic.ttf") format("truetype");font-weight:700;font-style:italic}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-italic.eot");src:url("../fonts/Lato/lato-italic.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-italic.woff2") format("woff2"),url("../fonts/Lato/lato-italic.woff") format("woff"),url("../fonts/Lato/lato-italic.ttf") format("truetype");font-weight:400;font-style:italic}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:url("../fonts/RobotoSlab/roboto-slab.eot");src:url("../fonts/RobotoSlab/roboto-slab-v7-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff2") format("woff2"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff") format("woff"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.ttf") format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot");src:url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot?#iefix") format("embedded-opentype"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff2") format("woff2"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff") format("woff"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.ttf") format("truetype")} ================================================ FILE: docs/_build/html/_static/doctools.js ================================================ /* * doctools.js * ~~~~~~~~~~~ * * Sphinx JavaScript utilities for all documentation. * * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ /** * select a different prefix for underscore */ $u = _.noConflict(); /** * make the code below compatible with browsers without * an installed firebug like debugger if (!window.console || !console.firebug) { var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i) window.console[names[i]] = function() {}; } */ /** * small helper function to urldecode strings */ jQuery.urldecode = function(x) { return decodeURIComponent(x).replace(/\+/g, ' '); }; /** * small helper function to urlencode strings */ jQuery.urlencode = encodeURIComponent; /** * This function returns the parsed url parameters of the * current request. Multiple values per key are supported, * it will always return arrays of strings for the value parts. */ jQuery.getQueryParameters = function(s) { if (typeof s === 'undefined') s = document.location.search; var parts = s.substr(s.indexOf('?') + 1).split('&'); var result = {}; for (var i = 0; i < parts.length; i++) { var tmp = parts[i].split('=', 2); var key = jQuery.urldecode(tmp[0]); var value = jQuery.urldecode(tmp[1]); if (key in result) result[key].push(value); else result[key] = [value]; } return result; }; /** * highlight a given string on a jquery object by wrapping it in * span elements with the given class name. */ jQuery.fn.highlightText = function(text, className) { function highlight(node, addItems) { if (node.nodeType === 3) { var val = node.nodeValue; var pos = val.toLowerCase().indexOf(text); if (pos >= 0 && !jQuery(node.parentNode).hasClass(className) && !jQuery(node.parentNode).hasClass("nohighlight")) { var span; var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); if (isInSVG) { span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); } else { span = document.createElement("span"); span.className = className; } span.appendChild(document.createTextNode(val.substr(pos, text.length))); node.parentNode.insertBefore(span, node.parentNode.insertBefore( document.createTextNode(val.substr(pos + text.length)), node.nextSibling)); node.nodeValue = val.substr(0, pos); if (isInSVG) { var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); var bbox = node.parentElement.getBBox(); rect.x.baseVal.value = bbox.x; rect.y.baseVal.value = bbox.y; rect.width.baseVal.value = bbox.width; rect.height.baseVal.value = bbox.height; rect.setAttribute('class', className); addItems.push({ "parent": node.parentNode, "target": rect}); } } } else if (!jQuery(node).is("button, select, textarea")) { jQuery.each(node.childNodes, function() { highlight(this, addItems); }); } } var addItems = []; var result = this.each(function() { highlight(this, addItems); }); for (var i = 0; i < addItems.length; ++i) { jQuery(addItems[i].parent).before(addItems[i].target); } return result; }; /* * backward compatibility for jQuery.browser * This will be supported until firefox bug is fixed. */ if (!jQuery.browser) { jQuery.uaMatch = function(ua) { ua = ua.toLowerCase(); var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; return { browser: match[ 1 ] || "", version: match[ 2 ] || "0" }; }; jQuery.browser = {}; jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; } /** * Small JavaScript module for the documentation. */ var Documentation = { init : function() { this.fixFirefoxAnchorBug(); this.highlightSearchWords(); this.initIndexTable(); if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { this.initOnKeyListeners(); } }, /** * i18n support */ TRANSLATIONS : {}, PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, LOCALE : 'unknown', // gettext and ngettext don't access this so that the functions // can safely bound to a different name (_ = Documentation.gettext) gettext : function(string) { var translated = Documentation.TRANSLATIONS[string]; if (typeof translated === 'undefined') return string; return (typeof translated === 'string') ? translated : translated[0]; }, ngettext : function(singular, plural, n) { var translated = Documentation.TRANSLATIONS[singular]; if (typeof translated === 'undefined') return (n == 1) ? singular : plural; return translated[Documentation.PLURALEXPR(n)]; }, addTranslations : function(catalog) { for (var key in catalog.messages) this.TRANSLATIONS[key] = catalog.messages[key]; this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); this.LOCALE = catalog.locale; }, /** * add context elements like header anchor links */ addContextElements : function() { $('div[id] > :header:first').each(function() { $('\u00B6'). attr('href', '#' + this.id). attr('title', _('Permalink to this headline')). appendTo(this); }); $('dt[id]').each(function() { $('\u00B6'). attr('href', '#' + this.id). attr('title', _('Permalink to this definition')). appendTo(this); }); }, /** * workaround a firefox stupidity * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 */ fixFirefoxAnchorBug : function() { if (document.location.hash && $.browser.mozilla) window.setTimeout(function() { document.location.href += ''; }, 10); }, /** * highlight the search words provided in the url in the text */ highlightSearchWords : function() { var params = $.getQueryParameters(); var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; if (terms.length) { var body = $('div.body'); if (!body.length) { body = $('body'); } window.setTimeout(function() { $.each(terms, function() { body.highlightText(this.toLowerCase(), 'highlighted'); }); }, 10); $('') .appendTo($('#searchbox')); } }, /** * init the domain index toggle buttons */ initIndexTable : function() { var togglers = $('img.toggler').click(function() { var src = $(this).attr('src'); var idnum = $(this).attr('id').substr(7); $('tr.cg-' + idnum).toggle(); if (src.substr(-9) === 'minus.png') $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); else $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); }).css('display', ''); if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { togglers.click(); } }, /** * helper function to hide the search marks again */ hideSearchWords : function() { $('#searchbox .highlight-link').fadeOut(300); $('span.highlighted').removeClass('highlighted'); }, /** * make the url absolute */ makeURL : function(relativeURL) { return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; }, /** * get the current relative url */ getCurrentURL : function() { var path = document.location.pathname; var parts = path.split(/\//); $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { if (this === '..') parts.pop(); }); var url = parts.join('/'); return path.substring(url.lastIndexOf('/') + 1, path.length - 1); }, initOnKeyListeners: function() { $(document).keyup(function(event) { var activeElementType = document.activeElement.tagName; // don't navigate when in search box or textarea if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { switch (event.keyCode) { case 37: // left var prevHref = $('link[rel="prev"]').prop('href'); if (prevHref) { window.location.href = prevHref; return false; } case 39: // right var nextHref = $('link[rel="next"]').prop('href'); if (nextHref) { window.location.href = nextHref; return false; } } } }); } }; // quick alias for translations _ = Documentation.gettext; $(document).ready(function() { Documentation.init(); }); ================================================ FILE: docs/_build/html/_static/documentation_options.js ================================================ var DOCUMENTATION_OPTIONS = { URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), VERSION: '0.2.0', LANGUAGE: 'None', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true, SOURCELINK_SUFFIX: '.txt', NAVIGATION_WITH_KEYS: false }; ================================================ FILE: docs/_build/html/_static/jquery-3.2.1.js ================================================ /*! * jQuery JavaScript Library v3.2.1 * https://jquery.com/ * * Includes Sizzle.js * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://jquery.org/license * * Date: 2017-03-20T18:59Z */ ( function( global, factory ) { "use strict"; if ( typeof module === "object" && typeof module.exports === "object" ) { // For CommonJS and CommonJS-like environments where a proper `window` // is present, execute the factory and get jQuery. // For environments that do not have a `window` with a `document` // (such as Node.js), expose a factory as module.exports. // This accentuates the need for the creation of a real `window`. // e.g. var jQuery = require("jquery")(window); // See ticket #14549 for more info. module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); } // Pass this if window is not defined yet } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { // Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 // throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode // arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common // enough that all such attempts are guarded in a try block. "use strict"; var arr = []; var document = window.document; var getProto = Object.getPrototypeOf; var slice = arr.slice; var concat = arr.concat; var push = arr.push; var indexOf = arr.indexOf; var class2type = {}; var toString = class2type.toString; var hasOwn = class2type.hasOwnProperty; var fnToString = hasOwn.toString; var ObjectFunctionString = fnToString.call( Object ); var support = {}; function DOMEval( code, doc ) { doc = doc || document; var script = doc.createElement( "script" ); script.text = code; doc.head.appendChild( script ).parentNode.removeChild( script ); } /* global Symbol */ // Defining this global in .eslintrc.json would create a danger of using the global // unguarded in another place, it seems safer to define global only for this module var version = "3.2.1", // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); }, // Support: Android <=4.0 only // Make sure we trim BOM and NBSP rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, // Matches dashed string for camelizing rmsPrefix = /^-ms-/, rdashAlpha = /-([a-z])/g, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return letter.toUpperCase(); }; jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: version, constructor: jQuery, // The default length of a jQuery object is 0 length: 0, toArray: function() { return slice.call( this ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { // Return all the elements in a clean array if ( num == null ) { return slice.call( this ); } // Return just the one element from the set return num < 0 ? this[ num + this.length ] : this[ num ]; }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. each: function( callback ) { return jQuery.each( this, callback ); }, map: function( callback ) { return this.pushStack( jQuery.map( this, function( elem, i ) { return callback.call( elem, i, elem ); } ) ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ) ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); }, end: function() { return this.prevObject || this.constructor(); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: arr.sort, splice: arr.splice }; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {}; } // Extend jQuery itself if only one argument is passed if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = Array.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && Array.isArray( src ) ? src : []; } else { clone = src && jQuery.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend( { // Unique for each copy of jQuery on the page expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), // Assume jQuery is ready without the ready module isReady: true, error: function( msg ) { throw new Error( msg ); }, noop: function() {}, isFunction: function( obj ) { return jQuery.type( obj ) === "function"; }, isWindow: function( obj ) { return obj != null && obj === obj.window; }, isNumeric: function( obj ) { // As of jQuery 3.0, isNumeric is limited to // strings and numbers (primitives or objects) // that can be coerced to finite numbers (gh-2662) var type = jQuery.type( obj ); return ( type === "number" || type === "string" ) && // parseFloat NaNs numeric-cast false positives ("") // ...but misinterprets leading-number strings, particularly hex literals ("0x...") // subtraction forces infinities to NaN !isNaN( obj - parseFloat( obj ) ); }, isPlainObject: function( obj ) { var proto, Ctor; // Detect obvious negatives // Use toString instead of jQuery.type to catch host objects if ( !obj || toString.call( obj ) !== "[object Object]" ) { return false; } proto = getProto( obj ); // Objects with no prototype (e.g., `Object.create( null )`) are plain if ( !proto ) { return true; } // Objects with prototype are plain iff they were constructed by a global Object function Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; }, isEmptyObject: function( obj ) { /* eslint-disable no-unused-vars */ // See https://github.com/eslint/eslint/issues/6125 var name; for ( name in obj ) { return false; } return true; }, type: function( obj ) { if ( obj == null ) { return obj + ""; } // Support: Android <=2.3 only (functionish RegExp) return typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call( obj ) ] || "object" : typeof obj; }, // Evaluates a script in a global context globalEval: function( code ) { DOMEval( code ); }, // Convert dashed to camelCase; used by the css and data modules // Support: IE <=9 - 11, Edge 12 - 13 // Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, each: function( obj, callback ) { var length, i = 0; if ( isArrayLike( obj ) ) { length = obj.length; for ( ; i < length; i++ ) { if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } } else { for ( i in obj ) { if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } } return obj; }, // Support: Android <=4.0 only trim: function( text ) { return text == null ? "" : ( text + "" ).replace( rtrim, "" ); }, // results is for internal usage only makeArray: function( arr, results ) { var ret = results || []; if ( arr != null ) { if ( isArrayLike( Object( arr ) ) ) { jQuery.merge( ret, typeof arr === "string" ? [ arr ] : arr ); } else { push.call( ret, arr ); } } return ret; }, inArray: function( elem, arr, i ) { return arr == null ? -1 : indexOf.call( arr, elem, i ); }, // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit merge: function( first, second ) { var len = +second.length, j = 0, i = first.length; for ( ; j < len; j++ ) { first[ i++ ] = second[ j ]; } first.length = i; return first; }, grep: function( elems, callback, invert ) { var callbackInverse, matches = [], i = 0, length = elems.length, callbackExpect = !invert; // Go through the array, only saving the items // that pass the validator function for ( ; i < length; i++ ) { callbackInverse = !callback( elems[ i ], i ); if ( callbackInverse !== callbackExpect ) { matches.push( elems[ i ] ); } } return matches; }, // arg is for internal usage only map: function( elems, callback, arg ) { var length, value, i = 0, ret = []; // Go through the array, translating each of the items to their new values if ( isArrayLike( elems ) ) { length = elems.length; for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } // Go through every key on the object, } else { for ( i in elems ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } } // Flatten any nested arrays return concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { var tmp, args, proxy; if ( typeof context === "string" ) { tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind args = slice.call( arguments, 2 ); proxy = function() { return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || jQuery.guid++; return proxy; }, now: Date.now, // jQuery.support is not used in Core but other projects attach their // properties to it so it needs to exist. support: support } ); if ( typeof Symbol === "function" ) { jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; } // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), function( i, name ) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); } ); function isArrayLike( obj ) { // Support: real iOS 8.2 only (not reproducible in simulator) // `in` check used to prevent JIT error (gh-2145) // hasOwn isn't used here due to false negatives // regarding Nodelist length in IE var length = !!obj && "length" in obj && obj.length, type = jQuery.type( obj ); if ( type === "function" || jQuery.isWindow( obj ) ) { return false; } return type === "array" || length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in obj; } var Sizzle = /*! * Sizzle CSS Selector Engine v2.3.3 * https://sizzlejs.com/ * * Copyright jQuery Foundation and other contributors * Released under the MIT license * http://jquery.org/license * * Date: 2016-08-08 */ (function( window ) { var i, support, Expr, getText, isXML, tokenize, compile, select, outermostContext, sortInput, hasDuplicate, // Local document vars setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains, // Instance-specific data expando = "sizzle" + 1 * new Date(), preferredDoc = window.document, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; } return 0; }, // Instance methods hasOwn = ({}).hasOwnProperty, arr = [], pop = arr.pop, push_native = arr.push, push = arr.push, slice = arr.slice, // Use a stripped-down indexOf as it's faster than native // https://jsperf.com/thor-indexof-vs-for/5 indexOf = function( list, elem ) { var i = 0, len = list.length; for ( ; i < len; i++ ) { if ( list[i] === elem ) { return i; } } return -1; }, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // http://www.w3.org/TR/css3-selectors/#whitespace whitespace = "[\\x20\\t\\r\\n\\f]", // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2) "*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", pseudos = ":(" + identifier + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: // 1. quoted (capture 3; capture 4 or capture 5) "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6) "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2) ".*" + ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rwhitespace = new RegExp( whitespace + "+", "g" ), rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = { "ID": new RegExp( "^#(" + identifier + ")" ), "CLASS": new RegExp( "^\\.(" + identifier + ")" ), "TAG": new RegExp( "^(" + identifier + "|[*])" ), "ATTR": new RegExp( "^" + attributes ), "PSEUDO": new RegExp( "^" + pseudos ), "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), // For use in libraries implementing .is() // We use this for POS matching in `select` "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rnative = /^[^{]+\{\s*\[native \w/, // Easily-parseable/retrievable ID or TAG or CLASS selectors rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, // CSS escapes // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), funescape = function( _, escaped, escapedWhitespace ) { var high = "0x" + escaped - 0x10000; // NaN means non-codepoint // Support: Firefox<24 // Workaround erroneous numeric interpretation of +"0x" return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint String.fromCharCode( high + 0x10000 ) : // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }, // CSS string/identifier serialization // https://drafts.csswg.org/cssom/#common-serializing-idioms rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, fcssescape = function( ch, asCodePoint ) { if ( asCodePoint ) { // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER if ( ch === "\0" ) { return "\uFFFD"; } // Control characters and (dependent upon position) numbers get escaped as code points return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; } // Other potentially-special ASCII characters get backslash-escaped return "\\" + ch; }, // Used for iframes // See setDocument() // Removing the function wrapper causes a "Permission Denied" // error in IE unloadHandler = function() { setDocument(); }, disabledAncestor = addCombinator( function( elem ) { return elem.disabled === true && ("form" in elem || "label" in elem); }, { dir: "parentNode", next: "legend" } ); // Optimize for push.apply( _, NodeList ) try { push.apply( (arr = slice.call( preferredDoc.childNodes )), preferredDoc.childNodes ); // Support: Android<4.0 // Detect silently failing push.apply arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { push = { apply: arr.length ? // Leverage slice if possible function( target, els ) { push_native.apply( target, slice.call(els) ); } : // Support: IE<9 // Otherwise append directly function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( (target[j++] = els[i++]) ) {} target.length = j - 1; } }; } function Sizzle( selector, context, results, seed ) { var m, i, elem, nid, match, groups, newSelector, newContext = context && context.ownerDocument, // nodeType defaults to 9, since context defaults to document nodeType = context ? context.nodeType : 9; results = results || []; // Return early from calls with invalid selector or context if ( typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { return results; } // Try to shortcut find operations (as opposed to filters) in HTML documents if ( !seed ) { if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { setDocument( context ); } context = context || document; if ( documentIsHTML ) { // If the selector is sufficiently simple, try using a "get*By*" DOM method // (excepting DocumentFragment context, where the methods don't exist) if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { // ID selector if ( (m = match[1]) ) { // Document context if ( nodeType === 9 ) { if ( (elem = context.getElementById( m )) ) { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if ( elem.id === m ) { results.push( elem ); return results; } } else { return results; } // Element context } else { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if ( newContext && (elem = newContext.getElementById( m )) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; } } // Type selector } else if ( match[2] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Class selector } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // Take advantage of querySelectorAll if ( support.qsa && !compilerCache[ selector + " " ] && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { if ( nodeType !== 1 ) { newContext = context; newSelector = selector; // qSA looks outside Element context, which is not what we want // Thanks to Andrew Dupont for this workaround technique // Support: IE <=8 // Exclude object elements } else if ( context.nodeName.toLowerCase() !== "object" ) { // Capture the context ID, setting it first if necessary if ( (nid = context.getAttribute( "id" )) ) { nid = nid.replace( rcssescape, fcssescape ); } else { context.setAttribute( "id", (nid = expando) ); } // Prefix every selector in the list groups = tokenize( selector ); i = groups.length; while ( i-- ) { groups[i] = "#" + nid + " " + toSelector( groups[i] ); } newSelector = groups.join( "," ); // Expand context for sibling selectors newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; } if ( newSelector ) { try { push.apply( results, newContext.querySelectorAll( newSelector ) ); return results; } catch ( qsaError ) { } finally { if ( nid === expando ) { context.removeAttribute( "id" ); } } } } } } // All others return select( selector.replace( rtrim, "$1" ), context, results, seed ); } /** * Create key-value caches of limited size * @returns {function(string, object)} Returns the Object data after storing it on itself with * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) * deleting the oldest entry */ function createCache() { var keys = []; function cache( key, value ) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key + " " ) > Expr.cacheLength ) { // Only keep the most recent entries delete cache[ keys.shift() ]; } return (cache[ key + " " ] = value); } return cache; } /** * Mark a function for special use by Sizzle * @param {Function} fn The function to mark */ function markFunction( fn ) { fn[ expando ] = true; return fn; } /** * Support testing using an element * @param {Function} fn Passed the created element and returns a boolean result */ function assert( fn ) { var el = document.createElement("fieldset"); try { return !!fn( el ); } catch (e) { return false; } finally { // Remove from its parent by default if ( el.parentNode ) { el.parentNode.removeChild( el ); } // release memory in IE el = null; } } /** * Adds the same handler for all of the specified attrs * @param {String} attrs Pipe-separated list of attributes * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { var arr = attrs.split("|"), i = arr.length; while ( i-- ) { Expr.attrHandle[ arr[i] ] = handler; } } /** * Checks document order of two siblings * @param {Element} a * @param {Element} b * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b */ function siblingCheck( a, b ) { var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex; // Use IE sourceIndex if available on both nodes if ( diff ) { return diff; } // Check if b follows a if ( cur ) { while ( (cur = cur.nextSibling) ) { if ( cur === b ) { return -1; } } } return a ? 1 : -1; } /** * Returns a function to use in pseudos for input types * @param {String} type */ function createInputPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === type; }; } /** * Returns a function to use in pseudos for buttons * @param {String} type */ function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && elem.type === type; }; } /** * Returns a function to use in pseudos for :enabled/:disabled * @param {Boolean} disabled true for :disabled; false for :enabled */ function createDisabledPseudo( disabled ) { // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable return function( elem ) { // Only certain elements can match :enabled or :disabled // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled if ( "form" in elem ) { // Check for inherited disabledness on relevant non-disabled elements: // * listed form-associated elements in a disabled fieldset // https://html.spec.whatwg.org/multipage/forms.html#category-listed // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled // * option elements in a disabled optgroup // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled // All such elements have a "form" property. if ( elem.parentNode && elem.disabled === false ) { // Option elements defer to a parent optgroup if present if ( "label" in elem ) { if ( "label" in elem.parentNode ) { return elem.parentNode.disabled === disabled; } else { return elem.disabled === disabled; } } // Support: IE 6 - 11 // Use the isDisabled shortcut property to check for disabled fieldset ancestors return elem.isDisabled === disabled || // Where there is no isDisabled, check manually /* jshint -W018 */ elem.isDisabled !== !disabled && disabledAncestor( elem ) === disabled; } return elem.disabled === disabled; // Try to winnow out elements that can't be disabled before trusting the disabled property. // Some victims get caught in our net (label, legend, menu, track), but it shouldn't // even exist on them, let alone have a boolean value. } else if ( "label" in elem ) { return elem.disabled === disabled; } // Remaining elements are neither :enabled nor :disabled return false; }; } /** * Returns a function to use in pseudos for positionals * @param {Function} fn */ function createPositionalPseudo( fn ) { return markFunction(function( argument ) { argument = +argument; return markFunction(function( seed, matches ) { var j, matchIndexes = fn( [], seed.length, argument ), i = matchIndexes.length; // Match elements found at the specified indexes while ( i-- ) { if ( seed[ (j = matchIndexes[i]) ] ) { seed[j] = !(matches[j] = seed[j]); } } }); }); } /** * Checks a node for validity as a Sizzle context * @param {Element|Object=} context * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext( context ) { return context && typeof context.getElementsByTagName !== "undefined" && context; } // Expose support vars for convenience support = Sizzle.support = {}; /** * Detects XML nodes * @param {Element|Object} elem An element or a document * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = elem && (elem.ownerDocument || elem).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; /** * Sets document-related variables once based on the current document * @param {Element|Object} [doc] An element or document object to use to set the document * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { var hasCompare, subWindow, doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { return document; } // Update global variables document = doc; docElem = document.documentElement; documentIsHTML = !isXML( document ); // Support: IE 9-11, Edge // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) if ( preferredDoc !== document && (subWindow = document.defaultView) && subWindow.top !== subWindow ) { // Support: IE 11, Edge if ( subWindow.addEventListener ) { subWindow.addEventListener( "unload", unloadHandler, false ); // Support: IE 9 - 10 only } else if ( subWindow.attachEvent ) { subWindow.attachEvent( "onunload", unloadHandler ); } } /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 // Verify that getAttribute really returns attributes and not properties // (excepting IE8 booleans) support.attributes = assert(function( el ) { el.className = "i"; return !el.getAttribute("className"); }); /* getElement(s)By* ---------------------------------------------------------------------- */ // Check if getElementsByTagName("*") returns only elements support.getElementsByTagName = assert(function( el ) { el.appendChild( document.createComment("") ); return !el.getElementsByTagName("*").length; }); // Support: IE<9 support.getElementsByClassName = rnative.test( document.getElementsByClassName ); // Support: IE<10 // Check if getElementById returns elements by name // The broken getElementById methods don't pick up programmatically-set names, // so use a roundabout getElementsByName test support.getById = assert(function( el ) { docElem.appendChild( el ).id = expando; return !document.getElementsByName || !document.getElementsByName( expando ).length; }); // ID filter and find if ( support.getById ) { Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { return elem.getAttribute("id") === attrId; }; }; Expr.find["ID"] = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var elem = context.getElementById( id ); return elem ? [ elem ] : []; } }; } else { Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return node && node.value === attrId; }; }; // Support: IE 6 - 7 only // getElementById is not reliable as a find shortcut Expr.find["ID"] = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var node, i, elems, elem = context.getElementById( id ); if ( elem ) { // Verify the id attribute node = elem.getAttributeNode("id"); if ( node && node.value === id ) { return [ elem ]; } // Fall back on getElementsByName elems = context.getElementsByName( id ); i = 0; while ( (elem = elems[i++]) ) { node = elem.getAttributeNode("id"); if ( node && node.value === id ) { return [ elem ]; } } } return []; } }; } // Tag Expr.find["TAG"] = support.getElementsByTagName ? function( tag, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( tag ); // DocumentFragment nodes don't have gEBTN } else if ( support.qsa ) { return context.querySelectorAll( tag ); } } : function( tag, context ) { var elem, tmp = [], i = 0, // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too results = context.getElementsByTagName( tag ); // Filter out possible comments if ( tag === "*" ) { while ( (elem = results[i++]) ) { if ( elem.nodeType === 1 ) { tmp.push( elem ); } } return tmp; } return results; }; // Class Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { return context.getElementsByClassName( className ); } }; /* QSA/matchesSelector ---------------------------------------------------------------------- */ // QSA and matchesSelector support // matchesSelector(:active) reports false when true (IE9/Opera 11.5) rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21) // We allow this because of a bug in IE8/9 that throws an error // whenever `document.activeElement` is accessed on an iframe // So, we allow :focus to pass through QSA all the time to avoid the IE error // See https://bugs.jquery.com/ticket/13378 rbuggyQSA = []; if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { // Build QSA regex // Regex strategy adopted from Diego Perini assert(function( el ) { // Select is set to empty string on purpose // This is to test IE's treatment of not explicitly // setting a boolean content attribute, // since its presence should be enough // https://bugs.jquery.com/ticket/12359 docElem.appendChild( el ).innerHTML = "" + ""; // Support: IE8, Opera 11-12.16 // Nothing should be selected when empty strings follow ^= or $= or *= // The test attribute must be unknown in Opera but "safe" for WinRT // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section if ( el.querySelectorAll("[msallowcapture^='']").length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } // Support: IE8 // Boolean attributes and "value" are not treated correctly if ( !el.querySelectorAll("[selected]").length ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { rbuggyQSA.push("~="); } // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests if ( !el.querySelectorAll(":checked").length ) { rbuggyQSA.push(":checked"); } // Support: Safari 8+, iOS 8+ // https://bugs.webkit.org/show_bug.cgi?id=136851 // In-page `selector#id sibling-combinator selector` fails if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { rbuggyQSA.push(".#.+[+~]"); } }); assert(function( el ) { el.innerHTML = "" + ""; // Support: Windows 8 Native Apps // The type and name attributes are restricted during .innerHTML assignment var input = document.createElement("input"); input.setAttribute( "type", "hidden" ); el.appendChild( input ).setAttribute( "name", "D" ); // Support: IE8 // Enforce case-sensitivity of name attribute if ( el.querySelectorAll("[name=d]").length ) { rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) // IE8 throws error here and will not see later tests if ( el.querySelectorAll(":enabled").length !== 2 ) { rbuggyQSA.push( ":enabled", ":disabled" ); } // Support: IE9-11+ // IE's :disabled selector does not pick up the children of disabled fieldsets docElem.appendChild( el ).disabled = true; if ( el.querySelectorAll(":disabled").length !== 2 ) { rbuggyQSA.push( ":enabled", ":disabled" ); } // Opera 10-11 does not throw on post-comma invalid pseudos el.querySelectorAll("*,:x"); rbuggyQSA.push(",.*:"); }); } if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector) )) ) { assert(function( el ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9) support.disconnectedMatch = matches.call( el, "*" ); // This should fail with an exception // Gecko does not error, returns false instead matches.call( el, "[s!='']:x" ); rbuggyMatches.push( "!=", pseudos ); }); } rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); /* Contains ---------------------------------------------------------------------- */ hasCompare = rnative.test( docElem.compareDocumentPosition ); // Element contains another // Purposefully self-exclusive // As in, an element does not contain itself contains = hasCompare || rnative.test( docElem.contains ) ? function( a, b ) { var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode; return a === bup || !!( bup && bup.nodeType === 1 && ( adown.contains ? adown.contains( bup ) : a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 )); } : function( a, b ) { if ( b ) { while ( (b = b.parentNode) ) { if ( b === a ) { return true; } } } return false; }; /* Sorting ---------------------------------------------------------------------- */ // Document order sorting sortOrder = hasCompare ? function( a, b ) { // Flag for duplicate removal if ( a === b ) { hasDuplicate = true; return 0; } // Sort on method existence if only one input has compareDocumentPosition var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; if ( compare ) { return compare; } // Calculate position if both inputs belong to the same document compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? a.compareDocumentPosition( b ) : // Otherwise we know they are disconnected 1; // Disconnected nodes if ( compare & 1 || (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { // Choose the first element that is related to our preferred document if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { return -1; } if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { return 1; } // Maintain original order return sortInput ? ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; } return compare & 4 ? -1 : 1; } : function( a, b ) { // Exit early if the nodes are identical if ( a === b ) { hasDuplicate = true; return 0; } var cur, i = 0, aup = a.parentNode, bup = b.parentNode, ap = [ a ], bp = [ b ]; // Parentless nodes are either documents or disconnected if ( !aup || !bup ) { return a === document ? -1 : b === document ? 1 : aup ? -1 : bup ? 1 : sortInput ? ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; // If the nodes are siblings, we can do a quick check } else if ( aup === bup ) { return siblingCheck( a, b ); } // Otherwise we need full lists of their ancestors for comparison cur = a; while ( (cur = cur.parentNode) ) { ap.unshift( cur ); } cur = b; while ( (cur = cur.parentNode) ) { bp.unshift( cur ); } // Walk down the tree looking for a discrepancy while ( ap[i] === bp[i] ) { i++; } return i ? // Do a sibling check if the nodes have a common ancestor siblingCheck( ap[i], bp[i] ) : // Otherwise nodes in our document sort first ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0; }; return document; }; Sizzle.matches = function( expr, elements ) { return Sizzle( expr, null, null, elements ); }; Sizzle.matchesSelector = function( elem, expr ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } // Make sure that attribute selectors are quoted expr = expr.replace( rattributeQuotes, "='$1']" ); if ( support.matchesSelector && documentIsHTML && !compilerCache[ expr + " " ] && ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { try { var ret = matches.call( elem, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9 elem.document && elem.document.nodeType !== 11 ) { return ret; } } catch (e) {} } return Sizzle( expr, document, null, [ elem ] ).length > 0; }; Sizzle.contains = function( context, elem ) { // Set document vars if needed if ( ( context.ownerDocument || context ) !== document ) { setDocument( context ); } return contains( context, elem ); }; Sizzle.attr = function( elem, name ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } var fn = Expr.attrHandle[ name.toLowerCase() ], // Don't get fooled by Object.prototype properties (jQuery #13807) val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? fn( elem, name, !documentIsHTML ) : undefined; return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute( name ) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null; }; Sizzle.escape = function( sel ) { return (sel + "").replace( rcssescape, fcssescape ); }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; /** * Document sorting and removing duplicates * @param {ArrayLike} results */ Sizzle.uniqueSort = function( results ) { var elem, duplicates = [], j = 0, i = 0; // Unless we *know* we can detect duplicates, assume their presence hasDuplicate = !support.detectDuplicates; sortInput = !support.sortStable && results.slice( 0 ); results.sort( sortOrder ); if ( hasDuplicate ) { while ( (elem = results[i++]) ) { if ( elem === results[ i ] ) { j = duplicates.push( i ); } } while ( j-- ) { results.splice( duplicates[ j ], 1 ); } } // Clear input after sorting to release objects // See https://github.com/jquery/sizzle/pull/225 sortInput = null; return results; }; /** * Utility function for retrieving the text value of an array of DOM nodes * @param {Array|Element} elem */ getText = Sizzle.getText = function( elem ) { var node, ret = "", i = 0, nodeType = elem.nodeType; if ( !nodeType ) { // If no nodeType, this is expected to be an array while ( (node = elem[i++]) ) { // Do not traverse comment nodes ret += getText( node ); } } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { // Use textContent for elements // innerText usage removed for consistency of new lines (jQuery #11153) if ( typeof elem.textContent === "string" ) { return elem.textContent; } else { // Traverse its children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } // Do not include comment or processing instruction nodes return ret; }; Expr = Sizzle.selectors = { // Can be adjusted by the user cacheLength: 50, createPseudo: markFunction, match: matchExpr, attrHandle: {}, find: {}, relative: { ">": { dir: "parentNode", first: true }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: true }, "~": { dir: "previousSibling" } }, preFilter: { "ATTR": function( match ) { match[1] = match[1].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); if ( match[2] === "~=" ) { match[3] = " " + match[3] + " "; } return match.slice( 0, 4 ); }, "CHILD": function( match ) { /* matches from matchExpr["CHILD"] 1 type (only|nth|...) 2 what (child|of-type) 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 4 xn-component of xn+y argument ([+-]?\d*n|) 5 sign of xn-component 6 x of xn-component 7 sign of y-component 8 y of y-component */ match[1] = match[1].toLowerCase(); if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument if ( !match[3] ) { Sizzle.error( match[0] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); // other types prohibit arguments } else if ( match[3] ) { Sizzle.error( match[0] ); } return match; }, "PSEUDO": function( match ) { var excess, unquoted = !match[6] && match[2]; if ( matchExpr["CHILD"].test( match[0] ) ) { return null; } // Accept quoted arguments as-is if ( match[3] ) { match[2] = match[4] || match[5] || ""; // Strip excess characters from unquoted arguments } else if ( unquoted && rpseudo.test( unquoted ) && // Get excess from tokenize (recursively) (excess = tokenize( unquoted, true )) && // advance to the next closing parenthesis (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { // excess is a negative index match[0] = match[0].slice( 0, excess ); match[2] = unquoted.slice( 0, excess ); } // Return only captures needed by the pseudo filter method (type and argument) return match.slice( 0, 3 ); } }, filter: { "TAG": function( nodeNameSelector ) { var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? function() { return true; } : function( elem ) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; }, "CLASS": function( className ) { var pattern = classCache[ className + " " ]; return pattern || (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && classCache( className, function( elem ) { return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); }); }, "ATTR": function( name, operator, check ) { return function( elem ) { var result = Sizzle.attr( elem, name ); if ( result == null ) { return operator === "!="; } if ( !operator ) { return true; } result += ""; return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf( check ) === 0 : operator === "*=" ? check && result.indexOf( check ) > -1 : operator === "$=" ? check && result.slice( -check.length ) === check : operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; }; }, "CHILD": function( type, what, argument, first, last ) { var simple = type.slice( 0, 3 ) !== "nth", forward = type.slice( -4 ) !== "last", ofType = what === "of-type"; return first === 1 && last === 0 ? // Shortcut for :nth-*(n) function( elem ) { return !!elem.parentNode; } : function( elem, context, xml ) { var cache, uniqueCache, outerCache, node, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), useCache = !xml && !ofType, diff = false; if ( parent ) { // :(first|last|only)-(child|of-type) if ( simple ) { while ( dir ) { node = elem; while ( (node = node[ dir ]) ) { if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { return false; } } // Reverse direction for :only-* (if we haven't yet done so) start = dir = type === "only" && !start && "nextSibling"; } return true; } start = [ forward ? parent.firstChild : parent.lastChild ]; // non-xml :nth-child(...) stores cache data on `parent` if ( forward && useCache ) { // Seek `elem` from a previously-cached index // ...in a gzip-friendly way node = parent; outerCache = node[ expando ] || (node[ expando ] = {}); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || (outerCache[ node.uniqueID ] = {}); cache = uniqueCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; diff = nodeIndex && cache[ 2 ]; node = nodeIndex && parent.childNodes[ nodeIndex ]; while ( (node = ++nodeIndex && node && node[ dir ] || // Fallback to seeking `elem` from the start (diff = nodeIndex = 0) || start.pop()) ) { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; break; } } } else { // Use previously-cached element index if available if ( useCache ) { // ...in a gzip-friendly way node = elem; outerCache = node[ expando ] || (node[ expando ] = {}); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || (outerCache[ node.uniqueID ] = {}); cache = uniqueCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; diff = nodeIndex; } // xml :nth-child(...) // or :nth-last-child(...) or :nth(-last)?-of-type(...) if ( diff === false ) { // Use the same loop as above to seek `elem` from the start while ( (node = ++nodeIndex && node && node[ dir ] || (diff = nodeIndex = 0) || start.pop()) ) { if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { // Cache the index of each encountered element if ( useCache ) { outerCache = node[ expando ] || (node[ expando ] = {}); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ node.uniqueID ] || (outerCache[ node.uniqueID ] = {}); uniqueCache[ type ] = [ dirruns, diff ]; } if ( node === elem ) { break; } } } } } // Incorporate the offset, then check against cycle size diff -= last; return diff === first || ( diff % first === 0 && diff / first >= 0 ); } }; }, "PSEUDO": function( pseudo, argument ) { // pseudo-class names are case-insensitive // http://www.w3.org/TR/selectors/#pseudo-classes // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters // Remember that setFilters inherits from pseudos var args, fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || Sizzle.error( "unsupported pseudo: " + pseudo ); // The user may use createPseudo to indicate that // arguments are needed to create the filter function // just as Sizzle does if ( fn[ expando ] ) { return fn( argument ); } // But maintain support for old signatures if ( fn.length > 1 ) { args = [ pseudo, pseudo, "", argument ]; return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? markFunction(function( seed, matches ) { var idx, matched = fn( seed, argument ), i = matched.length; while ( i-- ) { idx = indexOf( seed, matched[i] ); seed[ idx ] = !( matches[ idx ] = matched[i] ); } }) : function( elem ) { return fn( elem, 0, args ); }; } return fn; } }, pseudos: { // Potentially complex pseudos "not": markFunction(function( selector ) { // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators var input = [], results = [], matcher = compile( selector.replace( rtrim, "$1" ) ); return matcher[ expando ] ? markFunction(function( seed, matches, context, xml ) { var elem, unmatched = matcher( seed, null, xml, [] ), i = seed.length; // Match elements unmatched by `matcher` while ( i-- ) { if ( (elem = unmatched[i]) ) { seed[i] = !(matches[i] = elem); } } }) : function( elem, context, xml ) { input[0] = elem; matcher( input, null, xml, results ); // Don't keep the element (issue #299) input[0] = null; return !results.pop(); }; }), "has": markFunction(function( selector ) { return function( elem ) { return Sizzle( selector, elem ).length > 0; }; }), "contains": markFunction(function( text ) { text = text.replace( runescape, funescape ); return function( elem ) { return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; }; }), // "Whether an element is represented by a :lang() selector // is based solely on the element's language value // being equal to the identifier C, // or beginning with the identifier C immediately followed by "-". // The matching of C against the element's language value is performed case-insensitively. // The identifier C does not have to be a valid language name." // http://www.w3.org/TR/selectors/#lang-pseudo "lang": markFunction( function( lang ) { // lang value must be a valid identifier if ( !ridentifier.test(lang || "") ) { Sizzle.error( "unsupported lang: " + lang ); } lang = lang.replace( runescape, funescape ).toLowerCase(); return function( elem ) { var elemLang; do { if ( (elemLang = documentIsHTML ? elem.lang : elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { elemLang = elemLang.toLowerCase(); return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; } } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); return false; }; }), // Miscellaneous "target": function( elem ) { var hash = window.location && window.location.hash; return hash && hash.slice( 1 ) === elem.id; }, "root": function( elem ) { return elem === docElem; }, "focus": function( elem ) { return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); }, // Boolean properties "enabled": createDisabledPseudo( false ), "disabled": createDisabledPseudo( true ), "checked": function( elem ) { // In CSS3, :checked should return both checked and selected elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked var nodeName = elem.nodeName.toLowerCase(); return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); }, "selected": function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, // Contents "empty": function( elem ) { // http://www.w3.org/TR/selectors/#empty-pseudo // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), // but not by others (comment: 8; processing instruction: 7; etc.) // nodeType < 6 works because attributes (2) do not appear as children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { if ( elem.nodeType < 6 ) { return false; } } return true; }, "parent": function( elem ) { return !Expr.pseudos["empty"]( elem ); }, // Element/input types "header": function( elem ) { return rheader.test( elem.nodeName ); }, "input": function( elem ) { return rinputs.test( elem.nodeName ); }, "button": function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === "button" || name === "button"; }, "text": function( elem ) { var attr; return elem.nodeName.toLowerCase() === "input" && elem.type === "text" && // Support: IE<8 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); }, // Position-in-collection "first": createPositionalPseudo(function() { return [ 0 ]; }), "last": createPositionalPseudo(function( matchIndexes, length ) { return [ length - 1 ]; }), "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; }), "even": createPositionalPseudo(function( matchIndexes, length ) { var i = 0; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), "odd": createPositionalPseudo(function( matchIndexes, length ) { var i = 1; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; }), "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; --i >= 0; ) { matchIndexes.push( i ); } return matchIndexes; }), "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; ++i < length; ) { matchIndexes.push( i ); } return matchIndexes; }) } }; Expr.pseudos["nth"] = Expr.pseudos["eq"]; // Add button/input type pseudos for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { Expr.pseudos[ i ] = createInputPseudo( i ); } for ( i in { submit: true, reset: true } ) { Expr.pseudos[ i ] = createButtonPseudo( i ); } // Easy API for creating new setFilters function setFilters() {} setFilters.prototype = Expr.filters = Expr.pseudos; Expr.setFilters = new setFilters(); tokenize = Sizzle.tokenize = function( selector, parseOnly ) { var matched, match, tokens, type, soFar, groups, preFilters, cached = tokenCache[ selector + " " ]; if ( cached ) { return parseOnly ? 0 : cached.slice( 0 ); } soFar = selector; groups = []; preFilters = Expr.preFilter; while ( soFar ) { // Comma and first run if ( !matched || (match = rcomma.exec( soFar )) ) { if ( match ) { // Don't consume trailing commas as valid soFar = soFar.slice( match[0].length ) || soFar; } groups.push( (tokens = []) ); } matched = false; // Combinators if ( (match = rcombinators.exec( soFar )) ) { matched = match.shift(); tokens.push({ value: matched, // Cast descendant combinators to space type: match[0].replace( rtrim, " " ) }); soFar = soFar.slice( matched.length ); } // Filters for ( type in Expr.filter ) { if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || (match = preFilters[ type ]( match ))) ) { matched = match.shift(); tokens.push({ value: matched, type: type, matches: match }); soFar = soFar.slice( matched.length ); } } if ( !matched ) { break; } } // Return the length of the invalid excess // if we're just parsing // Otherwise, throw an error or return tokens return parseOnly ? soFar.length : soFar ? Sizzle.error( selector ) : // Cache the tokens tokenCache( selector, groups ).slice( 0 ); }; function toSelector( tokens ) { var i = 0, len = tokens.length, selector = ""; for ( ; i < len; i++ ) { selector += tokens[i].value; } return selector; } function addCombinator( matcher, combinator, base ) { var dir = combinator.dir, skip = combinator.next, key = skip || dir, checkNonElements = base && key === "parentNode", doneName = done++; return combinator.first ? // Check against closest ancestor/preceding element function( elem, context, xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { return matcher( elem, context, xml ); } } return false; } : // Check against all ancestor/preceding elements function( elem, context, xml ) { var oldCache, uniqueCache, outerCache, newCache = [ dirruns, doneName ]; // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching if ( xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { if ( matcher( elem, context, xml ) ) { return true; } } } } else { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { outerCache = elem[ expando ] || (elem[ expando ] = {}); // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); if ( skip && skip === elem.nodeName.toLowerCase() ) { elem = elem[ dir ] || elem; } else if ( (oldCache = uniqueCache[ key ]) && oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { // Assign to newCache so results back-propagate to previous elements return (newCache[ 2 ] = oldCache[ 2 ]); } else { // Reuse newcache so results back-propagate to previous elements uniqueCache[ key ] = newCache; // A match means we're done; a fail means we have to keep checking if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { return true; } } } } } return false; }; } function elementMatcher( matchers ) { return matchers.length > 1 ? function( elem, context, xml ) { var i = matchers.length; while ( i-- ) { if ( !matchers[i]( elem, context, xml ) ) { return false; } } return true; } : matchers[0]; } function multipleContexts( selector, contexts, results ) { var i = 0, len = contexts.length; for ( ; i < len; i++ ) { Sizzle( selector, contexts[i], results ); } return results; } function condense( unmatched, map, filter, context, xml ) { var elem, newUnmatched = [], i = 0, len = unmatched.length, mapped = map != null; for ( ; i < len; i++ ) { if ( (elem = unmatched[i]) ) { if ( !filter || filter( elem, context, xml ) ) { newUnmatched.push( elem ); if ( mapped ) { map.push( i ); } } } } return newUnmatched; } function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { if ( postFilter && !postFilter[ expando ] ) { postFilter = setMatcher( postFilter ); } if ( postFinder && !postFinder[ expando ] ) { postFinder = setMatcher( postFinder, postSelector ); } return markFunction(function( seed, results, context, xml ) { var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, // Get initial elements from seed or context elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), // Prefilter to get matcher input, preserving a map for seed-results synchronization matcherIn = preFilter && ( seed || !selector ) ? condense( elems, preMap, preFilter, context, xml ) : elems, matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, postFinder || ( seed ? preFilter : preexisting || postFilter ) ? // ...intermediate processing is necessary [] : // ...otherwise use results directly results : matcherIn; // Find primary matches if ( matcher ) { matcher( matcherIn, matcherOut, context, xml ); } // Apply postFilter if ( postFilter ) { temp = condense( matcherOut, postMap ); postFilter( temp, [], context, xml ); // Un-match failing elements by moving them back to matcherIn i = temp.length; while ( i-- ) { if ( (elem = temp[i]) ) { matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); } } } if ( seed ) { if ( postFinder || preFilter ) { if ( postFinder ) { // Get the final matcherOut by condensing this intermediate into postFinder contexts temp = []; i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) ) { // Restore matcherIn since elem is not yet a final match temp.push( (matcherIn[i] = elem) ); } } postFinder( null, (matcherOut = []), temp, xml ); } // Move matched elements from seed to results to keep them synchronized i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) && (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { seed[temp] = !(results[temp] = elem); } } } // Add elements to results, through postFinder if defined } else { matcherOut = condense( matcherOut === results ? matcherOut.splice( preexisting, matcherOut.length ) : matcherOut ); if ( postFinder ) { postFinder( null, results, matcherOut, xml ); } else { push.apply( results, matcherOut ); } } }); } function matcherFromTokens( tokens ) { var checkContext, matcher, j, len = tokens.length, leadingRelative = Expr.relative[ tokens[0].type ], implicitRelative = leadingRelative || Expr.relative[" "], i = leadingRelative ? 1 : 0, // The foundational matcher ensures that elements are reachable from top-level context(s) matchContext = addCombinator( function( elem ) { return elem === checkContext; }, implicitRelative, true ), matchAnyContext = addCombinator( function( elem ) { return indexOf( checkContext, elem ) > -1; }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( (checkContext = context).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); // Avoid hanging onto element (issue #299) checkContext = null; return ret; } ]; for ( ; i < len; i++ ) { if ( (matcher = Expr.relative[ tokens[i].type ]) ) { matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; } else { matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); // Return special upon seeing a positional matcher if ( matcher[ expando ] ) { // Find the next relative operator (if any) for proper handling j = ++i; for ( ; j < len; j++ ) { if ( Expr.relative[ tokens[j].type ] ) { break; } } return setMatcher( i > 1 && elementMatcher( matchers ), i > 1 && toSelector( // If the preceding token was a descendant combinator, insert an implicit any-element `*` tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) ).replace( rtrim, "$1" ), matcher, i < j && matcherFromTokens( tokens.slice( i, j ) ), j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), j < len && toSelector( tokens ) ); } matchers.push( matcher ); } } return elementMatcher( matchers ); } function matcherFromGroupMatchers( elementMatchers, setMatchers ) { var bySet = setMatchers.length > 0, byElement = elementMatchers.length > 0, superMatcher = function( seed, context, xml, results, outermost ) { var elem, j, matcher, matchedCount = 0, i = "0", unmatched = seed && [], setMatched = [], contextBackup = outermostContext, // We must always have either seed elements or outermost context elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), // Use integer dirruns iff this is the outermost matcher dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), len = elems.length; if ( outermost ) { outermostContext = context === document || context || outermost; } // Add elements passing elementMatchers directly to results // Support: IE<9, Safari // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id for ( ; i !== len && (elem = elems[i]) != null; i++ ) { if ( byElement && elem ) { j = 0; if ( !context && elem.ownerDocument !== document ) { setDocument( elem ); xml = !documentIsHTML; } while ( (matcher = elementMatchers[j++]) ) { if ( matcher( elem, context || document, xml) ) { results.push( elem ); break; } } if ( outermost ) { dirruns = dirrunsUnique; } } // Track unmatched elements for set filters if ( bySet ) { // They will have gone through all possible matchers if ( (elem = !matcher && elem) ) { matchedCount--; } // Lengthen the array for every element, matched or not if ( seed ) { unmatched.push( elem ); } } } // `i` is now the count of elements visited above, and adding it to `matchedCount` // makes the latter nonnegative. matchedCount += i; // Apply set filters to unmatched elements // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` // equals `i`), unless we didn't visit _any_ elements in the above loop because we have // no element matchers and no seed. // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that // case, which will result in a "00" `matchedCount` that differs from `i` but is also // numerically zero. if ( bySet && i !== matchedCount ) { j = 0; while ( (matcher = setMatchers[j++]) ) { matcher( unmatched, setMatched, context, xml ); } if ( seed ) { // Reintegrate element matches to eliminate the need for sorting if ( matchedCount > 0 ) { while ( i-- ) { if ( !(unmatched[i] || setMatched[i]) ) { setMatched[i] = pop.call( results ); } } } // Discard index placeholder values to get only actual matches setMatched = condense( setMatched ); } // Add matches to results push.apply( results, setMatched ); // Seedless set matches succeeding multiple successful matchers stipulate sorting if ( outermost && !seed && setMatched.length > 0 && ( matchedCount + setMatchers.length ) > 1 ) { Sizzle.uniqueSort( results ); } } // Override manipulation of globals by nested matchers if ( outermost ) { dirruns = dirrunsUnique; outermostContext = contextBackup; } return unmatched; }; return bySet ? markFunction( superMatcher ) : superMatcher; } compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { var i, setMatchers = [], elementMatchers = [], cached = compilerCache[ selector + " " ]; if ( !cached ) { // Generate a function of recursive functions that can be used to check each element if ( !match ) { match = tokenize( selector ); } i = match.length; while ( i-- ) { cached = matcherFromTokens( match[i] ); if ( cached[ expando ] ) { setMatchers.push( cached ); } else { elementMatchers.push( cached ); } } // Cache the compiled function cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); // Save selector and tokenization cached.selector = selector; } return cached; }; /** * A low-level selection function that works with Sizzle's compiled * selector functions * @param {String|Function} selector A selector or a pre-compiled * selector function built with Sizzle.compile * @param {Element} context * @param {Array} [results] * @param {Array} [seed] A set of elements to match against */ select = Sizzle.select = function( selector, context, results, seed ) { var i, tokens, token, type, find, compiled = typeof selector === "function" && selector, match = !seed && tokenize( (selector = compiled.selector || selector) ); results = results || []; // Try to minimize operations if there is only one selector in the list and no seed // (the latter of which guarantees us context) if ( match.length === 1 ) { // Reduce context if the leading compound selector is an ID tokens = match[0] = match[0].slice( 0 ); if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; if ( !context ) { return results; // Precompiled matchers will still verify ancestry, so step up a level } else if ( compiled ) { context = context.parentNode; } selector = selector.slice( tokens.shift().value.length ); } // Fetch a seed set for right-to-left matching i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; while ( i-- ) { token = tokens[i]; // Abort if we hit a combinator if ( Expr.relative[ (type = token.type) ] ) { break; } if ( (find = Expr.find[ type ]) ) { // Search, expanding context for leading sibling combinators if ( (seed = find( token.matches[0].replace( runescape, funescape ), rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context )) ) { // If seed is empty or no tokens remain, we can return early tokens.splice( i, 1 ); selector = seed.length && toSelector( tokens ); if ( !selector ) { push.apply( results, seed ); return results; } break; } } } } // Compile and execute a filtering function if one is not provided // Provide `match` to avoid retokenization if we modified the selector above ( compiled || compile( selector, match ) )( seed, context, !documentIsHTML, results, !context || rsibling.test( selector ) && testContext( context.parentNode ) || context ); return results; }; // One-time assignments // Sort stability support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; // Support: Chrome 14-35+ // Always assume duplicates if they aren't passed to the comparison function support.detectDuplicates = !!hasDuplicate; // Initialize against the default document setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) // Detached nodes confoundingly follow *each other* support.sortDetached = assert(function( el ) { // Should return 1, but returns 4 (following) return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; }); // Support: IE<8 // Prevent attribute/property "interpolation" // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx if ( !assert(function( el ) { el.innerHTML = ""; return el.firstChild.getAttribute("href") === "#" ; }) ) { addHandle( "type|href|height|width", function( elem, name, isXML ) { if ( !isXML ) { return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); } }); } // Support: IE<9 // Use defaultValue in place of getAttribute("value") if ( !support.attributes || !assert(function( el ) { el.innerHTML = ""; el.firstChild.setAttribute( "value", "" ); return el.firstChild.getAttribute( "value" ) === ""; }) ) { addHandle( "value", function( elem, name, isXML ) { if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { return elem.defaultValue; } }); } // Support: IE<9 // Use getAttributeNode to fetch booleans when getAttribute lies if ( !assert(function( el ) { return el.getAttribute("disabled") == null; }) ) { addHandle( booleans, function( elem, name, isXML ) { var val; if ( !isXML ) { return elem[ name ] === true ? name.toLowerCase() : (val = elem.getAttributeNode( name )) && val.specified ? val.value : null; } }); } return Sizzle; })( window ); jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; // Deprecated jQuery.expr[ ":" ] = jQuery.expr.pseudos; jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; jQuery.escapeSelector = Sizzle.escape; var dir = function( elem, dir, until ) { var matched = [], truncate = until !== undefined; while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { if ( elem.nodeType === 1 ) { if ( truncate && jQuery( elem ).is( until ) ) { break; } matched.push( elem ); } } return matched; }; var siblings = function( n, elem ) { var matched = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { matched.push( n ); } } return matched; }; var rneedsContext = jQuery.expr.match.needsContext; function nodeName( elem, name ) { return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); }; var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); var risSimple = /^.[^:#\[\.,]*$/; // Implement the identical functionality for filter and not function winnow( elements, qualifier, not ) { if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep( elements, function( elem, i ) { return !!qualifier.call( elem, i, elem ) !== not; } ); } // Single element if ( qualifier.nodeType ) { return jQuery.grep( elements, function( elem ) { return ( elem === qualifier ) !== not; } ); } // Arraylike of elements (jQuery, arguments, Array) if ( typeof qualifier !== "string" ) { return jQuery.grep( elements, function( elem ) { return ( indexOf.call( qualifier, elem ) > -1 ) !== not; } ); } // Simple selector that can be filtered directly, removing non-Elements if ( risSimple.test( qualifier ) ) { return jQuery.filter( qualifier, elements, not ); } // Complex selector, compare the two sets, removing non-Elements qualifier = jQuery.filter( qualifier, elements ); return jQuery.grep( elements, function( elem ) { return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1; } ); } jQuery.filter = function( expr, elems, not ) { var elem = elems[ 0 ]; if ( not ) { expr = ":not(" + expr + ")"; } if ( elems.length === 1 && elem.nodeType === 1 ) { return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; } return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { return elem.nodeType === 1; } ) ); }; jQuery.fn.extend( { find: function( selector ) { var i, ret, len = this.length, self = this; if ( typeof selector !== "string" ) { return this.pushStack( jQuery( selector ).filter( function() { for ( i = 0; i < len; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } } ) ); } ret = this.pushStack( [] ); for ( i = 0; i < len; i++ ) { jQuery.find( selector, self[ i ], ret ); } return len > 1 ? jQuery.uniqueSort( ret ) : ret; }, filter: function( selector ) { return this.pushStack( winnow( this, selector || [], false ) ); }, not: function( selector ) { return this.pushStack( winnow( this, selector || [], true ) ); }, is: function( selector ) { return !!winnow( this, // If this is a positional/relative selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". typeof selector === "string" && rneedsContext.test( selector ) ? jQuery( selector ) : selector || [], false ).length; } } ); // Initialize a jQuery object // A central reference to the root jQuery(document) var rootjQuery, // A simple way to check for HTML strings // Prioritize #id over to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) // Shortcut simple #id case for speed rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, init = jQuery.fn.init = function( selector, context, root ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } // Method init() accepts an alternate rootjQuery // so migrate can support jQuery.sub (gh-2101) root = root || rootjQuery; // Handle HTML strings if ( typeof selector === "string" ) { if ( selector[ 0 ] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id if ( match && ( match[ 1 ] || !context ) ) { // HANDLE: $(html) -> $(array) if ( match[ 1 ] ) { context = context instanceof jQuery ? context[ 0 ] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge( this, jQuery.parseHTML( match[ 1 ], context && context.nodeType ? context.ownerDocument || context : document, true ) ); // HANDLE: $(html, props) if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // Properties of context are called as methods if possible if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } } return this; // HANDLE: $(#id) } else { elem = document.getElementById( match[ 2 ] ); if ( elem ) { // Inject the element directly into the jQuery object this[ 0 ] = elem; this.length = 1; } return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || root ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(DOMElement) } else if ( selector.nodeType ) { this[ 0 ] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return root.ready !== undefined ? root.ready( selector ) : // Execute immediately if ready is not present selector( jQuery ); } return jQuery.makeArray( selector, this ); }; // Give the init function the jQuery prototype for later instantiation init.prototype = jQuery.fn; // Initialize central reference rootjQuery = jQuery( document ); var rparentsprev = /^(?:parents|prev(?:Until|All))/, // Methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.fn.extend( { has: function( target ) { var targets = jQuery( target, this ), l = targets.length; return this.filter( function() { var i = 0; for ( ; i < l; i++ ) { if ( jQuery.contains( this, targets[ i ] ) ) { return true; } } } ); }, closest: function( selectors, context ) { var cur, i = 0, l = this.length, matched = [], targets = typeof selectors !== "string" && jQuery( selectors ); // Positional selectors never match, since there's no _selection_ context if ( !rneedsContext.test( selectors ) ) { for ( ; i < l; i++ ) { for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { // Always skip document fragments if ( cur.nodeType < 11 && ( targets ? targets.index( cur ) > -1 : // Don't pass non-elements to Sizzle cur.nodeType === 1 && jQuery.find.matchesSelector( cur, selectors ) ) ) { matched.push( cur ); break; } } } } return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); }, // Determine the position of an element within the set index: function( elem ) { // No argument, return index in parent if ( !elem ) { return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; } // Index in selector if ( typeof elem === "string" ) { return indexOf.call( jQuery( elem ), this[ 0 ] ); } // Locate the position of the desired element return indexOf.call( this, // If it receives a jQuery object, the first element is used elem.jquery ? elem[ 0 ] : elem ); }, add: function( selector, context ) { return this.pushStack( jQuery.uniqueSort( jQuery.merge( this.get(), jQuery( selector, context ) ) ) ); }, addBack: function( selector ) { return this.add( selector == null ? this.prevObject : this.prevObject.filter( selector ) ); } } ); function sibling( cur, dir ) { while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} return cur; } jQuery.each( { parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return dir( elem, "parentNode", until ); }, next: function( elem ) { return sibling( elem, "nextSibling" ); }, prev: function( elem ) { return sibling( elem, "previousSibling" ); }, nextAll: function( elem ) { return dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return siblings( ( elem.parentNode || {} ).firstChild, elem ); }, children: function( elem ) { return siblings( elem.firstChild ); }, contents: function( elem ) { if ( nodeName( elem, "iframe" ) ) { return elem.contentDocument; } // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only // Treat the template element as a regular one in browsers that // don't support it. if ( nodeName( elem, "template" ) ) { elem = elem.content || elem; } return jQuery.merge( [], elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var matched = jQuery.map( this, fn, until ); if ( name.slice( -5 ) !== "Until" ) { selector = until; } if ( selector && typeof selector === "string" ) { matched = jQuery.filter( selector, matched ); } if ( this.length > 1 ) { // Remove duplicates if ( !guaranteedUnique[ name ] ) { jQuery.uniqueSort( matched ); } // Reverse order for parents* and prev-derivatives if ( rparentsprev.test( name ) ) { matched.reverse(); } } return this.pushStack( matched ); }; } ); var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); // Convert String-formatted options into Object-formatted ones function createOptions( options ) { var object = {}; jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { object[ flag ] = true; } ); return object; } /* * Create a callback list using the following parameters: * * options: an optional list of space-separated options that will change how * the callback list behaves or a more traditional option object * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible options: * * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function( options ) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof options === "string" ? createOptions( options ) : jQuery.extend( {}, options ); var // Flag to know if list is currently firing firing, // Last fire value for non-forgettable lists memory, // Flag to know if list was already fired fired, // Flag to prevent firing locked, // Actual callback list list = [], // Queue of execution data for repeatable lists queue = [], // Index of currently firing callback (modified by add/remove as needed) firingIndex = -1, // Fire callbacks fire = function() { // Enforce single-firing locked = locked || options.once; // Execute callbacks for all pending executions, // respecting firingIndex overrides and runtime changes fired = firing = true; for ( ; queue.length; firingIndex = -1 ) { memory = queue.shift(); while ( ++firingIndex < list.length ) { // Run callback and check for early termination if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && options.stopOnFalse ) { // Jump to end and forget the data so .add doesn't re-fire firingIndex = list.length; memory = false; } } } // Forget the data if we're done with it if ( !options.memory ) { memory = false; } firing = false; // Clean up if we're done firing for good if ( locked ) { // Keep an empty list if we have data for future add calls if ( memory ) { list = []; // Otherwise, this object is spent } else { list = ""; } } }, // Actual Callbacks object self = { // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { // If we have memory from a past run, we should fire after adding if ( memory && !firing ) { firingIndex = list.length - 1; queue.push( memory ); } ( function add( args ) { jQuery.each( args, function( _, arg ) { if ( jQuery.isFunction( arg ) ) { if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { // Inspect recursively add( arg ); } } ); } )( arguments ); if ( memory && !firing ) { fire(); } } return this; }, // Remove a callback from the list remove: function() { jQuery.each( arguments, function( _, arg ) { var index; while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { list.splice( index, 1 ); // Handle firing indexes if ( index <= firingIndex ) { firingIndex--; } } } ); return this; }, // Check if a given callback is in the list. // If no argument is given, return whether or not list has callbacks attached. has: function( fn ) { return fn ? jQuery.inArray( fn, list ) > -1 : list.length > 0; }, // Remove all callbacks from the list empty: function() { if ( list ) { list = []; } return this; }, // Disable .fire and .add // Abort any current/pending executions // Clear all callbacks and values disable: function() { locked = queue = []; list = memory = ""; return this; }, disabled: function() { return !list; }, // Disable .fire // Also disable .add unless we have memory (since it would have no effect) // Abort any pending executions lock: function() { locked = queue = []; if ( !memory && !firing ) { list = memory = ""; } return this; }, locked: function() { return !!locked; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( !locked ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; queue.push( args ); if ( !firing ) { fire(); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; return self; }; function Identity( v ) { return v; } function Thrower( ex ) { throw ex; } function adoptValue( value, resolve, reject, noValue ) { var method; try { // Check for promise aspect first to privilege synchronous behavior if ( value && jQuery.isFunction( ( method = value.promise ) ) ) { method.call( value ).done( resolve ).fail( reject ); // Other thenables } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) { method.call( value, resolve, reject ); // Other non-thenables } else { // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: // * false: [ value ].slice( 0 ) => resolve( value ) // * true: [ value ].slice( 1 ) => resolve() resolve.apply( undefined, [ value ].slice( noValue ) ); } // For Promises/A+, convert exceptions into rejections // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in // Deferred#then to conditionally suppress rejection. } catch ( value ) { // Support: Android 4.0 only // Strict mode functions invoked without .call/.apply get global-object context reject.apply( undefined, [ value ] ); } } jQuery.extend( { Deferred: function( func ) { var tuples = [ // action, add listener, callbacks, // ... .then handlers, argument index, [final state] [ "notify", "progress", jQuery.Callbacks( "memory" ), jQuery.Callbacks( "memory" ), 2 ], [ "resolve", "done", jQuery.Callbacks( "once memory" ), jQuery.Callbacks( "once memory" ), 0, "resolved" ], [ "reject", "fail", jQuery.Callbacks( "once memory" ), jQuery.Callbacks( "once memory" ), 1, "rejected" ] ], state = "pending", promise = { state: function() { return state; }, always: function() { deferred.done( arguments ).fail( arguments ); return this; }, "catch": function( fn ) { return promise.then( null, fn ); }, // Keep pipe for back-compat pipe: function( /* fnDone, fnFail, fnProgress */ ) { var fns = arguments; return jQuery.Deferred( function( newDefer ) { jQuery.each( tuples, function( i, tuple ) { // Map tuples (progress, done, fail) to arguments (done, fail, progress) var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; // deferred.progress(function() { bind to newDefer or newDefer.notify }) // deferred.done(function() { bind to newDefer or newDefer.resolve }) // deferred.fail(function() { bind to newDefer or newDefer.reject }) deferred[ tuple[ 1 ] ]( function() { var returned = fn && fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise() .progress( newDefer.notify ) .done( newDefer.resolve ) .fail( newDefer.reject ); } else { newDefer[ tuple[ 0 ] + "With" ]( this, fn ? [ returned ] : arguments ); } } ); } ); fns = null; } ).promise(); }, then: function( onFulfilled, onRejected, onProgress ) { var maxDepth = 0; function resolve( depth, deferred, handler, special ) { return function() { var that = this, args = arguments, mightThrow = function() { var returned, then; // Support: Promises/A+ section 2.3.3.3.3 // https://promisesaplus.com/#point-59 // Ignore double-resolution attempts if ( depth < maxDepth ) { return; } returned = handler.apply( that, args ); // Support: Promises/A+ section 2.3.1 // https://promisesaplus.com/#point-48 if ( returned === deferred.promise() ) { throw new TypeError( "Thenable self-resolution" ); } // Support: Promises/A+ sections 2.3.3.1, 3.5 // https://promisesaplus.com/#point-54 // https://promisesaplus.com/#point-75 // Retrieve `then` only once then = returned && // Support: Promises/A+ section 2.3.4 // https://promisesaplus.com/#point-64 // Only check objects and functions for thenability ( typeof returned === "object" || typeof returned === "function" ) && returned.then; // Handle a returned thenable if ( jQuery.isFunction( then ) ) { // Special processors (notify) just wait for resolution if ( special ) { then.call( returned, resolve( maxDepth, deferred, Identity, special ), resolve( maxDepth, deferred, Thrower, special ) ); // Normal processors (resolve) also hook into progress } else { // ...and disregard older resolution values maxDepth++; then.call( returned, resolve( maxDepth, deferred, Identity, special ), resolve( maxDepth, deferred, Thrower, special ), resolve( maxDepth, deferred, Identity, deferred.notifyWith ) ); } // Handle all other returned values } else { // Only substitute handlers pass on context // and multiple values (non-spec behavior) if ( handler !== Identity ) { that = undefined; args = [ returned ]; } // Process the value(s) // Default process is resolve ( special || deferred.resolveWith )( that, args ); } }, // Only normal processors (resolve) catch and reject exceptions process = special ? mightThrow : function() { try { mightThrow(); } catch ( e ) { if ( jQuery.Deferred.exceptionHook ) { jQuery.Deferred.exceptionHook( e, process.stackTrace ); } // Support: Promises/A+ section 2.3.3.3.4.1 // https://promisesaplus.com/#point-61 // Ignore post-resolution exceptions if ( depth + 1 >= maxDepth ) { // Only substitute handlers pass on context // and multiple values (non-spec behavior) if ( handler !== Thrower ) { that = undefined; args = [ e ]; } deferred.rejectWith( that, args ); } } }; // Support: Promises/A+ section 2.3.3.3.1 // https://promisesaplus.com/#point-57 // Re-resolve promises immediately to dodge false rejection from // subsequent errors if ( depth ) { process(); } else { // Call an optional hook to record the stack, in case of exception // since it's otherwise lost when execution goes async if ( jQuery.Deferred.getStackHook ) { process.stackTrace = jQuery.Deferred.getStackHook(); } window.setTimeout( process ); } }; } return jQuery.Deferred( function( newDefer ) { // progress_handlers.add( ... ) tuples[ 0 ][ 3 ].add( resolve( 0, newDefer, jQuery.isFunction( onProgress ) ? onProgress : Identity, newDefer.notifyWith ) ); // fulfilled_handlers.add( ... ) tuples[ 1 ][ 3 ].add( resolve( 0, newDefer, jQuery.isFunction( onFulfilled ) ? onFulfilled : Identity ) ); // rejected_handlers.add( ... ) tuples[ 2 ][ 3 ].add( resolve( 0, newDefer, jQuery.isFunction( onRejected ) ? onRejected : Thrower ) ); } ).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { return obj != null ? jQuery.extend( obj, promise ) : promise; } }, deferred = {}; // Add list-specific methods jQuery.each( tuples, function( i, tuple ) { var list = tuple[ 2 ], stateString = tuple[ 5 ]; // promise.progress = list.add // promise.done = list.add // promise.fail = list.add promise[ tuple[ 1 ] ] = list.add; // Handle state if ( stateString ) { list.add( function() { // state = "resolved" (i.e., fulfilled) // state = "rejected" state = stateString; }, // rejected_callbacks.disable // fulfilled_callbacks.disable tuples[ 3 - i ][ 2 ].disable, // progress_callbacks.lock tuples[ 0 ][ 2 ].lock ); } // progress_handlers.fire // fulfilled_handlers.fire // rejected_handlers.fire list.add( tuple[ 3 ].fire ); // deferred.notify = function() { deferred.notifyWith(...) } // deferred.resolve = function() { deferred.resolveWith(...) } // deferred.reject = function() { deferred.rejectWith(...) } deferred[ tuple[ 0 ] ] = function() { deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); return this; }; // deferred.notifyWith = list.fireWith // deferred.resolveWith = list.fireWith // deferred.rejectWith = list.fireWith deferred[ tuple[ 0 ] + "With" ] = list.fireWith; } ); // Make the deferred a promise promise.promise( deferred ); // Call given func if any if ( func ) { func.call( deferred, deferred ); } // All done! return deferred; }, // Deferred helper when: function( singleValue ) { var // count of uncompleted subordinates remaining = arguments.length, // count of unprocessed arguments i = remaining, // subordinate fulfillment data resolveContexts = Array( i ), resolveValues = slice.call( arguments ), // the master Deferred master = jQuery.Deferred(), // subordinate callback factory updateFunc = function( i ) { return function( value ) { resolveContexts[ i ] = this; resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; if ( !( --remaining ) ) { master.resolveWith( resolveContexts, resolveValues ); } }; }; // Single- and empty arguments are adopted like Promise.resolve if ( remaining <= 1 ) { adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, !remaining ); // Use .then() to unwrap secondary thenables (cf. gh-3000) if ( master.state() === "pending" || jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { return master.then(); } } // Multiple arguments are aggregated like Promise.all array elements while ( i-- ) { adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); } return master.promise(); } } ); // These usually indicate a programmer mistake during development, // warn about them ASAP rather than swallowing them by default. var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; jQuery.Deferred.exceptionHook = function( error, stack ) { // Support: IE 8 - 9 only // Console exists when dev tools are open, which can happen at any time if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); } }; jQuery.readyException = function( error ) { window.setTimeout( function() { throw error; } ); }; // The deferred used on DOM ready var readyList = jQuery.Deferred(); jQuery.fn.ready = function( fn ) { readyList .then( fn ) // Wrap jQuery.readyException in a function so that the lookup // happens at the time of error handling instead of callback // registration. .catch( function( error ) { jQuery.readyException( error ); } ); return this; }; jQuery.extend( { // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Handle when the DOM is ready ready: function( wait ) { // Abort if there are pending holds or we're already ready if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return; } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] ); } } ); jQuery.ready.then = readyList.then; // The ready event handler and self cleanup method function completed() { document.removeEventListener( "DOMContentLoaded", completed ); window.removeEventListener( "load", completed ); jQuery.ready(); } // Catch cases where $(document).ready() is called // after the browser event has already occurred. // Support: IE <=9 - 10 only // Older IE sometimes signals "interactive" too soon if ( document.readyState === "complete" || ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { // Handle it asynchronously to allow scripts the opportunity to delay ready window.setTimeout( jQuery.ready ); } else { // Use the handy event callback document.addEventListener( "DOMContentLoaded", completed ); // A fallback to window.onload, that will always work window.addEventListener( "load", completed ); } // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { var i = 0, len = elems.length, bulk = key == null; // Sets many values if ( jQuery.type( key ) === "object" ) { chainable = true; for ( i in key ) { access( elems, fn, i, key[ i ], true, emptyGet, raw ); } // Sets one value } else if ( value !== undefined ) { chainable = true; if ( !jQuery.isFunction( value ) ) { raw = true; } if ( bulk ) { // Bulk operations run against the entire set if ( raw ) { fn.call( elems, value ); fn = null; // ...except when executing function values } else { bulk = fn; fn = function( elem, key, value ) { return bulk.call( jQuery( elem ), value ); }; } } if ( fn ) { for ( ; i < len; i++ ) { fn( elems[ i ], key, raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) ) ); } } } if ( chainable ) { return elems; } // Gets if ( bulk ) { return fn.call( elems ); } return len ? fn( elems[ 0 ], key ) : emptyGet; }; var acceptData = function( owner ) { // Accepts only: // - Node // - Node.ELEMENT_NODE // - Node.DOCUMENT_NODE // - Object // - Any return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); }; function Data() { this.expando = jQuery.expando + Data.uid++; } Data.uid = 1; Data.prototype = { cache: function( owner ) { // Check if the owner object already has a cache var value = owner[ this.expando ]; // If not, create one if ( !value ) { value = {}; // We can accept data for non-element nodes in modern browsers, // but we should not, see #8335. // Always return an empty object. if ( acceptData( owner ) ) { // If it is a node unlikely to be stringify-ed or looped over // use plain assignment if ( owner.nodeType ) { owner[ this.expando ] = value; // Otherwise secure it in a non-enumerable property // configurable must be true to allow the property to be // deleted when data is removed } else { Object.defineProperty( owner, this.expando, { value: value, configurable: true } ); } } } return value; }, set: function( owner, data, value ) { var prop, cache = this.cache( owner ); // Handle: [ owner, key, value ] args // Always use camelCase key (gh-2257) if ( typeof data === "string" ) { cache[ jQuery.camelCase( data ) ] = value; // Handle: [ owner, { properties } ] args } else { // Copy the properties one-by-one to the cache object for ( prop in data ) { cache[ jQuery.camelCase( prop ) ] = data[ prop ]; } } return cache; }, get: function( owner, key ) { return key === undefined ? this.cache( owner ) : // Always use camelCase key (gh-2257) owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ]; }, access: function( owner, key, value ) { // In cases where either: // // 1. No key was specified // 2. A string key was specified, but no value provided // // Take the "read" path and allow the get method to determine // which value to return, respectively either: // // 1. The entire cache object // 2. The data stored at the key // if ( key === undefined || ( ( key && typeof key === "string" ) && value === undefined ) ) { return this.get( owner, key ); } // When the key is not a string, or both a key and value // are specified, set or extend (existing objects) with either: // // 1. An object of properties // 2. A key and value // this.set( owner, key, value ); // Since the "set" path can have two possible entry points // return the expected data based on which path was taken[*] return value !== undefined ? value : key; }, remove: function( owner, key ) { var i, cache = owner[ this.expando ]; if ( cache === undefined ) { return; } if ( key !== undefined ) { // Support array or space separated string of keys if ( Array.isArray( key ) ) { // If key is an array of keys... // We always set camelCase keys, so remove that. key = key.map( jQuery.camelCase ); } else { key = jQuery.camelCase( key ); // If a key with the spaces exists, use it. // Otherwise, create an array by matching non-whitespace key = key in cache ? [ key ] : ( key.match( rnothtmlwhite ) || [] ); } i = key.length; while ( i-- ) { delete cache[ key[ i ] ]; } } // Remove the expando if there's no more data if ( key === undefined || jQuery.isEmptyObject( cache ) ) { // Support: Chrome <=35 - 45 // Webkit & Blink performance suffers when deleting properties // from DOM nodes, so set to undefined instead // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) if ( owner.nodeType ) { owner[ this.expando ] = undefined; } else { delete owner[ this.expando ]; } } }, hasData: function( owner ) { var cache = owner[ this.expando ]; return cache !== undefined && !jQuery.isEmptyObject( cache ); } }; var dataPriv = new Data(); var dataUser = new Data(); // Implementation Summary // // 1. Enforce API surface and semantic compatibility with 1.9.x branch // 2. Improve the module's maintainability by reducing the storage // paths to a single mechanism. // 3. Use the same single mechanism to support "private" and "user" data. // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) // 5. Avoid exposing implementation details on user objects (eg. expando properties) // 6. Provide a clear path for implementation upgrade to WeakMap in 2014 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, rmultiDash = /[A-Z]/g; function getData( data ) { if ( data === "true" ) { return true; } if ( data === "false" ) { return false; } if ( data === "null" ) { return null; } // Only convert to a number if it doesn't change the string if ( data === +data + "" ) { return +data; } if ( rbrace.test( data ) ) { return JSON.parse( data ); } return data; } function dataAttr( elem, key, data ) { var name; // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = getData( data ); } catch ( e ) {} // Make sure we set the data so it isn't changed later dataUser.set( elem, key, data ); } else { data = undefined; } } return data; } jQuery.extend( { hasData: function( elem ) { return dataUser.hasData( elem ) || dataPriv.hasData( elem ); }, data: function( elem, name, data ) { return dataUser.access( elem, name, data ); }, removeData: function( elem, name ) { dataUser.remove( elem, name ); }, // TODO: Now that all calls to _data and _removeData have been replaced // with direct calls to dataPriv methods, these can be deprecated. _data: function( elem, name, data ) { return dataPriv.access( elem, name, data ); }, _removeData: function( elem, name ) { dataPriv.remove( elem, name ); } } ); jQuery.fn.extend( { data: function( key, value ) { var i, name, data, elem = this[ 0 ], attrs = elem && elem.attributes; // Gets all values if ( key === undefined ) { if ( this.length ) { data = dataUser.get( elem ); if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { i = attrs.length; while ( i-- ) { // Support: IE 11 only // The attrs elements can be null (#14894) if ( attrs[ i ] ) { name = attrs[ i ].name; if ( name.indexOf( "data-" ) === 0 ) { name = jQuery.camelCase( name.slice( 5 ) ); dataAttr( elem, name, data[ name ] ); } } } dataPriv.set( elem, "hasDataAttrs", true ); } } return data; } // Sets multiple values if ( typeof key === "object" ) { return this.each( function() { dataUser.set( this, key ); } ); } return access( this, function( value ) { var data; // The calling jQuery object (element matches) is not empty // (and therefore has an element appears at this[ 0 ]) and the // `value` parameter was not undefined. An empty jQuery object // will result in `undefined` for elem = this[ 0 ] which will // throw an exception if an attempt to read a data cache is made. if ( elem && value === undefined ) { // Attempt to get data from the cache // The key will always be camelCased in Data data = dataUser.get( elem, key ); if ( data !== undefined ) { return data; } // Attempt to "discover" the data in // HTML5 custom data-* attrs data = dataAttr( elem, key ); if ( data !== undefined ) { return data; } // We tried really hard, but the data doesn't exist. return; } // Set the data... this.each( function() { // We always store the camelCased key dataUser.set( this, key, value ); } ); }, null, value, arguments.length > 1, null, true ); }, removeData: function( key ) { return this.each( function() { dataUser.remove( this, key ); } ); } } ); jQuery.extend( { queue: function( elem, type, data ) { var queue; if ( elem ) { type = ( type || "fx" ) + "queue"; queue = dataPriv.get( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !queue || Array.isArray( data ) ) { queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); } else { queue.push( data ); } } return queue || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), startLength = queue.length, fn = queue.shift(), hooks = jQuery._queueHooks( elem, type ), next = function() { jQuery.dequeue( elem, type ); }; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); startLength--; } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift( "inprogress" ); } // Clear up the last queue stop function delete hooks.stop; fn.call( elem, next, hooks ); } if ( !startLength && hooks ) { hooks.empty.fire(); } }, // Not public - generate a queueHooks object, or return the current one _queueHooks: function( elem, type ) { var key = type + "queueHooks"; return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { empty: jQuery.Callbacks( "once memory" ).add( function() { dataPriv.remove( elem, [ type + "queue", key ] ); } ) } ); } } ); jQuery.fn.extend( { queue: function( type, data ) { var setter = 2; if ( typeof type !== "string" ) { data = type; type = "fx"; setter--; } if ( arguments.length < setter ) { return jQuery.queue( this[ 0 ], type ); } return data === undefined ? this : this.each( function() { var queue = jQuery.queue( this, type, data ); // Ensure a hooks for this queue jQuery._queueHooks( this, type ); if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { jQuery.dequeue( this, type ); } } ); }, dequeue: function( type ) { return this.each( function() { jQuery.dequeue( this, type ); } ); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, obj ) { var tmp, count = 1, defer = jQuery.Deferred(), elements = this, i = this.length, resolve = function() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } }; if ( typeof type !== "string" ) { obj = type; type = undefined; } type = type || "fx"; while ( i-- ) { tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); if ( tmp && tmp.empty ) { count++; tmp.empty.add( resolve ); } } resolve(); return defer.promise( obj ); } } ); var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; var isHiddenWithinTree = function( elem, el ) { // isHiddenWithinTree might be called from jQuery#filter function; // in that case, element will be second argument elem = el || elem; // Inline style trumps all return elem.style.display === "none" || elem.style.display === "" && // Otherwise, check computed style // Support: Firefox <=43 - 45 // Disconnected elements can have computed display: none, so first confirm that elem is // in the document. jQuery.contains( elem.ownerDocument, elem ) && jQuery.css( elem, "display" ) === "none"; }; var swap = function( elem, options, callback, args ) { var ret, name, old = {}; // Remember the old values, and insert the new ones for ( name in options ) { old[ name ] = elem.style[ name ]; elem.style[ name ] = options[ name ]; } ret = callback.apply( elem, args || [] ); // Revert the old values for ( name in options ) { elem.style[ name ] = old[ name ]; } return ret; }; function adjustCSS( elem, prop, valueParts, tween ) { var adjusted, scale = 1, maxIterations = 20, currentValue = tween ? function() { return tween.cur(); } : function() { return jQuery.css( elem, prop, "" ); }, initial = currentValue(), unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), // Starting value computation is required for potential unit mismatches initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && rcssNum.exec( jQuery.css( elem, prop ) ); if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { // Trust units reported by jQuery.css unit = unit || initialInUnit[ 3 ]; // Make sure we update the tween properties later on valueParts = valueParts || []; // Iteratively approximate from a nonzero starting point initialInUnit = +initial || 1; do { // If previous iteration zeroed out, double until we get *something*. // Use string for doubling so we don't accidentally see scale as unchanged below scale = scale || ".5"; // Adjust and apply initialInUnit = initialInUnit / scale; jQuery.style( elem, prop, initialInUnit + unit ); // Update scale, tolerating zero or NaN from tween.cur() // Break the loop if scale is unchanged or perfect, or if we've just had enough. } while ( scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations ); } if ( valueParts ) { initialInUnit = +initialInUnit || +initial || 0; // Apply relative offset (+=/-=) if specified adjusted = valueParts[ 1 ] ? initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : +valueParts[ 2 ]; if ( tween ) { tween.unit = unit; tween.start = initialInUnit; tween.end = adjusted; } } return adjusted; } var defaultDisplayMap = {}; function getDefaultDisplay( elem ) { var temp, doc = elem.ownerDocument, nodeName = elem.nodeName, display = defaultDisplayMap[ nodeName ]; if ( display ) { return display; } temp = doc.body.appendChild( doc.createElement( nodeName ) ); display = jQuery.css( temp, "display" ); temp.parentNode.removeChild( temp ); if ( display === "none" ) { display = "block"; } defaultDisplayMap[ nodeName ] = display; return display; } function showHide( elements, show ) { var display, elem, values = [], index = 0, length = elements.length; // Determine new display value for elements that need to change for ( ; index < length; index++ ) { elem = elements[ index ]; if ( !elem.style ) { continue; } display = elem.style.display; if ( show ) { // Since we force visibility upon cascade-hidden elements, an immediate (and slow) // check is required in this first loop unless we have a nonempty display value (either // inline or about-to-be-restored) if ( display === "none" ) { values[ index ] = dataPriv.get( elem, "display" ) || null; if ( !values[ index ] ) { elem.style.display = ""; } } if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { values[ index ] = getDefaultDisplay( elem ); } } else { if ( display !== "none" ) { values[ index ] = "none"; // Remember what we're overwriting dataPriv.set( elem, "display", display ); } } } // Set the display of the elements in a second loop to avoid constant reflow for ( index = 0; index < length; index++ ) { if ( values[ index ] != null ) { elements[ index ].style.display = values[ index ]; } } return elements; } jQuery.fn.extend( { show: function() { return showHide( this, true ); }, hide: function() { return showHide( this ); }, toggle: function( state ) { if ( typeof state === "boolean" ) { return state ? this.show() : this.hide(); } return this.each( function() { if ( isHiddenWithinTree( this ) ) { jQuery( this ).show(); } else { jQuery( this ).hide(); } } ); } } ); var rcheckableType = ( /^(?:checkbox|radio)$/i ); var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); var rscriptType = ( /^$|\/(?:java|ecma)script/i ); // We have to close these tags to support XHTML (#13200) var wrapMap = { // Support: IE <=9 only option: [ 1, "" ], // XHTML parsers do not magically insert elements in the // same way that tag soup parsers do. So we cannot shorten // this by omitting or other required elements. thead: [ 1, "", "
" ], col: [ 2, "", "
" ], tr: [ 2, "", "
" ], td: [ 3, "", "
" ], _default: [ 0, "", "" ] }; // Support: IE <=9 only wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; function getAll( context, tag ) { // Support: IE <=9 - 11 only // Use typeof to avoid zero-argument method invocation on host objects (#15151) var ret; if ( typeof context.getElementsByTagName !== "undefined" ) { ret = context.getElementsByTagName( tag || "*" ); } else if ( typeof context.querySelectorAll !== "undefined" ) { ret = context.querySelectorAll( tag || "*" ); } else { ret = []; } if ( tag === undefined || tag && nodeName( context, tag ) ) { return jQuery.merge( [ context ], ret ); } return ret; } // Mark scripts as having already been evaluated function setGlobalEval( elems, refElements ) { var i = 0, l = elems.length; for ( ; i < l; i++ ) { dataPriv.set( elems[ i ], "globalEval", !refElements || dataPriv.get( refElements[ i ], "globalEval" ) ); } } var rhtml = /<|&#?\w+;/; function buildFragment( elems, context, scripts, selection, ignored ) { var elem, tmp, tag, wrap, contains, j, fragment = context.createDocumentFragment(), nodes = [], i = 0, l = elems.length; for ( ; i < l; i++ ) { elem = elems[ i ]; if ( elem || elem === 0 ) { // Add nodes directly if ( jQuery.type( elem ) === "object" ) { // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); // Convert non-html into a text node } else if ( !rhtml.test( elem ) ) { nodes.push( context.createTextNode( elem ) ); // Convert html into DOM nodes } else { tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); // Deserialize a standard representation tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); wrap = wrapMap[ tag ] || wrapMap._default; tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; // Descend through wrappers to the right content j = wrap[ 0 ]; while ( j-- ) { tmp = tmp.lastChild; } // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( nodes, tmp.childNodes ); // Remember the top-level container tmp = fragment.firstChild; // Ensure the created nodes are orphaned (#12392) tmp.textContent = ""; } } } // Remove wrapper from fragment fragment.textContent = ""; i = 0; while ( ( elem = nodes[ i++ ] ) ) { // Skip elements already in the context collection (trac-4087) if ( selection && jQuery.inArray( elem, selection ) > -1 ) { if ( ignored ) { ignored.push( elem ); } continue; } contains = jQuery.contains( elem.ownerDocument, elem ); // Append to fragment tmp = getAll( fragment.appendChild( elem ), "script" ); // Preserve script evaluation history if ( contains ) { setGlobalEval( tmp ); } // Capture executables if ( scripts ) { j = 0; while ( ( elem = tmp[ j++ ] ) ) { if ( rscriptType.test( elem.type || "" ) ) { scripts.push( elem ); } } } } return fragment; } ( function() { var fragment = document.createDocumentFragment(), div = fragment.appendChild( document.createElement( "div" ) ), input = document.createElement( "input" ); // Support: Android 4.0 - 4.3 only // Check state lost if the name is set (#11217) // Support: Windows Web Apps (WWA) // `name` and `type` must use .setAttribute for WWA (#14901) input.setAttribute( "type", "radio" ); input.setAttribute( "checked", "checked" ); input.setAttribute( "name", "t" ); div.appendChild( input ); // Support: Android <=4.1 only // Older WebKit doesn't clone checked state correctly in fragments support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; // Support: IE <=11 only // Make sure textarea (and checkbox) defaultValue is properly cloned div.innerHTML = ""; support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; } )(); var documentElement = document.documentElement; var rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, rtypenamespace = /^([^.]*)(?:\.(.+)|)/; function returnTrue() { return true; } function returnFalse() { return false; } // Support: IE <=9 only // See #13393 for more info function safeActiveElement() { try { return document.activeElement; } catch ( err ) { } } function on( elem, types, selector, data, fn, one ) { var origFn, type; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // ( types-Object, data ) data = data || selector; selector = undefined; } for ( type in types ) { on( elem, type, selector, data, types[ type ], one ); } return elem; } if ( data == null && fn == null ) { // ( types, fn ) fn = selector; data = selector = undefined; } else if ( fn == null ) { if ( typeof selector === "string" ) { // ( types, selector, fn ) fn = data; data = undefined; } else { // ( types, data, fn ) fn = data; data = selector; selector = undefined; } } if ( fn === false ) { fn = returnFalse; } else if ( !fn ) { return elem; } if ( one === 1 ) { origFn = fn; fn = function( event ) { // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } return elem.each( function() { jQuery.event.add( this, types, fn, data, selector ); } ); } /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = { global: {}, add: function( elem, types, handler, data, selector ) { var handleObjIn, eventHandle, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, elemData = dataPriv.get( elem ); // Don't attach events to noData or text/comment nodes (but allow plain objects) if ( !elemData ) { return; } // Caller can pass in an object of custom data in lieu of the handler if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; selector = handleObjIn.selector; } // Ensure that invalid selectors throw exceptions at attach time // Evaluate against documentElement in case elem is a non-element node (e.g., document) if ( selector ) { jQuery.find.matchesSelector( documentElement, selector ); } // Make sure that the handler has a unique ID, used to find/remove it later if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure and main handler, if this is the first if ( !( events = elemData.events ) ) { events = elemData.events = {}; } if ( !( eventHandle = elemData.handle ) ) { eventHandle = elemData.handle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply( elem, arguments ) : undefined; }; } // Handle multiple events separated by a space types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; t = types.length; while ( t-- ) { tmp = rtypenamespace.exec( types[ t ] ) || []; type = origType = tmp[ 1 ]; namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); // There *must* be a type, no attaching namespace-only handlers if ( !type ) { continue; } // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; // If selector defined, determine special event api type, otherwise given type type = ( selector ? special.delegateType : special.bindType ) || type; // Update special based on newly reset type special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers handleObj = jQuery.extend( { type: type, origType: origType, data: data, handler: handler, guid: handler.guid, selector: selector, needsContext: selector && jQuery.expr.match.needsContext.test( selector ), namespace: namespaces.join( "." ) }, handleObjIn ); // Init the event handler queue if we're the first if ( !( handlers = events[ type ] ) ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener if the special events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add to the element's handler list, delegates in front if ( selector ) { handlers.splice( handlers.delegateCount++, 0, handleObj ); } else { handlers.push( handleObj ); } // Keep track of which events have ever been used, for event optimization jQuery.event.global[ type ] = true; } }, // Detach an event or set of events from an element remove: function( elem, types, handler, selector, mappedTypes ) { var j, origCount, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); if ( !elemData || !( events = elemData.events ) ) { return; } // Once for each type.namespace in types; type may be omitted types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; t = types.length; while ( t-- ) { tmp = rtypenamespace.exec( types[ t ] ) || []; type = origType = tmp[ 1 ]; namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); // Unbind all events (on this namespace, if provided) for the element if ( !type ) { for ( type in events ) { jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); } continue; } special = jQuery.event.special[ type ] || {}; type = ( selector ? special.delegateType : special.bindType ) || type; handlers = events[ type ] || []; tmp = tmp[ 2 ] && new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); // Remove matching events origCount = j = handlers.length; while ( j-- ) { handleObj = handlers[ j ]; if ( ( mappedTypes || origType === handleObj.origType ) && ( !handler || handler.guid === handleObj.guid ) && ( !tmp || tmp.test( handleObj.namespace ) ) && ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { handlers.splice( j, 1 ); if ( handleObj.selector ) { handlers.delegateCount--; } if ( special.remove ) { special.remove.call( elem, handleObj ); } } } // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( origCount && !handlers.length ) { if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } delete events[ type ]; } } // Remove data and the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { dataPriv.remove( elem, "handle events" ); } }, dispatch: function( nativeEvent ) { // Make a writable jQuery.Event from the native event object var event = jQuery.event.fix( nativeEvent ); var i, j, ret, matched, handleObj, handlerQueue, args = new Array( arguments.length ), handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event args[ 0 ] = event; for ( i = 1; i < arguments.length; i++ ) { args[ i ] = arguments[ i ]; } event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { return; } // Determine handlers handlerQueue = jQuery.event.handlers.call( this, event, handlers ); // Run delegates first; they may want to stop propagation beneath us i = 0; while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { event.currentTarget = matched.elem; j = 0; while ( ( handleObj = matched.handlers[ j++ ] ) && !event.isImmediatePropagationStopped() ) { // Triggered event must either 1) have no namespace, or 2) have namespace(s) // a subset or equal to those in the bound event (both can have no namespace). if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { event.handleObj = handleObj; event.data = handleObj.data; ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || handleObj.handler ).apply( matched.elem, args ); if ( ret !== undefined ) { if ( ( event.result = ret ) === false ) { event.preventDefault(); event.stopPropagation(); } } } } } // Call the postDispatch hook for the mapped type if ( special.postDispatch ) { special.postDispatch.call( this, event ); } return event.result; }, handlers: function( event, handlers ) { var i, handleObj, sel, matchedHandlers, matchedSelectors, handlerQueue = [], delegateCount = handlers.delegateCount, cur = event.target; // Find delegate handlers if ( delegateCount && // Support: IE <=9 // Black-hole SVG instance trees (trac-13180) cur.nodeType && // Support: Firefox <=42 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click // Support: IE 11 only // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) !( event.type === "click" && event.button >= 1 ) ) { for ( ; cur !== this; cur = cur.parentNode || this ) { // Don't check non-elements (#13208) // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { matchedHandlers = []; matchedSelectors = {}; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; // Don't conflict with Object.prototype properties (#13203) sel = handleObj.selector + " "; if ( matchedSelectors[ sel ] === undefined ) { matchedSelectors[ sel ] = handleObj.needsContext ? jQuery( sel, this ).index( cur ) > -1 : jQuery.find( sel, this, null, [ cur ] ).length; } if ( matchedSelectors[ sel ] ) { matchedHandlers.push( handleObj ); } } if ( matchedHandlers.length ) { handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); } } } } // Add the remaining (directly-bound) handlers cur = this; if ( delegateCount < handlers.length ) { handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); } return handlerQueue; }, addProp: function( name, hook ) { Object.defineProperty( jQuery.Event.prototype, name, { enumerable: true, configurable: true, get: jQuery.isFunction( hook ) ? function() { if ( this.originalEvent ) { return hook( this.originalEvent ); } } : function() { if ( this.originalEvent ) { return this.originalEvent[ name ]; } }, set: function( value ) { Object.defineProperty( this, name, { enumerable: true, configurable: true, writable: true, value: value } ); } } ); }, fix: function( originalEvent ) { return originalEvent[ jQuery.expando ] ? originalEvent : new jQuery.Event( originalEvent ); }, special: { load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, focus: { // Fire native event if possible so blur/focus sequence is correct trigger: function() { if ( this !== safeActiveElement() && this.focus ) { this.focus(); return false; } }, delegateType: "focusin" }, blur: { trigger: function() { if ( this === safeActiveElement() && this.blur ) { this.blur(); return false; } }, delegateType: "focusout" }, click: { // For checkbox, fire native event so checked state will be right trigger: function() { if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { this.click(); return false; } }, // For cross-browser consistency, don't fire native .click() on links _default: function( event ) { return nodeName( event.target, "a" ); } }, beforeunload: { postDispatch: function( event ) { // Support: Firefox 20+ // Firefox doesn't alert if the returnValue field is not set. if ( event.result !== undefined && event.originalEvent ) { event.originalEvent.returnValue = event.result; } } } } }; jQuery.removeEvent = function( elem, type, handle ) { // This "if" is needed for plain objects if ( elem.removeEventListener ) { elem.removeEventListener( type, handle ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !( this instanceof jQuery.Event ) ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && // Support: Android <=2.3 only src.returnValue === false ? returnTrue : returnFalse; // Create target properties // Support: Safari <=6 - 7 only // Target should not be a text node (#504, #13143) this.target = ( src.target && src.target.nodeType === 3 ) ? src.target.parentNode : src.target; this.currentTarget = src.currentTarget; this.relatedTarget = src.relatedTarget; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { constructor: jQuery.Event, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, isSimulated: false, preventDefault: function() { var e = this.originalEvent; this.isDefaultPrevented = returnTrue; if ( e && !this.isSimulated ) { e.preventDefault(); } }, stopPropagation: function() { var e = this.originalEvent; this.isPropagationStopped = returnTrue; if ( e && !this.isSimulated ) { e.stopPropagation(); } }, stopImmediatePropagation: function() { var e = this.originalEvent; this.isImmediatePropagationStopped = returnTrue; if ( e && !this.isSimulated ) { e.stopImmediatePropagation(); } this.stopPropagation(); } }; // Includes all common event props including KeyEvent and MouseEvent specific props jQuery.each( { altKey: true, bubbles: true, cancelable: true, changedTouches: true, ctrlKey: true, detail: true, eventPhase: true, metaKey: true, pageX: true, pageY: true, shiftKey: true, view: true, "char": true, charCode: true, key: true, keyCode: true, button: true, buttons: true, clientX: true, clientY: true, offsetX: true, offsetY: true, pointerId: true, pointerType: true, screenX: true, screenY: true, targetTouches: true, toElement: true, touches: true, which: function( event ) { var button = event.button; // Add which for key events if ( event.which == null && rkeyEvent.test( event.type ) ) { return event.charCode != null ? event.charCode : event.keyCode; } // Add which for click: 1 === left; 2 === middle; 3 === right if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { if ( button & 1 ) { return 1; } if ( button & 2 ) { return 3; } if ( button & 4 ) { return 2; } return 0; } return event.which; } }, jQuery.event.addProp ); // Create mouseenter/leave events using mouseover/out and event-time checks // so that event delegation works in jQuery. // Do the same for pointerenter/pointerleave and pointerover/pointerout // // Support: Safari 7 only // Safari sends mouseenter too often; see: // https://bugs.chromium.org/p/chromium/issues/detail?id=470258 // for the description of the bug (it existed in older Chrome versions as well). jQuery.each( { mouseenter: "mouseover", mouseleave: "mouseout", pointerenter: "pointerover", pointerleave: "pointerout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { delegateType: fix, bindType: fix, handle: function( event ) { var ret, target = this, related = event.relatedTarget, handleObj = event.handleObj; // For mouseenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; } return ret; } }; } ); jQuery.fn.extend( { on: function( types, selector, data, fn ) { return on( this, types, selector, data, fn ); }, one: function( types, selector, data, fn ) { return on( this, types, selector, data, fn, 1 ); }, off: function( types, selector, fn ) { var handleObj, type; if ( types && types.preventDefault && types.handleObj ) { // ( event ) dispatched jQuery.Event handleObj = types.handleObj; jQuery( types.delegateTarget ).off( handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler ); return this; } if ( typeof types === "object" ) { // ( types-object [, selector] ) for ( type in types ) { this.off( type, selector, types[ type ] ); } return this; } if ( selector === false || typeof selector === "function" ) { // ( types [, fn] ) fn = selector; selector = undefined; } if ( fn === false ) { fn = returnFalse; } return this.each( function() { jQuery.event.remove( this, types, fn, selector ); } ); } } ); var /* eslint-disable max-len */ // See https://github.com/eslint/eslint/issues/3229 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, /* eslint-enable */ // Support: IE <=10 - 11, Edge 12 - 13 // In IE/Edge using regex groups here causes severe slowdowns. // See https://connect.microsoft.com/IE/feedback/details/1736512/ rnoInnerhtml = /\s*$/g; // Prefer a tbody over its parent table for containing new rows function manipulationTarget( elem, content ) { if ( nodeName( elem, "table" ) && nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { return jQuery( ">tbody", elem )[ 0 ] || elem; } return elem; } // Replace/restore the type attribute of script elements for safe DOM manipulation function disableScript( elem ) { elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; return elem; } function restoreScript( elem ) { var match = rscriptTypeMasked.exec( elem.type ); if ( match ) { elem.type = match[ 1 ]; } else { elem.removeAttribute( "type" ); } return elem; } function cloneCopyEvent( src, dest ) { var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; if ( dest.nodeType !== 1 ) { return; } // 1. Copy private data: events, handlers, etc. if ( dataPriv.hasData( src ) ) { pdataOld = dataPriv.access( src ); pdataCur = dataPriv.set( dest, pdataOld ); events = pdataOld.events; if ( events ) { delete pdataCur.handle; pdataCur.events = {}; for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { jQuery.event.add( dest, type, events[ type ][ i ] ); } } } } // 2. Copy user data if ( dataUser.hasData( src ) ) { udataOld = dataUser.access( src ); udataCur = jQuery.extend( {}, udataOld ); dataUser.set( dest, udataCur ); } } // Fix IE bugs, see support tests function fixInput( src, dest ) { var nodeName = dest.nodeName.toLowerCase(); // Fails to persist the checked state of a cloned checkbox or radio button. if ( nodeName === "input" && rcheckableType.test( src.type ) ) { dest.checked = src.checked; // Fails to return the selected option to the default selected state when cloning options } else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; } } function domManip( collection, args, callback, ignored ) { // Flatten any nested arrays args = concat.apply( [], args ); var fragment, first, scripts, hasScripts, node, doc, i = 0, l = collection.length, iNoClone = l - 1, value = args[ 0 ], isFunction = jQuery.isFunction( value ); // We can't cloneNode fragments that contain checked, in WebKit if ( isFunction || ( l > 1 && typeof value === "string" && !support.checkClone && rchecked.test( value ) ) ) { return collection.each( function( index ) { var self = collection.eq( index ); if ( isFunction ) { args[ 0 ] = value.call( this, index, self.html() ); } domManip( self, args, callback, ignored ); } ); } if ( l ) { fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); first = fragment.firstChild; if ( fragment.childNodes.length === 1 ) { fragment = first; } // Require either new content or an interest in ignored elements to invoke the callback if ( first || ignored ) { scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); hasScripts = scripts.length; // Use the original fragment for the last item // instead of the first because it can end up // being emptied incorrectly in certain situations (#8070). for ( ; i < l; i++ ) { node = fragment; if ( i !== iNoClone ) { node = jQuery.clone( node, true, true ); // Keep references to cloned scripts for later restoration if ( hasScripts ) { // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( scripts, getAll( node, "script" ) ); } } callback.call( collection[ i ], node, i ); } if ( hasScripts ) { doc = scripts[ scripts.length - 1 ].ownerDocument; // Reenable scripts jQuery.map( scripts, restoreScript ); // Evaluate executable scripts on first document insertion for ( i = 0; i < hasScripts; i++ ) { node = scripts[ i ]; if ( rscriptType.test( node.type || "" ) && !dataPriv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { if ( node.src ) { // Optional AJAX dependency, but won't run scripts if not present if ( jQuery._evalUrl ) { jQuery._evalUrl( node.src ); } } else { DOMEval( node.textContent.replace( rcleanScript, "" ), doc ); } } } } } } return collection; } function remove( elem, selector, keepData ) { var node, nodes = selector ? jQuery.filter( selector, elem ) : elem, i = 0; for ( ; ( node = nodes[ i ] ) != null; i++ ) { if ( !keepData && node.nodeType === 1 ) { jQuery.cleanData( getAll( node ) ); } if ( node.parentNode ) { if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { setGlobalEval( getAll( node, "script" ) ); } node.parentNode.removeChild( node ); } } return elem; } jQuery.extend( { htmlPrefilter: function( html ) { return html.replace( rxhtmlTag, "<$1>" ); }, clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, clone = elem.cloneNode( true ), inPage = jQuery.contains( elem.ownerDocument, elem ); // Fix IE cloning issues if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 destElements = getAll( clone ); srcElements = getAll( elem ); for ( i = 0, l = srcElements.length; i < l; i++ ) { fixInput( srcElements[ i ], destElements[ i ] ); } } // Copy the events from the original to the clone if ( dataAndEvents ) { if ( deepDataAndEvents ) { srcElements = srcElements || getAll( elem ); destElements = destElements || getAll( clone ); for ( i = 0, l = srcElements.length; i < l; i++ ) { cloneCopyEvent( srcElements[ i ], destElements[ i ] ); } } else { cloneCopyEvent( elem, clone ); } } // Preserve script evaluation history destElements = getAll( clone, "script" ); if ( destElements.length > 0 ) { setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); } // Return the cloned set return clone; }, cleanData: function( elems ) { var data, elem, type, special = jQuery.event.special, i = 0; for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { if ( acceptData( elem ) ) { if ( ( data = elem[ dataPriv.expando ] ) ) { if ( data.events ) { for ( type in data.events ) { if ( special[ type ] ) { jQuery.event.remove( elem, type ); // This is a shortcut to avoid jQuery.event.remove's overhead } else { jQuery.removeEvent( elem, type, data.handle ); } } } // Support: Chrome <=35 - 45+ // Assign undefined instead of using delete, see Data#remove elem[ dataPriv.expando ] = undefined; } if ( elem[ dataUser.expando ] ) { // Support: Chrome <=35 - 45+ // Assign undefined instead of using delete, see Data#remove elem[ dataUser.expando ] = undefined; } } } } } ); jQuery.fn.extend( { detach: function( selector ) { return remove( this, selector, true ); }, remove: function( selector ) { return remove( this, selector ); }, text: function( value ) { return access( this, function( value ) { return value === undefined ? jQuery.text( this ) : this.empty().each( function() { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { this.textContent = value; } } ); }, null, value, arguments.length ); }, append: function() { return domManip( this, arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.appendChild( elem ); } } ); }, prepend: function() { return domManip( this, arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.insertBefore( elem, target.firstChild ); } } ); }, before: function() { return domManip( this, arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); } } ); }, after: function() { return domManip( this, arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); } } ); }, empty: function() { var elem, i = 0; for ( ; ( elem = this[ i ] ) != null; i++ ) { if ( elem.nodeType === 1 ) { // Prevent memory leaks jQuery.cleanData( getAll( elem, false ) ); // Remove any remaining nodes elem.textContent = ""; } } return this; }, clone: function( dataAndEvents, deepDataAndEvents ) { dataAndEvents = dataAndEvents == null ? false : dataAndEvents; deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; return this.map( function() { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); } ); }, html: function( value ) { return access( this, function( value ) { var elem = this[ 0 ] || {}, i = 0, l = this.length; if ( value === undefined && elem.nodeType === 1 ) { return elem.innerHTML; } // See if we can take a shortcut and just use innerHTML if ( typeof value === "string" && !rnoInnerhtml.test( value ) && !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { value = jQuery.htmlPrefilter( value ); try { for ( ; i < l; i++ ) { elem = this[ i ] || {}; // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; } } elem = 0; // If using innerHTML throws an exception, use the fallback method } catch ( e ) {} } if ( elem ) { this.empty().append( value ); } }, null, value, arguments.length ); }, replaceWith: function() { var ignored = []; // Make the changes, replacing each non-ignored context element with the new content return domManip( this, arguments, function( elem ) { var parent = this.parentNode; if ( jQuery.inArray( this, ignored ) < 0 ) { jQuery.cleanData( getAll( this ) ); if ( parent ) { parent.replaceChild( elem, this ); } } // Force callback invocation }, ignored ); } } ); jQuery.each( { appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function( name, original ) { jQuery.fn[ name ] = function( selector ) { var elems, ret = [], insert = jQuery( selector ), last = insert.length - 1, i = 0; for ( ; i <= last; i++ ) { elems = i === last ? this : this.clone( true ); jQuery( insert[ i ] )[ original ]( elems ); // Support: Android <=4.0 only, PhantomJS 1 only // .get() because push.apply(_, arraylike) throws on ancient WebKit push.apply( ret, elems.get() ); } return this.pushStack( ret ); }; } ); var rmargin = ( /^margin/ ); var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); var getStyles = function( elem ) { // Support: IE <=11 only, Firefox <=30 (#15098, #14150) // IE throws on elements created in popups // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" var view = elem.ownerDocument.defaultView; if ( !view || !view.opener ) { view = window; } return view.getComputedStyle( elem ); }; ( function() { // Executing both pixelPosition & boxSizingReliable tests require only one layout // so they're executed at the same time to save the second computation. function computeStyleTests() { // This is a singleton, we need to execute it only once if ( !div ) { return; } div.style.cssText = "box-sizing:border-box;" + "position:relative;display:block;" + "margin:auto;border:1px;padding:1px;" + "top:1%;width:50%"; div.innerHTML = ""; documentElement.appendChild( container ); var divStyle = window.getComputedStyle( div ); pixelPositionVal = divStyle.top !== "1%"; // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 reliableMarginLeftVal = divStyle.marginLeft === "2px"; boxSizingReliableVal = divStyle.width === "4px"; // Support: Android 4.0 - 4.3 only // Some styles come back with percentage values, even though they shouldn't div.style.marginRight = "50%"; pixelMarginRightVal = divStyle.marginRight === "4px"; documentElement.removeChild( container ); // Nullify the div so it wouldn't be stored in the memory and // it will also be a sign that checks already performed div = null; } var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal, container = document.createElement( "div" ), div = document.createElement( "div" ); // Finish early in limited (non-browser) environments if ( !div.style ) { return; } // Support: IE <=9 - 11 only // Style of cloned element affects source element cloned (#8908) div.style.backgroundClip = "content-box"; div.cloneNode( true ).style.backgroundClip = ""; support.clearCloneStyle = div.style.backgroundClip === "content-box"; container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" + "padding:0;margin-top:1px;position:absolute"; container.appendChild( div ); jQuery.extend( support, { pixelPosition: function() { computeStyleTests(); return pixelPositionVal; }, boxSizingReliable: function() { computeStyleTests(); return boxSizingReliableVal; }, pixelMarginRight: function() { computeStyleTests(); return pixelMarginRightVal; }, reliableMarginLeft: function() { computeStyleTests(); return reliableMarginLeftVal; } } ); } )(); function curCSS( elem, name, computed ) { var width, minWidth, maxWidth, ret, // Support: Firefox 51+ // Retrieving style before computed somehow // fixes an issue with getting wrong values // on detached elements style = elem.style; computed = computed || getStyles( elem ); // getPropertyValue is needed for: // .css('filter') (IE 9 only, #12537) // .css('--customProperty) (#3144) if ( computed ) { ret = computed.getPropertyValue( name ) || computed[ name ]; if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { ret = jQuery.style( elem, name ); } // A tribute to the "awesome hack by Dean Edwards" // Android Browser returns percentage for some values, // but width seems to be reliably pixels. // This is against the CSSOM draft spec: // https://drafts.csswg.org/cssom/#resolved-values if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) { // Remember the original values width = style.width; minWidth = style.minWidth; maxWidth = style.maxWidth; // Put in the new values to get a computed value out style.minWidth = style.maxWidth = style.width = ret; ret = computed.width; // Revert the changed values style.width = width; style.minWidth = minWidth; style.maxWidth = maxWidth; } } return ret !== undefined ? // Support: IE <=9 - 11 only // IE returns zIndex value as an integer. ret + "" : ret; } function addGetHookIf( conditionFn, hookFn ) { // Define the hook, we'll check on the first run if it's really needed. return { get: function() { if ( conditionFn() ) { // Hook not needed (or it's not possible to use it due // to missing dependency), remove it. delete this.get; return; } // Hook needed; redefine it so that the support test is not executed again. return ( this.get = hookFn ).apply( this, arguments ); } }; } var // Swappable if display is none or starts with table // except "table", "table-cell", or "table-caption" // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display rdisplayswap = /^(none|table(?!-c[ea]).+)/, rcustomProp = /^--/, cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssNormalTransform = { letterSpacing: "0", fontWeight: "400" }, cssPrefixes = [ "Webkit", "Moz", "ms" ], emptyStyle = document.createElement( "div" ).style; // Return a css property mapped to a potentially vendor prefixed property function vendorPropName( name ) { // Shortcut for names that are not vendor prefixed if ( name in emptyStyle ) { return name; } // Check for vendor prefixed names var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), i = cssPrefixes.length; while ( i-- ) { name = cssPrefixes[ i ] + capName; if ( name in emptyStyle ) { return name; } } } // Return a property mapped along what jQuery.cssProps suggests or to // a vendor prefixed property. function finalPropName( name ) { var ret = jQuery.cssProps[ name ]; if ( !ret ) { ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; } return ret; } function setPositiveNumber( elem, value, subtract ) { // Any relative (+/-) values have already been // normalized at this point var matches = rcssNum.exec( value ); return matches ? // Guard against undefined "subtract", e.g., when used as in cssHooks Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : value; } function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { var i, val = 0; // If we already have the right measurement, avoid augmentation if ( extra === ( isBorderBox ? "border" : "content" ) ) { i = 4; // Otherwise initialize for horizontal or vertical properties } else { i = name === "width" ? 1 : 0; } for ( ; i < 4; i += 2 ) { // Both box models exclude margin, so add it if we want it if ( extra === "margin" ) { val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); } if ( isBorderBox ) { // border-box includes padding, so remove it if we want content if ( extra === "content" ) { val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); } // At this point, extra isn't border nor margin, so remove border if ( extra !== "margin" ) { val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } else { // At this point, extra isn't content, so add padding val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); // At this point, extra isn't content nor padding, so add border if ( extra !== "padding" ) { val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } } return val; } function getWidthOrHeight( elem, name, extra ) { // Start with computed style var valueIsBorderBox, styles = getStyles( elem ), val = curCSS( elem, name, styles ), isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; // Computed unit is not pixels. Stop here and return. if ( rnumnonpx.test( val ) ) { return val; } // Check for style in case a browser which returns unreliable values // for getComputedStyle silently falls back to the reliable elem.style valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] ); // Fall back to offsetWidth/Height when value is "auto" // This happens for inline elements with no explicit setting (gh-3571) if ( val === "auto" ) { val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ]; } // Normalize "", auto, and prepare for extra val = parseFloat( val ) || 0; // Use the active box-sizing model to add/subtract irrelevant styles return ( val + augmentWidthOrHeight( elem, name, extra || ( isBorderBox ? "border" : "content" ), valueIsBorderBox, styles ) ) + "px"; } jQuery.extend( { // Add in style property hooks for overriding the default // behavior of getting and setting a style property cssHooks: { opacity: { get: function( elem, computed ) { if ( computed ) { // We should always get a number back from opacity var ret = curCSS( elem, "opacity" ); return ret === "" ? "1" : ret; } } } }, // Don't automatically add "px" to these possibly-unitless properties cssNumber: { "animationIterationCount": true, "columnCount": true, "fillOpacity": true, "flexGrow": true, "flexShrink": true, "fontWeight": true, "lineHeight": true, "opacity": true, "order": true, "orphans": true, "widows": true, "zIndex": true, "zoom": true }, // Add in properties whose names you wish to fix before // setting or getting the value cssProps: { "float": "cssFloat" }, // Get and set the style property on a DOM Node style: function( elem, name, value, extra ) { // Don't set styles on text and comment nodes if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { return; } // Make sure that we're working with the right name var ret, type, hooks, origName = jQuery.camelCase( name ), isCustomProp = rcustomProp.test( name ), style = elem.style; // Make sure that we're working with the right name. We don't // want to query the value if it is a CSS custom property // since they are user-defined. if ( !isCustomProp ) { name = finalPropName( origName ); } // Gets hook for the prefixed version, then unprefixed version hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // Check if we're setting a value if ( value !== undefined ) { type = typeof value; // Convert "+=" or "-=" to relative numbers (#7345) if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { value = adjustCSS( elem, name, ret ); // Fixes bug #9237 type = "number"; } // Make sure that null and NaN values aren't set (#7116) if ( value == null || value !== value ) { return; } // If a number was passed in, add the unit (except for certain CSS properties) if ( type === "number" ) { value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); } // background-* props affect original clone's values if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { style[ name ] = "inherit"; } // If a hook was provided, use that value, otherwise just set the specified value if ( !hooks || !( "set" in hooks ) || ( value = hooks.set( elem, value, extra ) ) !== undefined ) { if ( isCustomProp ) { style.setProperty( name, value ); } else { style[ name ] = value; } } } else { // If a hook was provided get the non-computed value from there if ( hooks && "get" in hooks && ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { return ret; } // Otherwise just get the value from the style object return style[ name ]; } }, css: function( elem, name, extra, styles ) { var val, num, hooks, origName = jQuery.camelCase( name ), isCustomProp = rcustomProp.test( name ); // Make sure that we're working with the right name. We don't // want to modify the value if it is a CSS custom property // since they are user-defined. if ( !isCustomProp ) { name = finalPropName( origName ); } // Try prefixed name followed by the unprefixed name hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // If a hook was provided get the computed value from there if ( hooks && "get" in hooks ) { val = hooks.get( elem, true, extra ); } // Otherwise, if a way to get the computed value exists, use that if ( val === undefined ) { val = curCSS( elem, name, styles ); } // Convert "normal" to computed value if ( val === "normal" && name in cssNormalTransform ) { val = cssNormalTransform[ name ]; } // Make numeric if forced or a qualifier was provided and val looks numeric if ( extra === "" || extra ) { num = parseFloat( val ); return extra === true || isFinite( num ) ? num || 0 : val; } return val; } } ); jQuery.each( [ "height", "width" ], function( i, name ) { jQuery.cssHooks[ name ] = { get: function( elem, computed, extra ) { if ( computed ) { // Certain elements can have dimension info if we invisibly show them // but it must have a current display style that would benefit return rdisplayswap.test( jQuery.css( elem, "display" ) ) && // Support: Safari 8+ // Table columns in Safari have non-zero offsetWidth & zero // getBoundingClientRect().width unless display is changed. // Support: IE <=11 only // Running getBoundingClientRect on a disconnected node // in IE throws an error. ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? swap( elem, cssShow, function() { return getWidthOrHeight( elem, name, extra ); } ) : getWidthOrHeight( elem, name, extra ); } }, set: function( elem, value, extra ) { var matches, styles = extra && getStyles( elem ), subtract = extra && augmentWidthOrHeight( elem, name, extra, jQuery.css( elem, "boxSizing", false, styles ) === "border-box", styles ); // Convert to pixels if value adjustment is needed if ( subtract && ( matches = rcssNum.exec( value ) ) && ( matches[ 3 ] || "px" ) !== "px" ) { elem.style[ name ] = value; value = jQuery.css( elem, name ); } return setPositiveNumber( elem, value, subtract ); } }; } ); jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, function( elem, computed ) { if ( computed ) { return ( parseFloat( curCSS( elem, "marginLeft" ) ) || elem.getBoundingClientRect().left - swap( elem, { marginLeft: 0 }, function() { return elem.getBoundingClientRect().left; } ) ) + "px"; } } ); // These hooks are used by animate to expand properties jQuery.each( { margin: "", padding: "", border: "Width" }, function( prefix, suffix ) { jQuery.cssHooks[ prefix + suffix ] = { expand: function( value ) { var i = 0, expanded = {}, // Assumes a single number if not a string parts = typeof value === "string" ? value.split( " " ) : [ value ]; for ( ; i < 4; i++ ) { expanded[ prefix + cssExpand[ i ] + suffix ] = parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; } return expanded; } }; if ( !rmargin.test( prefix ) ) { jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; } } ); jQuery.fn.extend( { css: function( name, value ) { return access( this, function( elem, name, value ) { var styles, len, map = {}, i = 0; if ( Array.isArray( name ) ) { styles = getStyles( elem ); len = name.length; for ( ; i < len; i++ ) { map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); } return map; } return value !== undefined ? jQuery.style( elem, name, value ) : jQuery.css( elem, name ); }, name, value, arguments.length > 1 ); } } ); function Tween( elem, options, prop, end, easing ) { return new Tween.prototype.init( elem, options, prop, end, easing ); } jQuery.Tween = Tween; Tween.prototype = { constructor: Tween, init: function( elem, options, prop, end, easing, unit ) { this.elem = elem; this.prop = prop; this.easing = easing || jQuery.easing._default; this.options = options; this.start = this.now = this.cur(); this.end = end; this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); }, cur: function() { var hooks = Tween.propHooks[ this.prop ]; return hooks && hooks.get ? hooks.get( this ) : Tween.propHooks._default.get( this ); }, run: function( percent ) { var eased, hooks = Tween.propHooks[ this.prop ]; if ( this.options.duration ) { this.pos = eased = jQuery.easing[ this.easing ]( percent, this.options.duration * percent, 0, 1, this.options.duration ); } else { this.pos = eased = percent; } this.now = ( this.end - this.start ) * eased + this.start; if ( this.options.step ) { this.options.step.call( this.elem, this.now, this ); } if ( hooks && hooks.set ) { hooks.set( this ); } else { Tween.propHooks._default.set( this ); } return this; } }; Tween.prototype.init.prototype = Tween.prototype; Tween.propHooks = { _default: { get: function( tween ) { var result; // Use a property on the element directly when it is not a DOM element, // or when there is no matching style property that exists. if ( tween.elem.nodeType !== 1 || tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { return tween.elem[ tween.prop ]; } // Passing an empty string as a 3rd parameter to .css will automatically // attempt a parseFloat and fallback to a string if the parse fails. // Simple values such as "10px" are parsed to Float; // complex values such as "rotate(1rad)" are returned as-is. result = jQuery.css( tween.elem, tween.prop, "" ); // Empty strings, null, undefined and "auto" are converted to 0. return !result || result === "auto" ? 0 : result; }, set: function( tween ) { // Use step hook for back compat. // Use cssHook if its there. // Use .style if available and use plain properties where available. if ( jQuery.fx.step[ tween.prop ] ) { jQuery.fx.step[ tween.prop ]( tween ); } else if ( tween.elem.nodeType === 1 && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); } else { tween.elem[ tween.prop ] = tween.now; } } } }; // Support: IE <=9 only // Panic based approach to setting things on disconnected nodes Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { set: function( tween ) { if ( tween.elem.nodeType && tween.elem.parentNode ) { tween.elem[ tween.prop ] = tween.now; } } }; jQuery.easing = { linear: function( p ) { return p; }, swing: function( p ) { return 0.5 - Math.cos( p * Math.PI ) / 2; }, _default: "swing" }; jQuery.fx = Tween.prototype.init; // Back compat <1.8 extension point jQuery.fx.step = {}; var fxNow, inProgress, rfxtypes = /^(?:toggle|show|hide)$/, rrun = /queueHooks$/; function schedule() { if ( inProgress ) { if ( document.hidden === false && window.requestAnimationFrame ) { window.requestAnimationFrame( schedule ); } else { window.setTimeout( schedule, jQuery.fx.interval ); } jQuery.fx.tick(); } } // Animations created synchronously will run synchronously function createFxNow() { window.setTimeout( function() { fxNow = undefined; } ); return ( fxNow = jQuery.now() ); } // Generate parameters to create a standard animation function genFx( type, includeWidth ) { var which, i = 0, attrs = { height: type }; // If we include width, step value is 1 to do all cssExpand values, // otherwise step value is 2 to skip over Left and Right includeWidth = includeWidth ? 1 : 0; for ( ; i < 4; i += 2 - includeWidth ) { which = cssExpand[ i ]; attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; } if ( includeWidth ) { attrs.opacity = attrs.width = type; } return attrs; } function createTween( value, prop, animation ) { var tween, collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), index = 0, length = collection.length; for ( ; index < length; index++ ) { if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { // We're done with this property return tween; } } } function defaultPrefilter( elem, props, opts ) { var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, isBox = "width" in props || "height" in props, anim = this, orig = {}, style = elem.style, hidden = elem.nodeType && isHiddenWithinTree( elem ), dataShow = dataPriv.get( elem, "fxshow" ); // Queue-skipping animations hijack the fx hooks if ( !opts.queue ) { hooks = jQuery._queueHooks( elem, "fx" ); if ( hooks.unqueued == null ) { hooks.unqueued = 0; oldfire = hooks.empty.fire; hooks.empty.fire = function() { if ( !hooks.unqueued ) { oldfire(); } }; } hooks.unqueued++; anim.always( function() { // Ensure the complete handler is called before this completes anim.always( function() { hooks.unqueued--; if ( !jQuery.queue( elem, "fx" ).length ) { hooks.empty.fire(); } } ); } ); } // Detect show/hide animations for ( prop in props ) { value = props[ prop ]; if ( rfxtypes.test( value ) ) { delete props[ prop ]; toggle = toggle || value === "toggle"; if ( value === ( hidden ? "hide" : "show" ) ) { // Pretend to be hidden if this is a "show" and // there is still data from a stopped show/hide if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { hidden = true; // Ignore all other no-op show/hide data } else { continue; } } orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); } } // Bail out if this is a no-op like .hide().hide() propTween = !jQuery.isEmptyObject( props ); if ( !propTween && jQuery.isEmptyObject( orig ) ) { return; } // Restrict "overflow" and "display" styles during box animations if ( isBox && elem.nodeType === 1 ) { // Support: IE <=9 - 11, Edge 12 - 13 // Record all 3 overflow attributes because IE does not infer the shorthand // from identically-valued overflowX and overflowY opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; // Identify a display type, preferring old show/hide data over the CSS cascade restoreDisplay = dataShow && dataShow.display; if ( restoreDisplay == null ) { restoreDisplay = dataPriv.get( elem, "display" ); } display = jQuery.css( elem, "display" ); if ( display === "none" ) { if ( restoreDisplay ) { display = restoreDisplay; } else { // Get nonempty value(s) by temporarily forcing visibility showHide( [ elem ], true ); restoreDisplay = elem.style.display || restoreDisplay; display = jQuery.css( elem, "display" ); showHide( [ elem ] ); } } // Animate inline elements as inline-block if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { if ( jQuery.css( elem, "float" ) === "none" ) { // Restore the original display value at the end of pure show/hide animations if ( !propTween ) { anim.done( function() { style.display = restoreDisplay; } ); if ( restoreDisplay == null ) { display = style.display; restoreDisplay = display === "none" ? "" : display; } } style.display = "inline-block"; } } } if ( opts.overflow ) { style.overflow = "hidden"; anim.always( function() { style.overflow = opts.overflow[ 0 ]; style.overflowX = opts.overflow[ 1 ]; style.overflowY = opts.overflow[ 2 ]; } ); } // Implement show/hide animations propTween = false; for ( prop in orig ) { // General show/hide setup for this element animation if ( !propTween ) { if ( dataShow ) { if ( "hidden" in dataShow ) { hidden = dataShow.hidden; } } else { dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); } // Store hidden/visible for toggle so `.stop().toggle()` "reverses" if ( toggle ) { dataShow.hidden = !hidden; } // Show elements before animating them if ( hidden ) { showHide( [ elem ], true ); } /* eslint-disable no-loop-func */ anim.done( function() { /* eslint-enable no-loop-func */ // The final step of a "hide" animation is actually hiding the element if ( !hidden ) { showHide( [ elem ] ); } dataPriv.remove( elem, "fxshow" ); for ( prop in orig ) { jQuery.style( elem, prop, orig[ prop ] ); } } ); } // Per-property setup propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); if ( !( prop in dataShow ) ) { dataShow[ prop ] = propTween.start; if ( hidden ) { propTween.end = propTween.start; propTween.start = 0; } } } } function propFilter( props, specialEasing ) { var index, name, easing, value, hooks; // camelCase, specialEasing and expand cssHook pass for ( index in props ) { name = jQuery.camelCase( index ); easing = specialEasing[ name ]; value = props[ index ]; if ( Array.isArray( value ) ) { easing = value[ 1 ]; value = props[ index ] = value[ 0 ]; } if ( index !== name ) { props[ name ] = value; delete props[ index ]; } hooks = jQuery.cssHooks[ name ]; if ( hooks && "expand" in hooks ) { value = hooks.expand( value ); delete props[ name ]; // Not quite $.extend, this won't overwrite existing keys. // Reusing 'index' because we have the correct "name" for ( index in value ) { if ( !( index in props ) ) { props[ index ] = value[ index ]; specialEasing[ index ] = easing; } } } else { specialEasing[ name ] = easing; } } } function Animation( elem, properties, options ) { var result, stopped, index = 0, length = Animation.prefilters.length, deferred = jQuery.Deferred().always( function() { // Don't match elem in the :animated selector delete tick.elem; } ), tick = function() { if ( stopped ) { return false; } var currentTime = fxNow || createFxNow(), remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), // Support: Android 2.3 only // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) temp = remaining / animation.duration || 0, percent = 1 - temp, index = 0, length = animation.tweens.length; for ( ; index < length; index++ ) { animation.tweens[ index ].run( percent ); } deferred.notifyWith( elem, [ animation, percent, remaining ] ); // If there's more to do, yield if ( percent < 1 && length ) { return remaining; } // If this was an empty animation, synthesize a final progress notification if ( !length ) { deferred.notifyWith( elem, [ animation, 1, 0 ] ); } // Resolve the animation and report its conclusion deferred.resolveWith( elem, [ animation ] ); return false; }, animation = deferred.promise( { elem: elem, props: jQuery.extend( {}, properties ), opts: jQuery.extend( true, { specialEasing: {}, easing: jQuery.easing._default }, options ), originalProperties: properties, originalOptions: options, startTime: fxNow || createFxNow(), duration: options.duration, tweens: [], createTween: function( prop, end ) { var tween = jQuery.Tween( elem, animation.opts, prop, end, animation.opts.specialEasing[ prop ] || animation.opts.easing ); animation.tweens.push( tween ); return tween; }, stop: function( gotoEnd ) { var index = 0, // If we are going to the end, we want to run all the tweens // otherwise we skip this part length = gotoEnd ? animation.tweens.length : 0; if ( stopped ) { return this; } stopped = true; for ( ; index < length; index++ ) { animation.tweens[ index ].run( 1 ); } // Resolve when we played the last frame; otherwise, reject if ( gotoEnd ) { deferred.notifyWith( elem, [ animation, 1, 0 ] ); deferred.resolveWith( elem, [ animation, gotoEnd ] ); } else { deferred.rejectWith( elem, [ animation, gotoEnd ] ); } return this; } } ), props = animation.props; propFilter( props, animation.opts.specialEasing ); for ( ; index < length; index++ ) { result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); if ( result ) { if ( jQuery.isFunction( result.stop ) ) { jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = jQuery.proxy( result.stop, result ); } return result; } } jQuery.map( props, createTween, animation ); if ( jQuery.isFunction( animation.opts.start ) ) { animation.opts.start.call( elem, animation ); } // Attach callbacks from options animation .progress( animation.opts.progress ) .done( animation.opts.done, animation.opts.complete ) .fail( animation.opts.fail ) .always( animation.opts.always ); jQuery.fx.timer( jQuery.extend( tick, { elem: elem, anim: animation, queue: animation.opts.queue } ) ); return animation; } jQuery.Animation = jQuery.extend( Animation, { tweeners: { "*": [ function( prop, value ) { var tween = this.createTween( prop, value ); adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); return tween; } ] }, tweener: function( props, callback ) { if ( jQuery.isFunction( props ) ) { callback = props; props = [ "*" ]; } else { props = props.match( rnothtmlwhite ); } var prop, index = 0, length = props.length; for ( ; index < length; index++ ) { prop = props[ index ]; Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; Animation.tweeners[ prop ].unshift( callback ); } }, prefilters: [ defaultPrefilter ], prefilter: function( callback, prepend ) { if ( prepend ) { Animation.prefilters.unshift( callback ); } else { Animation.prefilters.push( callback ); } } } ); jQuery.speed = function( speed, easing, fn ) { var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { complete: fn || !fn && easing || jQuery.isFunction( speed ) && speed, duration: speed, easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing }; // Go to the end state if fx are off if ( jQuery.fx.off ) { opt.duration = 0; } else { if ( typeof opt.duration !== "number" ) { if ( opt.duration in jQuery.fx.speeds ) { opt.duration = jQuery.fx.speeds[ opt.duration ]; } else { opt.duration = jQuery.fx.speeds._default; } } } // Normalize opt.queue - true/undefined/null -> "fx" if ( opt.queue == null || opt.queue === true ) { opt.queue = "fx"; } // Queueing opt.old = opt.complete; opt.complete = function() { if ( jQuery.isFunction( opt.old ) ) { opt.old.call( this ); } if ( opt.queue ) { jQuery.dequeue( this, opt.queue ); } }; return opt; }; jQuery.fn.extend( { fadeTo: function( speed, to, easing, callback ) { // Show any hidden elements after setting opacity to 0 return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() // Animate to the value specified .end().animate( { opacity: to }, speed, easing, callback ); }, animate: function( prop, speed, easing, callback ) { var empty = jQuery.isEmptyObject( prop ), optall = jQuery.speed( speed, easing, callback ), doAnimation = function() { // Operate on a copy of prop so per-property easing won't be lost var anim = Animation( this, jQuery.extend( {}, prop ), optall ); // Empty animations, or finishing resolves immediately if ( empty || dataPriv.get( this, "finish" ) ) { anim.stop( true ); } }; doAnimation.finish = doAnimation; return empty || optall.queue === false ? this.each( doAnimation ) : this.queue( optall.queue, doAnimation ); }, stop: function( type, clearQueue, gotoEnd ) { var stopQueue = function( hooks ) { var stop = hooks.stop; delete hooks.stop; stop( gotoEnd ); }; if ( typeof type !== "string" ) { gotoEnd = clearQueue; clearQueue = type; type = undefined; } if ( clearQueue && type !== false ) { this.queue( type || "fx", [] ); } return this.each( function() { var dequeue = true, index = type != null && type + "queueHooks", timers = jQuery.timers, data = dataPriv.get( this ); if ( index ) { if ( data[ index ] && data[ index ].stop ) { stopQueue( data[ index ] ); } } else { for ( index in data ) { if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { stopQueue( data[ index ] ); } } } for ( index = timers.length; index--; ) { if ( timers[ index ].elem === this && ( type == null || timers[ index ].queue === type ) ) { timers[ index ].anim.stop( gotoEnd ); dequeue = false; timers.splice( index, 1 ); } } // Start the next in the queue if the last step wasn't forced. // Timers currently will call their complete callbacks, which // will dequeue but only if they were gotoEnd. if ( dequeue || !gotoEnd ) { jQuery.dequeue( this, type ); } } ); }, finish: function( type ) { if ( type !== false ) { type = type || "fx"; } return this.each( function() { var index, data = dataPriv.get( this ), queue = data[ type + "queue" ], hooks = data[ type + "queueHooks" ], timers = jQuery.timers, length = queue ? queue.length : 0; // Enable finishing flag on private data data.finish = true; // Empty the queue first jQuery.queue( this, type, [] ); if ( hooks && hooks.stop ) { hooks.stop.call( this, true ); } // Look for any active animations, and finish them for ( index = timers.length; index--; ) { if ( timers[ index ].elem === this && timers[ index ].queue === type ) { timers[ index ].anim.stop( true ); timers.splice( index, 1 ); } } // Look for any animations in the old queue and finish them for ( index = 0; index < length; index++ ) { if ( queue[ index ] && queue[ index ].finish ) { queue[ index ].finish.call( this ); } } // Turn off finishing flag delete data.finish; } ); } } ); jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { var cssFn = jQuery.fn[ name ]; jQuery.fn[ name ] = function( speed, easing, callback ) { return speed == null || typeof speed === "boolean" ? cssFn.apply( this, arguments ) : this.animate( genFx( name, true ), speed, easing, callback ); }; } ); // Generate shortcuts for custom animations jQuery.each( { slideDown: genFx( "show" ), slideUp: genFx( "hide" ), slideToggle: genFx( "toggle" ), fadeIn: { opacity: "show" }, fadeOut: { opacity: "hide" }, fadeToggle: { opacity: "toggle" } }, function( name, props ) { jQuery.fn[ name ] = function( speed, easing, callback ) { return this.animate( props, speed, easing, callback ); }; } ); jQuery.timers = []; jQuery.fx.tick = function() { var timer, i = 0, timers = jQuery.timers; fxNow = jQuery.now(); for ( ; i < timers.length; i++ ) { timer = timers[ i ]; // Run the timer and safely remove it when done (allowing for external removal) if ( !timer() && timers[ i ] === timer ) { timers.splice( i--, 1 ); } } if ( !timers.length ) { jQuery.fx.stop(); } fxNow = undefined; }; jQuery.fx.timer = function( timer ) { jQuery.timers.push( timer ); jQuery.fx.start(); }; jQuery.fx.interval = 13; jQuery.fx.start = function() { if ( inProgress ) { return; } inProgress = true; schedule(); }; jQuery.fx.stop = function() { inProgress = null; }; jQuery.fx.speeds = { slow: 600, fast: 200, // Default speed _default: 400 }; // Based off of the plugin by Clint Helfers, with permission. // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ jQuery.fn.delay = function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; type = type || "fx"; return this.queue( type, function( next, hooks ) { var timeout = window.setTimeout( next, time ); hooks.stop = function() { window.clearTimeout( timeout ); }; } ); }; ( function() { var input = document.createElement( "input" ), select = document.createElement( "select" ), opt = select.appendChild( document.createElement( "option" ) ); input.type = "checkbox"; // Support: Android <=4.3 only // Default value for a checkbox should be "on" support.checkOn = input.value !== ""; // Support: IE <=11 only // Must access selectedIndex to make default options select support.optSelected = opt.selected; // Support: IE <=11 only // An input loses its value after becoming a radio input = document.createElement( "input" ); input.value = "t"; input.type = "radio"; support.radioValue = input.value === "t"; } )(); var boolHook, attrHandle = jQuery.expr.attrHandle; jQuery.fn.extend( { attr: function( name, value ) { return access( this, jQuery.attr, name, value, arguments.length > 1 ); }, removeAttr: function( name ) { return this.each( function() { jQuery.removeAttr( this, name ); } ); } } ); jQuery.extend( { attr: function( elem, name, value ) { var ret, hooks, nType = elem.nodeType; // Don't get/set attributes on text, comment and attribute nodes if ( nType === 3 || nType === 8 || nType === 2 ) { return; } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === "undefined" ) { return jQuery.prop( elem, name, value ); } // Attribute hooks are determined by the lowercase version // Grab necessary hook if one is defined if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { hooks = jQuery.attrHooks[ name.toLowerCase() ] || ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); return; } if ( hooks && "set" in hooks && ( ret = hooks.set( elem, value, name ) ) !== undefined ) { return ret; } elem.setAttribute( name, value + "" ); return value; } if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { return ret; } ret = jQuery.find.attr( elem, name ); // Non-existent attributes return null, we normalize to undefined return ret == null ? undefined : ret; }, attrHooks: { type: { set: function( elem, value ) { if ( !support.radioValue && value === "radio" && nodeName( elem, "input" ) ) { var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } } }, removeAttr: function( elem, value ) { var name, i = 0, // Attribute names can contain non-HTML whitespace characters // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 attrNames = value && value.match( rnothtmlwhite ); if ( attrNames && elem.nodeType === 1 ) { while ( ( name = attrNames[ i++ ] ) ) { elem.removeAttribute( name ); } } } } ); // Hooks for boolean attributes boolHook = { set: function( elem, value, name ) { if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else { elem.setAttribute( name, name ); } return name; } }; jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { var getter = attrHandle[ name ] || jQuery.find.attr; attrHandle[ name ] = function( elem, name, isXML ) { var ret, handle, lowercaseName = name.toLowerCase(); if ( !isXML ) { // Avoid an infinite loop by temporarily removing this function from the getter handle = attrHandle[ lowercaseName ]; attrHandle[ lowercaseName ] = ret; ret = getter( elem, name, isXML ) != null ? lowercaseName : null; attrHandle[ lowercaseName ] = handle; } return ret; }; } ); var rfocusable = /^(?:input|select|textarea|button)$/i, rclickable = /^(?:a|area)$/i; jQuery.fn.extend( { prop: function( name, value ) { return access( this, jQuery.prop, name, value, arguments.length > 1 ); }, removeProp: function( name ) { return this.each( function() { delete this[ jQuery.propFix[ name ] || name ]; } ); } } ); jQuery.extend( { prop: function( elem, name, value ) { var ret, hooks, nType = elem.nodeType; // Don't get/set properties on text, comment and attribute nodes if ( nType === 3 || nType === 8 || nType === 2 ) { return; } if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { if ( hooks && "set" in hooks && ( ret = hooks.set( elem, value, name ) ) !== undefined ) { return ret; } return ( elem[ name ] = value ); } if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { return ret; } return elem[ name ]; }, propHooks: { tabIndex: { get: function( elem ) { // Support: IE <=9 - 11 only // elem.tabIndex doesn't always return the // correct value when it hasn't been explicitly set // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ // Use proper attribute retrieval(#12072) var tabindex = jQuery.find.attr( elem, "tabindex" ); if ( tabindex ) { return parseInt( tabindex, 10 ); } if ( rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ) { return 0; } return -1; } } }, propFix: { "for": "htmlFor", "class": "className" } } ); // Support: IE <=11 only // Accessing the selectedIndex property // forces the browser to respect setting selected // on the option // The getter ensures a default option is selected // when in an optgroup // eslint rule "no-unused-expressions" is disabled for this code // since it considers such accessions noop if ( !support.optSelected ) { jQuery.propHooks.selected = { get: function( elem ) { /* eslint no-unused-expressions: "off" */ var parent = elem.parentNode; if ( parent && parent.parentNode ) { parent.parentNode.selectedIndex; } return null; }, set: function( elem ) { /* eslint no-unused-expressions: "off" */ var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } } }; } jQuery.each( [ "tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable" ], function() { jQuery.propFix[ this.toLowerCase() ] = this; } ); // Strip and collapse whitespace according to HTML spec // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace function stripAndCollapse( value ) { var tokens = value.match( rnothtmlwhite ) || []; return tokens.join( " " ); } function getClass( elem ) { return elem.getAttribute && elem.getAttribute( "class" ) || ""; } jQuery.fn.extend( { addClass: function( value ) { var classes, elem, cur, curValue, clazz, j, finalValue, i = 0; if ( jQuery.isFunction( value ) ) { return this.each( function( j ) { jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); } ); } if ( typeof value === "string" && value ) { classes = value.match( rnothtmlwhite ) || []; while ( ( elem = this[ i++ ] ) ) { curValue = getClass( elem ); cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); if ( cur ) { j = 0; while ( ( clazz = classes[ j++ ] ) ) { if ( cur.indexOf( " " + clazz + " " ) < 0 ) { cur += clazz + " "; } } // Only assign if different to avoid unneeded rendering. finalValue = stripAndCollapse( cur ); if ( curValue !== finalValue ) { elem.setAttribute( "class", finalValue ); } } } } return this; }, removeClass: function( value ) { var classes, elem, cur, curValue, clazz, j, finalValue, i = 0; if ( jQuery.isFunction( value ) ) { return this.each( function( j ) { jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); } ); } if ( !arguments.length ) { return this.attr( "class", "" ); } if ( typeof value === "string" && value ) { classes = value.match( rnothtmlwhite ) || []; while ( ( elem = this[ i++ ] ) ) { curValue = getClass( elem ); // This expression is here for better compressibility (see addClass) cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); if ( cur ) { j = 0; while ( ( clazz = classes[ j++ ] ) ) { // Remove *all* instances while ( cur.indexOf( " " + clazz + " " ) > -1 ) { cur = cur.replace( " " + clazz + " ", " " ); } } // Only assign if different to avoid unneeded rendering. finalValue = stripAndCollapse( cur ); if ( curValue !== finalValue ) { elem.setAttribute( "class", finalValue ); } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value; if ( typeof stateVal === "boolean" && type === "string" ) { return stateVal ? this.addClass( value ) : this.removeClass( value ); } if ( jQuery.isFunction( value ) ) { return this.each( function( i ) { jQuery( this ).toggleClass( value.call( this, i, getClass( this ), stateVal ), stateVal ); } ); } return this.each( function() { var className, i, self, classNames; if ( type === "string" ) { // Toggle individual class names i = 0; self = jQuery( this ); classNames = value.match( rnothtmlwhite ) || []; while ( ( className = classNames[ i++ ] ) ) { // Check each className given, space separated list if ( self.hasClass( className ) ) { self.removeClass( className ); } else { self.addClass( className ); } } // Toggle whole class name } else if ( value === undefined || type === "boolean" ) { className = getClass( this ); if ( className ) { // Store className if set dataPriv.set( this, "__className__", className ); } // If the element has a class name or if we're passed `false`, // then remove the whole classname (if there was one, the above saved it). // Otherwise bring back whatever was previously saved (if anything), // falling back to the empty string if nothing was stored. if ( this.setAttribute ) { this.setAttribute( "class", className || value === false ? "" : dataPriv.get( this, "__className__" ) || "" ); } } } ); }, hasClass: function( selector ) { var className, elem, i = 0; className = " " + selector + " "; while ( ( elem = this[ i++ ] ) ) { if ( elem.nodeType === 1 && ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { return true; } } return false; } } ); var rreturn = /\r/g; jQuery.fn.extend( { val: function( value ) { var hooks, ret, isFunction, elem = this[ 0 ]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; if ( hooks && "get" in hooks && ( ret = hooks.get( elem, "value" ) ) !== undefined ) { return ret; } ret = elem.value; // Handle most common string cases if ( typeof ret === "string" ) { return ret.replace( rreturn, "" ); } // Handle cases where value is null/undef or number return ret == null ? "" : ret; } return; } isFunction = jQuery.isFunction( value ); return this.each( function( i ) { var val; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call( this, i, jQuery( this ).val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( Array.isArray( val ) ) { val = jQuery.map( val, function( value ) { return value == null ? "" : value + ""; } ); } hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; // If set returns undefined, fall back to normal setting if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } } ); } } ); jQuery.extend( { valHooks: { option: { get: function( elem ) { var val = jQuery.find.attr( elem, "value" ); return val != null ? val : // Support: IE <=10 - 11 only // option.text throws exceptions (#14686, #14858) // Strip and collapse whitespace // https://html.spec.whatwg.org/#strip-and-collapse-whitespace stripAndCollapse( jQuery.text( elem ) ); } }, select: { get: function( elem ) { var value, option, i, options = elem.options, index = elem.selectedIndex, one = elem.type === "select-one", values = one ? null : [], max = one ? index + 1 : options.length; if ( index < 0 ) { i = max; } else { i = one ? index : 0; } // Loop through all the selected options for ( ; i < max; i++ ) { option = options[ i ]; // Support: IE <=9 only // IE8-9 doesn't update selected after form reset (#2551) if ( ( option.selected || i === index ) && // Don't return options that are disabled or in a disabled optgroup !option.disabled && ( !option.parentNode.disabled || !nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } return values; }, set: function( elem, value ) { var optionSet, option, options = elem.options, values = jQuery.makeArray( value ), i = options.length; while ( i-- ) { option = options[ i ]; /* eslint-disable no-cond-assign */ if ( option.selected = jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 ) { optionSet = true; } /* eslint-enable no-cond-assign */ } // Force browsers to behave consistently when non-matching value is set if ( !optionSet ) { elem.selectedIndex = -1; } return values; } } } } ); // Radios and checkboxes getter/setter jQuery.each( [ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { set: function( elem, value ) { if ( Array.isArray( value ) ) { return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); } } }; if ( !support.checkOn ) { jQuery.valHooks[ this ].get = function( elem ) { return elem.getAttribute( "value" ) === null ? "on" : elem.value; }; } } ); // Return jQuery for attributes-only inclusion var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/; jQuery.extend( jQuery.event, { trigger: function( event, data, elem, onlyHandlers ) { var i, cur, tmp, bubbleType, ontype, handle, special, eventPath = [ elem || document ], type = hasOwn.call( event, "type" ) ? event.type : event, namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; cur = tmp = elem = elem || document; // Don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } // focus/blur morphs to focusin/out; ensure we're not firing them right now if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { return; } if ( type.indexOf( "." ) > -1 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split( "." ); type = namespaces.shift(); namespaces.sort(); } ontype = type.indexOf( ":" ) < 0 && "on" + type; // Caller can pass in a jQuery.Event object, Object, or just an event type string event = event[ jQuery.expando ] ? event : new jQuery.Event( type, typeof event === "object" && event ); // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) event.isTrigger = onlyHandlers ? 2 : 3; event.namespace = namespaces.join( "." ); event.rnamespace = event.namespace ? new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : null; // Clean up the event in case it is being reused event.result = undefined; if ( !event.target ) { event.target = elem; } // Clone any incoming data and prepend the event, creating the handler arg list data = data == null ? [ event ] : jQuery.makeArray( data, [ event ] ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { return; } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { bubbleType = special.delegateType || type; if ( !rfocusMorph.test( bubbleType + type ) ) { cur = cur.parentNode; } for ( ; cur; cur = cur.parentNode ) { eventPath.push( cur ); tmp = cur; } // Only add window if we got to document (e.g., not plain obj or detached DOM) if ( tmp === ( elem.ownerDocument || document ) ) { eventPath.push( tmp.defaultView || tmp.parentWindow || window ); } } // Fire handlers on the event path i = 0; while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { event.type = i > 1 ? bubbleType : special.bindType || type; // jQuery handler handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && dataPriv.get( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } // Native handler handle = ontype && cur[ ontype ]; if ( handle && handle.apply && acceptData( cur ) ) { event.result = handle.apply( cur, data ); if ( event.result === false ) { event.preventDefault(); } } } event.type = type; // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { if ( ( !special._default || special._default.apply( eventPath.pop(), data ) === false ) && acceptData( elem ) ) { // Call a native DOM method on the target with the same name as the event. // Don't do default actions on window, that's where global variables be (#6170) if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method tmp = elem[ ontype ]; if ( tmp ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; elem[ type ](); jQuery.event.triggered = undefined; if ( tmp ) { elem[ ontype ] = tmp; } } } } return event.result; }, // Piggyback on a donor event to simulate a different one // Used only for `focus(in | out)` events simulate: function( type, elem, event ) { var e = jQuery.extend( new jQuery.Event(), event, { type: type, isSimulated: true } ); jQuery.event.trigger( e, null, elem ); } } ); jQuery.fn.extend( { trigger: function( type, data ) { return this.each( function() { jQuery.event.trigger( type, data, this ); } ); }, triggerHandler: function( type, data ) { var elem = this[ 0 ]; if ( elem ) { return jQuery.event.trigger( type, data, elem, true ); } } } ); jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup contextmenu" ).split( " " ), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( data, fn ) { return arguments.length > 0 ? this.on( name, null, data, fn ) : this.trigger( name ); }; } ); jQuery.fn.extend( { hover: function( fnOver, fnOut ) { return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } } ); support.focusin = "onfocusin" in window; // Support: Firefox <=44 // Firefox doesn't have focus(in | out) events // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 // // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 // focus(in | out) events fire after focus & blur events, // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 if ( !support.focusin ) { jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler on the document while someone wants focusin/focusout var handler = function( event ) { jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); }; jQuery.event.special[ fix ] = { setup: function() { var doc = this.ownerDocument || this, attaches = dataPriv.access( doc, fix ); if ( !attaches ) { doc.addEventListener( orig, handler, true ); } dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); }, teardown: function() { var doc = this.ownerDocument || this, attaches = dataPriv.access( doc, fix ) - 1; if ( !attaches ) { doc.removeEventListener( orig, handler, true ); dataPriv.remove( doc, fix ); } else { dataPriv.access( doc, fix, attaches ); } } }; } ); } var location = window.location; var nonce = jQuery.now(); var rquery = ( /\?/ ); // Cross-browser xml parsing jQuery.parseXML = function( data ) { var xml; if ( !data || typeof data !== "string" ) { return null; } // Support: IE 9 - 11 only // IE throws on parseFromString with invalid input. try { xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); } catch ( e ) { xml = undefined; } if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }; var rbracket = /\[\]$/, rCRLF = /\r?\n/g, rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, rsubmittable = /^(?:input|select|textarea|keygen)/i; function buildParams( prefix, obj, traditional, add ) { var name; if ( Array.isArray( obj ) ) { // Serialize array item. jQuery.each( obj, function( i, v ) { if ( traditional || rbracket.test( prefix ) ) { // Treat each array item as a scalar. add( prefix, v ); } else { // Item is non-scalar (array or object), encode its numeric index. buildParams( prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", v, traditional, add ); } } ); } else if ( !traditional && jQuery.type( obj ) === "object" ) { // Serialize object item. for ( name in obj ) { buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); } } else { // Serialize scalar item. add( prefix, obj ); } } // Serialize an array of form elements or a set of // key/values into a query string jQuery.param = function( a, traditional ) { var prefix, s = [], add = function( key, valueOrFunction ) { // If value is a function, invoke it and use its return value var value = jQuery.isFunction( valueOrFunction ) ? valueOrFunction() : valueOrFunction; s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value == null ? "" : value ); }; // If an array was passed in, assume that it is an array of form elements. if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { // Serialize the form elements jQuery.each( a, function() { add( this.name, this.value ); } ); } else { // If traditional, encode the "old" way (the way 1.3.2 or older // did it), otherwise encode params recursively. for ( prefix in a ) { buildParams( prefix, a[ prefix ], traditional, add ); } } // Return the resulting serialization return s.join( "&" ); }; jQuery.fn.extend( { serialize: function() { return jQuery.param( this.serializeArray() ); }, serializeArray: function() { return this.map( function() { // Can add propHook for "elements" to filter or add form elements var elements = jQuery.prop( this, "elements" ); return elements ? jQuery.makeArray( elements ) : this; } ) .filter( function() { var type = this.type; // Use .is( ":disabled" ) so that fieldset[disabled] works return this.name && !jQuery( this ).is( ":disabled" ) && rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && ( this.checked || !rcheckableType.test( type ) ); } ) .map( function( i, elem ) { var val = jQuery( this ).val(); if ( val == null ) { return null; } if ( Array.isArray( val ) ) { return jQuery.map( val, function( val ) { return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; } ); } return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; } ).get(); } } ); var r20 = /%20/g, rhash = /#.*$/, rantiCache = /([?&])_=[^&]*/, rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, // #7653, #8125, #8152: local protocol detection rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, /* Prefilters * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) * 2) These are called: * - BEFORE asking for a transport * - AFTER param serialization (s.data is a string if s.processData is true) * 3) key is the dataType * 4) the catchall symbol "*" can be used * 5) execution will start with transport dataType and THEN continue down to "*" if needed */ prefilters = {}, /* Transports bindings * 1) key is the dataType * 2) the catchall symbol "*" can be used * 3) selection will start with transport dataType and THEN go to "*" if needed */ transports = {}, // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression allTypes = "*/".concat( "*" ), // Anchor tag for parsing the document origin originAnchor = document.createElement( "a" ); originAnchor.href = location.href; // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports( structure ) { // dataTypeExpression is optional and defaults to "*" return function( dataTypeExpression, func ) { if ( typeof dataTypeExpression !== "string" ) { func = dataTypeExpression; dataTypeExpression = "*"; } var dataType, i = 0, dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; if ( jQuery.isFunction( func ) ) { // For each dataType in the dataTypeExpression while ( ( dataType = dataTypes[ i++ ] ) ) { // Prepend if requested if ( dataType[ 0 ] === "+" ) { dataType = dataType.slice( 1 ) || "*"; ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); // Otherwise append } else { ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); } } } }; } // Base inspection function for prefilters and transports function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { var inspected = {}, seekingTransport = ( structure === transports ); function inspect( dataType ) { var selected; inspected[ dataType ] = true; jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { options.dataTypes.unshift( dataTypeOrTransport ); inspect( dataTypeOrTransport ); return false; } else if ( seekingTransport ) { return !( selected = dataTypeOrTransport ); } } ); return selected; } return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); } // A special extend for ajax options // that takes "flat" options (not to be deep extended) // Fixes #9887 function ajaxExtend( target, src ) { var key, deep, flatOptions = jQuery.ajaxSettings.flatOptions || {}; for ( key in src ) { if ( src[ key ] !== undefined ) { ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; } } if ( deep ) { jQuery.extend( true, target, deep ); } return target; } /* Handles responses to an ajax request: * - finds the right dataType (mediates between content-type and expected dataType) * - returns the corresponding response */ function ajaxHandleResponses( s, jqXHR, responses ) { var ct, type, finalDataType, firstDataType, contents = s.contents, dataTypes = s.dataTypes; // Remove auto dataType and get content-type in the process while ( dataTypes[ 0 ] === "*" ) { dataTypes.shift(); if ( ct === undefined ) { ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); } } // Check if we're dealing with a known content-type if ( ct ) { for ( type in contents ) { if ( contents[ type ] && contents[ type ].test( ct ) ) { dataTypes.unshift( type ); break; } } } // Check to see if we have a response for the expected dataType if ( dataTypes[ 0 ] in responses ) { finalDataType = dataTypes[ 0 ]; } else { // Try convertible dataTypes for ( type in responses ) { if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { finalDataType = type; break; } if ( !firstDataType ) { firstDataType = type; } } // Or just use first one finalDataType = finalDataType || firstDataType; } // If we found a dataType // We add the dataType to the list if needed // and return the corresponding response if ( finalDataType ) { if ( finalDataType !== dataTypes[ 0 ] ) { dataTypes.unshift( finalDataType ); } return responses[ finalDataType ]; } } /* Chain conversions given the request and the original response * Also sets the responseXXX fields on the jqXHR instance */ function ajaxConvert( s, response, jqXHR, isSuccess ) { var conv2, current, conv, tmp, prev, converters = {}, // Work with a copy of dataTypes in case we need to modify it for conversion dataTypes = s.dataTypes.slice(); // Create converters map with lowercased keys if ( dataTypes[ 1 ] ) { for ( conv in s.converters ) { converters[ conv.toLowerCase() ] = s.converters[ conv ]; } } current = dataTypes.shift(); // Convert to each sequential dataType while ( current ) { if ( s.responseFields[ current ] ) { jqXHR[ s.responseFields[ current ] ] = response; } // Apply the dataFilter if provided if ( !prev && isSuccess && s.dataFilter ) { response = s.dataFilter( response, s.dataType ); } prev = current; current = dataTypes.shift(); if ( current ) { // There's only work to do if current dataType is non-auto if ( current === "*" ) { current = prev; // Convert response if prev dataType is non-auto and differs from current } else if ( prev !== "*" && prev !== current ) { // Seek a direct converter conv = converters[ prev + " " + current ] || converters[ "* " + current ]; // If none found, seek a pair if ( !conv ) { for ( conv2 in converters ) { // If conv2 outputs current tmp = conv2.split( " " ); if ( tmp[ 1 ] === current ) { // If prev can be converted to accepted input conv = converters[ prev + " " + tmp[ 0 ] ] || converters[ "* " + tmp[ 0 ] ]; if ( conv ) { // Condense equivalence converters if ( conv === true ) { conv = converters[ conv2 ]; // Otherwise, insert the intermediate dataType } else if ( converters[ conv2 ] !== true ) { current = tmp[ 0 ]; dataTypes.unshift( tmp[ 1 ] ); } break; } } } } // Apply converter (if not an equivalence) if ( conv !== true ) { // Unless errors are allowed to bubble, catch and return them if ( conv && s.throws ) { response = conv( response ); } else { try { response = conv( response ); } catch ( e ) { return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; } } } } } } return { state: "success", data: response }; } jQuery.extend( { // Counter for holding the number of active queries active: 0, // Last-Modified header cache for next request lastModified: {}, etag: {}, ajaxSettings: { url: location.href, type: "GET", isLocal: rlocalProtocol.test( location.protocol ), global: true, processData: true, async: true, contentType: "application/x-www-form-urlencoded; charset=UTF-8", /* timeout: 0, data: null, dataType: null, username: null, password: null, cache: null, throws: false, traditional: false, headers: {}, */ accepts: { "*": allTypes, text: "text/plain", html: "text/html", xml: "application/xml, text/xml", json: "application/json, text/javascript" }, contents: { xml: /\bxml\b/, html: /\bhtml/, json: /\bjson\b/ }, responseFields: { xml: "responseXML", text: "responseText", json: "responseJSON" }, // Data converters // Keys separate source (or catchall "*") and destination types with a single space converters: { // Convert anything to text "* text": String, // Text to html (true = no transformation) "text html": true, // Evaluate text as a json expression "text json": JSON.parse, // Parse text as xml "text xml": jQuery.parseXML }, // For options that shouldn't be deep extended: // you can add your own custom options here if // and when you create one that shouldn't be // deep extended (see ajaxExtend) flatOptions: { url: true, context: true } }, // Creates a full fledged settings object into target // with both ajaxSettings and settings fields. // If target is omitted, writes into ajaxSettings. ajaxSetup: function( target, settings ) { return settings ? // Building a settings object ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : // Extending ajaxSettings ajaxExtend( jQuery.ajaxSettings, target ); }, ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), ajaxTransport: addToPrefiltersOrTransports( transports ), // Main method ajax: function( url, options ) { // If url is an object, simulate pre-1.5 signature if ( typeof url === "object" ) { options = url; url = undefined; } // Force options to be an object options = options || {}; var transport, // URL without anti-cache param cacheURL, // Response headers responseHeadersString, responseHeaders, // timeout handle timeoutTimer, // Url cleanup var urlAnchor, // Request state (becomes false upon send and true upon completion) completed, // To know if global events are to be dispatched fireGlobals, // Loop variable i, // uncached part of the url uncached, // Create the final options object s = jQuery.ajaxSetup( {}, options ), // Callbacks context callbackContext = s.context || s, // Context for global events is callbackContext if it is a DOM node or jQuery collection globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? jQuery( callbackContext ) : jQuery.event, // Deferreds deferred = jQuery.Deferred(), completeDeferred = jQuery.Callbacks( "once memory" ), // Status-dependent callbacks statusCode = s.statusCode || {}, // Headers (they are sent all at once) requestHeaders = {}, requestHeadersNames = {}, // Default abort message strAbort = "canceled", // Fake xhr jqXHR = { readyState: 0, // Builds headers hashtable if needed getResponseHeader: function( key ) { var match; if ( completed ) { if ( !responseHeaders ) { responseHeaders = {}; while ( ( match = rheaders.exec( responseHeadersString ) ) ) { responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; } } match = responseHeaders[ key.toLowerCase() ]; } return match == null ? null : match; }, // Raw string getAllResponseHeaders: function() { return completed ? responseHeadersString : null; }, // Caches the header setRequestHeader: function( name, value ) { if ( completed == null ) { name = requestHeadersNames[ name.toLowerCase() ] = requestHeadersNames[ name.toLowerCase() ] || name; requestHeaders[ name ] = value; } return this; }, // Overrides response content-type header overrideMimeType: function( type ) { if ( completed == null ) { s.mimeType = type; } return this; }, // Status-dependent callbacks statusCode: function( map ) { var code; if ( map ) { if ( completed ) { // Execute the appropriate callbacks jqXHR.always( map[ jqXHR.status ] ); } else { // Lazy-add the new callbacks in a way that preserves old ones for ( code in map ) { statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; } } } return this; }, // Cancel the request abort: function( statusText ) { var finalText = statusText || strAbort; if ( transport ) { transport.abort( finalText ); } done( 0, finalText ); return this; } }; // Attach deferreds deferred.promise( jqXHR ); // Add protocol if not provided (prefilters might expect it) // Handle falsy url in the settings object (#10093: consistency with old signature) // We also use the url parameter if available s.url = ( ( url || s.url || location.href ) + "" ) .replace( rprotocol, location.protocol + "//" ); // Alias method option to type as per ticket #12004 s.type = options.method || options.type || s.method || s.type; // Extract dataTypes list s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; // A cross-domain request is in order when the origin doesn't match the current origin. if ( s.crossDomain == null ) { urlAnchor = document.createElement( "a" ); // Support: IE <=8 - 11, Edge 12 - 13 // IE throws exception on accessing the href property if url is malformed, // e.g. http://example.com:80x/ try { urlAnchor.href = s.url; // Support: IE <=8 - 11 only // Anchor's host property isn't correctly set when s.url is relative urlAnchor.href = urlAnchor.href; s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== urlAnchor.protocol + "//" + urlAnchor.host; } catch ( e ) { // If there is an error parsing the URL, assume it is crossDomain, // it can be rejected by the transport if it is invalid s.crossDomain = true; } } // Convert data if not already a string if ( s.data && s.processData && typeof s.data !== "string" ) { s.data = jQuery.param( s.data, s.traditional ); } // Apply prefilters inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); // If request was aborted inside a prefilter, stop there if ( completed ) { return jqXHR; } // We can fire global events as of now if asked to // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) fireGlobals = jQuery.event && s.global; // Watch for a new set of requests if ( fireGlobals && jQuery.active++ === 0 ) { jQuery.event.trigger( "ajaxStart" ); } // Uppercase the type s.type = s.type.toUpperCase(); // Determine if request has content s.hasContent = !rnoContent.test( s.type ); // Save the URL in case we're toying with the If-Modified-Since // and/or If-None-Match header later on // Remove hash to simplify url manipulation cacheURL = s.url.replace( rhash, "" ); // More options handling for requests with no content if ( !s.hasContent ) { // Remember the hash so we can put it back uncached = s.url.slice( cacheURL.length ); // If data is available, append data to url if ( s.data ) { cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; // #9682: remove data so that it's not used in an eventual retry delete s.data; } // Add or update anti-cache param if needed if ( s.cache === false ) { cacheURL = cacheURL.replace( rantiCache, "$1" ); uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; } // Put hash and anti-cache on the URL that will be requested (gh-1732) s.url = cacheURL + uncached; // Change '%20' to '+' if this is encoded form body content (gh-2658) } else if ( s.data && s.processData && ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { s.data = s.data.replace( r20, "+" ); } // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { if ( jQuery.lastModified[ cacheURL ] ) { jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); } if ( jQuery.etag[ cacheURL ] ) { jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); } } // Set the correct header, if data is being sent if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { jqXHR.setRequestHeader( "Content-Type", s.contentType ); } // Set the Accepts header for the server, depending on the dataType jqXHR.setRequestHeader( "Accept", s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? s.accepts[ s.dataTypes[ 0 ] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : s.accepts[ "*" ] ); // Check for headers option for ( i in s.headers ) { jqXHR.setRequestHeader( i, s.headers[ i ] ); } // Allow custom headers/mimetypes and early abort if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { // Abort if not done already and return return jqXHR.abort(); } // Aborting is no longer a cancellation strAbort = "abort"; // Install callbacks on deferreds completeDeferred.add( s.complete ); jqXHR.done( s.success ); jqXHR.fail( s.error ); // Get transport transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); // If no transport, we auto-abort if ( !transport ) { done( -1, "No Transport" ); } else { jqXHR.readyState = 1; // Send global event if ( fireGlobals ) { globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); } // If request was aborted inside ajaxSend, stop there if ( completed ) { return jqXHR; } // Timeout if ( s.async && s.timeout > 0 ) { timeoutTimer = window.setTimeout( function() { jqXHR.abort( "timeout" ); }, s.timeout ); } try { completed = false; transport.send( requestHeaders, done ); } catch ( e ) { // Rethrow post-completion exceptions if ( completed ) { throw e; } // Propagate others as results done( -1, e ); } } // Callback for when everything is done function done( status, nativeStatusText, responses, headers ) { var isSuccess, success, error, response, modified, statusText = nativeStatusText; // Ignore repeat invocations if ( completed ) { return; } completed = true; // Clear timeout if it exists if ( timeoutTimer ) { window.clearTimeout( timeoutTimer ); } // Dereference transport for early garbage collection // (no matter how long the jqXHR object will be used) transport = undefined; // Cache response headers responseHeadersString = headers || ""; // Set readyState jqXHR.readyState = status > 0 ? 4 : 0; // Determine if successful isSuccess = status >= 200 && status < 300 || status === 304; // Get response data if ( responses ) { response = ajaxHandleResponses( s, jqXHR, responses ); } // Convert no matter what (that way responseXXX fields are always set) response = ajaxConvert( s, response, jqXHR, isSuccess ); // If successful, handle type chaining if ( isSuccess ) { // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { modified = jqXHR.getResponseHeader( "Last-Modified" ); if ( modified ) { jQuery.lastModified[ cacheURL ] = modified; } modified = jqXHR.getResponseHeader( "etag" ); if ( modified ) { jQuery.etag[ cacheURL ] = modified; } } // if no content if ( status === 204 || s.type === "HEAD" ) { statusText = "nocontent"; // if not modified } else if ( status === 304 ) { statusText = "notmodified"; // If we have data, let's convert it } else { statusText = response.state; success = response.data; error = response.error; isSuccess = !error; } } else { // Extract error from statusText and normalize for non-aborts error = statusText; if ( status || !statusText ) { statusText = "error"; if ( status < 0 ) { status = 0; } } } // Set data for the fake xhr object jqXHR.status = status; jqXHR.statusText = ( nativeStatusText || statusText ) + ""; // Success/Error if ( isSuccess ) { deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); } else { deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); } // Status-dependent callbacks jqXHR.statusCode( statusCode ); statusCode = undefined; if ( fireGlobals ) { globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", [ jqXHR, s, isSuccess ? success : error ] ); } // Complete completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); if ( fireGlobals ) { globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); // Handle the global AJAX counter if ( !( --jQuery.active ) ) { jQuery.event.trigger( "ajaxStop" ); } } } return jqXHR; }, getJSON: function( url, data, callback ) { return jQuery.get( url, data, callback, "json" ); }, getScript: function( url, callback ) { return jQuery.get( url, undefined, callback, "script" ); } } ); jQuery.each( [ "get", "post" ], function( i, method ) { jQuery[ method ] = function( url, data, callback, type ) { // Shift arguments if data argument was omitted if ( jQuery.isFunction( data ) ) { type = type || callback; callback = data; data = undefined; } // The url can be an options object (which then must have .url) return jQuery.ajax( jQuery.extend( { url: url, type: method, dataType: type, data: data, success: callback }, jQuery.isPlainObject( url ) && url ) ); }; } ); jQuery._evalUrl = function( url ) { return jQuery.ajax( { url: url, // Make this explicit, since user can override this through ajaxSetup (#11264) type: "GET", dataType: "script", cache: true, async: false, global: false, "throws": true } ); }; jQuery.fn.extend( { wrapAll: function( html ) { var wrap; if ( this[ 0 ] ) { if ( jQuery.isFunction( html ) ) { html = html.call( this[ 0 ] ); } // The elements to wrap the target around wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); if ( this[ 0 ].parentNode ) { wrap.insertBefore( this[ 0 ] ); } wrap.map( function() { var elem = this; while ( elem.firstElementChild ) { elem = elem.firstElementChild; } return elem; } ).append( this ); } return this; }, wrapInner: function( html ) { if ( jQuery.isFunction( html ) ) { return this.each( function( i ) { jQuery( this ).wrapInner( html.call( this, i ) ); } ); } return this.each( function() { var self = jQuery( this ), contents = self.contents(); if ( contents.length ) { contents.wrapAll( html ); } else { self.append( html ); } } ); }, wrap: function( html ) { var isFunction = jQuery.isFunction( html ); return this.each( function( i ) { jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html ); } ); }, unwrap: function( selector ) { this.parent( selector ).not( "body" ).each( function() { jQuery( this ).replaceWith( this.childNodes ); } ); return this; } } ); jQuery.expr.pseudos.hidden = function( elem ) { return !jQuery.expr.pseudos.visible( elem ); }; jQuery.expr.pseudos.visible = function( elem ) { return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); }; jQuery.ajaxSettings.xhr = function() { try { return new window.XMLHttpRequest(); } catch ( e ) {} }; var xhrSuccessStatus = { // File protocol always yields status code 0, assume 200 0: 200, // Support: IE <=9 only // #1450: sometimes IE returns 1223 when it should be 204 1223: 204 }, xhrSupported = jQuery.ajaxSettings.xhr(); support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); support.ajax = xhrSupported = !!xhrSupported; jQuery.ajaxTransport( function( options ) { var callback, errorCallback; // Cross domain only allowed if supported through XMLHttpRequest if ( support.cors || xhrSupported && !options.crossDomain ) { return { send: function( headers, complete ) { var i, xhr = options.xhr(); xhr.open( options.type, options.url, options.async, options.username, options.password ); // Apply custom fields if provided if ( options.xhrFields ) { for ( i in options.xhrFields ) { xhr[ i ] = options.xhrFields[ i ]; } } // Override mime type if needed if ( options.mimeType && xhr.overrideMimeType ) { xhr.overrideMimeType( options.mimeType ); } // X-Requested-With header // For cross-domain requests, seeing as conditions for a preflight are // akin to a jigsaw puzzle, we simply never set it to be sure. // (it can always be set on a per-request basis or even using ajaxSetup) // For same-domain requests, won't change header if already provided. if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { headers[ "X-Requested-With" ] = "XMLHttpRequest"; } // Set headers for ( i in headers ) { xhr.setRequestHeader( i, headers[ i ] ); } // Callback callback = function( type ) { return function() { if ( callback ) { callback = errorCallback = xhr.onload = xhr.onerror = xhr.onabort = xhr.onreadystatechange = null; if ( type === "abort" ) { xhr.abort(); } else if ( type === "error" ) { // Support: IE <=9 only // On a manual native abort, IE9 throws // errors on any property access that is not readyState if ( typeof xhr.status !== "number" ) { complete( 0, "error" ); } else { complete( // File: protocol always yields status 0; see #8605, #14207 xhr.status, xhr.statusText ); } } else { complete( xhrSuccessStatus[ xhr.status ] || xhr.status, xhr.statusText, // Support: IE <=9 only // IE9 has no XHR2 but throws on binary (trac-11426) // For XHR2 non-text, let the caller handle it (gh-2498) ( xhr.responseType || "text" ) !== "text" || typeof xhr.responseText !== "string" ? { binary: xhr.response } : { text: xhr.responseText }, xhr.getAllResponseHeaders() ); } } }; }; // Listen to events xhr.onload = callback(); errorCallback = xhr.onerror = callback( "error" ); // Support: IE 9 only // Use onreadystatechange to replace onabort // to handle uncaught aborts if ( xhr.onabort !== undefined ) { xhr.onabort = errorCallback; } else { xhr.onreadystatechange = function() { // Check readyState before timeout as it changes if ( xhr.readyState === 4 ) { // Allow onerror to be called first, // but that will not handle a native abort // Also, save errorCallback to a variable // as xhr.onerror cannot be accessed window.setTimeout( function() { if ( callback ) { errorCallback(); } } ); } }; } // Create the abort callback callback = callback( "abort" ); try { // Do send the request (this may raise an exception) xhr.send( options.hasContent && options.data || null ); } catch ( e ) { // #14683: Only rethrow if this hasn't been notified as an error yet if ( callback ) { throw e; } } }, abort: function() { if ( callback ) { callback(); } } }; } } ); // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) jQuery.ajaxPrefilter( function( s ) { if ( s.crossDomain ) { s.contents.script = false; } } ); // Install script dataType jQuery.ajaxSetup( { accepts: { script: "text/javascript, application/javascript, " + "application/ecmascript, application/x-ecmascript" }, contents: { script: /\b(?:java|ecma)script\b/ }, converters: { "text script": function( text ) { jQuery.globalEval( text ); return text; } } } ); // Handle cache's special case and crossDomain jQuery.ajaxPrefilter( "script", function( s ) { if ( s.cache === undefined ) { s.cache = false; } if ( s.crossDomain ) { s.type = "GET"; } } ); // Bind script tag hack transport jQuery.ajaxTransport( "script", function( s ) { // This transport only deals with cross domain requests if ( s.crossDomain ) { var script, callback; return { send: function( _, complete ) { script = jQuery( "

claf.config.factory package

Submodules

class claf.config.factory.base.Factory[source]

Bases: object

Factory Base Class

Factory method pattern

In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.

create()[source]

interface

class claf.config.factory.data_loader.DataLoaderFactory(config)[source]

Bases: claf.config.factory.base.Factory

DataLoader Factory Class

  • Args:

    config: data_loader config from argument (config.data_loader)

create(datasets)[source]

create train, valid and test iterator

claf.config.factory.data_loader.make_data_loader(dataset, batch_size=32, shuffle=True, cuda_device_id=None)[source]
class claf.config.factory.data_reader.DataReaderFactory(config)[source]

Bases: claf.config.factory.base.Factory

DataReader Factory Class

Create Concrete reader according to config.dataset Get reader from reader registries (eg. @register(“reader:{reader_name}”))

  • Args:

    config: data_reader config from argument (config.data_reader)

create()[source]

interface

class claf.config.factory.model.ModelFactory(config)[source]

Bases: claf.config.factory.base.Factory

Model Factory Class

Create Concrete model according to config.model_name Get model from model registries (eg. @register(“model:{model_name}”))

  • Args:

    config: model config from argument (config.model)

create(token_makers, **params)[source]

interface

create_token_embedder(model, token_makers)[source]
class claf.config.factory.optimizer.OptimizerFactory(config)[source]

Bases: claf.config.factory.base.Factory

Optimizer Factory Class

include optimizer, learning_rate_scheduler and exponential_moving_average

  • Args:

    config: optimizer config from argument (config.optimizer)

create(model)[source]

interface

set_warmup_steps(config)[source]
class claf.config.factory.tokens.TokenMakersFactory(config)[source]

Bases: claf.config.factory.base.Factory

TokenMakers Factory Class

  • Args:

    config: token config from argument (config.token)

LANGS = ['eng', 'kor']
create()[source]

interface

claf.config.factory.tokens.make_all_tokenizers(all_tokenizer_config)[source]

Tokenizer is resource used all token together

claf.config.factory.tokens.make_tokenizer(tokenizer_cls, tokenizer_config, parent_tokenizers={})[source]

Module contents

class claf.config.factory.DataReaderFactory(config)[source]

Bases: claf.config.factory.base.Factory

DataReader Factory Class

Create Concrete reader according to config.dataset Get reader from reader registries (eg. @register(“reader:{reader_name}”))

  • Args:

    config: data_reader config from argument (config.data_reader)

create()[source]

interface

class claf.config.factory.DataLoaderFactory(config)[source]

Bases: claf.config.factory.base.Factory

DataLoader Factory Class

  • Args:

    config: data_loader config from argument (config.data_loader)

create(datasets)[source]

create train, valid and test iterator

class claf.config.factory.ModelFactory(config)[source]

Bases: claf.config.factory.base.Factory

Model Factory Class

Create Concrete model according to config.model_name Get model from model registries (eg. @register(“model:{model_name}”))

  • Args:

    config: model config from argument (config.model)

create(token_makers, **params)[source]

interface

create_token_embedder(model, token_makers)[source]
class claf.config.factory.OptimizerFactory(config)[source]

Bases: claf.config.factory.base.Factory

Optimizer Factory Class

include optimizer, learning_rate_scheduler and exponential_moving_average

  • Args:

    config: optimizer config from argument (config.optimizer)

create(model)[source]

interface

set_warmup_steps(config)[source]
class claf.config.factory.TokenMakersFactory(config)[source]

Bases: claf.config.factory.base.Factory

TokenMakers Factory Class

  • Args:

    config: token config from argument (config.token)

LANGS = ['eng', 'kor']
create()[source]

interface

================================================ FILE: docs/_build/html/claf.config.html ================================================ claf.config package — CLaF 0.2.0 documentation

claf.config package

Submodules

claf.config.args.arg_str2bool(v)[source]
claf.config.args.base_config(parser)[source]
claf.config.args.config(argv=None, mode=None)[source]
claf.config.args.data(parser)[source]
claf.config.args.evaluate(parser)[source]
claf.config.args.general(parser)[source]
claf.config.args.get_input_arguments(parser, input_arguments)[source]
claf.config.args.machine(parser)[source]
claf.config.args.model(parser)[source]
claf.config.args.nsml_for_internal(parser)[source]
claf.config.args.optimize_config(config, is_test=False)[source]
claf.config.args.predict(parser)[source]
claf.config.args.set_batch_size(config)[source]
claf.config.args.set_gpu_env(config)[source]
claf.config.args.token(parser)[source]
claf.config.args.train_config(parser, input_argv=None)[source]

Add argument only for hyperparameter tuning.

claf.config.args.trainer(parser)[source]
class claf.config.namespace.NestedNamespace(**kwargs)[source]

Bases: argparse.Namespace

Nested Namespace (Simple class used by default by parse_args() to create

an object holding attributes and return it.)

delete_unselected(namespace, excepts=[])[source]
load_from_json(dict_data)[source]
overwrite(config)[source]
class claf.config.pattern.Singleton[source]

Bases: type

Design Pattern Base

Singleton Meta Class the singleton pattern is a software design pattern that restricts the instantiation of a class to one object.

class claf.config.registry.Registry[source]

Bases: object

Registry class (Singleton)

add(name, obj)[source]
get(name)[source]
claf.config.utils.convert_config2dict(config)[source]
claf.config.utils.pretty_json_dumps(inputs)[source]
claf.config.utils.remove_none(obj)[source]
claf.config.utils.set_global_seed(seed=21)[source]

Module contents

================================================ FILE: docs/_build/html/claf.data.dataset.html ================================================ claf.data.dataset package — CLaF 0.2.0 documentation

claf.data.dataset package

Submodules

class claf.data.dataset.base.DatasetBase[source]

Bases: torch.utils.data.dataset.Dataset

Dataset Base Model An abstract class representing a Dataset.

collate_fn(cuda_device_id)[source]
get_ground_truth()[source]
get_ground_truths(data_idxs)[source]
get_predict()[source]
lazy_evaluation(index)[source]
class claf.data.dataset.seq_cls.SeqClsDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

Dataset for Sequence Classification

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

get_class_text_with_idx(class_index)[source]
get_ground_truth(data_id)[source]
get_id(data_index)[source]
property num_classes
property sequence_maxlen
class claf.data.dataset.squad.SQuADDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

SQuAD Dataset

compatible with v1.1 and v2.0

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

property context_maxlen
get_context(data_index)[source]
get_ground_truths(data_index)[source]
get_predict(data_index, start, end)[source]
get_qid(data_index)[source]
get_text_span(data_index)[source]
get_text_with_index(data_index, start, end)[source]
property question_maxlen
class claf.data.dataset.wikisql.WikiSQLDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

WikiSQL Dataset

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

get_ground_truth(data_index)[source]
get_id(data_index)[source]
get_table_id(data_index)[source]
get_tokenized_question(data_index)[source]
property question_maxlen

Module contents

class claf.data.dataset.MultiTaskBertDataset(batches, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

Dataset for Multi-Task GLUE using BERT

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]
init_iterators()[source]
class claf.data.dataset.RegressionBertDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

Dataset for Regression using BERT

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

get_ground_truth(data_id)[source]
get_id(data_index)[source]
property sequence_maxlen
class claf.data.dataset.SeqClsDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

Dataset for Sequence Classification

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

get_class_text_with_idx(class_index)[source]
get_ground_truth(data_id)[source]
get_id(data_index)[source]
property num_classes
property sequence_maxlen
class claf.data.dataset.SeqClsBertDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

Dataset for Sequence Classification using BERT

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

get_class_text_with_idx(class_index)[source]
get_ground_truth(data_id)[source]
get_id(data_index)[source]
property num_classes
property sequence_maxlen
class claf.data.dataset.SQuADDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

SQuAD Dataset

compatible with v1.1 and v2.0

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

property context_maxlen
get_context(data_index)[source]
get_ground_truths(data_index)[source]
get_predict(data_index, start, end)[source]
get_qid(data_index)[source]
get_text_span(data_index)[source]
get_text_with_index(data_index, start, end)[source]
property question_maxlen
class claf.data.dataset.SQuADBertDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

SQuAD Dataset for BERT

compatible with v1.1 and v2.0

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

property bert_input_maxlen
collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

get_bert_tokens(data_index)[source]
get_context(data_index)[source]
get_ground_truths(data_index)[source]
get_id(data_index)[source]
get_predict(data_index, start, end)[source]
get_qid(data_index)[source]
get_qid_index(data_index)[source]
get_text_with_index(data_index, start, end)[source]
class claf.data.dataset.TokClsBertDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

Dataset for Token Classification

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

get_ground_truth(data_id)[source]
get_id(data_index)[source]
get_tag_text_with_idx(tag_index)[source]
get_tag_texts_with_idxs(tag_idxs)[source]
property num_tags
property sequence_maxlen
class claf.data.dataset.WikiSQLDataset(batch, vocab, helper=None)[source]

Bases: claf.data.dataset.base.DatasetBase

WikiSQL Dataset

  • Args:

    batch: Batch DTO (claf.data.batch)

  • Kwargs:

    helper: helper from data_reader

collate_fn(cuda_device_id=None)[source]

collate: indexed features and labels -> tensor

get_ground_truth(data_index)[source]
get_id(data_index)[source]
get_table_id(data_index)[source]
get_tokenized_question(data_index)[source]
property question_maxlen
================================================ FILE: docs/_build/html/claf.data.html ================================================ claf.data package — CLaF 0.2.0 documentation

claf.data package

Submodules

class claf.data.collate.FeatLabelPadCollator(cuda_device_id=None, pad_value=0, skip_keys=['text'])[source]

Bases: claf.data.collate.PadCollator

Collator apply pad and make tensor Minimizes amount of padding needed while producing mini-batch.

FeatLabelPadCollator allows applying pad to not only features, but also labels.

  • Kwargs:
    cuda_device_id: tensor assign to cuda device id

    Default is None (CPU)

    skip_keys: skip to make tensor

collate(datas, apply_pad=True, apply_pad_labels=(), apply_pad_values=())[source]
class claf.data.collate.PadCollator(cuda_device_id=None, pad_value=0, skip_keys=['text'])[source]

Bases: object

Collator apply pad and make tensor Minimizes amount of padding needed while producing mini-batch.

  • Kwargs:
    cuda_device_id: tensor assign to cuda device id

    Default is None (CPU)

    skip_keys: skip to make tensor

collate(datas, apply_pad=True, pad_value=0)[source]
class claf.data.data_handler.CachePath[source]

Bases: object

DATASET = PosixPath('/Users/Dongjun/.claf_cache/dataset')
MACHINE = PosixPath('/Users/Dongjun/.claf_cache/machine')
PRETRAINED_VECTOR = PosixPath('/Users/Dongjun/.claf_cache/pretrained_vector')
ROOT = PosixPath('/Users/Dongjun/.claf_cache')
TOKEN_COUNTER = PosixPath('/Users/Dongjun/.claf_cache/token_counter')
VOCAB = PosixPath('/Users/Dongjun/.claf_cache/vocab')
class claf.data.data_handler.DataHandler(cache_path=PosixPath('/Users/Dongjun/.claf_cache'))[source]

Bases: object

DataHandler with CachePath

  • read (from_path, from_http)

  • dump (.msgpack or .pkl (pickle))

  • load

cache_token_counter(data_reader_config, tokenizer_name, obj=None)[source]
convert_cache_path(path)[source]
dump(file_path, obj, encoding='utf-8')[source]
load(file_path, encoding='utf-8')[source]
read(file_path, encoding='utf-8', return_path=False)[source]
read_embedding(file_path)[source]
claf.data.utils.get_is_head_of_word(naive_tokens, sequence_tokens)[source]

Return a list of flags whether the token is head(prefix) of naively split tokens

ex) naive_tokens: [“hello.”, “how”, “are”, “you?”]

sequence_tokens: [“hello”, “.”, “how”, “are”, “you”, “?”]

=> [1, 0, 1, 1, 1, 0]

  • Args:

    naive_tokens: a list of tokens, naively split by whitespace sequence_tokens: a list of tokens, split by ‘word_tokenizer’

  • Returns:
    is_head_of_word: a list with its length the same as that of ‘sequence_tokens’.

    has 1 if the tokenized word at the position is head(prefix) of a naive_token and 0 if otherwise.

claf.data.utils.get_sequence_a(example)[source]
claf.data.utils.get_token_dim(tokens, dim=0)[source]
claf.data.utils.get_token_type(tokens)[source]
claf.data.utils.is_lazy(tokens)[source]
claf.data.utils.make_batch(features, labels)[source]
claf.data.utils.make_bert_input(sequence_a, sequence_b, bert_tokenizer, max_seq_length=128, data_type='train', cls_token='[CLS]', sep_token='[SEP]', input_type='bert')[source]
claf.data.utils.make_bert_token_type(bert_input_text, SEP_token='[SEP]')[source]
claf.data.utils.make_bert_token_types(bert_inputs, SEP_token='[SEP]')[source]

Bert Inputs segment_ids

ex) [CLS] hi [SEP] he ##llo [SEP] => 0 0 0 1 1 1

  • Args:
    bert_inputs: feature dictionary consisting of
    • text: text from data_reader

    • token_name: text converted to corresponding token_type

  • Kwargs:

    SEP_token: SEP special token for BERT

claf.data.utils.padding_tokens(tokens, max_len=None, token_name=None, pad_value=0)[source]

Padding tokens according to token’s dimension

claf.data.utils.sanity_check_iob(naive_tokens, tag_texts)[source]

Check if the IOB tags are valid.

  • Args:

    naive_tokens: tokens split by .split() tag_texts: list of tags in IOB format

claf.data.utils.transpose(list_of_dict, skip_keys=[])[source]

Module contents

================================================ FILE: docs/_build/html/claf.data.reader.bert.html ================================================ claf.data.reader.bert package — CLaF 0.2.0 documentation

claf.data.reader.bert package

Submodules

class claf.data.reader.bert.conll2003.CoNLL2003BertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', ignore_tag_idx=-1)[source]

Bases: claf.data.reader.bert.tok_cls.TokClsBertReader

CoNLL2003 for BERT

  • Args:

    file_paths: file paths (train and dev)

  • Kwargs:

    ignore_tag_idx: prediction results that have this number as ground-truth idx are ignored

class claf.data.reader.bert.seq_cls.SeqClsBertReader(file_paths, tokenizers, sequence_max_length=None, class_key='class', cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.base.DataReader

DataReader for Sequence (Single and Pair) Classification using BERT

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword)

  • Kwargs:

    class_key: name of the label in .json file to use for classification

CLASS_DATA = None
METRIC_KEY = None
read_one_example(inputs)[source]

inputs keys: sequence_a and sequence_b

class claf.data.reader.bert.squad.SQuADBertReader(file_paths, lang_code, tokenizers, max_seq_length=384, context_stride=128, max_question_length=64, cls_token='[CLS]', sep_token='[SEP]')[source]

Bases: claf.data.reader.base.DataReader

SQuAD DataReader for BERT

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word)

METRIC_KEY = 'f1'
read_one_example(inputs)[source]

inputs keys: question, context

class claf.data.reader.bert.squad.Token(text, text_span=None)[source]

Bases: object

class claf.data.reader.bert.tok_cls.TokClsBertReader(file_paths, tokenizers, lang_code=None, sequence_max_length=None, tag_key='tags', cls_token='[CLS]', sep_token='[SEP]', ignore_tag_idx=-1)[source]

Bases: claf.data.reader.base.DataReader

DataReader for Token Classification using BERT

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword)

  • Kwargs:

    lang_code: language code: set as ‘ko’ if using BERT model trained with mecab-tokenized data tag_key: name of the label in .json file to use for classification ignore_tag_idx: prediction results that have this number as ground-truth idx are ignored

read_one_example(inputs)[source]

inputs keys: sequence

Module contents

================================================ FILE: docs/_build/html/claf.data.reader.html ================================================ claf.data.reader package — CLaF 0.2.0 documentation

claf.data.reader package

Submodules

class claf.data.reader.base.DataReader(file_paths, dataset_obj)[source]

Bases: object

DataReader Base Class

  • Args:

    file_paths: dictionary of consisting (‘train’ and ‘vaild’) file_path dataset_obj: Dataset Object (claf.data.dataset.base)

convert_to_dataset(datas, vocab, helpers=None)[source]

Batch to Dataset

filter_texts(dataset)[source]
read()[source]

read with Concrete DataReader each type

read_one_example(inputs)[source]
class claf.data.reader.cola.CoLAReader(file_paths, tokenizers, sequence_max_length=None)[source]

Bases: claf.data.reader.seq_cls.SeqClsReader

CoLA DataReader

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (word)

CLASS_DATA = [0, 1]
class claf.data.reader.seq_cls.SeqClsReader(file_paths, tokenizers, sequence_max_length=None, class_key='class')[source]

Bases: claf.data.reader.base.DataReader

DataReader for Sequence Classification

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (word)

  • Kwargs:

    class_key: name of the label in .json file to use for classification

CLASS_DATA = None
read_one_example(inputs)[source]

inputs keys: sequence

class claf.data.reader.squad.SQuADReader(file_paths, lang_code, tokenizers, context_max_length=None)[source]

Bases: claf.data.reader.base.DataReader

SQuAD DataReader

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word)

read_one_example(inputs)[source]

inputs keys: question, context

class claf.data.reader.wikisql.WikiSQLReader(file_paths, tokenizers, context_max_length=None, is_test=None)[source]

Bases: claf.data.reader.base.DataReader

WikiSQL DataReader (http://arxiv.org/abs/1709.00103)

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word)

get_coditions_value_position(question, values)[source]
load_data(sql_path, table_path, data_type=None)[source]
read_one_example(inputs)[source]

inputs keys: question, column, db_path, table_id

Module contents

class claf.data.reader.MultiTaskBertReader(file_paths, tokenizers, batch_sizes=[], readers=[])[source]

Bases: claf.data.reader.base.DataReader

DataReader for Multi-Task using BERT

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword)

  • Kwargs:

    class_key: name of the label in .json file to use for classification

CLASS_DATA = None
make_data_reader(config_dict)[source]
make_task_by_reader(name, data_reader, helper)[source]
read_one_example(inputs)[source]
class claf.data.reader.RegressionBertReader(file_paths, tokenizers, sequence_max_length=None, label_key='score', cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.base.DataReader

Regression DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

METRIC_KEY = None
read_one_example(inputs)[source]

inputs keys: sequence_a and sequence_b

class claf.data.reader.STSBBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.regression.RegressionBertReader

STS-B (Semantic Textual Similarity Benchmark) DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

METRIC_KEY = 'pearson_spearman_corr'
class claf.data.reader.SeqClsReader(file_paths, tokenizers, sequence_max_length=None, class_key='class')[source]

Bases: claf.data.reader.base.DataReader

DataReader for Sequence Classification

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (word)

  • Kwargs:

    class_key: name of the label in .json file to use for classification

CLASS_DATA = None
read_one_example(inputs)[source]

inputs keys: sequence

class claf.data.reader.CoLAReader(file_paths, tokenizers, sequence_max_length=None)[source]

Bases: claf.data.reader.seq_cls.SeqClsReader

CoLA DataReader

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (word)

CLASS_DATA = [0, 1]
class claf.data.reader.SeqClsBertReader(file_paths, tokenizers, sequence_max_length=None, class_key='class', cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.base.DataReader

DataReader for Sequence (Single and Pair) Classification using BERT

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword)

  • Kwargs:

    class_key: name of the label in .json file to use for classification

CLASS_DATA = None
METRIC_KEY = None
read_one_example(inputs)[source]

inputs keys: sequence_a and sequence_b

class claf.data.reader.CoLABertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.seq_cls.SeqClsBertReader

CoLA DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

CLASS_DATA = [0, 1]
METRIC_KEY = 'matthews_corr'
class claf.data.reader.MRPCBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.seq_cls.SeqClsBertReader

MRPC DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

CLASS_DATA = [0, 1]
METRIC_KEY = 'f1'
class claf.data.reader.MNLIBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.seq_cls.SeqClsBertReader

MNLI DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

CLASS_DATA = ['contradiction', 'entailment', 'neutral']
METRIC_KEY = 'accuracy'
class claf.data.reader.QNLIBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.seq_cls.SeqClsBertReader

QNLI DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

CLASS_DATA = ['entailment', 'not_entailment']
METRIC_KEY = 'accuracy'
class claf.data.reader.QQPBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.seq_cls.SeqClsBertReader

Quora Question Pairs DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

CLASS_DATA = [0, 1]
METRIC_KEY = 'f1'
class claf.data.reader.RTEBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.seq_cls.SeqClsBertReader

RTE (Recognizing Textual Entailment) DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

CLASS_DATA = ['entailment', 'not_entailment']
METRIC_KEY = 'accuracy'
class claf.data.reader.SSTBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.seq_cls.SeqClsBertReader

SST DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

CLASS_DATA = [0, 1]
METRIC_KEY = 'accuracy'
class claf.data.reader.STSBBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.regression.RegressionBertReader

STS-B (Semantic Textual Similarity Benchmark) DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

METRIC_KEY = 'pearson_spearman_corr'
class claf.data.reader.WNLIBertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', input_type='bert', is_test=False)[source]

Bases: claf.data.reader.bert.seq_cls.SeqClsBertReader

WNLI (Winograd NLI) DataReader for BERT

  • Args:

    file_paths: .tsv file paths (train and dev) tokenizers: defined tokenizers config

CLASS_DATA = [0, 1]
METRIC_KEY = 'accuracy'
class claf.data.reader.SQuADReader(file_paths, lang_code, tokenizers, context_max_length=None)[source]

Bases: claf.data.reader.base.DataReader

SQuAD DataReader

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word)

read_one_example(inputs)[source]

inputs keys: question, context

class claf.data.reader.SQuADBertReader(file_paths, lang_code, tokenizers, max_seq_length=384, context_stride=128, max_question_length=64, cls_token='[CLS]', sep_token='[SEP]')[source]

Bases: claf.data.reader.base.DataReader

SQuAD DataReader for BERT

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word)

METRIC_KEY = 'f1'
read_one_example(inputs)[source]

inputs keys: question, context

class claf.data.reader.TokClsBertReader(file_paths, tokenizers, lang_code=None, sequence_max_length=None, tag_key='tags', cls_token='[CLS]', sep_token='[SEP]', ignore_tag_idx=-1)[source]

Bases: claf.data.reader.base.DataReader

DataReader for Token Classification using BERT

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: define tokenizers config (subword)

  • Kwargs:

    lang_code: language code: set as ‘ko’ if using BERT model trained with mecab-tokenized data tag_key: name of the label in .json file to use for classification ignore_tag_idx: prediction results that have this number as ground-truth idx are ignored

read_one_example(inputs)[source]

inputs keys: sequence

class claf.data.reader.CoNLL2003BertReader(file_paths, tokenizers, sequence_max_length=None, cls_token='[CLS]', sep_token='[SEP]', ignore_tag_idx=-1)[source]

Bases: claf.data.reader.bert.tok_cls.TokClsBertReader

CoNLL2003 for BERT

  • Args:

    file_paths: file paths (train and dev)

  • Kwargs:

    ignore_tag_idx: prediction results that have this number as ground-truth idx are ignored

class claf.data.reader.WikiSQLReader(file_paths, tokenizers, context_max_length=None, is_test=None)[source]

Bases: claf.data.reader.base.DataReader

WikiSQL DataReader (http://arxiv.org/abs/1709.00103)

  • Args:

    file_paths: .json file paths (train and dev) tokenizers: defined tokenizers config (char/word)

get_coditions_value_position(question, values)[source]
load_data(sql_path, table_path, data_type=None)[source]
read_one_example(inputs)[source]

inputs keys: question, column, db_path, table_id

================================================ FILE: docs/_build/html/claf.decorator.html ================================================ claf.decorator package — CLaF 0.2.0 documentation

claf.decorator package

Submodules

class claf.decorator.arguments.arguments_required(required_fields)[source]

Bases: object

Decorator Class check required arguments for predict function (eg. @arguments_required([“db_path”, “table_id”]))

class claf.decorator.register.register(name)[source]

Bases: object

Decorator Class register subclass with decorator. (eg. @register(“model:bidaf”), @register(“reader:squad”) )

Module contents

class claf.decorator.arguments_required(required_fields)[source]

Bases: object

Decorator Class check required arguments for predict function (eg. @arguments_required([“db_path”, “table_id”]))

class claf.decorator.register(name)[source]

Bases: object

Decorator Class register subclass with decorator. (eg. @register(“model:bidaf”), @register(“reader:squad”) )

================================================ FILE: docs/_build/html/claf.html ================================================ claf package — CLaF 0.2.0 documentation

claf package

Subpackages

Submodules

claf.utils.flatten(l)[source]
claf.utils.get_user_input(category)[source]
claf.utils.set_logging_config(mode, config)[source]

Module contents

================================================ FILE: docs/_build/html/claf.learn.html ================================================ claf.learn package — CLaF 0.2.0 documentation

claf.learn package

Submodules

class claf.learn.experiment.Experiment(mode, config)[source]

Bases: object

Experiment settings with config.

  • Args:

    mode: Mode (ex. TRAIN, EVAL, INFER_EVAL, PREDICT) config: (NestedNamespace) Argument config according to mode

common_setting(mode, config)[source]

Common Setting - experiment config, use_gpu and cuda_device_ids

load_setting()[source]

Load Setting - need to load checkpoint case (ex. evaluate and predict)

predict(raw_features)[source]
set_eval_inference_latency_mode()[source]

Evaluate Inference Latency Mode

  • Pipeline 1. read raw_data (DataReader) 2. load vocabs from checkpoint (DataReader, Token) 3. define raw_to_tensor_fn (DataReader, Token) 4. define and load model 5. run!

set_eval_mode()[source]

Evaluate Mode

  • Pipeline 1. read raw_data (DataReader) 2. load vocabs from checkpoint (DataReader, Token) 3. indexing tokens (DataReader, Token) 4. convert to DataSet (DataReader) 5. create DataLoader (DataLoader) 6. define and load model 7. run!

set_predict_mode(preload=False)[source]

Predict Mode

  • Pipeline 1. read raw_data (Argument) 2. load vocabs from checkpoint (DataReader, Token) 3. define raw_to_tensor_fn (DataReader, Token) 4. define and load model 5. run!

set_train_mode()[source]

Training Mode

  • Pipeline 1. read raw_data (DataReader) 2. build vocabs (DataReader, Token) 3. indexing tokens (DataReader, Token) 4. convert to DataSet (DataReader) 5. create DataLoader (DataLoader) 6. define model and optimizer 7. run!

set_trainer(model, op_dict={}, save_params={})[source]
class claf.learn.mode.Mode[source]

Bases: object

Experiment Flag class

EVAL = 'eval'
INFER_EVAL = 'infer_eval'
MACHINE = 'machine'
PREDICT = 'predict'
TRAIN = 'train'
class claf.learn.tensorboard.TensorBoard(log_dir)[source]

Bases: object

TensorBoard Wrapper for Pytorch

embedding_summary(features, metadata=None, label_img=None)[source]
graph_summary(model, input_to_model=None)[source]
histogram_summary(tag, values, step, bins=1000)[source]

Log a histogram of the tensor of values.

image_summary(tag, images, step)[source]

Log a list of images.

scalar_summaries(step, summary)[source]
scalar_summary(step, tag, value)[source]

Log a scalar variable.

class claf.learn.trainer.Trainer(model, config={}, log_dir='logs/experiment', grad_max_norm=None, gradient_accumulation_steps=1, learning_rate_scheduler=None, exponential_moving_average=None, num_epochs=20, early_stopping_threshold=10, max_eval_examples=5, metric_key=None, verbose_step_count=100, eval_and_save_step_count='epoch', save_checkpoint=True)[source]

Bases: object

Run experiment

  • train

  • train_and_evaluate

  • evaluate

  • evaluate_inference_latency

  • predict

  • Args:

    config: experiment overall config model: Model based on torch.nn.Module

  • Kwargs:

    log_dir: path to directory for save model and other options grad_max_norm: Clips gradient norm of an iterable of parameters. learning_rate_scheduler: PyTorch’s Learning Rate Scheduler.

    exponential_moving_average: the moving averages of all weights of the model are maintained

    with the exponential decay rate of {ema}.

    num_epochs: the number of maximun epochs (Default is 20) early_stopping_threshold: the number of early stopping threshold (Default is 10) max_eval_examples: print evaluation examples metric_key: metric score’s control point verbose_step_count: print verbose step count (Default is 100) eval_and_save_step_count: evaluate valid_dataset then save every n step_count (Default is ‘epoch’)

evaluate(data_loader)[source]

Evaluate

evaluate_inference_latency(raw_examples, raw_to_tensor_fn, token_key=None, max_latency=1000)[source]

Evaluate with focusing inferece latency (Note: must use sorted synthetic data)

  • inference_latency: raw_data -> pre-processing -> model -> predict_value

    (elapsed_time) (elapsed_time)

predict(raw_feature, raw_to_tensor_fn, arguments, interactive=False)[source]

Inference / Predict

save(optimizer)[source]
set_model_base_properties(config, log_dir)[source]
train(data_loader, optimizer)[source]

Train

train_and_evaluate(train_loader, valid_loader, optimizer)[source]

Train and Evaluate

class claf.learn.utils.TrainCounter(display_unit='epoch')[source]

Bases: object

epoch = 0
get_display()[source]
global_step = 0
claf.learn.utils.bind_nsml(model, **kwargs)[source]
claf.learn.utils.get_session_name()[source]
claf.learn.utils.get_sorted_path(checkpoint_dir, both_exist=False)[source]
claf.learn.utils.load_model_checkpoint(model, checkpoint)[source]
claf.learn.utils.load_optimizer_checkpoint(optimizer, checkpoint)[source]
claf.learn.utils.load_vocabs(model_checkpoint)[source]
claf.learn.utils.logger = <Logger claf.learn.utils (WARNING)>

Train Counter

claf.learn.utils.save_checkpoint(path, model, optimizer, max_to_keep=10)[source]
claf.learn.utils.send_message_to_slack(webhook_url, title=None, message=None)[source]

Module contents

================================================ FILE: docs/_build/html/claf.machine.components.html ================================================ claf.machine.components package — CLaF 0.2.0 documentation

claf.machine.components package

Module contents

class claf.machine.components.TFIDF(texts, word_tokenizer, k=1)[source]

Bases: object

TF-IDF document retrieval model

  • Term Frequency

  • Inverse Document Frequency

  • log(tf + 1) * log((N - Nt + 0.5) / (Nt + 0.5))

  • Kwargs:

    k: the number of top k results

INDEX_FNAME = 'similarities.index'
TFIDF_FNAME = 'tfidf.model'
VOCAB_FNAME = 'vocab.txt'
get_closest(query)[source]
init()[source]
init_model()[source]
load(dir_path)[source]
parse(query, ngram=1)[source]
save(dir_path)[source]
text_to_tfidf(query)[source]

Create a tfidf-weighted word vector from query.

tfidf = log(tf + 1) * log((N - Nt + 0.5) / (Nt + 0.5))

================================================ FILE: docs/_build/html/claf.machine.components.retrieval.html ================================================ claf.machine.components.retrieval package — CLaF 0.2.0 documentation

claf.machine.components.retrieval package

Submodules

class claf.machine.components.retrieval.tfidf.TFIDF(texts, word_tokenizer, k=1)[source]

Bases: object

TF-IDF document retrieval model

  • Term Frequency

  • Inverse Document Frequency

  • log(tf + 1) * log((N - Nt + 0.5) / (Nt + 0.5))

  • Kwargs:

    k: the number of top k results

INDEX_FNAME = 'similarities.index'
TFIDF_FNAME = 'tfidf.model'
VOCAB_FNAME = 'vocab.txt'
get_closest(query)[source]
init()[source]
init_model()[source]
load(dir_path)[source]
parse(query, ngram=1)[source]
save(dir_path)[source]
text_to_tfidf(query)[source]

Create a tfidf-weighted word vector from query.

tfidf = log(tf + 1) * log((N - Nt + 0.5) / (Nt + 0.5))

Module contents

================================================ FILE: docs/_build/html/claf.machine.html ================================================ claf.machine package — CLaF 0.2.0 documentation

claf.machine package

Submodules

class claf.machine.base.Machine(config)[source]

Bases: object

Machine: Combine modules then make a NLP Machine

  • Args:

    config: machine_config

load()[source]
classmethod load_from_config(config_path)[source]
make_module(config)[source]

Make component or experiment for claf Machine’s module

  • Args:
    • config: module’s config (claf.config.namespace.NestedNamespace)

class claf.machine.module.Module[source]

Bases: object

Machine Flag class

COMPONENT = 'component'
EXPERIMENT = 'experiment'
KNOWLEDGE_BASE = 'knowledge_base'
class claf.machine.nlu.NLU(config)[source]

Bases: claf.machine.base.Machine

Natural Language Understanding Machine

  • Args:

    config: machine_config

intent_classification(utterance)[source]
load()[source]
slot_filling(utterance)[source]
class claf.machine.open_qa.OpenQA(config)[source]

Bases: claf.machine.base.Machine

Open-Domain Question Answer Machine (DrQA)

DrQA is a system for reading comprehension applied to open-domain question answering.

  • Args:

    config: machine_config

load()[source]
machine_reading(context, question)[source]
search_documents(question)[source]

Module contents

class claf.machine.OpenQA(config)[source]

Bases: claf.machine.base.Machine

Open-Domain Question Answer Machine (DrQA)

DrQA is a system for reading comprehension applied to open-domain question answering.

  • Args:

    config: machine_config

load()[source]
machine_reading(context, question)[source]
search_documents(question)[source]
class claf.machine.NLU(config)[source]

Bases: claf.machine.base.Machine

Natural Language Understanding Machine

  • Args:

    config: machine_config

intent_classification(utterance)[source]
load()[source]
slot_filling(utterance)[source]
================================================ FILE: docs/_build/html/claf.metric.html ================================================ claf.metric package — CLaF 0.2.0 documentation

claf.metric package

Submodules

claf.metric.classification.f1(pycm_obj)[source]
claf.metric.classification.macro_f1(pycm_obj)[source]
claf.metric.classification.macro_precision(pycm_obj)[source]
claf.metric.classification.macro_recall(pycm_obj)[source]
claf.metric.classification.precision(pycm_obj)[source]
claf.metric.classification.recall(pycm_obj)[source]

Official evaluation script for v1.1 of the SQuAD dataset.

claf.metric.squad_v1_official.evaluate(dataset, predictions)[source]
claf.metric.squad_v1_official.exact_match_score(prediction, ground_truth)[source]
claf.metric.squad_v1_official.f1_score(prediction, ground_truth)[source]
claf.metric.squad_v1_official.metric_max_over_ground_truths(metric_fn, prediction, ground_truths)[source]
claf.metric.squad_v1_official.normalize_answer(s)[source]

Lower text and remove punctuation, articles and extra whitespace.

Official evaluation script for SQuAD version 2.0.

In addition to basic functionality, we also compute additional statistics and plot precision-recall curves if an additional na_prob.json file is provided. This file is expected to map question ID’s to the model’s predicted probability that a question is unanswerable.

claf.metric.squad_v2_official.apply_no_ans_threshold(scores, na_probs, qid_to_has_ans, na_prob_thresh)[source]
claf.metric.squad_v2_official.compute_exact(a_gold, a_pred)[source]
claf.metric.squad_v2_official.compute_f1(a_gold, a_pred)[source]
claf.metric.squad_v2_official.evaluate(dataset, na_probs, preds, na_prob_thresh=1.0)[source]
claf.metric.squad_v2_official.find_all_best_thresh(main_eval, preds, exact_raw, f1_raw, na_probs, qid_to_has_ans)[source]
claf.metric.squad_v2_official.find_best_thresh(preds, scores, na_probs, qid_to_has_ans)[source]
claf.metric.squad_v2_official.get_raw_scores(dataset, preds)[source]
claf.metric.squad_v2_official.get_tokens(s)[source]
claf.metric.squad_v2_official.histogram_na_prob(na_probs, qid_list, image_dir, name)[source]
claf.metric.squad_v2_official.main()[source]
claf.metric.squad_v2_official.make_eval_dict(exact_scores, f1_scores, qid_list=None)[source]
claf.metric.squad_v2_official.make_precision_recall_eval(scores, na_probs, num_true_pos, qid_to_has_ans, out_image=None, title=None)[source]
claf.metric.squad_v2_official.make_qid_to_has_ans(dataset)[source]
claf.metric.squad_v2_official.merge_eval(main_eval, new_eval, prefix)[source]
claf.metric.squad_v2_official.normalize_answer(s)[source]

Lower text and remove punctuation, articles and extra whitespace.

claf.metric.squad_v2_official.parse_args()[source]
claf.metric.squad_v2_official.plot_pr_curve(precisions, recalls, out_image, title)[source]
claf.metric.squad_v2_official.run_precision_recall_analysis(main_eval, exact_raw, f1_raw, na_probs, qid_to_has_ans, out_image_dir)[source]

Official evaluation script for WikiSQL dataset.

claf.metric.wikisql_official.count_lines(fname)[source]
claf.metric.wikisql_official.evaluate(labels, predictions, db_path, ordered=True)[source]

labels and predictions: dictionary {data_uid: sql_data, …}

Module contents

================================================ FILE: docs/_build/html/claf.model.html ================================================ claf.model package — CLaF 0.2.0 documentation

claf.model package

Submodules

class claf.model.base.ModelBase[source]

Bases: torch.nn.modules.module.Module

Model Base Class

Args:

token_embedder: (claf.tokens.token_embedder.base) TokenEmbedder

property config
property dataset
forward(inputs)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

is_ready()[source]
property log_dir
make_metrics(predictions)[source]
make_predictions(features)[source]

for Metrics

property metrics
predict(features)[source]

Inference

print_examples(params)[source]

Print evaluation examples

property train_counter
property vocabs
write_predictions(predictions, file_path=None, is_dict=True)[source]
class claf.model.base.ModelWithTokenEmbedder(token_embedder)[source]

Bases: claf.model.base.ModelBase

class claf.model.base.ModelWithoutTokenEmbedder(token_makers)[source]

Bases: claf.model.base.ModelBase

claf.model.cls_utils.get_tag_dict(sequence, tag_texts)[source]
claf.model.cls_utils.write_confusion_matrix_to_csv(file_path, pycm_obj)[source]

Module contents

================================================ FILE: docs/_build/html/claf.model.reading_comprehension.html ================================================ claf.model.reading_comprehension package — CLaF 0.2.0 documentation

claf.model.reading_comprehension package

Submodules

class claf.model.reading_comprehension.bidaf.BiDAF(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=None, model_dim=100, contextual_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1, claf.model.base.ModelWithTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in BiDAF: Bidirectional Attention Flow for Machine Comprehension (https://arxiv.org/abs/1611.01603)

  • Embedding (Word + Char -> Contextual)

  • Attention Flow

  • Modeling (RNN)

  • Output

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension contextual_rnn_num_layer: the number of recurrent layers (contextual) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.bidaf_no_answer.BiDAF_No_Answer(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=None, model_dim=100, contextual_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv2, claf.model.base.ModelWithTokenEmbedder

Question Answering Model. Span Detector, No Answer

Bidirectional Attention Flow for Machine Comprehension + Bias (No_Answer)

  • Embedding (Word + Char -> Contextual)

  • Attention Flow

  • Modeling (RNN)

  • Output

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.docqa.DocQA(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=17, rnn_dim=100, linear_dim=200, preprocess_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, weight_init=True)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1, claf.model.base.ModelWithTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in Simple and Effective Multi-Paragraph Reading Comprehension (https://arxiv.org/abs/1710.10723)

  • Embedding (Word + Char -> Contextual)

  • Attention

  • Residual self-attention

  • Output

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} rnn_dim: the number of RNN cell dimension linear_dim: the number of attention linear dimension preprocess_rnn_num_layer: the number of recurrent layers (preprocess) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.docqa.SelfAttention(rnn_dim, linear_dim, dropout=0.2, weight_init=True)[source]

Bases: torch.nn.modules.module.Module

Same bi-attention mechanism, only now between the passage and itself.

forward(context, context_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.reading_comprehension.docqa_no_answer.DocQA_No_Answer(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=17, rnn_dim=100, linear_dim=200, preprocess_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, weight_init=True)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv2, claf.model.base.ModelWithTokenEmbedder

Question Answering Model. Span Detector, No Answer

Implementation of model presented in Simple and Effective Multi-Paragraph Reading Comprehension + No_Asnwer (https://arxiv.org/abs/1710.10723)

  • Embedding (Word + Char -> Contextual)

  • Attention

  • Residual self-attention

  • Output

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} rnn_dim: the number of RNN cell dimension linear_dim: the number of attention linear dimension preprocess_rnn_num_layer: the number of recurrent layers (preprocess) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.docqa_no_answer.NoAnswer(embed_dim, bias_hidden_dim)[source]

Bases: torch.nn.modules.module.Module

No-Answer Option

  • Args:

    embed_dim: the number of passage embedding dimension bias_hidden_dim: bias use two layer mlp, the number of hidden_size

forward(context_embed, span_start_logits, span_end_logits)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.reading_comprehension.docqa_no_answer.SelfAttention(rnn_dim, linear_dim, dropout=0.2, weight_init=True)[source]

Bases: torch.nn.modules.module.Module

Same bi-attention mechanism, only now between the passage and itself.

forward(context, context_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.reading_comprehension.drqa.DrQA(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=None, model_dim=128, dropout=0.3)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1, claf.model.base.ModelWithTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in Reading Wikipedia to Answer Open-Domain Questions (https://arxiv.org/abs/1704.00051)

  • Embedding + features

  • Align question embedding

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.mixin.ReadingComprehension[source]

Bases: object

Reading Comprehension Mixin Class

  • Args:

    token_embedder: ‘RCTokenEmbedder’, Used to embed the ‘context’ and ‘question’.

get_best_span(span_start_logits, span_end_logits, answer_maxlen=None)[source]

Take argmax of constrained score_s * score_e.

  • Args:

    span_start_logits: independent start logits span_end_logits: independent end logits

  • Kwargs:

    answer_maxlen: max span length to consider (default is None -> All)

make_predictions(output_dict)[source]

Make predictions with model’s output_dict

  • Args:
    output_dict: model’s output dictionary consisting of
    • data_idx: question id

    • best_span: calculate the span_start_logits and span_end_logits to what is the best span

    • start_logits: span start logits

    • end_logits: span end logits

  • Returns:
    predictions: prediction dictionary consisting of
    • key: ‘id’ (question id)

    • value: consisting of dictionary

      predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob

predict(**kwargs)
print_examples(index, inputs, predictions)[source]

Print evaluation examples

  • Args:

    index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of

    • key: ‘id’ (question id)

    • value: consisting of dictionary

      predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob

  • Returns:

    print(Context, Question, Answers and Predict)

write_predictions(predictions, file_path=None, is_dict=True)[source]
class claf.model.reading_comprehension.mixin.SQuADv1[source]

Bases: claf.model.reading_comprehension.mixin.ReadingComprehension

Reading Comprehension Mixin Class

with SQuAD v1.1 evaluation

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

make_metrics(predictions)[source]

Make metrics with prediction dictionary

  • Args:
    predictions: prediction dictionary consisting of
    • key: ‘id’ (question id)

    • value: (predict_text, pred_span_start, pred_span_end)

  • Returns:
    metrics: metric dictionary consisting of
    • ‘em’: exact_match (SQuAD v1.1 official evaluation)

    • ‘f1’: f1 (SQuAD v1.1 official evaluation)

    • ‘start_acc’: span_start accuracy

    • ‘end_acc’: span_end accuracy

    • ‘span_acc’: span accuracy (start and end)

class claf.model.reading_comprehension.mixin.SQuADv1ForBert[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1

Reading Comprehension Mixin Class

with SQuAD v1.1 evaluation

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

make_metrics(predictions)[source]

BERT predictions need to get nbest result

predict(output_dict, arguments, helper)[source]

Inference by raw_feature

  • Args:
    output_dict: model’s output dictionary consisting of
    • data_idx: question id

    • best_span: calculate the span_start_logits and span_end_logits to what is the best span

    arguments: arguments dictionary consisting of user_input helper: dictionary for helping get answer

  • Returns:

    span: predict best_span

class claf.model.reading_comprehension.mixin.SQuADv2[source]

Bases: claf.model.reading_comprehension.mixin.ReadingComprehension

Reading Comprehension Mixin Class

with SQuAD v2.0 evaluation

  • Args:

    token_embedder: ‘RCTokenEmbedder’, Used to embed the ‘context’ and ‘question’.

make_metrics(predictions)[source]

Make metrics with prediction dictionary

  • Args:
    predictions: prediction dictionary consisting of
    • key: ‘id’ (question id)

    • value: consisting of dictionary

      predict_text, pred_span_start, pred_span_end, span_start_prob, span_end_prob

  • Returns:
    metrics: metric dictionary consisting of
    • ‘start_acc’: span_start accuracy

    • ‘end_acc’: span_end accuracy

    • ‘span_acc’: span accuracy (start and end)

    • ‘em’: exact_match (SQuAD v2.0 official evaluation)

    • ‘f1’: f1 (SQuAD v2.0 official evaluation)

    • ‘HasAns_exact’: has answer exact_match

    • ‘HasAns_f1’: has answer f1

    • ‘NoAns_exact’: no answer exact_match

    • ‘NoAns_f1’: no answer f1

    • ‘best_exact’: best exact_match score with best_exact_thresh

    • ‘best_exact_thresh’: best exact_match answerable threshold

    • ‘best_f1’: best f1 score with best_f1_thresh

    • ‘best_f1_thresh’: best f1 answerable threshold

class claf.model.reading_comprehension.qanet.EncoderBlock(model_dim=128, num_head=8, kernel_size=5, num_conv_block=4, dropout=0.1, layer_dropout=0.9)[source]

Bases: torch.nn.modules.module.Module

Encoder Block

[]: residual position_encoding -> [convolution-layer] x # -> [self-attention-layer] -> [feed-forward-layer]

  • convolution-layer: depthwise separable convolutions

  • self-attention-layer: multi-head attention

  • feed-forward-layer: pointwise convolution

  • Args:

    model_dim: the number of model dimension num_heads: the number of head in multi-head attention kernel_size: convolution kernel size num_conv_block: the number of convolution block dropout: the dropout probability layer_dropout: the layer dropout probability

    (cf. Deep Networks with Stochastic Depth(https://arxiv.org/abs/1603.09382) )

forward(x, mask=None)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.reading_comprehension.qanet.QANet(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=None, model_dim=128, kernel_size_in_embedding=7, num_head_in_embedding=8, num_conv_block_in_embedding=4, num_embedding_encoder_block=1, kernel_size_in_modeling=5, num_head_in_modeling=8, num_conv_block_in_modeling=2, num_modeling_encoder_block=7, dropout=0.1, layer_dropout=0.9)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1, claf.model.base.ModelWithTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in QANet:Combining Local Convolution with Global Self-Attention for Reading Comprehension (https://arxiv.org/abs/1804.09541)

  • Input Embedding Layer

  • Embedding Encoder Layer

  • Context-Query Attention Layer

  • Model Encoder Layer

  • Output Layer

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension

    • Encoder Block Parameters (embedding, modeling) kernel_size: convolution kernel size in encoder block num_head: the number of multi-head attention’s head num_conv_block: the number of convolution block in encoder block

      [Layernorm -> Conv (residual)]

      num_encoder_block: the number of the encoder block
      [position_encoding -> [n repeat conv block] -> Layernorm -> Self-attention (residual)

      -> Layernorm -> Feedforward (residual)]

    dropout: the dropout probability layer_dropout: the layer dropout probability

    (cf. Deep Networks with Stochastic Depth(https://arxiv.org/abs/1603.09382) )

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

Module contents

class claf.model.reading_comprehension.BertForQA(token_makers, lang_code='en', pretrained_model_name=None, answer_maxlen=30)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1ForBert, claf.model.base.ModelWithoutTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805)

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] pretrained_model_name: the name of a pre-trained model answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen}

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.BiDAF(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=None, model_dim=100, contextual_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1, claf.model.base.ModelWithTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in BiDAF: Bidirectional Attention Flow for Machine Comprehension (https://arxiv.org/abs/1611.01603)

  • Embedding (Word + Char -> Contextual)

  • Attention Flow

  • Modeling (RNN)

  • Output

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension contextual_rnn_num_layer: the number of recurrent layers (contextual) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.QANet(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=None, model_dim=128, kernel_size_in_embedding=7, num_head_in_embedding=8, num_conv_block_in_embedding=4, num_embedding_encoder_block=1, kernel_size_in_modeling=5, num_head_in_modeling=8, num_conv_block_in_modeling=2, num_modeling_encoder_block=7, dropout=0.1, layer_dropout=0.9)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1, claf.model.base.ModelWithTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in QANet:Combining Local Convolution with Global Self-Attention for Reading Comprehension (https://arxiv.org/abs/1804.09541)

  • Input Embedding Layer

  • Embedding Encoder Layer

  • Context-Query Attention Layer

  • Model Encoder Layer

  • Output Layer

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension

    • Encoder Block Parameters (embedding, modeling) kernel_size: convolution kernel size in encoder block num_head: the number of multi-head attention’s head num_conv_block: the number of convolution block in encoder block

      [Layernorm -> Conv (residual)]

      num_encoder_block: the number of the encoder block
      [position_encoding -> [n repeat conv block] -> Layernorm -> Self-attention (residual)

      -> Layernorm -> Feedforward (residual)]

    dropout: the dropout probability layer_dropout: the layer dropout probability

    (cf. Deep Networks with Stochastic Depth(https://arxiv.org/abs/1603.09382) )

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.DocQA(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=17, rnn_dim=100, linear_dim=200, preprocess_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, weight_init=True)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1, claf.model.base.ModelWithTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in Simple and Effective Multi-Paragraph Reading Comprehension (https://arxiv.org/abs/1710.10723)

  • Embedding (Word + Char -> Contextual)

  • Attention

  • Residual self-attention

  • Output

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} rnn_dim: the number of RNN cell dimension linear_dim: the number of attention linear dimension preprocess_rnn_num_layer: the number of recurrent layers (preprocess) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.DrQA(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=None, model_dim=128, dropout=0.3)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1, claf.model.base.ModelWithTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in Reading Wikipedia to Answer Open-Domain Questions (https://arxiv.org/abs/1704.00051)

  • Embedding + features

  • Align question embedding

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.RoBertaForQA(token_makers, lang_code='en', pretrained_model_name=None, answer_maxlen=30)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv1ForBert, claf.model.base.ModelWithoutTokenEmbedder

Document Reader Model. Span Detector

Implementation of model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805)

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] pretrained_model_name: the name of a pre-trained model answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen}

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.BiDAF_No_Answer(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=None, model_dim=100, contextual_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv2, claf.model.base.ModelWithTokenEmbedder

Question Answering Model. Span Detector, No Answer

Bidirectional Attention Flow for Machine Comprehension + Bias (No_Answer)

  • Embedding (Word + Char -> Contextual)

  • Attention Flow

  • Modeling (RNN)

  • Output

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} model_dim: the number of model dimension dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

class claf.model.reading_comprehension.DocQA_No_Answer(token_embedder, lang_code='en', aligned_query_embedding=False, answer_maxlen=17, rnn_dim=100, linear_dim=200, preprocess_rnn_num_layer=1, modeling_rnn_num_layer=2, predict_rnn_num_layer=1, dropout=0.2, weight_init=True)[source]

Bases: claf.model.reading_comprehension.mixin.SQuADv2, claf.model.base.ModelWithTokenEmbedder

Question Answering Model. Span Detector, No Answer

Implementation of model presented in Simple and Effective Multi-Paragraph Reading Comprehension + No_Asnwer (https://arxiv.org/abs/1710.10723)

  • Embedding (Word + Char -> Contextual)

  • Attention

  • Residual self-attention

  • Output

  • Args:

    token_embedder: ‘QATokenEmbedder’, Used to embed the ‘context’ and ‘question’.

  • Kwargs:

    lang_code: Dataset language code [en|ko] aligned_query_embedding: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

    answer_maxlen: the most probable answer span of length less than or equal to {answer_maxlen} rnn_dim: the number of RNN cell dimension linear_dim: the number of attention linear dimension preprocess_rnn_num_layer: the number of recurrent layers (preprocess) modeling_rnn_num_layer: the number of recurrent layers (modeling) predict_rnn_num_layer: the number of recurrent layers (predict) dropout: the dropout probability

forward(features, labels=None)[source]
  • Args:
    features: feature dictionary like below.
    {“feature_name1”: {

    “token_name1”: tensor, “toekn_name2”: tensor},

    “feature_name2”: …}

  • Kwargs:
    label: label dictionary like below.
    {“label_name1”: tensor,

    “label_name2”: tensor} Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • start_logits: representing unnormalized log probabilities of the span start position.

    • end_logits: representing unnormalized log probabilities of the span end position.

    • best_span: the string from the original passage that the model thinks is the best answer to the question.

    • data_idx: the question id, mapping with answer

    • loss: A scalar loss to be optimised.

================================================ FILE: docs/_build/html/claf.model.semantic_parsing.html ================================================ claf.model.semantic_parsing package — CLaF 0.2.0 documentation

claf.model.semantic_parsing package

Submodules

class claf.model.semantic_parsing.mixin.WikiSQL[source]

Bases: object

WikiSQL Mixin Class

with official evaluation

  • Args:

    token_embedder: ‘TokenEmbedder’

AGG_OPS = ['None', 'MAX', 'MIN', 'COUNT', 'SUM', 'AVG']
COND_OPS = ['EQL', 'GT', 'LT']
decode_pointer(tokenized_question, cond_value_logits)[source]
generate_queries(output_dict)[source]
make_metrics(predictions)[source]

aggregator, select_column, conditions accuracy

make_predictions(output_dict)[source]
merge_tokens(tok_list, raw_tok_str)[source]
predict(**kwargs)
print_examples(index, inputs, predictions)[source]

Print evaluation examples

  • Args:

    index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of

    • key: ‘id’ (question id)

    • value: consisting of dictionary

      table_id, query (agg, sel, conds)

  • Returns:

    print(Context, Question, Answers and Predict)

class claf.model.semantic_parsing.sqlnet.AggPredictor(embed_dim, model_dim, rnn_num_layer, dropout, agg_count)[source]

Bases: torch.nn.modules.module.Module

forward(question_embed, question_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.semantic_parsing.sqlnet.CondsColPredictor(embed_dim, model_dim, rnn_num_layer, dropout, column_attention=None)[source]

Bases: torch.nn.modules.module.Module

forward(question_embed, question_mask, column_embed, column_name_mask, column_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.semantic_parsing.sqlnet.CondsNumPredictor(embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen)[source]

Bases: torch.nn.modules.module.Module

forward(question_embed, question_mask, column_embed, column_name_mask, column_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.semantic_parsing.sqlnet.CondsOpPredictor(embed_dim, model_dim, rnn_num_layer, dropout, op_count, column_maxlen, column_attention=None)[source]

Bases: torch.nn.modules.module.Module

forward(question_embed, question_mask, column_embed, column_name_mask, col_idx)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.semantic_parsing.sqlnet.CondsPredictor(embed_dim, model_dim, rnn_num_layer, dropout, conds_op_count, column_maxlen, token_maxlen, column_attention=None)[source]

Bases: torch.nn.modules.module.Module

forward(question_embed, question_mask, column_embed, column_name_mask, column_mask, col_idx, conds_val_pos)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.semantic_parsing.sqlnet.CondsValuePointer(embed_dim, model_dim, rnn_num_layer, dropout, column_maxlen, token_maxlen)[source]

Bases: torch.nn.modules.module.Module

concat_start_and_end_zero_padding(question_embed, mask)[source]
decode_then_output(encoded_used_column, encoded_question, question_mask, decoder_input, decoder_hidden=None)[source]
forward(question_embed, question_mask, column_embed, column_name_mask, col_idx, conds_val_pos)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.semantic_parsing.sqlnet.SQLNet(token_embedder, column_attention=None, model_dim=100, rnn_num_layer=2, dropout=0.3, column_maxlen=4, token_maxlen=200, conds_column_loss_alpha=3)[source]

Bases: claf.model.semantic_parsing.mixin.WikiSQL, claf.model.base.ModelWithTokenEmbedder

Nature Language to SQL Query Model. Semantic Parsing, NL2SQL

Implementation of model presented in SQLNet: Generating Structured Queries From Natural Language

Without Reinforcement Learning

(https://arxiv.org/abs/1711.04436)

  • Args:

    token_embedder: ‘WikiSQLTokenEmbedder’, Used to embed the ‘column’ and ‘question’.

  • Kwargs:
    column_attention: highlight that column attention is a special instance of

    the generic attention mechanism to compute the attention map on a question conditioned on the column names.

    model_dim: the number of model dimension rnn_num_layer: the number of recurrent layers (all of rnn) column_maxlen: an upper-bound N on the number of columns to choose token_maxlen: conds value slot - pointer network an upper-bound N on the number of token conds_column_loss_alpha: balance the positive data versus negative data

forward(features, labels=None)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.model.semantic_parsing.sqlnet.SelPredictor(embed_dim, model_dim, rnn_num_layer, dropout, column_attention=None)[source]

Bases: torch.nn.modules.module.Module

forward(question_embed, question_mask, column_embed, column_name_mask, column_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

claf.model.semantic_parsing.utils.convert_position_to_decoder_input(conds_val_pos, token_maxlen=200)[source]
claf.model.semantic_parsing.utils.encode_column(column_embed, column_name_mask, rnn_module)[source]
claf.model.semantic_parsing.utils.filter_used_column(encoded_columns, col_idx, padding_count=4)[source]
claf.model.semantic_parsing.utils.get_column_lengths(column_embed, column_name_mask)[source]

Module contents

class claf.model.semantic_parsing.SQLNet(token_embedder, column_attention=None, model_dim=100, rnn_num_layer=2, dropout=0.3, column_maxlen=4, token_maxlen=200, conds_column_loss_alpha=3)[source]

Bases: claf.model.semantic_parsing.mixin.WikiSQL, claf.model.base.ModelWithTokenEmbedder

Nature Language to SQL Query Model. Semantic Parsing, NL2SQL

Implementation of model presented in SQLNet: Generating Structured Queries From Natural Language

Without Reinforcement Learning

(https://arxiv.org/abs/1711.04436)

  • Args:

    token_embedder: ‘WikiSQLTokenEmbedder’, Used to embed the ‘column’ and ‘question’.

  • Kwargs:
    column_attention: highlight that column attention is a special instance of

    the generic attention mechanism to compute the attention map on a question conditioned on the column names.

    model_dim: the number of model dimension rnn_num_layer: the number of recurrent layers (all of rnn) column_maxlen: an upper-bound N on the number of columns to choose token_maxlen: conds value slot - pointer network an upper-bound N on the number of token conds_column_loss_alpha: balance the positive data versus negative data

forward(features, labels=None)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

================================================ FILE: docs/_build/html/claf.model.sequence_classification.html ================================================ claf.model.sequence_classification package — CLaF 0.2.0 documentation

claf.model.sequence_classification package

Submodules

class claf.model.sequence_classification.mixin.SequenceClassification[source]

Bases: object

Sequence Classification Mixin Class

make_metrics(predictions)[source]

Make metrics with prediction dictionary

  • Args:
    predictions: prediction dictionary consisting of
    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • class_idx

  • Returns:
    metrics: metric dictionary consisting of
    • ‘macro_f1’: class prediction macro(unweighted mean) f1

    • ‘macro_precision’: class prediction macro(unweighted mean) precision

    • ‘macro_recall’: class prediction macro(unweighted mean) recall

    • ‘accuracy’: class prediction accuracy

make_predictions(output_dict)[source]

Make predictions with model’s output_dict

  • Args:
    output_dict: model’s output dictionary consisting of
    • sequence_embed: embedding vector of the sequence

    • logits: representing unnormalized log probabilities of the class

    • class_idx: target class idx

    • data_idx: data idx

    • loss: a scalar loss to be optimized

  • Returns:
    predictions: prediction dictionary consisting of
    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • class_idx

predict(output_dict, arguments, helper)[source]

Inference by raw_feature

  • Args:
    output_dict: model’s output dictionary consisting of
    • sequence_embed: embedding vector of the sequence

    • logits: representing unnormalized log probabilities of the class.

    arguments: arguments dictionary consisting of user_input helper: dictionary to get the classification result, consisting of

    • class_idx2text: dictionary converting class_idx to class_text

  • Returns: output dict (dict) consisting of
    • logits: representing unnormalized log probabilities of the class

    • class_idx: predicted class idx

    • class_text: predicted class text

print_examples(index, inputs, predictions)[source]

Print evaluation examples

  • Args:

    index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of

    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • class_idx

  • Returns:

    print(Sequence, Target Class, Predicted Class)

write_predictions(predictions, file_path=None, is_dict=True, pycm_obj=None)[source]

Override write_predictions() in ModelBase to log confusion matrix

class claf.model.sequence_classification.structured_self_attention.StructuredSelfAttention(token_embedder, num_classes, encoding_rnn_hidden_dim=300, encoding_rnn_num_layer=2, encoding_rnn_dropout=0.0, attention_dim=350, num_attention_heads=30, sequence_embed_dim=2000, dropout=0.5, penalization_coefficient=1.0)[source]

Bases: claf.model.sequence_classification.mixin.SequenceClassification, claf.model.base.ModelWithTokenEmbedder

Implementation of model presented in A Structured Self-attentive Sentence Embedding (https://arxiv.org/abs/1703.03130)

  • Args:

    token_embedder: used to embed the sequence num_classes: number of classified classes

  • Kwargs:

    encoding_rnn_hidden_dim: hidden dimension of rnn (unidirectional) encoding_rnn_num_layer: the number of rnn layers encoding_rnn_dropout: rnn dropout probability attention_dim: attention dimension # d_a in the paper num_attention_heads: number of attention heads # r in the paper sequence_embed_dim: dimension of sequence embedding dropout: classification layer dropout penalization_coefficient: penalty coefficient for frobenius norm

forward(features, labels=None)[source]
  • Args:

    features: feature dictionary like below. {“sequence”: [0, 3, 4, 1]}

  • Kwargs:

    label: label dictionary like below. {“class_idx”: 2, “data_idx”: 0}

    Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • sequence_embed: embedding vector of the sequence

    • logits: representing unnormalized log probabilities of the class.

    • class_idx: target class idx

    • data_idx: data idx

    • loss: a scalar loss to be optimized

penalty(attention)[source]

Module contents

class claf.model.sequence_classification.BertForSeqCls(token_makers, num_classes, pretrained_model_name=None, dropout=0.2)[source]

Bases: claf.model.sequence_classification.mixin.SequenceClassification, claf.model.base.ModelWithoutTokenEmbedder

Implementation of Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805)

  • Args:

    token_embedder: used to embed the sequence num_classes: number of classified classes

  • Kwargs:

    pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout

forward(features, labels=None)[source]
  • Args:

    features: feature dictionary like below. {

    “bert_input”: {
    “feature”: [

    [3, 4, 1, 0, 0, 0, …], …,

    ]

    }, “token_type”: {

    “feature”: [

    [0, 0, 0, 0, 0, 0, …], …,

    ],

    }

    }

  • Kwargs:

    label: label dictionary like below. {

    “class_idx”: [2, 1, 0, 4, 5, …] “data_idx”: [2, 4, 5, 7, 2, 1, …]

    } Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • sequence_embed: embedding vector of the sequence

    • logits: representing unnormalized log probabilities of the class.

    • class_idx: target class idx

    • data_idx: data idx

    • loss: a scalar loss to be optimized

print_examples(index, inputs, predictions)[source]

Print evaluation examples

  • Args:

    index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of

    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • class_idx

  • Returns:

    print(Sequence, Sequence Tokens, Target Class, Predicted Class)

class claf.model.sequence_classification.RobertaForSeqCls(token_makers, num_classes, pretrained_model_name=None, dropout=0.2)[source]

Bases: claf.model.sequence_classification.mixin.SequenceClassification, claf.model.base.ModelWithoutTokenEmbedder

Implementation of Sentence Classification model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805)

  • Args:

    token_embedder: used to embed the sequence num_classes: number of classified classes

  • Kwargs:

    pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout

forward(features, labels=None)[source]
  • Args:

    features: feature dictionary like below. {

    “bert_input”: {
    “feature”: [

    [3, 4, 1, 0, 0, 0, …], …,

    ]

    },

    }

  • Kwargs:

    label: label dictionary like below. {

    “class_idx”: [2, 1, 0, 4, 5, …] “data_idx”: [2, 4, 5, 7, 2, 1, …]

    } Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • sequence_embed: embedding vector of the sequence

    • logits: representing unnormalized log probabilities of the class.

    • class_idx: target class idx

    • data_idx: data idx

    • loss: a scalar loss to be optimized

print_examples(index, inputs, predictions)[source]

Print evaluation examples

  • Args:

    index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of

    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • class_idx

  • Returns:

    print(Sequence, Sequence Tokens, Target Class, Predicted Class)

class claf.model.sequence_classification.StructuredSelfAttention(token_embedder, num_classes, encoding_rnn_hidden_dim=300, encoding_rnn_num_layer=2, encoding_rnn_dropout=0.0, attention_dim=350, num_attention_heads=30, sequence_embed_dim=2000, dropout=0.5, penalization_coefficient=1.0)[source]

Bases: claf.model.sequence_classification.mixin.SequenceClassification, claf.model.base.ModelWithTokenEmbedder

Implementation of model presented in A Structured Self-attentive Sentence Embedding (https://arxiv.org/abs/1703.03130)

  • Args:

    token_embedder: used to embed the sequence num_classes: number of classified classes

  • Kwargs:

    encoding_rnn_hidden_dim: hidden dimension of rnn (unidirectional) encoding_rnn_num_layer: the number of rnn layers encoding_rnn_dropout: rnn dropout probability attention_dim: attention dimension # d_a in the paper num_attention_heads: number of attention heads # r in the paper sequence_embed_dim: dimension of sequence embedding dropout: classification layer dropout penalization_coefficient: penalty coefficient for frobenius norm

forward(features, labels=None)[source]
  • Args:

    features: feature dictionary like below. {“sequence”: [0, 3, 4, 1]}

  • Kwargs:

    label: label dictionary like below. {“class_idx”: 2, “data_idx”: 0}

    Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • sequence_embed: embedding vector of the sequence

    • logits: representing unnormalized log probabilities of the class.

    • class_idx: target class idx

    • data_idx: data idx

    • loss: a scalar loss to be optimized

penalty(attention)[source]
================================================ FILE: docs/_build/html/claf.model.token_classification.html ================================================ claf.model.token_classification package — CLaF 0.2.0 documentation

claf.model.token_classification package

Submodules

class claf.model.token_classification.mixin.TokenClassification[source]

Bases: object

Token Classification Mixin Class

make_metrics(predictions)[source]

Make metrics with prediction dictionary

  • Args:
    predictions: prediction dictionary consisting of
    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • tag_idxs

  • Returns:
    metrics: metric dictionary consisting of
    • ‘accuracy’: sequence level accuracy

    • ‘tag_accuracy’: tag level accuracy

    • ‘macro_f1’: tag prediction macro(unweighted mean) f1

    • ‘macro_precision’: tag prediction macro(unweighted mean) precision

    • ‘macro_recall’: tag prediction macro(unweighted mean) recall

make_predictions(output_dict)[source]

Make predictions with model’s output_dict

  • Args:
    output_dict: model’s output dictionary consisting of
    • sequence_embed: embedding vector of the sequence

    • tag_logits: representing unnormalized log probabilities of the tag

    • tag_idxs: target tag idxs

    • data_idx: data idx

    • loss: a scalar loss to be optimized

  • Returns:
    predictions: prediction dictionary consisting of
    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • tag_idxs

predict(**kwargs)
print_examples(index, inputs, predictions)[source]

Print evaluation examples

  • Args:

    index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of

    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • class_idx

  • Returns:

    print(Sequence, Target Tags, Target Slots, Predicted Tags, Predicted Slots)

write_predictions(predictions, file_path=None, is_dict=True, pycm_obj=None)[source]

Override write_predictions() in ModelBase to log confusion matrix

Module contents

class claf.model.token_classification.BertForTokCls(token_makers, num_tags, ignore_tag_idx, pretrained_model_name=None, dropout=0.2)[source]

Bases: claf.model.token_classification.mixin.TokenClassification, claf.model.base.ModelWithoutTokenEmbedder

Implementation of Single Sentence Tagging model presented in BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805)

  • Args:

    token_embedder: used to embed the sequence num_tags: number of classified tags ignore_tag_idx: index of the tag to ignore when calculating loss (tag pad value)

  • Kwargs:

    pretrained_model_name: the name of a pre-trained model dropout: classification layer dropout

forward(features, labels=None)[source]
  • Args:

    features: feature dictionary like below. {

    “bert_input”: {
    “feature”: [

    [100, 576, 21, 45, 7, 91, 101, 0, 0, …], …,

    ]

    } “token_type”: {

    “feature”: [

    [0, 0, 0, 0, 0, 0, 0, 0, 0, …], …,

    ]

    }, “tagged_sub_token_idxs”: {

    [

    [1, 3, 4, 0, 0, 0, 0, 0, 0, …], …,

    ]

    }

    }

  • Kwargs:

    label: label dictionary like below. {

    “class_idx”: [2, 1, 0, 4, 5, …] “data_idx”: [2, 4, 5, 7, 2, 1, …]

    } Do not calculate loss when there is no label. (inference/predict mode)

  • Returns: output_dict (dict) consisting of
    • sequence_embed: embedding vector of the sequence

    • tag_logits: representing unnormalized log probabilities of the tags.

    • tag_idxs: target class idx

    • data_idx: data idx

    • loss: a scalar loss to be optimized

print_examples(index, inputs, predictions)[source]

Print evaluation examples

  • Args:

    index: data index inputs: mini-batch inputs predictions: prediction dictionary consisting of

    • key: ‘id’ (sequence id)

    • value: dictionary consisting of
      • class_idx

  • Returns:

    print(Sequence, Sequence Tokens, Target Tags, Target Slots, Predicted Tags, Predicted Slots)

================================================ FILE: docs/_build/html/claf.modules.attention.html ================================================ claf.modules.attention package — CLaF 0.2.0 documentation

claf.modules.attention package

Submodules

class claf.modules.attention.bi_attention.BiAttention(model_dim)[source]

Bases: torch.nn.modules.module.Module

Attention Flow Layer

in BiDAF (https://arxiv.org/pdf/1611.01603.pdf)

The Similarity matrix Context-to-query Attention (C2Q) Query-to-context Attention (Q2C)

  • Args:

    model_dim: The number of module dimension

forward(context, context_mask, query, query_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.co_attention.CoAttention(embed_dim)[source]

Bases: torch.nn.modules.module.Module

CoAttention encoder

in Dynamic Coattention Networks For Question Answering (https://arxiv.org/abs/1611.01604)

check the Figure 2 in paper

  • Args:

    embed_dim: the number of input embedding dimension

forward(context_embed, question_embed, context_mask=None, question_mask=None)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.docqa_attention.DocQAAttention(rnn_dim, linear_dim, self_attn=False, weight_init=True)[source]

Bases: torch.nn.modules.module.Module

Bi-Attention Layer + (Self-Attention)

in DocumentQA (https://arxiv.org/abs/1710.10723)

  • Args:

    rnn_dim: the number of GRU cell hidden size linear_dim: the number of linear hidden size

  • Kwargs:

    self_attn: (bool) self-attention weight_init: (bool) weight initialization

forward(x, x_mask, key, key_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.multi_head_attention.MultiHeadAttention(num_head=8, model_dim=100, dropout=0.1, linear_key_dim=None, linear_value_dim=None)[source]

Bases: torch.nn.modules.module.Module

Transformer’s Multi-Head Attention

in “Attention is All You Need” (https://arxiv.org/abs/1706.03762)

  • Kwargs:

    num_head: the number of Head model_dim: the number of model dimension linear_key_dim: the number of linear key dimemsion linear_value_dim: the number of linear value dimension

forward(q, k, v, mask=None)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

original code from: https://github.com/facebookresearch/DrQA/blob/master/drqa/reader/layers.py

class claf.modules.attention.seq_attention.BilinearSeqAttn(x_size, y_size, identity=False, normalize=True)[source]

Bases: torch.nn.modules.module.Module

A bilinear attention layer over a sequence X w.r.t y: * o_i = softmax(x_i’Wy) for x_i in X. Optionally don’t normalize output weights.

forward(x, y, x_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.seq_attention.LinearSeqAttn(input_size)[source]

Bases: torch.nn.modules.module.Module

Self attention over a sequence: * o_i = softmax(Wx_i) for x_i in X.

forward(x, x_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.seq_attention.SeqAttnMatch(embed_dim, identity=False)[source]

Bases: torch.nn.modules.module.Module

Given sequences X and Y, match sequence Y to each element in X. * o_i = sum(alpha_j * y_j) for i in X * alpha_j = softmax(y_j * x_i)

forward(x, y, y_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

Module contents

class claf.modules.attention.BiAttention(model_dim)[source]

Bases: torch.nn.modules.module.Module

Attention Flow Layer

in BiDAF (https://arxiv.org/pdf/1611.01603.pdf)

The Similarity matrix Context-to-query Attention (C2Q) Query-to-context Attention (Q2C)

  • Args:

    model_dim: The number of module dimension

forward(context, context_mask, query, query_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.CoAttention(embed_dim)[source]

Bases: torch.nn.modules.module.Module

CoAttention encoder

in Dynamic Coattention Networks For Question Answering (https://arxiv.org/abs/1611.01604)

check the Figure 2 in paper

  • Args:

    embed_dim: the number of input embedding dimension

forward(context_embed, question_embed, context_mask=None, question_mask=None)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.MultiHeadAttention(num_head=8, model_dim=100, dropout=0.1, linear_key_dim=None, linear_value_dim=None)[source]

Bases: torch.nn.modules.module.Module

Transformer’s Multi-Head Attention

in “Attention is All You Need” (https://arxiv.org/abs/1706.03762)

  • Kwargs:

    num_head: the number of Head model_dim: the number of model dimension linear_key_dim: the number of linear key dimemsion linear_value_dim: the number of linear value dimension

forward(q, k, v, mask=None)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.DocQAAttention(rnn_dim, linear_dim, self_attn=False, weight_init=True)[source]

Bases: torch.nn.modules.module.Module

Bi-Attention Layer + (Self-Attention)

in DocumentQA (https://arxiv.org/abs/1710.10723)

  • Args:

    rnn_dim: the number of GRU cell hidden size linear_dim: the number of linear hidden size

  • Kwargs:

    self_attn: (bool) self-attention weight_init: (bool) weight initialization

forward(x, x_mask, key, key_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.SeqAttnMatch(embed_dim, identity=False)[source]

Bases: torch.nn.modules.module.Module

Given sequences X and Y, match sequence Y to each element in X. * o_i = sum(alpha_j * y_j) for i in X * alpha_j = softmax(y_j * x_i)

forward(x, y, y_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.LinearSeqAttn(input_size)[source]

Bases: torch.nn.modules.module.Module

Self attention over a sequence: * o_i = softmax(Wx_i) for x_i in X.

forward(x, x_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.attention.BilinearSeqAttn(x_size, y_size, identity=False, normalize=True)[source]

Bases: torch.nn.modules.module.Module

A bilinear attention layer over a sequence X w.r.t y: * o_i = softmax(x_i’Wy) for x_i in X. Optionally don’t normalize output weights.

forward(x, y, x_mask)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

================================================ FILE: docs/_build/html/claf.modules.conv.html ================================================ claf.modules.conv package — CLaF 0.2.0 documentation

claf.modules.conv package

Submodules

class claf.modules.conv.depthwise_separable_conv.DepSepConv(input_size=None, num_filters=None, kernel_size=None)[source]

Bases: torch.nn.modules.module.Module

Depthwise Separable Convolutions

in Xception: Deep Learning with Depthwise Separable Convolutions (https://arxiv.org/abs/1610.02357)

depthwise -> pointwise (1x1 conv)

  • Args:

    input_size: the number of input tensor’s dimension num_filters: the number of convolution filter kernel_size: the number of convolution kernel size

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.conv.pointwise_conv.PointwiseConv(input_size, num_filters)[source]

Bases: torch.nn.modules.module.Module

Pointwise Convolution (1x1 Conv)

Convolution 1 Dimension (Faster version) (cf. https://github.com/huggingface/pytorch-openai-transformer-lm/blob/ eafc28abdfadfa0732f03a0fc65805c5bfb2ffe7/model_pytorch.py#L45)

  • Args:

    input_size: the number of input tensor’s dimension num_filters: the number of convolution filter

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

Module contents

class claf.modules.conv.DepSepConv(input_size=None, num_filters=None, kernel_size=None)[source]

Bases: torch.nn.modules.module.Module

Depthwise Separable Convolutions

in Xception: Deep Learning with Depthwise Separable Convolutions (https://arxiv.org/abs/1610.02357)

depthwise -> pointwise (1x1 conv)

  • Args:

    input_size: the number of input tensor’s dimension num_filters: the number of convolution filter kernel_size: the number of convolution kernel size

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.conv.PointwiseConv(input_size, num_filters)[source]

Bases: torch.nn.modules.module.Module

Pointwise Convolution (1x1 Conv)

Convolution 1 Dimension (Faster version) (cf. https://github.com/huggingface/pytorch-openai-transformer-lm/blob/ eafc28abdfadfa0732f03a0fc65805c5bfb2ffe7/model_pytorch.py#L45)

  • Args:

    input_size: the number of input tensor’s dimension num_filters: the number of convolution filter

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

================================================ FILE: docs/_build/html/claf.modules.encoder.html ================================================ claf.modules.encoder package — CLaF 0.2.0 documentation

claf.modules.encoder package

Submodules

This code is from allenai/allennlp (https://github.com/allenai/allennlp/blob/master/allennlp/modules/lstm_cell_with_projection.py)

class claf.modules.encoder.lstm_cell_with_projection.LstmCellWithProjection(input_size: int, hidden_size: int, cell_size: int, go_forward: bool = True, recurrent_dropout_probability: float = 0.0, memory_cell_clip_value: Optional[float] = None, state_projection_clip_value: Optional[float] = None)[source]

Bases: torch.nn.modules.module.Module

An LSTM with Recurrent Dropout and a projected and clipped hidden state and memory. Note: this implementation is slower than the native Pytorch LSTM because it cannot make use of CUDNN optimizations for stacked RNNs due to and variational dropout and the custom nature of the cell state. Parameters ———- input_size : int, required.

The dimension of the inputs to the LSTM.

hidden_sizeint, required.

The dimension of the outputs of the LSTM.

cell_sizeint, required.

The dimension of the memory cell used for the LSTM.

go_forward: bool, optional (default = True)

The direction in which the LSTM is applied to the sequence. Forwards by default, or backwards if False.

recurrent_dropout_probability: float, optional (default = 0.0)

The dropout probability to be used in a dropout scheme as stated in A Theoretically Grounded Application of Dropout in Recurrent Neural Networks . Implementation wise, this simply applies a fixed dropout mask per sequence to the recurrent connection of the LSTM.

state_projection_clip_value: float, optional, (default = None)

The magnitude with which to clip the hidden_state after projecting it.

memory_cell_clip_value: float, optional, (default = None)

The magnitude with which to clip the memory cell.

output_accumulatortorch.FloatTensor

The outputs of the LSTM for each timestep. A tensor of shape (batch_size, max_timesteps, hidden_size) where for a given batch element, all outputs past the sequence length for that batch are zero tensors.

final_state: Tuple[torch.FloatTensor, torch.FloatTensor]

The final (state, memory) states of the LSTM, with shape (1, batch_size, hidden_size) and (1, batch_size, cell_size) respectively. The first dimension is 1 in order to match the Pytorch API for returning stacked LSTM states.

forward(inputs: torch.FloatTensor, batch_lengths: List[int], initial_state: Optional[Tuple[torch.Tensor, torch.Tensor]] = None)[source]
inputstorch.FloatTensor, required.

A tensor of shape (batch_size, num_timesteps, input_size) to apply the LSTM over.

batch_lengthsList[int], required.

A list of length batch_size containing the lengths of the sequences in batch.

initial_stateTuple[torch.Tensor, torch.Tensor], optional, (default = None)

A tuple (state, memory) representing the initial hidden state and memory of the LSTM. The state has shape (1, batch_size, hidden_size) and the memory has shape (1, batch_size, cell_size).

output_accumulatortorch.FloatTensor

The outputs of the LSTM for each timestep. A tensor of shape (batch_size, max_timesteps, hidden_size) where for a given batch element, all outputs past the sequence length for that batch are zero tensors.

final_stateTuple[``torch.FloatTensor, torch.FloatTensor]

A tuple (state, memory) representing the initial hidden state and memory of the LSTM. The state has shape (1, batch_size, hidden_size) and the memory has shape (1, batch_size, cell_size).

reset_parameters()[source]
claf.modules.encoder.lstm_cell_with_projection.block_orthogonal(tensor: torch.Tensor, split_sizes: List[int], gain: float = 1.0) → None[source]

An initializer which allows initializing model parameters in “blocks”. This is helpful in the case of recurrent models which use multiple gates applied to linear projections, which can be computed efficiently if they are concatenated together. However, they are separate parameters which should be initialized independently. Parameters ———- tensor : torch.Tensor, required.

A tensor to initialize.

split_sizesList[int], required.

A list of length tensor.ndim() specifying the size of the blocks along that particular dimension. E.g. [10, 20] would result in the tensor being split into chunks of size 10 along the first dimension and 20 along the second.

gainfloat, optional (default = 1.0)

The gain (scaling) applied to the orthogonal initialization.

claf.modules.encoder.lstm_cell_with_projection.get_dropout_mask(dropout_probability: float, tensor_for_masking: torch.Tensor)[source]

Computes and returns an element-wise dropout mask for a given tensor, where each element in the mask is dropped out with probability dropout_probability. Note that the mask is NOT applied to the tensor - the tensor is passed to retain the correct CUDA tensor type for the mask. Parameters ———- dropout_probability : float, required.

Probability of dropping a dimension of the input.

tensor_for_masking : torch.Tensor, required. Returns ——- A torch.FloatTensor consisting of the binary mask scaled by 1/ (1 - dropout_probability). This scaling ensures expected values and variances of the output of applying this mask

and the original tensor are the same.

claf.modules.encoder.lstm_cell_with_projection.sort_batch_by_length(tensor: torch.Tensor, sequence_lengths: torch.Tensor)[source]

Sort a batch first tensor by some specified lengths. Parameters ———- tensor : torch.FloatTensor, required.

A batch first Pytorch tensor.

sequence_lengthstorch.LongTensor, required.

A tensor representing the lengths of some dimension of the tensor which we want to sort by.

sorted_tensortorch.FloatTensor

The original tensor sorted along the batch dimension with respect to sequence_lengths.

sorted_sequence_lengthstorch.LongTensor

The original sequence_lengths sorted by decreasing size.

restoration_indicestorch.LongTensor

Indices into the sorted_tensor such that sorted_tensor.index_select(0, restoration_indices) == original_tensor

permuation_indextorch.LongTensor

The indices used to sort the tensor. This is useful if you want to sort many tensors using the same ordering.

class claf.modules.encoder.positional.PositionalEncoding(embed_dim, max_length=2000)[source]

Bases: torch.nn.modules.module.Module

Positional Encoding

in “Attention is All You Need” (https://arxiv.org/abs/1706.03762)

The use of relative position is possible because sin(x+y) and cos(x+y) can be expressed in terms of y, sin(x) and cos(x).

(cf. https://github.com/tensorflow/tensor2tensor/blob/42c3f377f441e5a0f431127d63e71414ead291c4/ tensor2tensor/layers/common_attention.py#L388)

  • Args:

    embed_dim: the number of embedding dimension

  • Kwargs:

    max_len: the number of maximum sequence length

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

Module contents

class claf.modules.encoder.PositionalEncoding(embed_dim, max_length=2000)[source]

Bases: torch.nn.modules.module.Module

Positional Encoding

in “Attention is All You Need” (https://arxiv.org/abs/1706.03762)

The use of relative position is possible because sin(x+y) and cos(x+y) can be expressed in terms of y, sin(x) and cos(x).

(cf. https://github.com/tensorflow/tensor2tensor/blob/42c3f377f441e5a0f431127d63e71414ead291c4/ tensor2tensor/layers/common_attention.py#L388)

  • Args:

    embed_dim: the number of embedding dimension

  • Kwargs:

    max_len: the number of maximum sequence length

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.encoder.LstmCellWithProjection(input_size: int, hidden_size: int, cell_size: int, go_forward: bool = True, recurrent_dropout_probability: float = 0.0, memory_cell_clip_value: Optional[float] = None, state_projection_clip_value: Optional[float] = None)[source]

Bases: torch.nn.modules.module.Module

An LSTM with Recurrent Dropout and a projected and clipped hidden state and memory. Note: this implementation is slower than the native Pytorch LSTM because it cannot make use of CUDNN optimizations for stacked RNNs due to and variational dropout and the custom nature of the cell state. Parameters ———- input_size : int, required.

The dimension of the inputs to the LSTM.

hidden_sizeint, required.

The dimension of the outputs of the LSTM.

cell_sizeint, required.

The dimension of the memory cell used for the LSTM.

go_forward: bool, optional (default = True)

The direction in which the LSTM is applied to the sequence. Forwards by default, or backwards if False.

recurrent_dropout_probability: float, optional (default = 0.0)

The dropout probability to be used in a dropout scheme as stated in A Theoretically Grounded Application of Dropout in Recurrent Neural Networks . Implementation wise, this simply applies a fixed dropout mask per sequence to the recurrent connection of the LSTM.

state_projection_clip_value: float, optional, (default = None)

The magnitude with which to clip the hidden_state after projecting it.

memory_cell_clip_value: float, optional, (default = None)

The magnitude with which to clip the memory cell.

output_accumulatortorch.FloatTensor

The outputs of the LSTM for each timestep. A tensor of shape (batch_size, max_timesteps, hidden_size) where for a given batch element, all outputs past the sequence length for that batch are zero tensors.

final_state: Tuple[torch.FloatTensor, torch.FloatTensor]

The final (state, memory) states of the LSTM, with shape (1, batch_size, hidden_size) and (1, batch_size, cell_size) respectively. The first dimension is 1 in order to match the Pytorch API for returning stacked LSTM states.

forward(inputs: torch.FloatTensor, batch_lengths: List[int], initial_state: Optional[Tuple[torch.Tensor, torch.Tensor]] = None)[source]
inputstorch.FloatTensor, required.

A tensor of shape (batch_size, num_timesteps, input_size) to apply the LSTM over.

batch_lengthsList[int], required.

A list of length batch_size containing the lengths of the sequences in batch.

initial_stateTuple[torch.Tensor, torch.Tensor], optional, (default = None)

A tuple (state, memory) representing the initial hidden state and memory of the LSTM. The state has shape (1, batch_size, hidden_size) and the memory has shape (1, batch_size, cell_size).

output_accumulatortorch.FloatTensor

The outputs of the LSTM for each timestep. A tensor of shape (batch_size, max_timesteps, hidden_size) where for a given batch element, all outputs past the sequence length for that batch are zero tensors.

final_stateTuple[``torch.FloatTensor, torch.FloatTensor]

A tuple (state, memory) representing the initial hidden state and memory of the LSTM. The state has shape (1, batch_size, hidden_size) and the memory has shape (1, batch_size, cell_size).

reset_parameters()[source]
================================================ FILE: docs/_build/html/claf.modules.html ================================================ claf.modules package — CLaF 0.2.0 documentation

claf.modules package

Submodules

claf.modules.activation.get_activation_fn(name)[source]

PyTorch built-in activation functions

some functional codes from allennlp: https://github.com/allenai/allennlp

  • add_masked_value : replace_masked_values (allennlp)

  • get_mask_from_tokens : get_mask_from_tokens (allennlp)

  • last_dim_masked_softmax : last_dim_masked_softmax (allennlp)

  • masked_softmax : masked_softmax (allennlp)

  • weighted_sum : weighted_sum (allennlp)

claf.modules.functional.add_masked_value(tensor, mask, value=-10000000.0)[source]
claf.modules.functional.forward_rnn_with_pack(rnn_module, tensor, seq_config)[source]
claf.modules.functional.get_mask_from_tokens(tokens)[source]
claf.modules.functional.get_sorted_seq_config(features, pad_index=0)[source]
claf.modules.functional.last_dim_masked_softmax(x, mask)[source]
claf.modules.functional.masked_log_softmax(vector, mask)[source]
claf.modules.functional.masked_softmax(x, mask)[source]
claf.modules.functional.masked_zero(tensor, mask)[source]

Tensor masking operation

claf.modules.functional.weighted_sum(attention, matrix)[source]
claf.modules.initializer.weight(module)[source]

weight initialization (according to module type)

  • Args:

    module: torch.nn.Module

Module contents

================================================ FILE: docs/_build/html/claf.modules.layer.html ================================================ claf.modules.layer package — CLaF 0.2.0 documentation

claf.modules.layer package

Submodules

class claf.modules.layer.highway.Highway(input_size, num_layers=2, activation='relu')[source]

Bases: torch.nn.modules.module.Module

Highway Networks (https://arxiv.org/abs/1505.00387) https://github.com/allenai/allennlp/blob/master/allennlp/modules/highway.py

  • Args:

    input_size: The number of expected features in the input x num_layers: The number of Highway layers. activation: Activation Function (ReLU is default)

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.layer.normalization.LayerNorm(normalized_shape, eps=1e-05)[source]

Bases: torch.nn.modules.module.Module

Layer Normalization (https://arxiv.org/abs/1607.06450)

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.layer.positionwise.PositionwiseFeedForward(input_size, hidden_size, dropout=0.1)[source]

Bases: torch.nn.modules.module.Module

Pointwise Feed-Forward Layer

  • Args:

    input_size: the number of input size hidden_size: the number of hidden size

  • Kwargs:

    dropout: the probability of dropout

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.layer.residual.ResidualConnection(dim, layer_dropout=None, layernorm=False)[source]

Bases: torch.nn.modules.module.Module

in Deep Residual Learning for Image Recognition (https://arxiv.org/abs/1512.03385)

=> f(x) + x

  • Args:

    dim: the number of dimension

  • Kwargs:

    layer_dropout: layer dropout probability (stochastic depth) dropout: dropout probability

forward(x, sub_layer_fn)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

This code is from allenai/allennlp (https://github.com/allenai/allennlp/blob/master/allennlp/modules/scalar_mix.py)

class claf.modules.layer.scalar_mix.ScalarMix(mixture_size: int, do_layer_norm: bool = False, initial_scalar_parameters: List[float] = None, trainable: bool = True)[source]

Bases: torch.nn.modules.module.Module

Computes a parameterised scalar mixture of N tensors, mixture = gamma * sum(s_k * tensor_k) where s = softmax(w), with w and gamma scalar parameters. In addition, if do_layer_norm=True then apply layer normalization to each tensor before weighting.

forward(tensors: List[torch.Tensor], mask: torch.Tensor = None) → torch.Tensor[source]

Compute a weighted average of the tensors. The input tensors an be any shape with at least two dimensions, but must all be the same shape. When do_layer_norm=True, the mask is required input. If the tensors are dimensioned (dim_0, ..., dim_{n-1}, dim_n), then the mask is dimensioned (dim_0, ..., dim_{n-1}), as in the typical case with tensors of shape (batch_size, timesteps, dim) and mask of shape (batch_size, timesteps). When do_layer_norm=False the mask is ignored.

Module contents

class claf.modules.layer.Highway(input_size, num_layers=2, activation='relu')[source]

Bases: torch.nn.modules.module.Module

Highway Networks (https://arxiv.org/abs/1505.00387) https://github.com/allenai/allennlp/blob/master/allennlp/modules/highway.py

  • Args:

    input_size: The number of expected features in the input x num_layers: The number of Highway layers. activation: Activation Function (ReLU is default)

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.layer.PositionwiseFeedForward(input_size, hidden_size, dropout=0.1)[source]

Bases: torch.nn.modules.module.Module

Pointwise Feed-Forward Layer

  • Args:

    input_size: the number of input size hidden_size: the number of hidden size

  • Kwargs:

    dropout: the probability of dropout

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.layer.ResidualConnection(dim, layer_dropout=None, layernorm=False)[source]

Bases: torch.nn.modules.module.Module

in Deep Residual Learning for Image Recognition (https://arxiv.org/abs/1512.03385)

=> f(x) + x

  • Args:

    dim: the number of dimension

  • Kwargs:

    layer_dropout: layer dropout probability (stochastic depth) dropout: dropout probability

forward(x, sub_layer_fn)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class claf.modules.layer.ScalarMix(mixture_size: int, do_layer_norm: bool = False, initial_scalar_parameters: List[float] = None, trainable: bool = True)[source]

Bases: torch.nn.modules.module.Module

Computes a parameterised scalar mixture of N tensors, mixture = gamma * sum(s_k * tensor_k) where s = softmax(w), with w and gamma scalar parameters. In addition, if do_layer_norm=True then apply layer normalization to each tensor before weighting.

forward(tensors: List[torch.Tensor], mask: torch.Tensor = None) → torch.Tensor[source]

Compute a weighted average of the tensors. The input tensors an be any shape with at least two dimensions, but must all be the same shape. When do_layer_norm=True, the mask is required input. If the tensors are dimensioned (dim_0, ..., dim_{n-1}, dim_n), then the mask is dimensioned (dim_0, ..., dim_{n-1}), as in the typical case with tensors of shape (batch_size, timesteps, dim) and mask of shape (batch_size, timesteps). When do_layer_norm=False the mask is ignored.

================================================ FILE: docs/_build/html/claf.tokens.embedding.html ================================================ claf.tokens.embedding package — CLaF 0.2.0 documentation

claf.tokens.embedding package

Submodules

class claf.tokens.embedding.base.TokenEmbedding(vocab)[source]

Bases: torch.nn.modules.module.Module

Token Embedding

It can be embedding matrix, language model (ELMo), neural machine translation model (CoVe) and features.

  • Args:

    vocab: Vocab (rqa.tokens.vocab)

forward(tokens)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

get_vocab_size()[source]
class claf.tokens.embedding.bert_embedding.BertEmbedding(vocab, pretrained_model_name=None, trainable=False, unit='subword')[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

BERT Embedding(Encoder)

BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805)

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    pretrained_model_name: … use_as_embedding: … trainable: Finetune or fixed

forward(inputs)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

remove_cls_sep_token(inputs, outputs)[source]
class claf.tokens.embedding.char_embedding.CharEmbedding(vocab, dropout=0.2, embed_dim=16, kernel_sizes=[5], num_filter=100, activation='relu')[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Character Embedding (CharCNN) (https://arxiv.org/abs/1509.01626)

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    dropout: The number of dropout probability embed_dim: The number of embedding dimension kernel_sizes: The list of kernel size (n-gram) num_filter: The number of cnn filter activation: Activation Function (eg. ReLU)

forward(chars)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.cove_embedding.CoveEmbedding(vocab, glove_pretrained_path=None, model_pretrained_path=None, dropout=0.2, trainable=False, project_dim=None)[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Cove Embedding

Learned in Translation: Contextualized Word Vectors (http://papers.nips.cc/paper/7209-learned-in-translation-contextualized-word-vectors.pdf)

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    dropout: The number of dropout probability pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed project_dim: The number of project (linear) dimension

forward(words)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.elmo_embedding.ELMoEmbedding(vocab, options_file='elmo_2x4096_512_2048cnn_2xhighway_options.json', weight_file='elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5', do_layer_norm=False, dropout=0.5, trainable=False, project_dim=None)[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

ELMo Embedding Embedding From Language Model

Deep contextualized word representations (https://arxiv.org/abs/1802.0536)

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    options_file: ELMo model config file path weight_file: ELMo model weight file path do_layer_norm: Should we apply layer normalization (passed to ScalarMix)?

    default is False

    dropout: The number of dropout probability trainable: Finetune or fixed project_dim: The number of project (linear) dimension

forward(chars)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.frequent_word_embedding.FrequentTuningWordEmbedding(vocab, dropout=0.2, embed_dim=100, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, pretrained_path=None)[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Frequent Word Finetuning Embedding Finetuning embedding matrix, according to ‘threshold_index’

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx

    (initialized to zeros) whenever it encounters the index.

    max_norm: If given, will renormalize the embedding vectors to have a norm lesser

    than this before extracting. Note: this will modify weight in-place.

    norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of

    frequency of the words in the mini-batch. Default False.

    sparse: if True, gradient w.r.t. weight will be a sparse tensor.

    See Notes under torch.nn.Embedding for more details regarding sparse gradients.

    pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed

forward(words, frequent_tuning=False)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.sparse_feature.OneHotEncoding(index, token_name, classes)[source]

Bases: torch.nn.modules.module.Module

Sparse to one-hot encoding

  • Args:

    vocab: Vocab (claf.tokens.vocab)

forward(inputs)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

get_output_dim()[source]
class claf.tokens.embedding.sparse_feature.SparseFeature(vocab, embed_type, feature_count, params={})[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Sparse Feature

  1. Sparse to Embedding

  2. One Hot Encoding

  • Args:

    vocab: Vocab (claf.tokens.vocab) embed_type: The type of embedding [one_hot|embedding] feature_count: The number of feature count

  • Kwargs:

    params: additional parameters for embedding module

forward(inputs)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.sparse_feature.SparseToEmbedding(index, token_name, classes, dropout=0, embed_dim=15, trainable=True, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False)[source]

Bases: torch.nn.modules.module.Module

Sparse to Embedding

  • Args:

    token_name: token_name

  • Kwargs:

    dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx

    (initialized to zeros) whenever it encounters the index.

    max_norm: If given, will renormalize the embedding vectors to have a norm lesser

    than this before extracting. Note: this will modify weight in-place.

    norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of

    frequency of the words in the mini-batch. Default False.

    sparse: if True, gradient w.r.t. weight will be a sparse tensor.

    See Notes under torch.nn.Embedding for more details regarding sparse gradients.

    pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed

forward(inputs)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

get_output_dim()[source]
class claf.tokens.embedding.word_embedding.WordEmbedding(vocab, dropout=0.2, embed_dim=100, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, pretrained_path=None, trainable=True)[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Word Embedding Default Token Embedding

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx

    (initialized to zeros) whenever it encounters the index.

    max_norm: If given, will renormalize the embedding vectors to have a norm lesser

    than this before extracting. Note: this will modify weight in-place.

    norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of

    frequency of the words in the mini-batch. Default False.

    sparse: if True, gradient w.r.t. weight will be a sparse tensor.

    See Notes under torch.nn.Embedding for more details regarding sparse gradients.

    pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed

forward(words)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

Module contents

class claf.tokens.embedding.BertEmbedding(vocab, pretrained_model_name=None, trainable=False, unit='subword')[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

BERT Embedding(Encoder)

BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (https://arxiv.org/abs/1810.04805)

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    pretrained_model_name: … use_as_embedding: … trainable: Finetune or fixed

forward(inputs)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

remove_cls_sep_token(inputs, outputs)[source]
class claf.tokens.embedding.CharEmbedding(vocab, dropout=0.2, embed_dim=16, kernel_sizes=[5], num_filter=100, activation='relu')[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Character Embedding (CharCNN) (https://arxiv.org/abs/1509.01626)

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    dropout: The number of dropout probability embed_dim: The number of embedding dimension kernel_sizes: The list of kernel size (n-gram) num_filter: The number of cnn filter activation: Activation Function (eg. ReLU)

forward(chars)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.CoveEmbedding(vocab, glove_pretrained_path=None, model_pretrained_path=None, dropout=0.2, trainable=False, project_dim=None)[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Cove Embedding

Learned in Translation: Contextualized Word Vectors (http://papers.nips.cc/paper/7209-learned-in-translation-contextualized-word-vectors.pdf)

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    dropout: The number of dropout probability pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed project_dim: The number of project (linear) dimension

forward(words)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.ELMoEmbedding(vocab, options_file='elmo_2x4096_512_2048cnn_2xhighway_options.json', weight_file='elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5', do_layer_norm=False, dropout=0.5, trainable=False, project_dim=None)[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

ELMo Embedding Embedding From Language Model

Deep contextualized word representations (https://arxiv.org/abs/1802.0536)

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    options_file: ELMo model config file path weight_file: ELMo model weight file path do_layer_norm: Should we apply layer normalization (passed to ScalarMix)?

    default is False

    dropout: The number of dropout probability trainable: Finetune or fixed project_dim: The number of project (linear) dimension

forward(chars)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.FrequentTuningWordEmbedding(vocab, dropout=0.2, embed_dim=100, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, pretrained_path=None)[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Frequent Word Finetuning Embedding Finetuning embedding matrix, according to ‘threshold_index’

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx

    (initialized to zeros) whenever it encounters the index.

    max_norm: If given, will renormalize the embedding vectors to have a norm lesser

    than this before extracting. Note: this will modify weight in-place.

    norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of

    frequency of the words in the mini-batch. Default False.

    sparse: if True, gradient w.r.t. weight will be a sparse tensor.

    See Notes under torch.nn.Embedding for more details regarding sparse gradients.

    pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed

forward(words, frequent_tuning=False)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.SparseFeature(vocab, embed_type, feature_count, params={})[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Sparse Feature

  1. Sparse to Embedding

  2. One Hot Encoding

  • Args:

    vocab: Vocab (claf.tokens.vocab) embed_type: The type of embedding [one_hot|embedding] feature_count: The number of feature count

  • Kwargs:

    params: additional parameters for embedding module

forward(inputs)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

class claf.tokens.embedding.WordEmbedding(vocab, dropout=0.2, embed_dim=100, padding_idx=None, max_norm=None, norm_type=2, scale_grad_by_freq=False, sparse=False, pretrained_path=None, trainable=True)[source]

Bases: claf.tokens.embedding.base.TokenEmbedding

Word Embedding Default Token Embedding

  • Args:

    vocab: Vocab (claf.tokens.vocab)

  • Kwargs:

    dropout: The number of dropout probability embed_dim: The number of embedding dimension padding_idx: If given, pads the output with the embedding vector at padding_idx

    (initialized to zeros) whenever it encounters the index.

    max_norm: If given, will renormalize the embedding vectors to have a norm lesser

    than this before extracting. Note: this will modify weight in-place.

    norm_type: The p of the p-norm to compute for the max_norm option. Default 2. scale_grad_by_freq: if given, this will scale gradients by the inverse of

    frequency of the words in the mini-batch. Default False.

    sparse: if True, gradient w.r.t. weight will be a sparse tensor.

    See Notes under torch.nn.Embedding for more details regarding sparse gradients.

    pretrained_path: pretrained vector path (eg. GloVe) trainable: finetune or fixed

forward(words)[source]

embedding look-up

get_output_dim()[source]

get embedding dimension

================================================ FILE: docs/_build/html/claf.tokens.html ================================================ claf.tokens package — CLaF 0.2.0 documentation

claf.tokens package

Submodules

This code is from salesforce/cove (https://github.com/salesforce/cove/blob/master/cove/encoder.py)

class claf.tokens.cove.MTLSTM(word_embedding, pretrained_path=None, requires_grad=False, residual_embeddings=False)[source]

Bases: torch.nn.modules.module.Module

forward(inputs)[source]

A pretrained MT-LSTM (McCann et. al. 2017). This LSTM was trained with 300d 840B GloVe on the WMT 2017 machine translation dataset.

Arguments:
inputs (Tensor): If MTLSTM handles embedding, a Long Tensor of size (batch_size, timesteps).

Otherwise, a Float Tensor of size (batch_size, timesteps, features).

lengths (Long Tensor): (batch_size, lengths) lenghts of each sequence for handling padding hidden (Float Tensor): initial hidden state of the LSTM

This code is from allenai/allennlp (https://github.com/allenai/allennlp/blob/master/allennlp/modules/elmo.py)

class claf.tokens.elmo.Elmo(options_file: str, weight_file: str, num_output_representations: int, requires_grad: bool = False, do_layer_norm: bool = False, dropout: float = 0.5, vocab_to_cache: List[str] = None, module: torch.nn.modules.module.Module = None)[source]

Bases: torch.nn.modules.module.Module

Compute ELMo representations using a pre-trained bidirectional language model. See “Deep contextualized word representations”, Peters et al. for details. This module takes character id input and computes num_output_representations different layers of ELMo representations. Typically num_output_representations is 1 or 2. For example, in the case of the SRL model in the above paper, num_output_representations=1 where ELMo was included at the input token representation layer. In the case of the SQuAD model, num_output_representations=2 as ELMo was also included at the GRU output layer. In the implementation below, we learn separate scalar weights for each output layer, but only run the biLM once on each input sequence for efficiency. Parameters ———- options_file : str, required.

ELMo JSON options file

weight_filestr, required.

ELMo hdf5 weight file

num_output_representations: int, required.

The number of ELMo representation layers to output.

requires_grad: bool, optional

If True, compute gradient of ELMo parameters for fine tuning.

do_layer_normbool, optional, (default=False).

Should we apply layer normalization (passed to ScalarMix)?

dropoutfloat, optional, (default = 0.5).

The dropout to be applied to the ELMo representations.

vocab_to_cacheList[str], optional, (default = 0.5).

A list of words to pre-compute and cache character convolutions for. If you use this option, Elmo expects that you pass word indices of shape (batch_size, timesteps) to forward, instead of character indices. If you use this option and pass a word which wasn’t pre-cached, this will break.

moduletorch.nn.Module, optional, (default = None).

If provided, then use this module instead of the pre-trained ELMo biLM. If using this option, then pass None for both options_file and weight_file. The module must provide a public attribute num_layers with the number of internal layers and its forward method must return a dict with activations and mask keys (see _ElmoBilm` for an example). Note that requires_grad is also ignored with this option.

forward(inputs: torch.Tensor, word_inputs: torch.Tensor = None) → Dict[str, Union[torch.Tensor, List[torch.Tensor]]][source]

inputs: torch.Tensor, required. Shape (batch_size, timesteps, 50) of character ids representing the current batch. word_inputs : torch.Tensor, required.

If you passed a cached vocab, you can in addition pass a tensor of shape (batch_size, timesteps), which represent word ids which have been pre-cached.

Dict with keys: 'elmo_representations': List[torch.Tensor]

A num_output_representations list of ELMo representations for the input sequence. Each representation is shape (batch_size, timesteps, embedding_dim)

'mask': torch.Tensor

Shape (batch_size, timesteps) long tensor with sequence mask.

classmethod from_params(params) → claf.tokens.elmo.Elmo[source]
get_output_dim()[source]
class claf.tokens.elmo.ElmoLstm(input_size: int, hidden_size: int, cell_size: int, num_layers: int, requires_grad: bool = False, recurrent_dropout_probability: float = 0.0, memory_cell_clip_value: Optional[float] = None, state_projection_clip_value: Optional[float] = None)[source]

Bases: claf.modules.encoder.lstm_cell_with_projection._EncoderBase

A stacked, bidirectional LSTM which uses LstmCellWithProjection’s with highway layers between the inputs to layers. The inputs to the forward and backward directions are independent - forward and backward states are not concatenated between layers. Additionally, this LSTM maintains its own state, which is updated every time forward is called. It is dynamically resized for different batch sizes and is designed for use with non-continuous inputs (i.e inputs which aren’t formatted as a stream, such as text used for a language modelling task, which is how stateful RNNs are typically used). This is non-standard, but can be thought of as having an “end of sentence” state, which is carried across different sentences. Parameters ———- input_size : int, required

The dimension of the inputs to the LSTM.

hidden_sizeint, required

The dimension of the outputs of the LSTM.

cell_sizeint, required.

The dimension of the memory cell of the LstmCellWithProjection.

num_layersint, required

The number of bidirectional LSTMs to use.

requires_grad: bool, optional

If True, compute gradient of ELMo parameters for fine tuning.

recurrent_dropout_probability: float, optional (default = 0.0)

The dropout probability to be used in a dropout scheme as stated in A Theoretically Grounded Application of Dropout in Recurrent Neural Networks .

state_projection_clip_value: float, optional, (default = None)

The magnitude with which to clip the hidden_state after projecting it.

memory_cell_clip_value: float, optional, (default = None)

The magnitude with which to clip the memory cell.

forward(inputs: torch.Tensor, mask: torch.LongTensor) → torch.Tensor[source]
inputstorch.Tensor, required.

A Tensor of shape (batch_size, sequence_length, hidden_size).

masktorch.LongTensor, required.

A binary mask of shape (batch_size, sequence_length) representing the non-padded elements in each sequence in the batch.

A torch.Tensor of shape (num_layers, batch_size, sequence_length, hidden_size), where the num_layers dimension represents the LSTM output from that layer.

load_weights(weight_file: str) → None[source]

Load the pre-trained weights from the file.

claf.tokens.elmo.add_sentence_boundary_token_ids(tensor: torch.Tensor, mask: torch.Tensor, sentence_begin_token: Any, sentence_end_token: Any) → Tuple[torch.Tensor, torch.Tensor][source]

Add begin/end of sentence tokens to the batch of sentences. Given a batch of sentences with size (batch_size, timesteps) or (batch_size, timesteps, dim) this returns a tensor of shape (batch_size, timesteps + 2) or (batch_size, timesteps + 2, dim) respectively. Returns both the new tensor and updated mask. Parameters ———- tensor : torch.Tensor

A tensor of shape (batch_size, timesteps) or (batch_size, timesteps, dim)

masktorch.Tensor

A tensor of shape (batch_size, timesteps)

sentence_begin_token: Any (anything that can be broadcast in torch for assignment)

For 2D input, a scalar with the <S> id. For 3D input, a tensor with length dim.

sentence_end_token: Any (anything that can be broadcast in torch for assignment)

For 2D input, a scalar with the </S> id. For 3D input, a tensor with length dim.

tensor_with_boundary_tokenstorch.Tensor

The tensor with the appended and prepended boundary tokens. If the input was 2D, it has shape (batch_size, timesteps + 2) and if the input was 3D, it has shape (batch_size, timesteps + 2, dim).

new_masktorch.Tensor

The new mask for the tensor, taking into account the appended tokens marking the beginning and end of the sentence.

claf.tokens.elmo.remove_sentence_boundaries(tensor: torch.Tensor, mask: torch.Tensor) → Tuple[torch.Tensor, torch.Tensor][source]

Remove begin/end of sentence embeddings from the batch of sentences. Given a batch of sentences with size (batch_size, timesteps, dim) this returns a tensor of shape (batch_size, timesteps - 2, dim) after removing the beginning and end sentence markers. The sentences are assumed to be padded on the right, with the beginning of each sentence assumed to occur at index 0 (i.e., mask[:, 0] is assumed to be 1). Returns both the new tensor and updated mask. This function is the inverse of add_sentence_boundary_token_ids. Parameters ———- tensor : torch.Tensor

A tensor of shape (batch_size, timesteps, dim)

masktorch.Tensor

A tensor of shape (batch_size, timesteps)

tensor_without_boundary_tokenstorch.Tensor

The tensor after removing the boundary tokens of shape (batch_size, timesteps - 2, dim)

new_masktorch.Tensor

The new mask for the tensor of shape (batch_size, timesteps - 2).

Hangulpy.py Copyright (C) 2012 Ryan Rho, Hyunwoo Cho Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

exception claf.tokens.hangul.NotHangulException[source]

Bases: Exception

exception claf.tokens.hangul.NotLetterException[source]

Bases: Exception

exception claf.tokens.hangul.NotWordException[source]

Bases: Exception

claf.tokens.hangul.add_ryul(word)[source]

add suffix either ‘률’ or ‘율’ at the end of this word

claf.tokens.hangul.compose(chosung, joongsung, jongsung='')[source]

This function returns a Hangul letter by composing the specified chosung, joongsung, and jongsung. @param chosung @param joongsung @param jongsung the terminal Hangul letter. This is optional if you do not need a jongsung.

claf.tokens.hangul.decompose(hangul_letter)[source]

This function returns letters by decomposing the specified Hangul letter.

claf.tokens.hangul.has_approximant(letter)[source]

Approximant makes complex vowels, such as ones starting with y or w. In Korean there is a unique approximant euㅡ making uiㅢ, but ㅢ does not make many irregularities.

claf.tokens.hangul.has_batchim(letter)[source]

This method is the same as has_jongsung()

claf.tokens.hangul.has_jongsung(letter)[source]

Check whether this letter contains Jongsung

claf.tokens.hangul.ili(word)[source]

convert {가} or {이} to their correct respective particles automagically.

claf.tokens.hangul.is_all_hangul(phrase)[source]

Check whether the phrase contains all Hangul letters @param phrase a target string @return True if the phrase only consists of Hangul. False otherwise.

claf.tokens.hangul.is_hangul(phrase)[source]

Check whether the phrase is Hangul. This method ignores white spaces, punctuations, and numbers. @param phrase a target string @return True if the phrase is Hangul. False otherwise.

claf.tokens.hangul.josa_eg(word)[source]

add josa either ‘이’ or ‘가’ at the end of this word

claf.tokens.hangul.josa_el(word)[source]

add josa either ‘을’ or ‘를’ at the end of this word

claf.tokens.hangul.josa_en(word)[source]

add josa either ‘은’ or ‘는’ at the end of this word

claf.tokens.hangul.josa_gwa(word)[source]

add josa either ‘과’ or ‘와’ at the end of this word

claf.tokens.hangul.josa_ida(word)[source]

add josa either ‘이다’ or ‘다’ at the end of this word

claf.tokens.hangul.josa_ro(word)[source]

add josa either ‘으로’ or ‘로’ at the end of this word

class claf.tokens.linguistic.NER[source]

Bases: object

Named Entity Recognition

Models trained on the OntoNotes 5 corpus support the following entity types: (https://spacy.io/api/annotation#section-dependency-parsing)

classes = ['NONE', 'PERSON', 'NORP', 'FAC', 'ORG', 'GPE', 'LOC', 'PRODUCT', 'EVENT', 'WORK_OF_ART', 'LAW', 'LANGUAGE', 'DATE', 'TIME', 'PERCENT', 'MONEY', 'QUANTITY', 'ORDINAL', 'CARDINAL']
class claf.tokens.linguistic.POSTag[source]

Bases: object

Universal POS tags expends by spacy (https://spacy.io/api/annotation#section-pos-tagging)

classes = ['ADJ', 'ADP', 'ADV', 'AUX', 'CONJ', 'CCONJ', 'DET', 'INTJ', 'NOUN', 'NUM', 'PART', 'PRON', 'PROPN', 'PUNCT', 'SCONJ', 'SYM', 'VERB', 'X', 'SPACE']
class claf.tokens.text_handler.TextHandler(token_makers, lazy_indexing=True)[source]

Bases: object

Text Handler

  • voacb and token_counter

  • raw_features -> indexed_features

  • raw_features -> tensor

  • Args:
    token_makers: Dictionary consisting of
    • key: token_name

    • value: TokenMaker (claf.tokens.token_maker)

  • Kwargs:

    lazy_indexing: Apply Lazy Evaluation to text indexing

build_vocabs(token_counters)[source]
index(datas, text_columns)[source]
is_all_vocab_use_pretrained()[source]
make_token_counters(texts, config=None)[source]
raw_to_tensor_fn(data_reader, cuda_device=None, helper={})[source]
class claf.tokens.token_maker.TokenMaker(token_type, tokenizer=None, indexer=None, embedding_fn=None, vocab_config=None)[source]

Bases: object

Token Maker (Data Transfer Object)

Token Maker consists of Tokenizer, Indexer, Embedding and Vocab

  • Kwargs:

    tokenizer: Tokenizer (claf.tokens.tokenizer.base) indexer: TokenIndexer (claf.tokens.indexer.base) embedding_fn: wrapper function of TokenEmbedding (claf.tokens.embedding.base) vocab_config: config dict of Vocab (claf.tokens.vocaburary)

BERT_TYPE = 'bert'
CHAR_TYPE = 'char'
COVE_TYPE = 'cove'
ELMO_TYPE = 'elmo'
EXACT_MATCH_TYPE = 'exact_match'
FEATURE_TYPE = 'feature'
FREQUENT_WORD_TYPE = 'frequent_word'
LINGUISTIC_TYPE = 'linguistic'
WORD_TYPE = 'word'
property embedding_fn
property indexer
set_vocab(vocab)[source]
property tokenizer
property vocab
property vocab_config
class claf.tokens.vocabulary.Vocab(token_name, pad_token=None, oov_token=None, start_token=None, end_token=None, cls_token=None, sep_token=None, min_count=None, max_vocab_size=None, frequent_count=None, pretrained_path=None, pretrained_token=None)[source]

Bases: object

Vocaburary Class

Vocab consists of token_to_index and index_to_token.

  • Args:

    token_name: Token name (Token and Vocab is one-to-one relationship)

  • Kwargs:

    pad_token: padding token value (eg. <pad>) oov_token: out-of-vocaburary token value (eg. <unk>) start_token: start token value (eg. <s>, <bos>) end_token: end token value (eg. </s>, <eos>) cls_token: CLS token value for BERT (eg. [CLS]) sep_token: SEP token value for BERT (eg. [SEP]) min_count: token’s minimal frequent count.

    when you define min_count, tokens remain that bigger than min_count.

    max_vocab_size: vocaburary’s maximun size.

    when you define max_vocab_size, tokens are selected according to frequent count.

    frequent_count: get frequent_count threshold_index.

    (eg. frequent_count = 1000, threshold_index is the tokens that frequent_count is 999 index number.)

    pretrained_path: pretrained vocab file path

    (format: A

B C D …)

DEFAULT_OOV_INDEX = 1
DEFAULT_OOV_TOKEN = '[UNK]'
DEFAULT_PAD_INDEX = 0
DEFAULT_PAD_TOKEN = '[PAD]'
PRETRAINED_ALL = 'all'
PRETRAINED_INTERSECT = 'intersect'
add(token, predefine_vocab=None)[source]
build(token_counter, predefine_vocab=None)[source]

build token with token_counter

  • Args:

    token_counter: (collections.Counter) token’s frequent_count Counter.

build_with_pretrained_file(token_counter)[source]
dump(path)[source]
from_texts(texts)[source]
get_all_tokens()[source]
get_index(token)[source]
get_token(index)[source]
init()[source]
load(path)[source]
to_text()[source]
class claf.tokens.vocabulary.VocabDict(oov_value)[source]

Bases: collections.defaultdict

Vocab DefaultDict Class

  • Kwargs:

    oov_value: out-of-vocaburary token value (eg. <unk>)

Module contents

class claf.tokens.BertTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

BERT Token Pre-training of Deep Bidirectional Transformers for Language Understanding

example.

hello -> [‘[CLS]’, ‘he’, ‘##llo’, [SEP]] -> [1, 4, 7, 2] -> BERT -> tensor

consisting of
  • tokenizer: WordTokenizer

  • indexer: WordIndexer

  • embedding: ELMoEmbedding (Language Modeling BiLSTM)

  • vocab: Vocab

class claf.tokens.CharTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

Character Token

Character-level Convolutional Networks for Text Classification (https://arxiv.org/abs/1509.01626)

example.

hello -> [‘h’, ‘e’, ‘l’, ‘l’, ‘o’] -> [2, 3, 4, 4, 5] -> CharCNN -> tensor

consisting of
  • tokenizer: CharTokenizer

  • indexer: CharIndexer

  • embedding: CharEmbedding (CharCNN)

  • vocab: Vocab

class claf.tokens.CoveTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

CoVe Token

Learned in Translation: Contextualized Word Vectors (McCann et. al. 2017) (https://github.com/salesforce/cove)

example.

hello -> [‘hello’] -> [2] -> CoVe -> tensor

consisting of
  • tokenizer: WordTokenizer

  • indexer: WordIndexer

  • embedding: CoveEmbedding (Machine Translation LSTM)

  • vocab: Vocab

class claf.tokens.ElmoTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

ELMo Token Embedding from Language Modeling

Deep contextualized word representations (https://github.com/allenai/allennlp/blob/master/allennlp/modules/elmo.py)

example.

hello -> [‘h’, ‘e’, ‘l’, ‘l’, ‘o’] -> [2, 3, 4, 4, 5] -> ELMo -> tensor

consisting of
  • tokenizer: WordTokenizer

  • indexer: WordIndexer

  • embedding: ELMoEmbedding (Language Modeling BiLSTM)

  • vocab: Vocab

class claf.tokens.ExactMatchTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

Exact Match Token (Sparse Feature)

Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form.

example.

c: i do, q: i -> [‘i’, ‘do’] -> [1, 0] -> tensor

consisting of
  • tokenizer: WordTokenizer

  • indexer: WordIndexer

  • embedding: SparseFeature

  • vocab: Vocab

class claf.tokens.FeatureTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

Feature Token

Do not use Embedding function. Just pass indexed_feature

example.

hello -> [‘hello’, ‘world’] -> [3, 5] -> tensor

consisting of
  • tokenizer: Tokenizer (need to define unit)

  • indexer: WordIndexer

  • embedding: None

  • vocab: Vocab

class claf.tokens.FrequentWordTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

Frequent-Tuning Word Token

word token + pre-trained word embeddings fixed and only fine-tune the N most frequent

example.

i do -> [‘i’, ‘do’] -> [1, 2] -> Embedding Matrix -> tensor finetuning only ‘do’

consisting of
  • tokenizer: WordTokenizer

  • indexer: WordIndexer

  • embedding: FrequentTuningWordEmbedding

  • vocab: Vocab

class claf.tokens.LinguisticTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

Exact Match Token (Sparse Feature)

Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form.

example.

c: i do, q: i -> [‘i’, ‘do’] -> [1, 0] -> tensor

consisting of
  • tokenizer: WordTokenizer

  • indexer: WordIndexer

  • embedding: SparseFeature

  • vocab: Vocab

class claf.tokens.WordTokenMaker(tokenizers, indexer_config, embedding_config, vocab_config)[source]

Bases: claf.tokens.token_maker.TokenMaker

Word Token (default)

i do -> [‘i’, ‘do’] -> [1, 2] -> Embedding Matrix -> tensor

consisting of
  • tokenizer: WordTokenizer

  • indexer: WordIndexer

  • embedding: WordEmbedding

  • vocab: Vocab

claf.tokens.basic_embedding_fn(embedding_config, module)[source]
================================================ FILE: docs/_build/html/claf.tokens.indexer.html ================================================ claf.tokens.indexer package — CLaF 0.2.0 documentation

claf.tokens.indexer package

Submodules

class claf.tokens.indexer.base.TokenIndexer(tokenizer)[source]

Bases: object

Token Indexer

indexing tokens (eg. ‘hi’ -> 4)

index(token)[source]

indexing function

set_vocab(vocab)[source]
class claf.tokens.indexer.bert_indexer.BertIndexer(tokenizer, do_tokenize=True)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Bert Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: SubwordTokenizer

  • Kwargs:

    lowercase: word token to lowercase insert_start: insert start_token to first insert_end: append end_token

index(text)[source]

indexing function

class claf.tokens.indexer.char_indexer.CharIndexer(tokenizer, insert_char_start=None, insert_char_end=None)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Character Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: CharTokenizer

  • Kwargs:
    insert_char_start: insert start index (eg. [‘h’, ‘i’] -> [‘<s>’, ‘h’, ‘i’] )

    default is None

    insert_char_end: insert end index (eg. [‘h’, ‘i’] -> [‘h’, ‘i’, ‘</s>’] )

    default is None

index(text)[source]

indexing function

index_token(chars)[source]

This code is from allenai/allennlp (https://github.com/allenai/allennlp/blob/master/allennlp/data/token_indexers/elmo_indexer.py)

class claf.tokens.indexer.elmo_indexer.ELMoIndexer(tokenizer)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Maps individual tokens to sequences of character ids, compatible with ELMo. To be consistent with previously trained models, we include it here as special of existing character indexers.

BOS_TOKEN = '<S>'
EOS_TOKEN = '</S>'
beginning_of_sentence_character = 256
beginning_of_sentence_characters = [258, 256, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260]
beginning_of_word_character = 258
end_of_sentence_character = 257
end_of_sentence_characters = [258, 257, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260]
end_of_word_character = 259
index(text)[source]

indexing function

index_token(word)[source]
max_word_length = 50
padding_character = 260
class claf.tokens.indexer.exact_match_indexer.ExactMatchIndexer(tokenizer, lower=True, lemma=True)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Exact Match Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: WordTokenizer

  • Kwargs:

    lower: add lower feature. default is True (0 or 1) lemma: add lemma case feature. feature is True (0 or 1)

index(text, query_text)[source]

indexing function

index_token(token, query_tokens)[source]
class claf.tokens.indexer.linguistic_indexer.LinguisticIndexer(tokenizer, pos_tag=None, ner=None, dep=None)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Linguistic Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: WordTokenizer

  • Kwargs:

    pos_tag: POS Tagging ner: Named Entity Recognition dep: Dependency Parser

index(text)[source]

indexing function

class claf.tokens.indexer.word_indexer.WordIndexer(tokenizer, do_tokenize=True, lowercase=False, insert_start=None, insert_end=None)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Word Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: WordTokenizer

  • Kwargs:

    lowercase: word token to lowercase insert_start: insert start_token to first insert_end: append end_token

index(text)[source]

indexing function

Module contents

class claf.tokens.indexer.BertIndexer(tokenizer, do_tokenize=True)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Bert Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: SubwordTokenizer

  • Kwargs:

    lowercase: word token to lowercase insert_start: insert start_token to first insert_end: append end_token

index(text)[source]

indexing function

class claf.tokens.indexer.CharIndexer(tokenizer, insert_char_start=None, insert_char_end=None)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Character Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: CharTokenizer

  • Kwargs:
    insert_char_start: insert start index (eg. [‘h’, ‘i’] -> [‘<s>’, ‘h’, ‘i’] )

    default is None

    insert_char_end: insert end index (eg. [‘h’, ‘i’] -> [‘h’, ‘i’, ‘</s>’] )

    default is None

index(text)[source]

indexing function

index_token(chars)[source]
class claf.tokens.indexer.ELMoIndexer(tokenizer)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Maps individual tokens to sequences of character ids, compatible with ELMo. To be consistent with previously trained models, we include it here as special of existing character indexers.

BOS_TOKEN = '<S>'
EOS_TOKEN = '</S>'
beginning_of_sentence_character = 256
beginning_of_sentence_characters = [258, 256, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260]
beginning_of_word_character = 258
end_of_sentence_character = 257
end_of_sentence_characters = [258, 257, 259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260]
end_of_word_character = 259
index(text)[source]

indexing function

index_token(word)[source]
max_word_length = 50
padding_character = 260
class claf.tokens.indexer.ExactMatchIndexer(tokenizer, lower=True, lemma=True)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Exact Match Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: WordTokenizer

  • Kwargs:

    lower: add lower feature. default is True (0 or 1) lemma: add lemma case feature. feature is True (0 or 1)

index(text, query_text)[source]

indexing function

index_token(token, query_tokens)[source]
class claf.tokens.indexer.LinguisticIndexer(tokenizer, pos_tag=None, ner=None, dep=None)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Linguistic Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: WordTokenizer

  • Kwargs:

    pos_tag: POS Tagging ner: Named Entity Recognition dep: Dependency Parser

index(text)[source]

indexing function

class claf.tokens.indexer.WordIndexer(tokenizer, do_tokenize=True, lowercase=False, insert_start=None, insert_end=None)[source]

Bases: claf.tokens.indexer.base.TokenIndexer

Word Token Indexer

  • Property

    vocab: Vocab (claf.tokens.vocabulary)

  • Args:

    tokenizer: WordTokenizer

  • Kwargs:

    lowercase: word token to lowercase insert_start: insert start_token to first insert_end: append end_token

index(text)[source]

indexing function

================================================ FILE: docs/_build/html/claf.tokens.token_embedder.html ================================================ claf.tokens.token_embedder package — CLaF 0.2.0 documentation

claf.tokens.token_embedder package

Submodules

class claf.tokens.token_embedder.base.TokenEmbedder(token_makers)[source]

Bases: torch.nn.modules.module.Module

Token Embedder

Take a tensor(indexed token) look up Embedding modules.

  • Args:

    token_makers: dictionary of TokenMaker (claf.token_makers.token)

add_embedding_modules(token_makers)[source]

add embedding module to TokenEmbedder

forward(inputs, params={})[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

get_embed_dim()[source]
class claf.tokens.token_embedder.basic_embedder.BasicTokenEmbedder(token_makers)[source]

Bases: claf.tokens.token_embedder.base.TokenEmbedder

Basic Token Embedder

Take a tensor(indexed token) look up Embedding modules. Output is concatenating all embedded tensors.

  • Args:

    token_makers: dictionary of TokenMaker (claf.tokens.token_maker)

forward(inputs, except_keys=[], params={})[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

get_embed_dim(except_keys=[])[source]
class claf.tokens.token_embedder.reading_comprehension_embedder.RCTokenEmbedder(token_makers)[source]

Bases: claf.tokens.token_embedder.base.TokenEmbedder

Reading Comprehension Token Embedder

Take a tensor(indexed token) look up Embedding modules. Inputs are seperated context and query for individual token setting.

  • Args:

    token_makers: dictionary of TokenMaker (claf.tokens.token_maker) vocabs: dictionary of vocab

    {“token_name”: Vocab (claf.token_makers.vocaburary), …}

EXCLUSIVE_TOKENS = ['exact_match']
forward(context, query, context_params={}, query_params={}, query_align=False)[source]
  • Args:

    context: context inputs (eg. {“token_name1”: tensor, “token_name2”: tensor, …}) query: query inputs (eg. {“token_name1”: tensor, “token_name2”: tensor, …})

  • Kwargs:

    context_params: custom context parameters query_params: query context parameters query_align: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

get_embed_dim()[source]

Module contents

class claf.tokens.token_embedder.BasicTokenEmbedder(token_makers)[source]

Bases: claf.tokens.token_embedder.base.TokenEmbedder

Basic Token Embedder

Take a tensor(indexed token) look up Embedding modules. Output is concatenating all embedded tensors.

  • Args:

    token_makers: dictionary of TokenMaker (claf.tokens.token_maker)

forward(inputs, except_keys=[], params={})[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

get_embed_dim(except_keys=[])[source]
class claf.tokens.token_embedder.RCTokenEmbedder(token_makers)[source]

Bases: claf.tokens.token_embedder.base.TokenEmbedder

Reading Comprehension Token Embedder

Take a tensor(indexed token) look up Embedding modules. Inputs are seperated context and query for individual token setting.

  • Args:

    token_makers: dictionary of TokenMaker (claf.tokens.token_maker) vocabs: dictionary of vocab

    {“token_name”: Vocab (claf.token_makers.vocaburary), …}

EXCLUSIVE_TOKENS = ['exact_match']
forward(context, query, context_params={}, query_params={}, query_align=False)[source]
  • Args:

    context: context inputs (eg. {“token_name1”: tensor, “token_name2”: tensor, …}) query: query inputs (eg. {“token_name1”: tensor, “token_name2”: tensor, …})

  • Kwargs:

    context_params: custom context parameters query_params: query context parameters query_align: f_align(p_i) = sum(a_ij, E(qj), where the attention score a_ij

    captures the similarity between pi and each question words q_j. these features add soft alignments between similar but non-identical words (e.g., car and vehicle) it only apply to ‘context_embed’.

get_embed_dim()[source]
================================================ FILE: docs/_build/html/claf.tokens.tokenizer.html ================================================ claf.tokens.tokenizer package — CLaF 0.2.0 documentation

claf.tokens.tokenizer package

Submodules

class claf.tokens.tokenizer.base.Tokenizer(name, cache_name)[source]

Bases: object

Tokenizer Base Class

MAX_TO_KEEP_CACHE = 3
tokenize(text, unit='text')[source]
class claf.tokens.tokenizer.char.CharTokenizer(name, word_tokenizer, config={})[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

Character Tokenizer

text -> word tokens -> [char tokens]

  • Args:

    name: tokenizer name [character|decompose_ko] word_tokenizer: word tokenizer object

class claf.tokens.tokenizer.pass_text.PassText[source]

Bases: object

Pass text without tokenize

tokenize(text)[source]
class claf.tokens.tokenizer.sent.SentTokenizer(name, config={})[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

Sentence Tokenizer

text -> [sent tokens]

  • Args:

    name: tokenizer name [punkt]

class claf.tokens.tokenizer.subword.SubwordTokenizer(name, word_tokenizer, config={})[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

Subword Tokenizer

text -> [word tokens] -> [[sub word tokens], …]

  • Args:

    name: tokenizer name [wordpiece]

claf.tokens.tokenizer.utils.create_tokenizer_with_regex(nlp, split_regex)[source]
claf.tokens.tokenizer.utils.load_spacy_model_for_tokenizer(split_regex)[source]
class claf.tokens.tokenizer.word.WordTokenizer(name, sent_tokenizer, config={}, split_with_regex=True)[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

Word Tokenizer

  • Args:

    name: tokenizer name [treebank_en|spacy_en|mecab_ko|bert_basic]

  • Kwargs:

    flatten: return type as flatten list split_with_regex: post split action. Split tokens that the tokenizer cannot split.

make_split_regex_expression()[source]

Apply a small amount of extra splitting to the given tokens, this is in particular to avoid UNK tokens due to contraction, quotation, or other forms of puncutation. I haven’t really done tests to see if/how much difference this makes, but it does avoid some common UNKs I noticed in SQuAD/TriviaQA

Module contents

class claf.tokens.tokenizer.PassText[source]

Bases: object

Pass text without tokenize

tokenize(text)[source]
class claf.tokens.tokenizer.BPETokenizer(name, config={})[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

BPTE(Byte-Pair Encoding) Tokenizer text -> … * Args:

name: tokenizer name [roberta]

class claf.tokens.tokenizer.CharTokenizer(name, word_tokenizer, config={})[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

Character Tokenizer

text -> word tokens -> [char tokens]

  • Args:

    name: tokenizer name [character|decompose_ko] word_tokenizer: word tokenizer object

class claf.tokens.tokenizer.SubwordTokenizer(name, word_tokenizer, config={})[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

Subword Tokenizer

text -> [word tokens] -> [[sub word tokens], …]

  • Args:

    name: tokenizer name [wordpiece]

class claf.tokens.tokenizer.WordTokenizer(name, sent_tokenizer, config={}, split_with_regex=True)[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

Word Tokenizer

  • Args:

    name: tokenizer name [treebank_en|spacy_en|mecab_ko|bert_basic]

  • Kwargs:

    flatten: return type as flatten list split_with_regex: post split action. Split tokens that the tokenizer cannot split.

make_split_regex_expression()[source]

Apply a small amount of extra splitting to the given tokens, this is in particular to avoid UNK tokens due to contraction, quotation, or other forms of puncutation. I haven’t really done tests to see if/how much difference this makes, but it does avoid some common UNKs I noticed in SQuAD/TriviaQA

class claf.tokens.tokenizer.SentTokenizer(name, config={})[source]

Bases: claf.tokens.tokenizer.base.Tokenizer

Sentence Tokenizer

text -> [sent tokens]

  • Args:

    name: tokenizer name [punkt]

================================================ FILE: docs/_build/html/contents/dataset_and_model.html ================================================ Dataset and Model — CLaF 0.2.0 documentation

Dataset and Model

Table of Contents


Multi-Task

Dataset

  • GLUE Benchmark: The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems.

    • CoLA, MNLI, MRPC, QNLI, QQP, RTE, SST-2, STS-B, WNLI

Reading Comprehension

Dataset

  • HistoryQA: Joseon History Question Answering Dataset (SQuAD Style)

  • KorQuAD: KorQuAD는 한국어 Machine Reading Comprehension을 위해 만든 데이터셋입니다. 모든 질의에 대한 답변은 해당 Wikipedia 아티클 문단의 일부 하위 영역으로 이루어집니다. Stanford Question Answering Dataset(SQuAD) v1.0과 동일한 방식으로 구성되었습니다.

  • SQuAD: Stanford Question Answering Dataset is a reading comprehension dataset, consisting of questions posed by crowdworkers on a set of Wikipedia articles, where the answer to every question is a segment of text, or span, from the corresponding reading passage, or the question might be unanswerable.


Regression

  • GLUE Benchmark: The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems.

    • STS-B


Semantic Parsing

Dataset


Sequence Classification

Dataset

  • GLUE Benchmark: The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems.

    • CoLA, MNLI, MRPC, QNLI, QQP, RTE, SST-2, WNLI


Token Classification

Dataset

  • NER - CoNLL 2013: The shared task of CoNLL-2003 concerns language-independent named entity recognition. Named entities are phrases that contain the names of persons, organizations, locations, times and quantities.

================================================ FILE: docs/_build/html/contents/pretrained_vector.html ================================================ Pretrained Vector — CLaF 0.2.0 documentation

Pretrained Vector

English

Korean

================================================ FILE: docs/_build/html/contents/tokens.html ================================================ Tokens — CLaF 0.2.0 documentation

Tokens

TokenMakers consists of Tokenizer, Indexer, Vocabulary, and Embedding Modules.
TokenMaker is responsible for the indexing of text and the generation of the tensors through the embedding module.

Tokenizers

  • Tokenizer Design

images

class SentTokenizer(name, config): ...
class WordTokenizer(name, sent_tokenizer, config) ...
class SubwordTokenizer(name, word_tokenizer, config) ...
class CharTokenizer(name, word_tokenizer, config) ...

The Tokenizer has a dependency with the other unit’s tokenizer and the tokenize() function takes the input of text units.
(* unit: unit of input e.g. ‘text’, ‘sentence’ and ‘word’)

  • tokenizer() example

>>> text = "Hello World.This is tokenizer example code."
>>> word_tokenizer.tokenize(text, unit="text")  # text -> sentences -> words
>>> ['Hello', 'World', '.', 'This', 'is', 'tokenizer', 'example', 'code', '.']
>>> word_tokenizer.tokenize(text, unit="sentence")  # text -> words
>>> ['Hello', 'World.This', 'is', 'tokenizer', 'example', 'code', '.']

Several tensors in a sub-level text unit can be combined into a single tensor of higher level via a vector operation. For example, subword level tensors can be averaged to represent a word level tensor.

e.g.) concatenate [word; subword] (subword tokens –average–> word token)

  • The list of pre-defined Tokenizers:

Text Unit Language Name Example
BPE All (depend on vocab) roberta Hello World
-> ["ĠHello", "ĠWorld"]
Char All character Hello World
-> ["Hello", "World"]
-> [["H", "e", "l", "l", "o"], ["W", "o", "r", "l", "d"]]
Char Korean jamo_ko "안녕 세상"
-> ["안녕", "세상"]
-> [["ㅇ", "ㅏ", "ㄴ", "ㄴ", "ㅕ", "ㅇ"], ["ㅅ", "ㅔ", "ㅅ", "ㅏ", "ㅇ"]]
Subword All (but, need vocab.txt) wordpiece "expectancy of anyone"
-> ["expectancy", "of", "anyone"]
-> ["expect", "##ancy", "of", "anyone"]
Word English nltk_en -
Word English spacy_en -
Word Korean mecab_ko -
Word All bert_basic -
Word All space_all "Hello World"
-> ["Hello", "World"]
Sent All punkt "Hello World. This is punkt tokenizer."
-> ["Hello World.", "This is punkt tokenizer."]

Token Maker

  • The list of pre-defined Token Maker:

Type Description Category Notes
char character -> convolution -> maxpool CharCNN -
cove Embeddings from Neural Machine Translation NMT - From Salesforce
feature Do not use embedding function, just pass feature Feature -
word word -> Embedding (+pretrained) Word2Vec -
frequent_word word token + pre-trained word embeddings fixed and only fine-tune the N most frequent Word2Vec + Fine-tune -
exact_match Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form. Feature - Sparse or Embedding
- Only for RC
elmo Embeddings from Language Models LM From Allennlp
linguistic Linguistic Features like POS Tagging, NER and Dependency Parser Feature - Sparse or Embedding
"token": {
   "names": ["char", "glove"],
   "types": ["char", "word"],
   "tokenizer": {  # Define the tokenizer in each unit.
       "char": {
           "name": "character"
       },
       "word": {
           "name": "treebank_en",
           "split_with_regex": true
       }
   },
   "char": {  # token_name
       "vocab": {
           "start_token": "<s>",
           "end_token": "</s>",
           "max_vocab_size": 260
       },
       "indexer": {
           "insert_char_start": true,
           "insert_char_end": true
       },
       "embedding": {
           "embed_dim": 16,
           "kernel_sizes": [5],
           "num_filter": 100,
           "activation": "relu",
           "dropout": 0.2
       }
   },
   "glove": {  # token_name
       "indexer": {
           "lowercase": true
       },
       "embedding": {
           "embed_dim": 100,
           "pretrained_path": "<glove.6B.100d path>,
           "trainable": false,
           "dropout": 0.2
       }
   }
},

# Tokens process
#   Text -> Indexed Featrues -> Tensor -> TokenEmbedder -> Model

# Visualization
# - Text: Hello World
# - Indexed Feature: {'char': [[2, 3, 4, 4, 5], [6, 7, 8, 4, 9]], 'glove': [2, 3]} 
# - Tensor: {'char': tensor, 'glove': tensor} 
# - TokenEmbedder: [char; glove]  (default: concatenate)
# - Model: use embedded_value
================================================ FILE: docs/_build/html/genindex.html ================================================ Index — CLaF 0.2.0 documentation

Index

A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | V | W

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

V

W

================================================ FILE: docs/_build/html/index.html ================================================ CLaF documentation — CLaF 0.2.0 documentation

CLaF documentation

CLaF: Clova Language Framework

Package Reference

Appendix

Indices and tables

================================================ FILE: docs/_build/html/modules.html ================================================ claf — CLaF 0.2.0 documentation ================================================ FILE: docs/_build/html/py-modindex.html ================================================ Python Module Index — CLaF 0.2.0 documentation
  • Docs »
  • Python Module Index

Python Module Index

c
 
c
claf
    claf.config
    claf.config.args
    claf.config.factory
    claf.config.factory.base
    claf.config.factory.data_loader
    claf.config.factory.data_reader
    claf.config.factory.model
    claf.config.factory.optimizer
    claf.config.factory.tokens
    claf.config.namespace
    claf.config.pattern
    claf.config.registry
    claf.config.utils
    claf.data
    claf.data.collate
    claf.data.data_handler
    claf.data.dataset
    claf.data.dataset.base
    claf.data.dataset.seq_cls
    claf.data.dataset.squad
    claf.data.dataset.wikisql
    claf.data.reader
    claf.data.reader.base
    claf.data.reader.bert
    claf.data.reader.bert.conll2003
    claf.data.reader.bert.seq_cls
    claf.data.reader.bert.squad
    claf.data.reader.bert.tok_cls
    claf.data.reader.cola
    claf.data.reader.seq_cls
    claf.data.reader.squad
    claf.data.reader.wikisql
    claf.data.utils
    claf.decorator
    claf.decorator.arguments
    claf.decorator.register
    claf.learn
    claf.learn.experiment
    claf.learn.mode
    claf.learn.tensorboard
    claf.learn.trainer
    claf.learn.utils
    claf.machine
    claf.machine.base
    claf.machine.components
    claf.machine.components.retrieval
    claf.machine.components.retrieval.tfidf
    claf.machine.module
    claf.machine.nlu
    claf.machine.open_qa
    claf.metric
    claf.metric.classification
    claf.metric.squad_v1_official
    claf.metric.squad_v2_official
    claf.metric.wikisql_official
    claf.model
    claf.model.base
    claf.model.cls_utils
    claf.model.reading_comprehension
    claf.model.reading_comprehension.bidaf
    claf.model.reading_comprehension.bidaf_no_answer
    claf.model.reading_comprehension.docqa
    claf.model.reading_comprehension.docqa_no_answer
    claf.model.reading_comprehension.drqa
    claf.model.reading_comprehension.mixin
    claf.model.reading_comprehension.qanet
    claf.model.semantic_parsing
    claf.model.semantic_parsing.mixin
    claf.model.semantic_parsing.sqlnet
    claf.model.semantic_parsing.utils
    claf.model.sequence_classification
    claf.model.sequence_classification.mixin
    claf.model.sequence_classification.structured_self_attention
    claf.model.token_classification
    claf.model.token_classification.mixin
    claf.modules
    claf.modules.activation
    claf.modules.attention
    claf.modules.attention.bi_attention
    claf.modules.attention.co_attention
    claf.modules.attention.docqa_attention
    claf.modules.attention.multi_head_attention
    claf.modules.attention.seq_attention
    claf.modules.conv
    claf.modules.conv.depthwise_separable_conv
    claf.modules.conv.pointwise_conv
    claf.modules.encoder
    claf.modules.encoder.lstm_cell_with_projection
    claf.modules.encoder.positional
    claf.modules.functional
    claf.modules.initializer
    claf.modules.layer
    claf.modules.layer.highway
    claf.modules.layer.normalization
    claf.modules.layer.positionwise
    claf.modules.layer.residual
    claf.modules.layer.scalar_mix
    claf.tokens
    claf.tokens.cove
    claf.tokens.elmo
    claf.tokens.embedding
    claf.tokens.embedding.base
    claf.tokens.embedding.bert_embedding
    claf.tokens.embedding.char_embedding
    claf.tokens.embedding.cove_embedding
    claf.tokens.embedding.elmo_embedding
    claf.tokens.embedding.frequent_word_embedding
    claf.tokens.embedding.sparse_feature
    claf.tokens.embedding.word_embedding
    claf.tokens.hangul
    claf.tokens.indexer
    claf.tokens.indexer.base
    claf.tokens.indexer.bert_indexer
    claf.tokens.indexer.char_indexer
    claf.tokens.indexer.elmo_indexer
    claf.tokens.indexer.exact_match_indexer
    claf.tokens.indexer.linguistic_indexer
    claf.tokens.indexer.word_indexer
    claf.tokens.linguistic
    claf.tokens.text_handler
    claf.tokens.token_embedder
    claf.tokens.token_embedder.base
    claf.tokens.token_embedder.basic_embedder
    claf.tokens.token_embedder.reading_comprehension_embedder
    claf.tokens.token_maker
    claf.tokens.tokenizer
    claf.tokens.tokenizer.base
    claf.tokens.tokenizer.char
    claf.tokens.tokenizer.pass_text
    claf.tokens.tokenizer.sent
    claf.tokens.tokenizer.subword
    claf.tokens.tokenizer.utils
    claf.tokens.tokenizer.word
    claf.tokens.vocabulary
    claf.utils
================================================ FILE: docs/_build/html/references.html ================================================ References — CLaF 0.2.0 documentation

References

================================================ FILE: docs/_build/html/reports/glue.html ================================================ GLUE — CLaF 0.2.0 documentation

GLUE

  • GLUE: The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems.


Results

Dev Set

  • Base Size : 12-layer, 768-hidden, 12-heads, 110M parameters

Task (Metric) Model CLaF Result Official Result BaseConfig
CoLA (Matthew's Corr) BERT-Base 59.393 52.1 (Test set) glue/cola_bert.json
MT-DNN (BERT) Base 54.658 - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 64.828 63.6 glue/cola_roberta.json
MNLI m/mm (Accuracy) BERT-Base 83.923/84.306 84.6/83.4 (Test set) glue/mnli{m/mm}_bert.json
MT-DNN (BERT) Base 84.452/84.225 - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 87.305/87.236 87.6/- glue/mnli{m/mm}_roberta.json
MRPC (Accuracy/F1) BERT-Base 87.5/91.282 88.9 (Test set) glue/mrpc_bert.json
MT-DNN (BERT) Base 87.5/91.005 - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 88.480/91.681 90.2 glue/mrpc_roberta.json
QNLI (Accuracy) BERT-Base 88.521 90.5 (Test set) glue/qnli_bert.json
MT-DNN (BERT) Base - - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 90.823 92.8 glue/qnli_roberta.json
QQP (Accuracy/F1) BERT-Base 90.378/87.171 71.2 (Test set) glue/qqp_bert.json
MT-DNN (BERT) Base 91.261/88.219 - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 91.541/88.768 91.9 glue/qqp_roberta.json
RTE (Accuracy) BERT-Base 69.314 66.4 (Test set) glue/rte_bert.json
MT-DNN (BERT) Base 79.422 - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 73.646 78.7 glue/rte_roberta.json
SST-2 (Accuracy) BERT-Base 92.546 93.5 (Test set) glue/sst_bert.json
MT-DNN (BERT) Base 93.005 - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 94.495 94.8 glue/sst_roberta.json
STS-B (Pearson/Spearman) BERT-Base 88.070/87.881 85.8 (Test set) glue/stsb_bert.json
MT-DNN (BERT) Base 88.444/88.807 - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 89.003/89.094 91.2 glue/stsb_roberta.json
WNLI (Accuracy) BERT-Base 56.338 65.1 (Test set) glue/wnli_bert.json
MT-DNN (BERT) Base 57.746 - 1. multi_task/bert_base_glue.json
2. fine-fune
RoBERTa-Base 60.563 - glue/wnli_roberta.json
  • Large Size : 24-layer, 1024-hidden, 16-heads, 340M parameters

Task (Metric) Model CLaF Result Official Result BaseConfig
CoLA (Matthew's Corr) BERT-Large 61.151 60.6 glue/cola_bert.json
MT-DNN (BERT) Large - 63.5 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large - 68.0 glue/cola_roberta.json
MNLI m/mm (Accuracy) BERT-Large - 86.6/- glue/mnli{m/mm}_bert.json
MT-DNN (BERT) Large - 87.1/86.7 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large - 90.2/90.2 glue/mnli{m/mm}_roberta.json
MRPC (Accuracy/F1) BERT-Large 87.255/90.845 88.0 glue/mrpc_bert.json
MT-DNN (BERT) Large - 91.0/87.5 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large 90.686/93.214 90.9 glue/mrpc_roberta.json
QNLI (Accuracy) BERT-Large 90.440 92.3 glue/qnli_bert.json
MT-DNN (BERT) Large - 87.1/86.7 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large - 94.7 glue/qnli_roberta.json
QQP (Accuracy/F1) BERT-Large 91.640/88.745 91.3 glue/qqp_bert.json
MT-DNN (BERT) Large - 87.1/86.7 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large 91.848/89.031 92.2 glue/qqp_roberta.json
RTE (Accuracy) BERT-Large 69.675 70.4 glue/rte_bert.json
MT-DNN (BERT) Large - 83.4 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large 84.838 86.6 glue/rte_roberta.json
SST-2 (Accuracy) BERT-Large 93.349 93.2 glue/sst_bert.json
MT-DNN (BERT) Large - 94.3 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large 95.642 96.4 glue/sst_roberta.json
STS-B (Pearson/Spearman) BERT-Large 90.041/89735 90.0 glue/stsb_bert.json
MT-DNN (BERT) Large - 90.7/90.6 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large 91.980/91.764 92.4 glue/stsb_roberta.json
WNLI (Accuracy) BERT-Large 59.155 - glue/wnli_bert.json
MT-DNN (BERT) Large - - 1. multi_task/bert_large_glue.json
2. fine-fune
RoBERTa-Large - 91.3 -
================================================ FILE: docs/_build/html/reports/historyqa.html ================================================ HistoryQA — CLaF 0.2.0 documentation

HistoryQA

Span Detector

  • HistoryQA: Joseon History Question Answering Dataset

    • Train: 31901 / Dev: 3067


Results

  • Dev Set

Model EM F1 BaseConfig Note
BiDAF 81.709 84.743 history/bidaf.json -
DocQA 85.099 87.789 history/docqa.json -
================================================ FILE: docs/_build/html/reports/korquad.html ================================================ KorQuAD — CLaF 0.2.0 documentation

KorQuAD

Span Detector

  • KorQuAD: KorQuAD는 한국어 Machine Reading Comprehension을 위해 만든 데이터셋입니다. 모든 질의에 대한 답변은 해당 Wikipedia 아티클 문단의 일부 하위 영역으로 이루어집니다. Stanford Question Answering Dataset(SQuAD) v1.0과 동일한 방식으로 구성되었습니다.

    • v1.0

      • Train: 60359 / Dev: 5774


Results

  • Dev Set

Model EM F1 BaseConfig Note
BiDAF 75.476 85.915 korquad/bidaf.json -
DocQA 77.693 88.115 korquad/docqa.json -
BERT-Base, Multilingual Uncased 81.573 90.679 korquad/bert_base_multilingual_uncased.json -
BERT-Base, Multilingual Cased 82.542 91.692 korquad/bert_base_multilingual_cased.json -
================================================ FILE: docs/_build/html/reports/squad.html ================================================ SQuAD — CLaF 0.2.0 documentation

SQuAD

Span Detector, No Answer

  • SQuAD: Stanford Question Answering Dataset (SQuAD), a new reading comprehension dataset consisting of 100,000+ questions posed by crowdworkers on a set of Wikipedia articles, where the answer to each question is a segment of text from the corresponding reading passage.

    • v1.1

      • Train: 87599 / Dev: 10570 / Test: 9533

    • v2.0 + no_answer

      • Train : 130319 / Dev: 11873 / Test: 8862


Results (v1.1)

  • Dev Set

Model EM (official) F1 (official) BaseConfig Note
BiDAF 68.108 (67.7) 77.780 (77.3) squad/bidaf.json -
BiDAF + ELMo 74.295 82.727 squad/bidaf+elmo.json -
DrQA 68.316 (68.8) 77.493 (78.0) squad/drqa.json -
DocQA 71.760 (71.513) 80.635 (80.422) squad/docqa.json -
DocQA + ELMo 76.244 (77.5) 84.372 (84.5) squad/docqa+elmo.json -
QANet 70.918 (73.6) 79.800 (82.7) squad/qanet.json -
BERT-Base Uncased 79.508 (80.8) 87.642 (88.5) squad/bert_base_uncased.json -
BERT-Large Uncased 83.254 (84.1) 90.440 (90.9) squad/bert_large_uncased.json -
RoBERTa-Base 82.980 90.459 roberta_base.json/bert_base_uncased.json -
RoBERTa-Large 88.061 (88.9) 94.034 (94.6) squad/roberta_large.json -

Results (v2.0)

  • Dev Set

Model EM (official) F1 (official) BaseConfig Note
BiDAF 62.570 65.461 squad/bidaf_no_answer.json -
DocQA 61.728 64.489 squad/docqa_no_answer.json -
================================================ FILE: docs/_build/html/reports/wikisql.html ================================================ WikiSQL — CLaF 0.2.0 documentation

WikiSQL

Semantic Parsing, NL2SQL

  • WikiSQL: A large crowd-sourced dataset for developing natural language interfaces for relational databases.


Results

  • Column details

    • Agg: Aggregator

    • Sel: SELECT Column

    • Cond: Where clause

    • LF: Logical Form

    • EX: Execution

    • (): Paper result

Model Agg Sel Cond LF EX BaseConfig
SQLNet (90.1) (91.1) (72.1) - (69.8) wikisql/sqlnet.json
================================================ FILE: docs/_build/html/search.html ================================================ Search — CLaF 0.2.0 documentation

================================================ FILE: docs/_build/html/searchindex.js ================================================ Search.setIndex({docnames:["claf","claf.config","claf.config.factory","claf.data","claf.data.dataset","claf.data.reader","claf.data.reader.bert","claf.decorator","claf.learn","claf.machine","claf.machine.components","claf.machine.components.retrieval","claf.metric","claf.model","claf.model.reading_comprehension","claf.model.semantic_parsing","claf.model.sequence_classification","claf.model.token_classification","claf.modules","claf.modules.attention","claf.modules.conv","claf.modules.encoder","claf.modules.layer","claf.tokens","claf.tokens.embedding","claf.tokens.indexer","claf.tokens.token_embedder","claf.tokens.tokenizer","contents/dataset_and_model","contents/pretrained_vector","contents/tokens","index","modules","references","reports/glue","reports/historyqa","reports/korquad","reports/squad","reports/wikisql","summary/reading_comprehension"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.intersphinx":1,"sphinx.ext.viewcode":1,sphinx:56},filenames:["claf.rst","claf.config.rst","claf.config.factory.rst","claf.data.rst","claf.data.dataset.rst","claf.data.reader.rst","claf.data.reader.bert.rst","claf.decorator.rst","claf.learn.rst","claf.machine.rst","claf.machine.components.rst","claf.machine.components.retrieval.rst","claf.metric.rst","claf.model.rst","claf.model.reading_comprehension.rst","claf.model.semantic_parsing.rst","claf.model.sequence_classification.rst","claf.model.token_classification.rst","claf.modules.rst","claf.modules.attention.rst","claf.modules.conv.rst","claf.modules.encoder.rst","claf.modules.layer.rst","claf.tokens.rst","claf.tokens.embedding.rst","claf.tokens.indexer.rst","claf.tokens.token_embedder.rst","claf.tokens.tokenizer.rst","contents/dataset_and_model.md","contents/pretrained_vector.md","contents/tokens.md","index.rst","modules.rst","references.md","reports/glue.md","reports/historyqa.md","reports/korquad.md","reports/squad.md","reports/wikisql.md","summary/reading_comprehension.md"],objects:{"":{claf:[0,0,0,"-"]},"claf.config":{args:[1,0,0,"-"],factory:[2,0,0,"-"],namespace:[1,0,0,"-"],pattern:[1,0,0,"-"],registry:[1,0,0,"-"],utils:[1,0,0,"-"]},"claf.config.args":{arg_str2bool:[1,1,1,""],base_config:[1,1,1,""],config:[1,1,1,""],data:[1,1,1,""],evaluate:[1,1,1,""],general:[1,1,1,""],get_input_arguments:[1,1,1,""],machine:[1,1,1,""],model:[1,1,1,""],nsml_for_internal:[1,1,1,""],optimize_config:[1,1,1,""],predict:[1,1,1,""],set_batch_size:[1,1,1,""],set_gpu_env:[1,1,1,""],token:[1,1,1,""],train_config:[1,1,1,""],trainer:[1,1,1,""]},"claf.config.factory":{DataLoaderFactory:[2,2,1,""],DataReaderFactory:[2,2,1,""],ModelFactory:[2,2,1,""],OptimizerFactory:[2,2,1,""],TokenMakersFactory:[2,2,1,""],base:[2,0,0,"-"],data_loader:[2,0,0,"-"],data_reader:[2,0,0,"-"],model:[2,0,0,"-"],optimizer:[2,0,0,"-"],tokens:[2,0,0,"-"]},"claf.config.factory.DataLoaderFactory":{create:[2,3,1,""]},"claf.config.factory.DataReaderFactory":{create:[2,3,1,""]},"claf.config.factory.ModelFactory":{create:[2,3,1,""],create_token_embedder:[2,3,1,""]},"claf.config.factory.OptimizerFactory":{create:[2,3,1,""],set_warmup_steps:[2,3,1,""]},"claf.config.factory.TokenMakersFactory":{LANGS:[2,4,1,""],create:[2,3,1,""]},"claf.config.factory.base":{Factory:[2,2,1,""]},"claf.config.factory.base.Factory":{create:[2,3,1,""]},"claf.config.factory.data_loader":{DataLoaderFactory:[2,2,1,""],make_data_loader:[2,1,1,""]},"claf.config.factory.data_loader.DataLoaderFactory":{create:[2,3,1,""]},"claf.config.factory.data_reader":{DataReaderFactory:[2,2,1,""]},"claf.config.factory.data_reader.DataReaderFactory":{create:[2,3,1,""]},"claf.config.factory.model":{ModelFactory:[2,2,1,""]},"claf.config.factory.model.ModelFactory":{create:[2,3,1,""],create_token_embedder:[2,3,1,""]},"claf.config.factory.optimizer":{OptimizerFactory:[2,2,1,""]},"claf.config.factory.optimizer.OptimizerFactory":{create:[2,3,1,""],set_warmup_steps:[2,3,1,""]},"claf.config.factory.tokens":{TokenMakersFactory:[2,2,1,""],make_all_tokenizers:[2,1,1,""],make_tokenizer:[2,1,1,""]},"claf.config.factory.tokens.TokenMakersFactory":{LANGS:[2,4,1,""],create:[2,3,1,""]},"claf.config.namespace":{NestedNamespace:[1,2,1,""]},"claf.config.namespace.NestedNamespace":{delete_unselected:[1,3,1,""],load_from_json:[1,3,1,""],overwrite:[1,3,1,""]},"claf.config.pattern":{Singleton:[1,2,1,""]},"claf.config.registry":{Registry:[1,2,1,""]},"claf.config.registry.Registry":{add:[1,3,1,""],get:[1,3,1,""]},"claf.config.utils":{convert_config2dict:[1,1,1,""],pretty_json_dumps:[1,1,1,""],remove_none:[1,1,1,""],set_global_seed:[1,1,1,""]},"claf.data":{collate:[3,0,0,"-"],data_handler:[3,0,0,"-"],dataset:[4,0,0,"-"],reader:[5,0,0,"-"],utils:[3,0,0,"-"]},"claf.data.collate":{FeatLabelPadCollator:[3,2,1,""],PadCollator:[3,2,1,""]},"claf.data.collate.FeatLabelPadCollator":{collate:[3,3,1,""]},"claf.data.collate.PadCollator":{collate:[3,3,1,""]},"claf.data.data_handler":{CachePath:[3,2,1,""],DataHandler:[3,2,1,""]},"claf.data.data_handler.CachePath":{DATASET:[3,4,1,""],MACHINE:[3,4,1,""],PRETRAINED_VECTOR:[3,4,1,""],ROOT:[3,4,1,""],TOKEN_COUNTER:[3,4,1,""],VOCAB:[3,4,1,""]},"claf.data.data_handler.DataHandler":{cache_token_counter:[3,3,1,""],convert_cache_path:[3,3,1,""],dump:[3,3,1,""],load:[3,3,1,""],read:[3,3,1,""],read_embedding:[3,3,1,""]},"claf.data.dataset":{MultiTaskBertDataset:[4,2,1,""],RegressionBertDataset:[4,2,1,""],SQuADBertDataset:[4,2,1,""],SQuADDataset:[4,2,1,""],SeqClsBertDataset:[4,2,1,""],SeqClsDataset:[4,2,1,""],TokClsBertDataset:[4,2,1,""],WikiSQLDataset:[4,2,1,""],base:[4,0,0,"-"],seq_cls:[4,0,0,"-"],squad:[4,0,0,"-"],wikisql:[4,0,0,"-"]},"claf.data.dataset.MultiTaskBertDataset":{collate_fn:[4,3,1,""],init_iterators:[4,3,1,""]},"claf.data.dataset.RegressionBertDataset":{collate_fn:[4,3,1,""],get_ground_truth:[4,3,1,""],get_id:[4,3,1,""],sequence_maxlen:[4,3,1,""]},"claf.data.dataset.SQuADBertDataset":{bert_input_maxlen:[4,3,1,""],collate_fn:[4,3,1,""],get_bert_tokens:[4,3,1,""],get_context:[4,3,1,""],get_ground_truths:[4,3,1,""],get_id:[4,3,1,""],get_predict:[4,3,1,""],get_qid:[4,3,1,""],get_qid_index:[4,3,1,""],get_text_with_index:[4,3,1,""]},"claf.data.dataset.SQuADDataset":{collate_fn:[4,3,1,""],context_maxlen:[4,3,1,""],get_context:[4,3,1,""],get_ground_truths:[4,3,1,""],get_predict:[4,3,1,""],get_qid:[4,3,1,""],get_text_span:[4,3,1,""],get_text_with_index:[4,3,1,""],question_maxlen:[4,3,1,""]},"claf.data.dataset.SeqClsBertDataset":{collate_fn:[4,3,1,""],get_class_text_with_idx:[4,3,1,""],get_ground_truth:[4,3,1,""],get_id:[4,3,1,""],num_classes:[4,3,1,""],sequence_maxlen:[4,3,1,""]},"claf.data.dataset.SeqClsDataset":{collate_fn:[4,3,1,""],get_class_text_with_idx:[4,3,1,""],get_ground_truth:[4,3,1,""],get_id:[4,3,1,""],num_classes:[4,3,1,""],sequence_maxlen:[4,3,1,""]},"claf.data.dataset.TokClsBertDataset":{collate_fn:[4,3,1,""],get_ground_truth:[4,3,1,""],get_id:[4,3,1,""],get_tag_text_with_idx:[4,3,1,""],get_tag_texts_with_idxs:[4,3,1,""],num_tags:[4,3,1,""],sequence_maxlen:[4,3,1,""]},"claf.data.dataset.WikiSQLDataset":{collate_fn:[4,3,1,""],get_ground_truth:[4,3,1,""],get_id:[4,3,1,""],get_table_id:[4,3,1,""],get_tokenized_question:[4,3,1,""],question_maxlen:[4,3,1,""]},"claf.data.dataset.base":{DatasetBase:[4,2,1,""]},"claf.data.dataset.base.DatasetBase":{collate_fn:[4,3,1,""],get_ground_truth:[4,3,1,""],get_ground_truths:[4,3,1,""],get_predict:[4,3,1,""],lazy_evaluation:[4,3,1,""]},"claf.data.dataset.seq_cls":{SeqClsDataset:[4,2,1,""]},"claf.data.dataset.seq_cls.SeqClsDataset":{collate_fn:[4,3,1,""],get_class_text_with_idx:[4,3,1,""],get_ground_truth:[4,3,1,""],get_id:[4,3,1,""],num_classes:[4,3,1,""],sequence_maxlen:[4,3,1,""]},"claf.data.dataset.squad":{SQuADDataset:[4,2,1,""]},"claf.data.dataset.squad.SQuADDataset":{collate_fn:[4,3,1,""],context_maxlen:[4,3,1,""],get_context:[4,3,1,""],get_ground_truths:[4,3,1,""],get_predict:[4,3,1,""],get_qid:[4,3,1,""],get_text_span:[4,3,1,""],get_text_with_index:[4,3,1,""],question_maxlen:[4,3,1,""]},"claf.data.dataset.wikisql":{WikiSQLDataset:[4,2,1,""]},"claf.data.dataset.wikisql.WikiSQLDataset":{collate_fn:[4,3,1,""],get_ground_truth:[4,3,1,""],get_id:[4,3,1,""],get_table_id:[4,3,1,""],get_tokenized_question:[4,3,1,""],question_maxlen:[4,3,1,""]},"claf.data.reader":{CoLABertReader:[5,2,1,""],CoLAReader:[5,2,1,""],CoNLL2003BertReader:[5,2,1,""],MNLIBertReader:[5,2,1,""],MRPCBertReader:[5,2,1,""],MultiTaskBertReader:[5,2,1,""],QNLIBertReader:[5,2,1,""],QQPBertReader:[5,2,1,""],RTEBertReader:[5,2,1,""],RegressionBertReader:[5,2,1,""],SQuADBertReader:[5,2,1,""],SQuADReader:[5,2,1,""],SSTBertReader:[5,2,1,""],STSBBertReader:[5,2,1,""],SeqClsBertReader:[5,2,1,""],SeqClsReader:[5,2,1,""],TokClsBertReader:[5,2,1,""],WNLIBertReader:[5,2,1,""],WikiSQLReader:[5,2,1,""],base:[5,0,0,"-"],bert:[6,0,0,"-"],cola:[5,0,0,"-"],seq_cls:[5,0,0,"-"],squad:[5,0,0,"-"],wikisql:[5,0,0,"-"]},"claf.data.reader.CoLABertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""]},"claf.data.reader.CoLAReader":{CLASS_DATA:[5,4,1,""]},"claf.data.reader.MNLIBertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""]},"claf.data.reader.MRPCBertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""]},"claf.data.reader.MultiTaskBertReader":{CLASS_DATA:[5,4,1,""],make_data_reader:[5,3,1,""],make_task_by_reader:[5,3,1,""],read_one_example:[5,3,1,""]},"claf.data.reader.QNLIBertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""]},"claf.data.reader.QQPBertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""]},"claf.data.reader.RTEBertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""]},"claf.data.reader.RegressionBertReader":{METRIC_KEY:[5,4,1,""],read_one_example:[5,3,1,""]},"claf.data.reader.SQuADBertReader":{METRIC_KEY:[5,4,1,""],read_one_example:[5,3,1,""]},"claf.data.reader.SQuADReader":{read_one_example:[5,3,1,""]},"claf.data.reader.SSTBertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""]},"claf.data.reader.STSBBertReader":{METRIC_KEY:[5,4,1,""]},"claf.data.reader.SeqClsBertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""],read_one_example:[5,3,1,""]},"claf.data.reader.SeqClsReader":{CLASS_DATA:[5,4,1,""],read_one_example:[5,3,1,""]},"claf.data.reader.TokClsBertReader":{read_one_example:[5,3,1,""]},"claf.data.reader.WNLIBertReader":{CLASS_DATA:[5,4,1,""],METRIC_KEY:[5,4,1,""]},"claf.data.reader.WikiSQLReader":{get_coditions_value_position:[5,3,1,""],load_data:[5,3,1,""],read_one_example:[5,3,1,""]},"claf.data.reader.base":{DataReader:[5,2,1,""]},"claf.data.reader.base.DataReader":{convert_to_dataset:[5,3,1,""],filter_texts:[5,3,1,""],read:[5,3,1,""],read_one_example:[5,3,1,""]},"claf.data.reader.bert":{conll2003:[6,0,0,"-"],seq_cls:[6,0,0,"-"],squad:[6,0,0,"-"],tok_cls:[6,0,0,"-"]},"claf.data.reader.bert.conll2003":{CoNLL2003BertReader:[6,2,1,""]},"claf.data.reader.bert.seq_cls":{SeqClsBertReader:[6,2,1,""]},"claf.data.reader.bert.seq_cls.SeqClsBertReader":{CLASS_DATA:[6,4,1,""],METRIC_KEY:[6,4,1,""],read_one_example:[6,3,1,""]},"claf.data.reader.bert.squad":{SQuADBertReader:[6,2,1,""],Token:[6,2,1,""]},"claf.data.reader.bert.squad.SQuADBertReader":{METRIC_KEY:[6,4,1,""],read_one_example:[6,3,1,""]},"claf.data.reader.bert.tok_cls":{TokClsBertReader:[6,2,1,""]},"claf.data.reader.bert.tok_cls.TokClsBertReader":{read_one_example:[6,3,1,""]},"claf.data.reader.cola":{CoLAReader:[5,2,1,""]},"claf.data.reader.cola.CoLAReader":{CLASS_DATA:[5,4,1,""]},"claf.data.reader.seq_cls":{SeqClsReader:[5,2,1,""]},"claf.data.reader.seq_cls.SeqClsReader":{CLASS_DATA:[5,4,1,""],read_one_example:[5,3,1,""]},"claf.data.reader.squad":{SQuADReader:[5,2,1,""]},"claf.data.reader.squad.SQuADReader":{read_one_example:[5,3,1,""]},"claf.data.reader.wikisql":{WikiSQLReader:[5,2,1,""]},"claf.data.reader.wikisql.WikiSQLReader":{get_coditions_value_position:[5,3,1,""],load_data:[5,3,1,""],read_one_example:[5,3,1,""]},"claf.data.utils":{get_is_head_of_word:[3,1,1,""],get_sequence_a:[3,1,1,""],get_token_dim:[3,1,1,""],get_token_type:[3,1,1,""],is_lazy:[3,1,1,""],make_batch:[3,1,1,""],make_bert_input:[3,1,1,""],make_bert_token_type:[3,1,1,""],make_bert_token_types:[3,1,1,""],padding_tokens:[3,1,1,""],sanity_check_iob:[3,1,1,""],transpose:[3,1,1,""]},"claf.decorator":{arguments:[7,0,0,"-"],arguments_required:[7,2,1,""],register:[7,0,0,"-"]},"claf.decorator.arguments":{arguments_required:[7,2,1,""]},"claf.decorator.register":{register:[7,2,1,""]},"claf.learn":{experiment:[8,0,0,"-"],mode:[8,0,0,"-"],tensorboard:[8,0,0,"-"],trainer:[8,0,0,"-"],utils:[8,0,0,"-"]},"claf.learn.experiment":{Experiment:[8,2,1,""]},"claf.learn.experiment.Experiment":{common_setting:[8,3,1,""],load_setting:[8,3,1,""],predict:[8,3,1,""],set_eval_inference_latency_mode:[8,3,1,""],set_eval_mode:[8,3,1,""],set_predict_mode:[8,3,1,""],set_train_mode:[8,3,1,""],set_trainer:[8,3,1,""]},"claf.learn.mode":{Mode:[8,2,1,""]},"claf.learn.mode.Mode":{EVAL:[8,4,1,""],INFER_EVAL:[8,4,1,""],MACHINE:[8,4,1,""],PREDICT:[8,4,1,""],TRAIN:[8,4,1,""]},"claf.learn.tensorboard":{TensorBoard:[8,2,1,""]},"claf.learn.tensorboard.TensorBoard":{embedding_summary:[8,3,1,""],graph_summary:[8,3,1,""],histogram_summary:[8,3,1,""],image_summary:[8,3,1,""],scalar_summaries:[8,3,1,""],scalar_summary:[8,3,1,""]},"claf.learn.trainer":{Trainer:[8,2,1,""]},"claf.learn.trainer.Trainer":{evaluate:[8,3,1,""],evaluate_inference_latency:[8,3,1,""],predict:[8,3,1,""],save:[8,3,1,""],set_model_base_properties:[8,3,1,""],train:[8,3,1,""],train_and_evaluate:[8,3,1,""]},"claf.learn.utils":{TrainCounter:[8,2,1,""],bind_nsml:[8,1,1,""],get_session_name:[8,1,1,""],get_sorted_path:[8,1,1,""],load_model_checkpoint:[8,1,1,""],load_optimizer_checkpoint:[8,1,1,""],load_vocabs:[8,1,1,""],logger:[8,5,1,""],save_checkpoint:[8,1,1,""],send_message_to_slack:[8,1,1,""]},"claf.learn.utils.TrainCounter":{epoch:[8,4,1,""],get_display:[8,3,1,""],global_step:[8,4,1,""]},"claf.machine":{NLU:[9,2,1,""],OpenQA:[9,2,1,""],base:[9,0,0,"-"],components:[10,0,0,"-"],module:[9,0,0,"-"],nlu:[9,0,0,"-"],open_qa:[9,0,0,"-"]},"claf.machine.NLU":{intent_classification:[9,3,1,""],load:[9,3,1,""],slot_filling:[9,3,1,""]},"claf.machine.OpenQA":{load:[9,3,1,""],machine_reading:[9,3,1,""],search_documents:[9,3,1,""]},"claf.machine.base":{Machine:[9,2,1,""]},"claf.machine.base.Machine":{load:[9,3,1,""],load_from_config:[9,3,1,""],make_module:[9,3,1,""]},"claf.machine.components":{TFIDF:[10,2,1,""],retrieval:[11,0,0,"-"]},"claf.machine.components.TFIDF":{INDEX_FNAME:[10,4,1,""],TFIDF_FNAME:[10,4,1,""],VOCAB_FNAME:[10,4,1,""],get_closest:[10,3,1,""],init:[10,3,1,""],init_model:[10,3,1,""],load:[10,3,1,""],parse:[10,3,1,""],save:[10,3,1,""],text_to_tfidf:[10,3,1,""]},"claf.machine.components.retrieval":{tfidf:[11,0,0,"-"]},"claf.machine.components.retrieval.tfidf":{TFIDF:[11,2,1,""]},"claf.machine.components.retrieval.tfidf.TFIDF":{INDEX_FNAME:[11,4,1,""],TFIDF_FNAME:[11,4,1,""],VOCAB_FNAME:[11,4,1,""],get_closest:[11,3,1,""],init:[11,3,1,""],init_model:[11,3,1,""],load:[11,3,1,""],parse:[11,3,1,""],save:[11,3,1,""],text_to_tfidf:[11,3,1,""]},"claf.machine.module":{Module:[9,2,1,""]},"claf.machine.module.Module":{COMPONENT:[9,4,1,""],EXPERIMENT:[9,4,1,""],KNOWLEDGE_BASE:[9,4,1,""]},"claf.machine.nlu":{NLU:[9,2,1,""]},"claf.machine.nlu.NLU":{intent_classification:[9,3,1,""],load:[9,3,1,""],slot_filling:[9,3,1,""]},"claf.machine.open_qa":{OpenQA:[9,2,1,""]},"claf.machine.open_qa.OpenQA":{load:[9,3,1,""],machine_reading:[9,3,1,""],search_documents:[9,3,1,""]},"claf.metric":{classification:[12,0,0,"-"],squad_v1_official:[12,0,0,"-"],squad_v2_official:[12,0,0,"-"],wikisql_official:[12,0,0,"-"]},"claf.metric.classification":{f1:[12,1,1,""],macro_f1:[12,1,1,""],macro_precision:[12,1,1,""],macro_recall:[12,1,1,""],precision:[12,1,1,""],recall:[12,1,1,""]},"claf.metric.squad_v1_official":{evaluate:[12,1,1,""],exact_match_score:[12,1,1,""],f1_score:[12,1,1,""],metric_max_over_ground_truths:[12,1,1,""],normalize_answer:[12,1,1,""]},"claf.metric.squad_v2_official":{apply_no_ans_threshold:[12,1,1,""],compute_exact:[12,1,1,""],compute_f1:[12,1,1,""],evaluate:[12,1,1,""],find_all_best_thresh:[12,1,1,""],find_best_thresh:[12,1,1,""],get_raw_scores:[12,1,1,""],get_tokens:[12,1,1,""],histogram_na_prob:[12,1,1,""],main:[12,1,1,""],make_eval_dict:[12,1,1,""],make_precision_recall_eval:[12,1,1,""],make_qid_to_has_ans:[12,1,1,""],merge_eval:[12,1,1,""],normalize_answer:[12,1,1,""],parse_args:[12,1,1,""],plot_pr_curve:[12,1,1,""],run_precision_recall_analysis:[12,1,1,""]},"claf.metric.wikisql_official":{count_lines:[12,1,1,""],evaluate:[12,1,1,""]},"claf.model":{base:[13,0,0,"-"],cls_utils:[13,0,0,"-"],reading_comprehension:[14,0,0,"-"],semantic_parsing:[15,0,0,"-"],sequence_classification:[16,0,0,"-"],token_classification:[17,0,0,"-"]},"claf.model.base":{ModelBase:[13,2,1,""],ModelWithTokenEmbedder:[13,2,1,""],ModelWithoutTokenEmbedder:[13,2,1,""]},"claf.model.base.ModelBase":{config:[13,3,1,""],dataset:[13,3,1,""],forward:[13,3,1,""],is_ready:[13,3,1,""],log_dir:[13,3,1,""],make_metrics:[13,3,1,""],make_predictions:[13,3,1,""],metrics:[13,3,1,""],predict:[13,3,1,""],print_examples:[13,3,1,""],train_counter:[13,3,1,""],vocabs:[13,3,1,""],write_predictions:[13,3,1,""]},"claf.model.cls_utils":{get_tag_dict:[13,1,1,""],write_confusion_matrix_to_csv:[13,1,1,""]},"claf.model.reading_comprehension":{BertForQA:[14,2,1,""],BiDAF:[14,2,1,""],BiDAF_No_Answer:[14,2,1,""],DocQA:[14,2,1,""],DocQA_No_Answer:[14,2,1,""],DrQA:[14,2,1,""],QANet:[14,2,1,""],RoBertaForQA:[14,2,1,""],bidaf:[14,0,0,"-"],bidaf_no_answer:[14,0,0,"-"],docqa:[14,0,0,"-"],docqa_no_answer:[14,0,0,"-"],drqa:[14,0,0,"-"],mixin:[14,0,0,"-"],qanet:[14,0,0,"-"]},"claf.model.reading_comprehension.BertForQA":{forward:[14,3,1,""]},"claf.model.reading_comprehension.BiDAF":{forward:[14,3,1,""]},"claf.model.reading_comprehension.BiDAF_No_Answer":{forward:[14,3,1,""]},"claf.model.reading_comprehension.DocQA":{forward:[14,3,1,""]},"claf.model.reading_comprehension.DocQA_No_Answer":{forward:[14,3,1,""]},"claf.model.reading_comprehension.DrQA":{forward:[14,3,1,""]},"claf.model.reading_comprehension.QANet":{forward:[14,3,1,""]},"claf.model.reading_comprehension.RoBertaForQA":{forward:[14,3,1,""]},"claf.model.reading_comprehension.bidaf":{BiDAF:[14,2,1,""]},"claf.model.reading_comprehension.bidaf.BiDAF":{forward:[14,3,1,""]},"claf.model.reading_comprehension.bidaf_no_answer":{BiDAF_No_Answer:[14,2,1,""]},"claf.model.reading_comprehension.bidaf_no_answer.BiDAF_No_Answer":{forward:[14,3,1,""]},"claf.model.reading_comprehension.docqa":{DocQA:[14,2,1,""],SelfAttention:[14,2,1,""]},"claf.model.reading_comprehension.docqa.DocQA":{forward:[14,3,1,""]},"claf.model.reading_comprehension.docqa.SelfAttention":{forward:[14,3,1,""]},"claf.model.reading_comprehension.docqa_no_answer":{DocQA_No_Answer:[14,2,1,""],NoAnswer:[14,2,1,""],SelfAttention:[14,2,1,""]},"claf.model.reading_comprehension.docqa_no_answer.DocQA_No_Answer":{forward:[14,3,1,""]},"claf.model.reading_comprehension.docqa_no_answer.NoAnswer":{forward:[14,3,1,""]},"claf.model.reading_comprehension.docqa_no_answer.SelfAttention":{forward:[14,3,1,""]},"claf.model.reading_comprehension.drqa":{DrQA:[14,2,1,""]},"claf.model.reading_comprehension.drqa.DrQA":{forward:[14,3,1,""]},"claf.model.reading_comprehension.mixin":{ReadingComprehension:[14,2,1,""],SQuADv1:[14,2,1,""],SQuADv1ForBert:[14,2,1,""],SQuADv2:[14,2,1,""]},"claf.model.reading_comprehension.mixin.ReadingComprehension":{get_best_span:[14,3,1,""],make_predictions:[14,3,1,""],predict:[14,3,1,""],print_examples:[14,3,1,""],write_predictions:[14,3,1,""]},"claf.model.reading_comprehension.mixin.SQuADv1":{make_metrics:[14,3,1,""]},"claf.model.reading_comprehension.mixin.SQuADv1ForBert":{make_metrics:[14,3,1,""],predict:[14,3,1,""]},"claf.model.reading_comprehension.mixin.SQuADv2":{make_metrics:[14,3,1,""]},"claf.model.reading_comprehension.qanet":{EncoderBlock:[14,2,1,""],QANet:[14,2,1,""]},"claf.model.reading_comprehension.qanet.EncoderBlock":{forward:[14,3,1,""]},"claf.model.reading_comprehension.qanet.QANet":{forward:[14,3,1,""]},"claf.model.semantic_parsing":{SQLNet:[15,2,1,""],mixin:[15,0,0,"-"],sqlnet:[15,0,0,"-"],utils:[15,0,0,"-"]},"claf.model.semantic_parsing.SQLNet":{forward:[15,3,1,""]},"claf.model.semantic_parsing.mixin":{WikiSQL:[15,2,1,""]},"claf.model.semantic_parsing.mixin.WikiSQL":{AGG_OPS:[15,4,1,""],COND_OPS:[15,4,1,""],decode_pointer:[15,3,1,""],generate_queries:[15,3,1,""],make_metrics:[15,3,1,""],make_predictions:[15,3,1,""],merge_tokens:[15,3,1,""],predict:[15,3,1,""],print_examples:[15,3,1,""]},"claf.model.semantic_parsing.sqlnet":{AggPredictor:[15,2,1,""],CondsColPredictor:[15,2,1,""],CondsNumPredictor:[15,2,1,""],CondsOpPredictor:[15,2,1,""],CondsPredictor:[15,2,1,""],CondsValuePointer:[15,2,1,""],SQLNet:[15,2,1,""],SelPredictor:[15,2,1,""]},"claf.model.semantic_parsing.sqlnet.AggPredictor":{forward:[15,3,1,""]},"claf.model.semantic_parsing.sqlnet.CondsColPredictor":{forward:[15,3,1,""]},"claf.model.semantic_parsing.sqlnet.CondsNumPredictor":{forward:[15,3,1,""]},"claf.model.semantic_parsing.sqlnet.CondsOpPredictor":{forward:[15,3,1,""]},"claf.model.semantic_parsing.sqlnet.CondsPredictor":{forward:[15,3,1,""]},"claf.model.semantic_parsing.sqlnet.CondsValuePointer":{concat_start_and_end_zero_padding:[15,3,1,""],decode_then_output:[15,3,1,""],forward:[15,3,1,""]},"claf.model.semantic_parsing.sqlnet.SQLNet":{forward:[15,3,1,""]},"claf.model.semantic_parsing.sqlnet.SelPredictor":{forward:[15,3,1,""]},"claf.model.semantic_parsing.utils":{convert_position_to_decoder_input:[15,1,1,""],encode_column:[15,1,1,""],filter_used_column:[15,1,1,""],get_column_lengths:[15,1,1,""]},"claf.model.sequence_classification":{BertForSeqCls:[16,2,1,""],RobertaForSeqCls:[16,2,1,""],StructuredSelfAttention:[16,2,1,""],mixin:[16,0,0,"-"],structured_self_attention:[16,0,0,"-"]},"claf.model.sequence_classification.BertForSeqCls":{forward:[16,3,1,""],print_examples:[16,3,1,""]},"claf.model.sequence_classification.RobertaForSeqCls":{forward:[16,3,1,""],print_examples:[16,3,1,""]},"claf.model.sequence_classification.StructuredSelfAttention":{forward:[16,3,1,""],penalty:[16,3,1,""]},"claf.model.sequence_classification.mixin":{SequenceClassification:[16,2,1,""]},"claf.model.sequence_classification.mixin.SequenceClassification":{make_metrics:[16,3,1,""],make_predictions:[16,3,1,""],predict:[16,3,1,""],print_examples:[16,3,1,""],write_predictions:[16,3,1,""]},"claf.model.sequence_classification.structured_self_attention":{StructuredSelfAttention:[16,2,1,""]},"claf.model.sequence_classification.structured_self_attention.StructuredSelfAttention":{forward:[16,3,1,""],penalty:[16,3,1,""]},"claf.model.token_classification":{BertForTokCls:[17,2,1,""],mixin:[17,0,0,"-"]},"claf.model.token_classification.BertForTokCls":{forward:[17,3,1,""],print_examples:[17,3,1,""]},"claf.model.token_classification.mixin":{TokenClassification:[17,2,1,""]},"claf.model.token_classification.mixin.TokenClassification":{make_metrics:[17,3,1,""],make_predictions:[17,3,1,""],predict:[17,3,1,""],print_examples:[17,3,1,""],write_predictions:[17,3,1,""]},"claf.modules":{activation:[18,0,0,"-"],attention:[19,0,0,"-"],conv:[20,0,0,"-"],encoder:[21,0,0,"-"],functional:[18,0,0,"-"],initializer:[18,0,0,"-"],layer:[22,0,0,"-"]},"claf.modules.activation":{get_activation_fn:[18,1,1,""]},"claf.modules.attention":{BiAttention:[19,2,1,""],BilinearSeqAttn:[19,2,1,""],CoAttention:[19,2,1,""],DocQAAttention:[19,2,1,""],LinearSeqAttn:[19,2,1,""],MultiHeadAttention:[19,2,1,""],SeqAttnMatch:[19,2,1,""],bi_attention:[19,0,0,"-"],co_attention:[19,0,0,"-"],docqa_attention:[19,0,0,"-"],multi_head_attention:[19,0,0,"-"],seq_attention:[19,0,0,"-"]},"claf.modules.attention.BiAttention":{forward:[19,3,1,""]},"claf.modules.attention.BilinearSeqAttn":{forward:[19,3,1,""]},"claf.modules.attention.CoAttention":{forward:[19,3,1,""]},"claf.modules.attention.DocQAAttention":{forward:[19,3,1,""]},"claf.modules.attention.LinearSeqAttn":{forward:[19,3,1,""]},"claf.modules.attention.MultiHeadAttention":{forward:[19,3,1,""]},"claf.modules.attention.SeqAttnMatch":{forward:[19,3,1,""]},"claf.modules.attention.bi_attention":{BiAttention:[19,2,1,""]},"claf.modules.attention.bi_attention.BiAttention":{forward:[19,3,1,""]},"claf.modules.attention.co_attention":{CoAttention:[19,2,1,""]},"claf.modules.attention.co_attention.CoAttention":{forward:[19,3,1,""]},"claf.modules.attention.docqa_attention":{DocQAAttention:[19,2,1,""]},"claf.modules.attention.docqa_attention.DocQAAttention":{forward:[19,3,1,""]},"claf.modules.attention.multi_head_attention":{MultiHeadAttention:[19,2,1,""]},"claf.modules.attention.multi_head_attention.MultiHeadAttention":{forward:[19,3,1,""]},"claf.modules.attention.seq_attention":{BilinearSeqAttn:[19,2,1,""],LinearSeqAttn:[19,2,1,""],SeqAttnMatch:[19,2,1,""]},"claf.modules.attention.seq_attention.BilinearSeqAttn":{forward:[19,3,1,""]},"claf.modules.attention.seq_attention.LinearSeqAttn":{forward:[19,3,1,""]},"claf.modules.attention.seq_attention.SeqAttnMatch":{forward:[19,3,1,""]},"claf.modules.conv":{DepSepConv:[20,2,1,""],PointwiseConv:[20,2,1,""],depthwise_separable_conv:[20,0,0,"-"],pointwise_conv:[20,0,0,"-"]},"claf.modules.conv.DepSepConv":{forward:[20,3,1,""]},"claf.modules.conv.PointwiseConv":{forward:[20,3,1,""]},"claf.modules.conv.depthwise_separable_conv":{DepSepConv:[20,2,1,""]},"claf.modules.conv.depthwise_separable_conv.DepSepConv":{forward:[20,3,1,""]},"claf.modules.conv.pointwise_conv":{PointwiseConv:[20,2,1,""]},"claf.modules.conv.pointwise_conv.PointwiseConv":{forward:[20,3,1,""]},"claf.modules.encoder":{LstmCellWithProjection:[21,2,1,""],PositionalEncoding:[21,2,1,""],lstm_cell_with_projection:[21,0,0,"-"],positional:[21,0,0,"-"]},"claf.modules.encoder.LstmCellWithProjection":{forward:[21,3,1,""],reset_parameters:[21,3,1,""]},"claf.modules.encoder.PositionalEncoding":{forward:[21,3,1,""]},"claf.modules.encoder.lstm_cell_with_projection":{LstmCellWithProjection:[21,2,1,""],block_orthogonal:[21,1,1,""],get_dropout_mask:[21,1,1,""],sort_batch_by_length:[21,1,1,""]},"claf.modules.encoder.lstm_cell_with_projection.LstmCellWithProjection":{forward:[21,3,1,""],reset_parameters:[21,3,1,""]},"claf.modules.encoder.positional":{PositionalEncoding:[21,2,1,""]},"claf.modules.encoder.positional.PositionalEncoding":{forward:[21,3,1,""]},"claf.modules.functional":{add_masked_value:[18,1,1,""],forward_rnn_with_pack:[18,1,1,""],get_mask_from_tokens:[18,1,1,""],get_sorted_seq_config:[18,1,1,""],last_dim_masked_softmax:[18,1,1,""],masked_log_softmax:[18,1,1,""],masked_softmax:[18,1,1,""],masked_zero:[18,1,1,""],weighted_sum:[18,1,1,""]},"claf.modules.initializer":{weight:[18,1,1,""]},"claf.modules.layer":{Highway:[22,2,1,""],PositionwiseFeedForward:[22,2,1,""],ResidualConnection:[22,2,1,""],ScalarMix:[22,2,1,""],highway:[22,0,0,"-"],normalization:[22,0,0,"-"],positionwise:[22,0,0,"-"],residual:[22,0,0,"-"],scalar_mix:[22,0,0,"-"]},"claf.modules.layer.Highway":{forward:[22,3,1,""]},"claf.modules.layer.PositionwiseFeedForward":{forward:[22,3,1,""]},"claf.modules.layer.ResidualConnection":{forward:[22,3,1,""]},"claf.modules.layer.ScalarMix":{forward:[22,3,1,""]},"claf.modules.layer.highway":{Highway:[22,2,1,""]},"claf.modules.layer.highway.Highway":{forward:[22,3,1,""]},"claf.modules.layer.normalization":{LayerNorm:[22,2,1,""]},"claf.modules.layer.normalization.LayerNorm":{forward:[22,3,1,""]},"claf.modules.layer.positionwise":{PositionwiseFeedForward:[22,2,1,""]},"claf.modules.layer.positionwise.PositionwiseFeedForward":{forward:[22,3,1,""]},"claf.modules.layer.residual":{ResidualConnection:[22,2,1,""]},"claf.modules.layer.residual.ResidualConnection":{forward:[22,3,1,""]},"claf.modules.layer.scalar_mix":{ScalarMix:[22,2,1,""]},"claf.modules.layer.scalar_mix.ScalarMix":{forward:[22,3,1,""]},"claf.tokens":{BertTokenMaker:[23,2,1,""],CharTokenMaker:[23,2,1,""],CoveTokenMaker:[23,2,1,""],ElmoTokenMaker:[23,2,1,""],ExactMatchTokenMaker:[23,2,1,""],FeatureTokenMaker:[23,2,1,""],FrequentWordTokenMaker:[23,2,1,""],LinguisticTokenMaker:[23,2,1,""],WordTokenMaker:[23,2,1,""],basic_embedding_fn:[23,1,1,""],cove:[23,0,0,"-"],elmo:[23,0,0,"-"],embedding:[24,0,0,"-"],hangul:[23,0,0,"-"],indexer:[25,0,0,"-"],linguistic:[23,0,0,"-"],text_handler:[23,0,0,"-"],token_embedder:[26,0,0,"-"],token_maker:[23,0,0,"-"],tokenizer:[27,0,0,"-"],vocabulary:[23,0,0,"-"]},"claf.tokens.cove":{MTLSTM:[23,2,1,""]},"claf.tokens.cove.MTLSTM":{forward:[23,3,1,""]},"claf.tokens.elmo":{Elmo:[23,2,1,""],ElmoLstm:[23,2,1,""],add_sentence_boundary_token_ids:[23,1,1,""],remove_sentence_boundaries:[23,1,1,""]},"claf.tokens.elmo.Elmo":{forward:[23,3,1,""],from_params:[23,3,1,""],get_output_dim:[23,3,1,""]},"claf.tokens.elmo.ElmoLstm":{forward:[23,3,1,""],load_weights:[23,3,1,""]},"claf.tokens.embedding":{BertEmbedding:[24,2,1,""],CharEmbedding:[24,2,1,""],CoveEmbedding:[24,2,1,""],ELMoEmbedding:[24,2,1,""],FrequentTuningWordEmbedding:[24,2,1,""],SparseFeature:[24,2,1,""],WordEmbedding:[24,2,1,""],base:[24,0,0,"-"],bert_embedding:[24,0,0,"-"],char_embedding:[24,0,0,"-"],cove_embedding:[24,0,0,"-"],elmo_embedding:[24,0,0,"-"],frequent_word_embedding:[24,0,0,"-"],sparse_feature:[24,0,0,"-"],word_embedding:[24,0,0,"-"]},"claf.tokens.embedding.BertEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""],remove_cls_sep_token:[24,3,1,""]},"claf.tokens.embedding.CharEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.CoveEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.ELMoEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.FrequentTuningWordEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.SparseFeature":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.WordEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.base":{TokenEmbedding:[24,2,1,""]},"claf.tokens.embedding.base.TokenEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""],get_vocab_size:[24,3,1,""]},"claf.tokens.embedding.bert_embedding":{BertEmbedding:[24,2,1,""]},"claf.tokens.embedding.bert_embedding.BertEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""],remove_cls_sep_token:[24,3,1,""]},"claf.tokens.embedding.char_embedding":{CharEmbedding:[24,2,1,""]},"claf.tokens.embedding.char_embedding.CharEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.cove_embedding":{CoveEmbedding:[24,2,1,""]},"claf.tokens.embedding.cove_embedding.CoveEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.elmo_embedding":{ELMoEmbedding:[24,2,1,""]},"claf.tokens.embedding.elmo_embedding.ELMoEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.frequent_word_embedding":{FrequentTuningWordEmbedding:[24,2,1,""]},"claf.tokens.embedding.frequent_word_embedding.FrequentTuningWordEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.sparse_feature":{OneHotEncoding:[24,2,1,""],SparseFeature:[24,2,1,""],SparseToEmbedding:[24,2,1,""]},"claf.tokens.embedding.sparse_feature.OneHotEncoding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.sparse_feature.SparseFeature":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.sparse_feature.SparseToEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.embedding.word_embedding":{WordEmbedding:[24,2,1,""]},"claf.tokens.embedding.word_embedding.WordEmbedding":{forward:[24,3,1,""],get_output_dim:[24,3,1,""]},"claf.tokens.hangul":{NotHangulException:[23,6,1,""],NotLetterException:[23,6,1,""],NotWordException:[23,6,1,""],add_ryul:[23,1,1,""],compose:[23,1,1,""],decompose:[23,1,1,""],has_approximant:[23,1,1,""],has_batchim:[23,1,1,""],has_jongsung:[23,1,1,""],ili:[23,1,1,""],is_all_hangul:[23,1,1,""],is_hangul:[23,1,1,""],josa_eg:[23,1,1,""],josa_el:[23,1,1,""],josa_en:[23,1,1,""],josa_gwa:[23,1,1,""],josa_ida:[23,1,1,""],josa_ro:[23,1,1,""]},"claf.tokens.indexer":{BertIndexer:[25,2,1,""],CharIndexer:[25,2,1,""],ELMoIndexer:[25,2,1,""],ExactMatchIndexer:[25,2,1,""],LinguisticIndexer:[25,2,1,""],WordIndexer:[25,2,1,""],base:[25,0,0,"-"],bert_indexer:[25,0,0,"-"],char_indexer:[25,0,0,"-"],elmo_indexer:[25,0,0,"-"],exact_match_indexer:[25,0,0,"-"],linguistic_indexer:[25,0,0,"-"],word_indexer:[25,0,0,"-"]},"claf.tokens.indexer.BertIndexer":{index:[25,3,1,""]},"claf.tokens.indexer.CharIndexer":{index:[25,3,1,""],index_token:[25,3,1,""]},"claf.tokens.indexer.ELMoIndexer":{BOS_TOKEN:[25,4,1,""],EOS_TOKEN:[25,4,1,""],beginning_of_sentence_character:[25,4,1,""],beginning_of_sentence_characters:[25,4,1,""],beginning_of_word_character:[25,4,1,""],end_of_sentence_character:[25,4,1,""],end_of_sentence_characters:[25,4,1,""],end_of_word_character:[25,4,1,""],index:[25,3,1,""],index_token:[25,3,1,""],max_word_length:[25,4,1,""],padding_character:[25,4,1,""]},"claf.tokens.indexer.ExactMatchIndexer":{index:[25,3,1,""],index_token:[25,3,1,""]},"claf.tokens.indexer.LinguisticIndexer":{index:[25,3,1,""]},"claf.tokens.indexer.WordIndexer":{index:[25,3,1,""]},"claf.tokens.indexer.base":{TokenIndexer:[25,2,1,""]},"claf.tokens.indexer.base.TokenIndexer":{index:[25,3,1,""],set_vocab:[25,3,1,""]},"claf.tokens.indexer.bert_indexer":{BertIndexer:[25,2,1,""]},"claf.tokens.indexer.bert_indexer.BertIndexer":{index:[25,3,1,""]},"claf.tokens.indexer.char_indexer":{CharIndexer:[25,2,1,""]},"claf.tokens.indexer.char_indexer.CharIndexer":{index:[25,3,1,""],index_token:[25,3,1,""]},"claf.tokens.indexer.elmo_indexer":{ELMoIndexer:[25,2,1,""]},"claf.tokens.indexer.elmo_indexer.ELMoIndexer":{BOS_TOKEN:[25,4,1,""],EOS_TOKEN:[25,4,1,""],beginning_of_sentence_character:[25,4,1,""],beginning_of_sentence_characters:[25,4,1,""],beginning_of_word_character:[25,4,1,""],end_of_sentence_character:[25,4,1,""],end_of_sentence_characters:[25,4,1,""],end_of_word_character:[25,4,1,""],index:[25,3,1,""],index_token:[25,3,1,""],max_word_length:[25,4,1,""],padding_character:[25,4,1,""]},"claf.tokens.indexer.exact_match_indexer":{ExactMatchIndexer:[25,2,1,""]},"claf.tokens.indexer.exact_match_indexer.ExactMatchIndexer":{index:[25,3,1,""],index_token:[25,3,1,""]},"claf.tokens.indexer.linguistic_indexer":{LinguisticIndexer:[25,2,1,""]},"claf.tokens.indexer.linguistic_indexer.LinguisticIndexer":{index:[25,3,1,""]},"claf.tokens.indexer.word_indexer":{WordIndexer:[25,2,1,""]},"claf.tokens.indexer.word_indexer.WordIndexer":{index:[25,3,1,""]},"claf.tokens.linguistic":{NER:[23,2,1,""],POSTag:[23,2,1,""]},"claf.tokens.linguistic.NER":{classes:[23,4,1,""]},"claf.tokens.linguistic.POSTag":{classes:[23,4,1,""]},"claf.tokens.text_handler":{TextHandler:[23,2,1,""]},"claf.tokens.text_handler.TextHandler":{build_vocabs:[23,3,1,""],index:[23,3,1,""],is_all_vocab_use_pretrained:[23,3,1,""],make_token_counters:[23,3,1,""],raw_to_tensor_fn:[23,3,1,""]},"claf.tokens.token_embedder":{BasicTokenEmbedder:[26,2,1,""],RCTokenEmbedder:[26,2,1,""],base:[26,0,0,"-"],basic_embedder:[26,0,0,"-"],reading_comprehension_embedder:[26,0,0,"-"]},"claf.tokens.token_embedder.BasicTokenEmbedder":{forward:[26,3,1,""],get_embed_dim:[26,3,1,""]},"claf.tokens.token_embedder.RCTokenEmbedder":{EXCLUSIVE_TOKENS:[26,4,1,""],forward:[26,3,1,""],get_embed_dim:[26,3,1,""]},"claf.tokens.token_embedder.base":{TokenEmbedder:[26,2,1,""]},"claf.tokens.token_embedder.base.TokenEmbedder":{add_embedding_modules:[26,3,1,""],forward:[26,3,1,""],get_embed_dim:[26,3,1,""]},"claf.tokens.token_embedder.basic_embedder":{BasicTokenEmbedder:[26,2,1,""]},"claf.tokens.token_embedder.basic_embedder.BasicTokenEmbedder":{forward:[26,3,1,""],get_embed_dim:[26,3,1,""]},"claf.tokens.token_embedder.reading_comprehension_embedder":{RCTokenEmbedder:[26,2,1,""]},"claf.tokens.token_embedder.reading_comprehension_embedder.RCTokenEmbedder":{EXCLUSIVE_TOKENS:[26,4,1,""],forward:[26,3,1,""],get_embed_dim:[26,3,1,""]},"claf.tokens.token_maker":{TokenMaker:[23,2,1,""]},"claf.tokens.token_maker.TokenMaker":{BERT_TYPE:[23,4,1,""],CHAR_TYPE:[23,4,1,""],COVE_TYPE:[23,4,1,""],ELMO_TYPE:[23,4,1,""],EXACT_MATCH_TYPE:[23,4,1,""],FEATURE_TYPE:[23,4,1,""],FREQUENT_WORD_TYPE:[23,4,1,""],LINGUISTIC_TYPE:[23,4,1,""],WORD_TYPE:[23,4,1,""],embedding_fn:[23,3,1,""],indexer:[23,3,1,""],set_vocab:[23,3,1,""],tokenizer:[23,3,1,""],vocab:[23,3,1,""],vocab_config:[23,3,1,""]},"claf.tokens.tokenizer":{"char":[27,0,0,"-"],BPETokenizer:[27,2,1,""],CharTokenizer:[27,2,1,""],PassText:[27,2,1,""],SentTokenizer:[27,2,1,""],SubwordTokenizer:[27,2,1,""],WordTokenizer:[27,2,1,""],base:[27,0,0,"-"],pass_text:[27,0,0,"-"],sent:[27,0,0,"-"],subword:[27,0,0,"-"],utils:[27,0,0,"-"],word:[27,0,0,"-"]},"claf.tokens.tokenizer.PassText":{tokenize:[27,3,1,""]},"claf.tokens.tokenizer.WordTokenizer":{make_split_regex_expression:[27,3,1,""]},"claf.tokens.tokenizer.base":{Tokenizer:[27,2,1,""]},"claf.tokens.tokenizer.base.Tokenizer":{MAX_TO_KEEP_CACHE:[27,4,1,""],tokenize:[27,3,1,""]},"claf.tokens.tokenizer.char":{CharTokenizer:[27,2,1,""]},"claf.tokens.tokenizer.pass_text":{PassText:[27,2,1,""]},"claf.tokens.tokenizer.pass_text.PassText":{tokenize:[27,3,1,""]},"claf.tokens.tokenizer.sent":{SentTokenizer:[27,2,1,""]},"claf.tokens.tokenizer.subword":{SubwordTokenizer:[27,2,1,""]},"claf.tokens.tokenizer.utils":{create_tokenizer_with_regex:[27,1,1,""],load_spacy_model_for_tokenizer:[27,1,1,""]},"claf.tokens.tokenizer.word":{WordTokenizer:[27,2,1,""]},"claf.tokens.tokenizer.word.WordTokenizer":{make_split_regex_expression:[27,3,1,""]},"claf.tokens.vocabulary":{Vocab:[23,2,1,""],VocabDict:[23,2,1,""]},"claf.tokens.vocabulary.Vocab":{DEFAULT_OOV_INDEX:[23,4,1,""],DEFAULT_OOV_TOKEN:[23,4,1,""],DEFAULT_PAD_INDEX:[23,4,1,""],DEFAULT_PAD_TOKEN:[23,4,1,""],PRETRAINED_ALL:[23,4,1,""],PRETRAINED_INTERSECT:[23,4,1,""],add:[23,3,1,""],build:[23,3,1,""],build_with_pretrained_file:[23,3,1,""],dump:[23,3,1,""],from_texts:[23,3,1,""],get_all_tokens:[23,3,1,""],get_index:[23,3,1,""],get_token:[23,3,1,""],init:[23,3,1,""],load:[23,3,1,""],to_text:[23,3,1,""]},"claf.utils":{flatten:[0,1,1,""],get_user_input:[0,1,1,""],set_logging_config:[0,1,1,""]},claf:{config:[1,0,0,"-"],data:[3,0,0,"-"],decorator:[7,0,0,"-"],learn:[8,0,0,"-"],machine:[9,0,0,"-"],metric:[12,0,0,"-"],model:[13,0,0,"-"],modules:[18,0,0,"-"],tokens:[23,0,0,"-"],utils:[0,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","method","Python method"],"4":["py","attribute","Python attribute"],"5":["py","data","Python data"],"6":["py","exception","Python exception"]},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:method","4":"py:attribute","5":"py:data","6":"py:exception"},terms:{"100d":[29,30],"110m":34,"1x1":20,"200d":29,"2048cnn":29,"2x4096":29,"2xhighwai":29,"300d":[23,29],"340m":34,"42c3f377f441e5a0f431127d63e71414ead291c4":21,"50d":29,"840b":[23,29],"\u0121hello":30,"\u0121world":30,"\u3134":30,"\u3145":30,"\u3147":30,"\u314f":30,"\u3154":30,"\u3155":30,"\u3162":23,"\uac00":23,"\uacfc":23,"\uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4":[28,36],"\ub294":23,"\ub2e4":23,"\ub2f5\ubcc0\uc740":[28,36],"\ub300\ud55c":[28,36],"\ub370\uc774\ud130\uc14b\uc785\ub2c8\ub2e4":[28,36],"\ub3d9\uc77c\ud55c":[28,36],"\ub85c":23,"\ub960":23,"\ub97c":23,"\ub9cc\ub4e0":[28,36],"\ubaa8\ub4e0":[28,36],"\ubb38\ub2e8\uc758":[28,36],"\ubc29\uc2dd\uc73c\ub85c":[28,36],"\uc138\uc0c1":30,"\uc544\ud2f0\ud074":[28,36],"\uc548\ub155":30,"\uc601\uc5ed\uc73c\ub85c":[28,36],"\uc640":23,"\uc704\ud574":[28,36],"\uc728":23,"\uc73c\ub85c":23,"\uc740":23,"\uc744":23,"\uc774":23,"\uc774\ub2e4":23,"\uc774\ub8e8\uc5b4\uc9d1\ub2c8\ub2e4":[28,36],"\uc77c\ubd80":[28,36],"\uc9c8\uc758\uc5d0":[28,36],"\ud558\uc704":[28,36],"\ud55c\uad6d\uc5b4":[28,36],"\ud574\ub2f9":[28,36],"abstract":4,"break":23,"byte":27,"case":[8,21,22,23,25,36],"char":[5,6,14,23,24,25,27,30],"class":[1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,26,27,30],"comprehension\uc744":[28,36],"default":[1,3,8,14,21,22,23,24,25,30],"eu\u3161":23,"final":21,"float":[21,22,23],"function":[7,12,13,14,15,18,19,20,21,22,23,24,25,26,30],"int":[21,22,23],"korquad\ub294":[28,36],"long":23,"new":[23,37],"public":23,"return":[1,3,14,15,16,17,21,23,27],"true":[2,3,8,12,13,14,16,17,19,21,22,23,24,25,27,30],"ui\u3162":23,"while":[3,13,14,15,19,20,21,22,24,26],AND:23,BUT:23,CLS:[3,5,6,23],FOR:23,For:[19,23,30],NOT:[21,23],One:24,POS:[23,25,30],STS:[5,28,34],THE:23,The:[19,21,22,23,24,28,30,34],USE:23,Used:[14,15],WITH:23,_bert:34,_bert_bas:[],_elmobilm:23,_encoderbas:23,_modul:8,_roberta:34,_roberta_bas:[],_uncas:39,a_gold:12,a_ij:[14,26],a_pr:12,abov:23,abs:[5,14,15,16,17,19,20,21,22,23,24],accord:[2,3,8,18,23,24],account:23,accuraci:[5,14,15,16,17,34],across:23,action:[23,27],activ:[18,22,23,24,30],adam:33,add:[1,14,23,25,26],add_embedding_modul:26,add_masked_valu:18,add_ryul:23,add_sentence_boundary_token_id:23,addit:[12,22,23,24],addition:23,adj:23,adp:23,adv:23,after:[21,23],afterward:[13,14,15,19,20,21,22,24,26],agg:[15,38],agg_count:15,agg_op:15,aggpredictor:15,aggreg:[15,38],alexand:33,ali:33,align:[14,26],aligned_query_embed:14,all:[2,8,13,14,15,19,20,21,22,23,24,26,30],all_tokenizer_config:2,allenai:[18,21,22,23,25],allennlp:[18,21,22,23,25,30,33],allow:[3,21],along:[21,28],alpha_j:19,also:[3,12,23],although:[13,14,15,19,20,21,22,24,26],amount:[3,27],analyz:[28,34],anci:30,ani:[22,23],aniruddha:33,annot:23,answer:[9,14,15,19,28,33,35,36,37],answer_idx:[],answer_maxlen:14,antoin:33,anyon:30,anyth:23,api:[21,23],append:[23,25],appendix:31,appli:[3,9,14,21,22,23,24,26,27],applic:[21,23],apply_no_ans_threshold:12,apply_pad:3,apply_pad_label:3,apply_pad_valu:3,approach:28,approxim:23,aren:23,arg:[1,2,3,4,5,6,8,9,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],arg_str2bool:1,argmax:14,argpars:1,argument:[1,2,7,8,14,16,23],arguments_requir:7,argv:1,aris:23,articl:[12,28,37],arxiv:[5,14,15,16,17,19,20,21,22,23,24],assign:[3,23],associ:23,assum:23,ataset:28,attent:[0,14,15,16,18,21,26,28,33],attention_dim:16,attribut:[1,23],author:23,automag:23,aux:23,averag:[8,22,30],avg:15,avoid:27,b142a7f2:29,backward:[21,23],balanc:15,base:[1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,26,27,34,36,37],base_config:1,baseconfig:[30,34,35,36,37,38,39],basic:[12,26],basic_embedd:26,basic_embedding_fn:23,basictokenembedd:26,batch:[3,4,5,14,15,16,17,21,23,24],batch_length:21,batch_siz:[2,5,21,22,23],becaus:21,been:23,befor:[22,24],begin:23,beginning_of_sentence_charact:25,beginning_of_word_charact:25,being:21,below:[14,16,17,23],benchmark:[5,28,34],bert:[0,3,4,5,14,16,17,23,24,25,28,33,34,36,37,39],bert_bas:[27,30,39],bert_base_glu:34,bert_base_multilingual_cas:36,bert_base_multilingual_uncas:36,bert_base_uncas:37,bert_embed:24,bert_index:25,bert_input:[3,16,17],bert_input_maxlen:4,bert_input_text:3,bert_large_glu:34,bert_large_uncas:37,bert_token:3,bert_typ:23,bertembed:24,bertforqa:14,bertforseqcl:16,bertfortokcl:17,bertindex:25,berttokenmak:23,best:14,best_exact:14,best_exact_thresh:14,best_f1:14,best_f1_thresh:14,best_span:14,between:[14,23,26],bi_attent:19,bia:14,bias_hidden_dim:14,biattent:19,bidaf:[7,14,19,28,35,36,37,39],bidaf_no_answ:[14,37],bidirect:[14,16,17,23,24,28,33],bigger:23,bilinear:19,bilinearseqattn:19,bilm:23,bilstm:23,bin:8,binari:[21,23,30],bind_nsml:8,birect:28,blob:[19,20,21,22,23,25],block:[14,21],block_orthogon:21,bojanowski:33,bool:[19,21,22,23],bord:33,bos:23,bos_token:25,both:23,both_exist:8,bound:15,boundari:23,bpe:30,bpetoken:27,bpte:27,bradburi:33,broadcast:23,build:[8,23],build_vocab:23,build_with_pretrained_fil:23,built:18,c2q:19,cach:23,cache_nam:27,cache_path:3,cache_token_count:3,cachepath:3,caim:33,calcul:[14,16,17],call:[2,13,14,15,19,20,21,22,23,24,26],can:[21,23,24,30],cannot:[21,27],captur:[14,26],car:[14,26],cardin:23,care:[13,14,15,19,20,21,22,24,26],carri:23,categori:[0,30],cconj:23,cell:[14,19,21,23],cell_siz:[21,23],chang:33,char_embed:24,char_index:25,char_typ:23,charact:[23,24,25,27,30],charcnn:[23,24,30],charembed:[23,24],charg:23,charindex:[23,25],chartoken:[23,25,27,30],chartokenmak:23,check:[3,7,19,23],checkpoint:8,checkpoint_dir:8,chen:33,child:2,cho:23,choos:15,chosung:23,christoph:33,chunk:21,claf:34,claf_cach:3,claim:23,clark:33,class_data:[5,6],class_idx2text:16,class_idx:[16,17],class_index:4,class_kei:[5,6],class_text:16,classif:[4,5,6,12,16,17,23,33],classifi:[16,17],classmethod:[9,23],claus:38,clip:[8,21,23],clova:31,cls_token:[3,5,6,23],cls_util:13,cnn:24,co_attent:19,coattent:19,code:[5,6,14,18,19,21,22,23,25,30],coeffici:16,col_idx:15,cola:[5,28,34],cola_bert:34,cola_bert_bas:[],cola_roberta:34,cola_roberta_bas:[],colabertread:5,colaread:5,collat:[3,4],collate_fn:4,collect:[23,28,34],column:[5,15,38],column_attent:15,column_emb:15,column_mask:15,column_maxlen:15,column_name_mask:15,com:[18,19,20,21,22,23,25],combin:[9,14,28,30,33],common:[8,27],common_attent:21,common_set:8,compat:[4,25],complex:23,compon:[0,9],compos:23,composition:29,comprehens:[9,14,26,31,33,37],comput:[12,13,14,15,19,20,21,22,23,24,26],compute_exact:12,compute_f1:12,concat_start_and_end_zero_pad:15,concaten:[21,23,26,30],concern:28,concret:[2,5],cond:[15,38],cond_op:15,cond_value_logit:15,condit:[15,23],conds_column_loss_alpha:15,conds_op_count:15,conds_val_po:15,condscolpredictor:15,condsnumpredictor:15,condsoppredictor:15,condspredictor:15,condsvaluepoint:15,config:[0,5,6,8,9,13,23,24,27,30,31,32],config_dict:5,config_path:9,confus:[16,17],conj:23,conll2003:[5,6],conll2003bertread:[5,6],conll:28,connect:[21,23],consid:14,consist:[3,5,14,15,16,17,21,23,25,28,30,37],constrain:14,constraint:29,constructor:2,contain:[21,23,28],content:[28,31,32],context:[5,6,9,14,15,19,26],context_emb:[14,19,26],context_mask:[14,19],context_max_length:5,context_maxlen:4,context_param:26,context_strid:[5,6],contextu:[14,23,24,29,33],contextual_rnn_num_lay:14,continu:23,contract:[23,27],contradict:5,control:8,conv:[0,14,18],convert:[3,8,16,23],convert_cache_path:3,convert_config2dict:1,convert_position_to_decoder_input:15,convert_to_dataset:5,convolut:[14,20,23,28,30,33],copi:23,copyright:23,corpu:23,corr:34,correct:[21,23],correspond:[3,28,37],cos:21,count:[8,15,23,24],count_lin:12,counter:[8,23,29],cove:[23,24,29,30],cove_embed:24,cove_typ:23,coveembed:[23,24],covetokenmak:23,cpu:[3,39],creat:[1,2,8,10,11],create_token_embedd:2,create_tokenizer_with_regex:27,creation:2,crowd:[28,38],crowdwork:[28,37],cuda:[3,21],cuda_devic:23,cuda_device_id:[2,3,4,8],cudnn:21,current:23,curv:12,custom:[21,26],d_a:16,damag:23,danqi:33,dasigi:33,data:[0,1,8,14,15,16,17,23,25,31,32],data_handl:3,data_id:4,data_idx:[4,14,16,17],data_index:4,data_load:[2,8],data_read:[2,3,4,5,23],data_reader_config:3,data_typ:[3,5],data_uid:12,databas:[28,38],datahandl:3,dataload:[2,8],dataloaderfactori:2,dataread:[2,5,6,8],datareaderfactori:2,dataserv:29,dataset:[0,2,3,5,8,12,13,14,23,31,33,35,36,37,38],dataset_obj:5,datasetbas:4,date:23,david:33,dawn:33,db_path:[5,7,12],deal:[2,23],decai:8,decode_point:15,decode_then_output:15,decoder_hidden:15,decoder_input:15,decompos:23,decompose_ko:27,decor:[0,32],decreas:21,deep:[14,16,17,20,22,23,24,28,29,33],default_oov_index:23,default_oov_token:23,default_pad_index:23,default_pad_token:23,defaultdict:23,defin:[5,6,8,13,14,15,19,20,21,22,23,24,26,30],delete_unselect:1,deng:33,dep:25,depend:[23,25,30],depsepconv:20,depth:[14,22],depthwis:[14,20],depthwise_separable_conv:20,deriv:2,descript:30,design:[1,23,30],det:23,detail:[23,24,38],detector:[14,35,36,37],dev:[5,6,35,36,37],develop:[28,38],devic:3,devlin:33,dict:[14,16,17,23],dict_data:1,dictionari:[3,5,12,14,15,16,17,23,26],differ:[23,27],dim:[3,22,23],dim_0:22,dim_:22,dim_n:22,dimems:19,dimens:[3,14,15,16,19,20,21,22,23,24],dir_path:[10,11],direct:[21,23],directori:[8,39],display_unit:8,distribut:[23,29],dnn:34,do_layer_norm:[22,23,24],do_token:25,doc:8,docqa:[14,28,35,36,37,39],docqa_attent:19,docqa_no_answ:[14,37],docqaattent:19,document:[10,11,14,23],documentqa:19,doe:[23,27],dohan:33,domain:[9,14,28,33],don:[19,33],done:[2,27],dongjun:3,drop:21,dropout:[14,15,16,17,19,21,22,23,24,30],dropout_prob:21,drqa:[9,14,19,28,37,39],dto:4,due:[21,27],dump:[3,23],dynam:[19,23],each:[5,14,19,21,22,23,26,30,37],eafc28abdfadfa0732f03a0fc65805c5bfb2ffe7:20,earli:8,early_stopping_threshold:8,effect:[14,28,33],effici:[21,23],either:[2,23,30],elapsed_tim:8,element:[19,21,23],elmo:[23,24,25,29,30,37,39],elmo_2x4096_512_2048cnn_2xhighway_opt:24,elmo_2x4096_512_2048cnn_2xhighway_weight:24,elmo_embed:24,elmo_index:25,elmo_represent:23,elmo_typ:23,elmoembed:[23,24],elmoindex:25,elmolstm:23,elmotokenmak:23,ema:8,emb:[14,15,16,17],embed:[0,14,16,17,19,21,23,26,28,30],embed_dim:[14,15,19,21,24,30],embed_typ:24,embedd:26,embedded_valu:30,embedding_config:23,embedding_dim:23,embedding_fn:23,embedding_summari:8,encod:[0,3,14,18,19,23,24,27],encode_column:15,encoded_column:15,encoded_quest:15,encoded_used_column:15,encoderblock:14,encoding_rnn_dropout:16,encoding_rnn_hidden_dim:16,encoding_rnn_num_lay:16,encount:24,end:[4,14,23,25],end_acc:14,end_logit:14,end_of_sentence_charact:25,end_of_word_charact:25,end_token:[23,25,30],eng:2,english:30,enrich:[29,33],ensur:21,entail:5,entiti:[23,25,28],eos:23,eos_token:25,epoch:8,eps:22,eql:15,equal:14,estion:28,eval:8,eval_and_save_step_count:8,evalu:[1,8,12,13,14,15,16,17,23,28,34],evaluate_inference_lat:8,event:23,everi:[8,13,14,15,19,20,21,22,23,24,26,28],exact:[2,23,25],exact_match:[14,23,26,30],exact_match_index:25,exact_match_scor:12,exact_match_typ:23,exact_raw:12,exact_scor:12,exactli:[23,30],exactmatchindex:25,exactmatchtokenmak:23,exampl:[3,8,13,14,15,16,17,23,30,39],except:[1,23],except_kei:26,exclusive_token:26,execut:38,exist:[25,39],expect:[12,21,22,23,30],expend:23,experi:[8,9],exponenti:8,exponential_moving_averag:[2,8],express:[21,23],extra:[12,27],extract:24,f1_raw:12,f1_score:12,f_align:[14,26],fac:23,facebookresearch:19,factori:[0,1],fals:[1,3,5,6,8,14,19,21,22,23,24,25,26,30],farhadi:33,faster:20,fasttext:29,featlabelpadcol:3,featru:30,featur:[3,4,8,13,14,15,16,17,18,22,23,24,25,26,30],feature_count:24,feature_name1:14,feature_name2:14,feature_typ:23,featuretokenmak:23,feed:[14,22],feedforward:14,figur:19,file:[5,6,12,23,24],file_path:[3,5,6,13,14,16,17],filter:[20,24],filter_text:5,filter_used_column:15,final_st:21,find_all_best_thresh:12,find_best_thresh:12,fine:[23,30,34],finetun:[23,24],first:[21,25],fisch:33,fit:[23,29],fix:[21,23,24,30],flag:[3,8,9],flatten:[0,27],floattensor:21,flow:[14,19,28,33],fname:12,focu:39,focus:8,follow:23,form:[23,27,30,38],format:[3,23],former:[13,14,15,19,20,21,22,24,26],forward:[13,14,15,16,17,19,20,21,22,23,24,26],forward_rnn_with_pack:18,framework:[31,33],free:23,frequenc:[10,11,24],frequent:[23,24,30],frequent_count:23,frequent_tun:24,frequent_word:[23,30],frequent_word_embed:24,frequent_word_typ:23,frequenttuningwordembed:[23,24],frequentwordtokenmak:23,frobeniu:16,from:[2,3,4,8,10,11,14,15,18,19,21,22,23,24,25,28,30,33,37],from_http:3,from_param:23,from_path:3,from_text:23,fune:34,furnish:23,gain:21,gamma:22,gardner:33,gate:21,gener:[1,15,28,30,33,34],generate_queri:15,get:[1,2,14,16,23,24],get_activation_fn:18,get_all_token:23,get_bert_token:4,get_best_span:14,get_class_text_with_idx:4,get_closest:[10,11],get_coditions_value_posit:5,get_column_length:15,get_context:4,get_displai:8,get_dropout_mask:21,get_embed_dim:26,get_ground_truth:4,get_id:4,get_index:23,get_input_argu:1,get_is_head_of_word:3,get_mask_from_token:18,get_output_dim:[23,24],get_predict:4,get_qid:4,get_qid_index:4,get_raw_scor:12,get_sequence_a:3,get_session_nam:8,get_sorted_path:8,get_sorted_seq_config:18,get_table_id:4,get_tag_dict:13,get_tag_text_with_idx:4,get_tag_texts_with_idx:4,get_text_span:4,get_text_with_index:4,get_token:[12,23],get_token_dim:3,get_token_typ:3,get_tokenized_quest:4,get_user_input:0,get_vocab_s:24,github:[18,19,20,21,22,23,25],given:[19,21,23,24,27],global:[14,28,29,33],global_step:8,glove:[23,24,29,30],glove_pretrained_path:24,glue:[4,28,31],go_forward:21,googlenew:29,gpe:23,gpu:39,grad_max_norm:8,gradient:[8,23,24],gradient_accumulation_step:8,gram:24,grant:23,graph_summari:8,grave:33,ground:[5,6,21,23],ground_truth:12,gru:[19,23,33],guillaum:33,hajishirzi:33,handl:23,handler:23,hangul:23,hangul_lett:23,hangulpi:23,hannaneh:33,has:[3,14,21,23,30],has_approxim:23,has_batchim:23,has_jongsung:23,hasans_exact:14,hasans_f1:14,have:[2,5,6,23,24],haven:27,hdf5:[23,24,29],head:[3,14,16,19,34],hello:[3,23,30],help:[14,21],helper:[4,5,14,16,23],here:25,herebi:23,hidden:[16,19,21,22,23,34],hidden_s:[14,21,22,23],hidden_st:[21,23],higher:30,highlight:15,highwai:[22,23],histogram:8,histogram_na_prob:12,histogram_summari:8,histori:[28,35],historyqa:[28,31],hold:1,holder:23,hook:[13,14,15,19,20,21,22,24,26],hot:24,how:[3,23,27],howev:21,html:8,http:[5,8,14,15,16,17,18,19,20,21,22,23,24,25],huggingfac:20,hyperparamet:1,hyunwoo:23,ident:[14,19,26],idf:[10,11],ids:[23,25],idx:[5,6,16,17],ignor:[5,6,13,14,15,17,19,20,21,22,23,24,26],ignore_tag_idx:[5,6,17],ili:23,imag:[8,22],image_dir:12,image_summari:8,implement:[2,14,15,16,17,21,23],impli:23,includ:[2,23,25],independ:[14,21,23,28],index:[0,4,8,10,11,14,15,16,17,23,24,26,30,31],index_fnam:[10,11],index_select:21,index_to_token:23,index_token:25,indexed_featur:23,indexer_config:23,indic:[21,23,30],individu:[25,26],infer:[8,13,14,16,17,39],infer_ev:8,inferec:8,inference_lat:8,inform:[29,33],init:[10,11,23],init_iter:4,init_model:[10,11],initi:[18,19,21,23,24],initial_scalar_paramet:22,initial_st:21,input:[1,3,5,6,13,14,15,16,17,19,20,21,22,23,24,26,30],input_argu:1,input_argv:1,input_s:[19,20,21,22,23],input_to_model:8,input_typ:[3,5,6],insert:25,insert_char_end:[25,30],insert_char_start:[25,30],insert_end:25,insert_start:25,instanc:[13,14,15,19,20,21,22,24,26],instanti:1,instead:[13,14,15,19,20,21,22,23,24,26],intent_classif:9,interact:8,interfac:[2,28,38],intern:23,intersect:23,intj:23,invers:[10,11,23,24],iob:3,irregular:23,is_all_hangul:23,is_all_vocab_use_pretrain:23,is_dict:[13,14,16,17],is_hangul:23,is_head_of_word:3,is_lazi:3,is_readi:13,is_test:[1,5,6],iter:[2,8],its:[3,23,30],itself:14,iyyer:33,jacob:33,jamo_ko:30,jason:33,jean:33,jia:33,jian:33,joel:33,jongsung:23,joongsung:23,josa:23,josa_eg:23,josa_el:23,josa_en:23,josa_gwa:23,josa_ida:23,josa_ro:23,joseon:[28,35],joulin:33,json:[5,6,12,23,24,34,35,36,37,38,39],just:[23,30],kai:33,kei:[5,6,14,15,16,17,19,23],kembhavi:33,kenton:33,kernel:[14,20,24],kernel_s:[14,20,24,30],kernel_size_in_embed:14,kernel_size_in_model:14,key_mask:19,kim:33,kind:23,klein:33,know:33,knowledge_bas:9,konstantin:33,kor:2,korean:[23,30],korquad:[28,31],kristina:33,kwarg:[1,3,4,5,6,8,10,11,14,15,16,17,19,21,22,23,24,25,26,27],l388:21,l45:20,label:[3,4,5,6,12,14,15,16,17],label_img:8,label_kei:5,label_name1:14,label_name2:14,lang:2,lang_cod:[5,6,14],languag:[5,6,9,14,15,16,17,23,24,28,30,31,33,34,38],larg:[28,34,37,38],last_dim_masked_softmax:18,latenc:[8,39],latter:[13,14,15,19,20,21,22,24,26],law:23,layer:[0,14,15,16,17,18,19,21,23,24,34],layer_dropout:[14,22],layernorm:[14,22],lazi:23,lazy_evalu:4,lazy_index:23,learn:[0,15,20,22,23,24,28,29,31,32,33],learning_rate_schedul:[2,8],least:22,lee:33,lemma:[23,25,30],lenght:23,length:[3,14,21,23],less:14,lesser:24,letter:23,level:[17,23,30],liabil:23,liabl:23,liang:33,like:[14,16,17,30],limit:23,linear:[14,19,21,24],linear_dim:[14,19],linear_key_dim:19,linear_value_dim:19,linearseqattn:19,linguist:[23,25,29,30],linguistic_index:25,linguistic_typ:23,linguisticindex:25,linguistictokenmak:23,list:[3,8,21,22,23,24,27,29,30],list_of_dict:3,liu:33,llo:[3,23],load:[3,8,9,10,11,23],load_data:5,load_from_config:9,load_from_json:1,load_model_checkpoint:8,load_optimizer_checkpoint:8,load_set:8,load_spacy_model_for_token:27,load_vocab:8,load_weight:23,loc:23,local:[14,28,33],locat:28,log:[8,10,11,14,16,17],log_dir:[8,13],logger:8,logic:38,logit:[14,16],longtensor:[21,23],look:[24,26],lopyrev:33,loss:[14,16,17],lower:[12,25],lowercas:[23,25,30],lr_schedul:8,lstm:[21,23],lstm_cell_with_project:[21,23],lstmcellwithproject:[21,23],luke:33,luong:33,machin:[0,1,3,8,14,23,24,28,30,32,33,36],machine_config:9,machine_read:9,macro:[16,17],macro_f1:[12,16,17],macro_precis:[12,16,17],macro_recal:[12,16,17],magnitud:[21,23],main:12,main_ev:12,maintain:[8,23],make:[3,9,14,16,17,21,23,27],make_all_token:2,make_batch:3,make_bert_input:3,make_bert_token_typ:3,make_data_load:2,make_data_read:5,make_eval_dict:12,make_metr:[13,14,15,16,17],make_modul:9,make_precision_recall_ev:12,make_predict:[13,14,15,16,17],make_qid_to_has_an:12,make_split_regex_express:27,make_task_by_read:5,make_token:2,make_token_count:23,maker:23,mani:[21,23],map:[12,14,15,25],mark:[23,33],marker:23,mask:[14,15,18,19,21,22,23],masked_log_softmax:18,masked_softmax:18,masked_zero:18,master:[19,21,22,23,25],match:[19,21,23,25,30],matrix:[16,17,18,19,23,24],matt:33,matthew:[33,34],matthews_corr:5,max:[14,15],max_eval_exampl:8,max_lat:8,max_len:[3,21],max_length:21,max_norm:24,max_question_length:[5,6],max_seq_length:[3,5,6],max_timestep:21,max_to_keep:8,max_to_keep_cach:27,max_vocab_s:[23,30],max_word_length:25,maximum:21,maximun:[8,23],maxpool:30,mccann:[23,29,33],mean:[16,17],mecab:[5,6],mecab_ko:[27,30],mechan:[14,15],memori:[21,23],memory_cell_clip_valu:[21,23],merchant:23,merg:23,merge_ev:12,merge_token:15,messag:8,meta:1,metadata:8,method:[2,23],metric:[0,8,13,14,16,17,31,32,34,39],metric_fn:12,metric_kei:[5,6,8],metric_max_over_ground_truth:12,michael:33,might:28,mikolov:33,min:15,min_count:23,ming:33,minh:33,mini:[3,14,15,16,17,24],minim:[3,23],minjoon:33,mixin:[14,15,16,17],mixtur:22,mixture_s:22,mlp:14,mnli:[5,28,34],mnlibertread:5,mode:[0,1,8,14,16,17],model:[0,1,2,4,5,6,7,8,10,11,12,19,21,23,24,25,30,31,32,33,34,35,36,37,38,39],model_checkpoint:8,model_dim:[14,15,19],model_nam:2,model_pretrained_path:24,model_pytorch:20,modelbas:[13,16,17],modelfactori:2,modeling_rnn_num_lay:14,modelwithouttokenembedd:[13,14,16,17],modelwithtokenembedd:[13,14,15,16],modifi:[23,24],modul:[30,31,32],mohammad:33,mohit:33,monei:23,more:24,most:[14,23,30],move:8,mrpc:[5,28,34],mrpc_bert:34,mrpc_bert_bas:[],mrpc_roberta:34,mrpc_roberta_bas:[],mrpcbertread:5,msgpack:3,mtlstm:23,much:27,multi:[4,5,14,19,33],multi_head_attent:19,multi_task:34,multiheadattent:19,multilingu:36,multipl:21,multitaskbertdataset:4,multitaskbertread:5,must:[8,22,23],na_prob:12,na_prob_thresh:12,naiv:3,naive_token:3,name:[1,5,6,7,12,14,15,16,17,18,23,25,27,28,30],namespac:[1,9],nativ:21,natur:[9,15,21,28,33,34,38],nbest:14,ndim:21,need:[3,8,13,14,15,19,20,21,22,23,24,26,30],neg:15,negative300:29,nelson:33,ner:[23,25,28,30],nest:1,nestednamespac:[1,8,9],network:[14,15,19,21,22,23,28,33],neumann:33,neural:[21,23,24,28,30,33],neutral:5,new_ev:12,new_mask:23,ngram:[10,11],nguyen:33,nip:24,nl2sql:[15,38],nli:5,nlp:[9,27],nltk_en:30,nlu:9,nmt:30,no_answ:14,no_asnw:14,noans_exact:14,noans_f1:14,noanswer:14,non:[14,23,26],none:[1,2,3,4,5,6,8,12,13,14,15,16,17,19,20,21,22,23,24,25],noninfring:23,norm:[8,16,24],norm_typ:24,normal:[19,22,23,24],normalize_answ:12,normalized_shap:22,norouzi:33,norp:23,not_entail:5,note:[8,21,23,24,30,35,36,37,39],nothangulexcept:23,notic:[23,27],notletterexcept:23,notwordexcept:23,noun:23,now:14,nsml_for_intern:1,nswere:28,num:23,num_attention_head:16,num_class:[4,16],num_conv_block:14,num_conv_block_in_embed:14,num_conv_block_in_model:14,num_embedding_encoder_block:14,num_encoder_block:14,num_epoch:8,num_filt:[20,24,30],num_head:[14,19],num_head_in_embed:14,num_head_in_model:14,num_lay:[22,23],num_modeling_encoder_block:14,num_output_represent:23,num_tag:[4,17],num_timestep:21,num_true_po:12,number:[5,6,8,10,11,14,15,16,17,19,20,21,22,23,24],o_i:19,obj:[1,3],object:[1,2,3,5,6,7,8,9,10,11,14,15,16,17,23,25,27],obtain:23,occur:23,offici:[12,14,15,34,37],onc:23,one:[1,13,14,15,19,20,21,22,23,24,26,30],one_hot:24,onehotencod:24,ones:23,onli:[1,3,14,23,26,30],ontonot:23,oov_token:23,oov_valu:23,op_count:15,op_dict:8,open:[9,14,28,33],open_qa:9,openai:20,opennmt:33,openqa:9,oper:[18,30],optim:[2,8,16,17,21,28],optimis:14,optimize_config:1,optimizerfactori:2,option:[2,8,14,19,21,23,24,29],options_fil:[23,24],order:[12,21],ordin:23,org:[5,8,14,15,16,17,19,20,21,22,23,24],organ:28,orienti:39,origin:[14,19,21,23,30],original_tensor:21,orthogon:21,other:[8,23,27,30,33],otherwis:[3,23],our:28,out:[21,23],out_imag:12,out_image_dir:12,output:[14,16,17,19,21,23,24,26],output_accumul:21,output_dict:[14,15,16,17],over:[19,21],overal:8,overrid:[16,17],overridden:[2,13,14,15,19,20,21,22,24,26],overwrit:1,own:23,oyvind:33,p_i:[14,23,26,30],packag:[31,32],pad:[3,17,23,24],pad_index:18,pad_token:23,pad_valu:3,padcol:3,padding_charact:25,padding_count:15,padding_idx:24,padding_token:3,pair:[5,6,27],paper:[16,19,23,24,38],paragraph:[14,28,33],param:[2,13,23,24,26],paramet:[8,14,21,22,23,24,26,34],parameteris:22,parent_token:2,pars:[10,11,15,23,38],parse_arg:[1,12],parser:[1,25,30],part:23,particl:23,particular:[21,23,27],pass:[13,14,15,19,20,21,22,23,24,26,27,30],pass_text:27,passag:[14,28,37],passtext:27,past:21,path:[3,5,6,8,23,24,30],pattern:[1,2],pdf:[19,24],pearson:34,pearson_spearman_corr:5,penalization_coeffici:16,penalti:16,per:21,percent:23,perci:33,perform:[13,14,15,19,20,21,22,24,26],permiss:23,permit:23,permuation_index:21,person:[23,28],peter:[23,33],phrase:[23,28,29],pickl:3,pipelin:8,pkl:3,place:24,platform:33,plot:12,plot_pr_curv:12,point:8,pointer:15,pointwis:[14,20,22],pointwise_conv:20,pointwiseconv:20,portion:23,pos:23,pos_tag:25,pose:[28,37],posit:[3,14,15,21],position_encod:14,positionalencod:21,positionwis:22,positionwisefeedforward:22,posixpath:3,possibl:21,post:27,postag:23,pradeep:33,pranav:33,pre:[8,14,16,17,23,24,28,30,33],precis:[12,16,17],pred:12,pred_span_end:14,pred_span_start:14,predefine_vocab:23,predict:[1,5,6,7,8,12,13,14,15,16,17],predict_rnn_num_lay:14,predict_text:14,predict_valu:8,prefix:[3,12],preload:8,prepend:23,preprocess:14,preprocess_rnn_num_lay:14,present:[14,15,16,17],pretrain:[23,24,28,30,31],pretrained_al:23,pretrained_intersect:23,pretrained_model_nam:[14,16,17,24],pretrained_path:[23,24,30],pretrained_token:23,pretrained_vector:3,pretty_json_dump:1,previous:25,print:[8,13,14,15,16,17],print_exampl:[13,14,15,16,17],probabl:[12,14,16,17,21,22,23,24],problem:2,process:[8,30,33],produc:3,product:23,program:2,project:[21,23,24],project_dim:24,pron:23,properti:[4,13,23,25],propn:23,provid:[12,23],pth:29,publish:23,punct:23,punctuat:[12,23],puncut:27,punkt:[27,30],purpos:23,pycm_obj:[12,13,16,17],pytorch:[8,18,20,21],q2c:19,q_j:[14,26],qanet:[14,28,33,37,39],qatokenembedd:14,qid_list:12,qid_to_has_an:12,qnli:[5,28,34],qnli_bert:34,qnli_bert_bas:[],qnli_roberta:34,qnli_roberta_bas:[],qnlibertread:5,qqp:[28,34],qqp_bert:34,qqp_bert_bas:[],qqp_roberta:34,qqp_roberta_bas:[],qqpbertread:5,quantiti:[23,28],queri:[10,11,14,15,19,26,28,33],query_align:26,query_mask:19,query_param:26,query_text:25,query_token:25,question:[5,6,9,12,14,15,19,23,26,28,30,33,35,36,37],question_emb:[15,19],question_mask:[15,19],question_maxlen:4,quoc:33,quora:5,quotat:27,rajpurkar:33,rate:8,rather:2,raw_data:8,raw_exampl:8,raw_featur:[8,14,16,23],raw_to_tensor_fn:[8,23],raw_tok_str:15,rctokenembedd:[14,26],read:[3,5,8,9,14,26,31,33,36,37],read_embed:3,read_one_exampl:[5,6],reader:[0,2,3,7,14,19],reader_nam:2,reading_comprehens:[0,13],reading_comprehension_embedd:26,readingcomprehens:14,realli:27,recal:[12,16,17],recip:[13,14,15,19,20,21,22,24,26],recogn:5,recognit:[22,23,25,28],recurr:[14,15,21,23],recurrent_dropout_prob:[21,23],refer:31,regard:24,regist:[2,7,13,14,15,19,20,21,22,24,26],registri:[1,2],regress:[4,5],regressionbertdataset:4,regressionbertread:5,reinforc:[15,28,33],rel:21,relat:[28,38],relationship:23,releas:28,relu:[22,24,30],remain:23,remov:[12,23],remove_cls_sep_token:24,remove_non:1,remove_sentence_boundari:23,renorm:24,repeat:14,replace_masked_valu:18,report:[31,39],repres:[4,14,16,17,21,23,30],represent:[23,24,29,33],requir:[7,21,22,23],required_field:7,requires_grad:23,reset_paramet:21,residu:[14,22],residual_embed:23,residualconnect:22,resiz:23,resourc:[2,28,34],respect:[21,23],respons:30,restoration_indic:21,restrict:[1,23],result:[5,6,10,11,14,16,21],retain:21,retriev:[0,9,10],return_path:3,rho:23,richard:33,right:23,rnn:[14,15,16,21,23],rnn_dim:[14,19],rnn_modul:[15,18],rnn_num_lay:15,roberta:[27,28,30,34,37],roberta_bas:37,roberta_larg:37,robertaforqa:14,robertaforseqcl:16,robin:33,robustli:28,root:3,rqa:24,rte:[5,28,34],rte_bert:34,rte_bert_bas:[],rte_roberta:34,rte_roberta_bas:[],rtebertread:5,rui:33,run:[8,13,14,15,19,20,21,22,23,24,26],run_precision_recall_analysi:12,rush:33,ryan:23,s_k:22,salesforc:[23,30],same:[3,14,21,22,23],sampl:39,sanity_check_iob:3,save:[8,10,11],save_checkpoint:8,save_param:8,scalar:[8,14,16,17,22,23],scalar_mix:22,scalar_summari:8,scalarmix:[22,23,24],scale:[21,24],scale_grad_by_freq:24,schedul:8,scheme:[21,23],schmitz:33,sconj:23,score:[5,8,12,14,26],score_:14,script:12,search_docu:9,second:21,section:23,see:[23,24,27],seed:1,segment:[28,37],segment_id:3,sel:[15,38],select:[23,38],select_column:15,self:[14,16,19,28,33],self_attn:19,selfattent:14,sell:23,selpredictor:15,semant:[5,15,33,38],semantic_pars:[0,13],send_message_to_slack:8,senellart:33,sent:[27,30],sent_token:[27,30],sentenc:[16,17,23,27,28,30,33],sentence_begin_token:23,sentence_end_token:23,senttoken:[27,30],seo:33,sep:[3,5,6,23],sep_token:[3,5,6,23],separ:[14,20,21,23],seper:26,seq2sql:[28,33],seq_attent:19,seq_cl:[4,5,6],seq_config:18,seqattnmatch:19,seqclsbertdataset:4,seqclsbertread:[5,6],seqclsdataset:4,seqclsread:5,sequenc:[4,5,6,13,16,17,19,21,23,25],sequence_a:[3,5,6],sequence_b:[3,5,6],sequence_classif:[0,13],sequence_emb:[16,17],sequence_embed_dim:16,sequence_length:[21,23],sequence_max_length:[5,6],sequence_maxlen:4,sequence_token:3,sequenceclassif:16,servic:39,set:[5,6,8,26,28,35,36,37],set_batch_s:1,set_eval_inference_latency_mod:8,set_eval_mod:8,set_global_se:1,set_gpu_env:1,set_logging_config:0,set_model_base_properti:8,set_predict_mod:8,set_train:8,set_train_mod:8,set_vocab:[23,25],set_warmup_step:2,sever:30,shall:23,shape:[21,22,23],share:28,should:[13,14,15,19,20,21,22,23,24,26],shuffl:2,silent:[13,14,15,19,20,21,22,24,26],similar:[5,10,11,14,19,26],simpl:[1,14,23,28,30,33],simpli:21,sin:21,sinc:[13,14,15,19,20,21,22,24,26],singl:[5,6,17,30],singleton:1,size:[14,19,20,21,22,23,24,34],skip:3,skip_kei:3,slot:[15,17],slot_fil:9,slower:21,small:27,socher:33,soft:[14,26],softmax:[19,22],softwar:[1,23],some:[18,21,27],song:33,sort:[8,21],sort_batch_by_length:21,sorted_sequence_length:21,sorted_tensor:21,sourc:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,38],space:23,space_al:30,spaci:23,spacy_en:[27,30],span:[14,28,35,36,37],span_acc:14,span_end:14,span_end_logit:14,span_end_prob:14,span_start:14,span_start_logit:14,span_start_prob:14,spars:[23,24,30],sparse_featur:24,sparsefeatur:[23,24],sparsetoembed:24,spearman:34,special:[3,15,25],specifi:[2,21,23],split:[3,21,27],split_regex:27,split_siz:21,split_with_regex:[27,30],sql:15,sql_data:12,sql_path:5,sqlnet:[15,28,33,38],squad:[4,5,6,7,12,14,23,27,28,31,33,36],squad_v1_offici:12,squad_v2_offici:12,squadbertdataset:4,squadbertread:[5,6],squaddataset:4,squadread:5,squadv1:14,squadv1forbert:14,squadv2:14,srl:23,sst:[5,28,34],sst_bert:34,sst_bert_bas:[],sst_roberta:34,sst_roberta_bas:[],sstbertread:5,stabl:8,stack:[21,23],standard:23,stanford:[28,36,37],start:[4,14,23,25],start_acc:14,start_logit:14,start_token:[23,25,30],state:[21,23],state_projection_clip_valu:[21,23],statist:12,step:8,step_count:8,stochast:[14,22],stop:8,str:23,stream:23,string:[14,23],structur:[15,16,28,33],structured_self_attent:16,structuredselfattent:16,stsb_bert:34,stsb_bert_bas:[],stsb_roberta:34,stsb_roberta_bas:[],stsbbertread:5,style:28,sub:[27,30],sub_layer_fn:22,subclass:[7,13,14,15,19,20,21,22,24,26],subject:23,sublicens:23,submodul:[10,32],subpackag:32,substanti:23,subword:[5,6,24,27,29,30,33],subwordtoken:[25,27,30],suffix:23,sum:[14,15,19,22,26],summari:[8,31,39],support:23,sym:23,synthet:8,system:[9,28,34],tabl:28,table_id:[5,7,15],table_path:5,tafjord:33,tag:[3,5,6,8,17,23,25,30],tag_accuraci:17,tag_idx:[4,17],tag_index:4,tag_kei:[5,6],tag_logit:17,tag_text:[3,13],tagged_sub_token_idx:17,take:[13,14,15,19,20,21,22,23,24,26,30],tanford:28,target:[16,17,23],task:[4,5,23,34],tensor2tensor:21,tensor:[3,4,8,14,18,20,21,22,23,24,26,30],tensor_for_mask:21,tensor_k:22,tensor_with_boundary_token:23,tensor_without_boundary_token:23,tensorboard:8,tensorflow:21,term:[10,11,21],termin:23,test:[2,27,34,37],text:[3,6,10,11,12,16,23,25,27,28,30,33,37],text_column:23,text_handl:23,text_span:6,text_to_tfidf:[10,11],texthandl:23,textual:5,tfidf:[10,11],tfidf_fnam:[10,11],than:[2,14,21,23,24],thang:33,thei:21,them:[13,14,15,19,20,21,22,24,26],theoret:[21,23],thi:[2,5,6,12,13,14,15,19,20,21,22,23,24,25,26,27,30],think:14,thought:23,three:[23,30],threshold:[8,14],threshold_index:[23,24],through:30,time:[23,28],timestep:[21,22,23],titl:[8,12],to_text:23,toekn_name2:14,togeth:[2,21],tok_cl:[5,6],tok_list:15,tokclsbertdataset:4,tokclsbertread:[5,6],token:[0,1,2,3,4,5,6,8,13,15,16,17,18,31,32,33],token_classif:[0,13],token_count:[3,23],token_embedd:[0,13,14,15,16,17,23],token_index:25,token_kei:8,token_mak:[2,13,14,16,17,23,26],token_maxlen:15,token_nam:[3,23,24,26,30],token_name1:[14,26],token_name2:26,token_to_index:23,token_typ:[3,16,17,23],tokenclassif:17,tokenembed:[23,24],tokenembedd:[13,15,26,30],tokenindex:[23,25],tokenized_quest:15,tokenizer_cl:2,tokenizer_config:2,tokenizer_nam:3,tokenmak:[2,23,26,30],tokenmakersfactori:2,toolkit:33,top:[10,11],torch:[4,8,13,14,15,18,19,20,21,22,23,24,26],tort:23,toutanova:33,train:[2,3,5,6,8,14,16,17,23,24,25,28,30,33,34,35,36,37],train_and_evalu:8,train_config:1,train_count:13,train_load:8,trainabl:[22,24,30],traincount:8,trainer:[1,8],transfer:23,transform:[14,16,17,19,20,23,24,28,33],translat:[23,24,29,30,33],transpos:3,treebank_en:[27,30],triviaqa:27,truth:[5,6],tsv:5,tune:[1,23,30],tupl:[21,23],two:[14,22],txt:[10,11,29,30],type:[1,5,18,21,23,24,27,30],typic:[22,23],unanswer:[12,28,33],uncas:[36,37],under:24,understand:[9,14,16,17,23,24,28,33,34],unidirect:16,union:23,uniqu:23,unit:[23,24,27,30],univers:23,unk:[23,27],unnorm:[14,16,17],unweight:[16,17],updat:23,upper:15,use:[5,6,8,14,21,23,30],use_as_embed:24,use_gpu:8,used:[1,2,16,17,21,23],useful:21,user:3,user_input:[14,16],uses:[2,23],using:[4,5,6,21,23,28,33],utf:3,util:[0,1,3,4,8,15,27],utter:9,vaild:5,valid:[2,3],valid_dataset:8,valid_load:8,valu:[5,8,14,15,16,17,18,19,21,23],variabl:8,varianc:21,variat:21,vector:[10,11,16,17,18,23,24,30,31,33],vehicl:[14,26],verb:23,verbos:8,verbose_step_count:8,version:[12,20],versu:15,via:30,victor:33,vincent:33,visual:30,voacb:23,vocab:[3,4,5,8,10,11,13,23,24,25,26,30],vocab_config:23,vocab_fnam:[10,11],vocab_to_cach:23,vocabdict:23,vocabulari:[23,25,30],vocaburari:[23,26],vowel:23,want:21,warn:8,warranti:23,wasn:23,webhook_url:8,wei:33,weight:[8,10,11,18,19,22,23,24,29],weight_fil:[23,24],weight_init:[14,19],weighted_sum:18,weston:33,what:[14,33],when:[14,16,17,22,23],whenev:24,where:[14,21,22,23,26,28,37,38],whether:[3,23,30],which:[21,23],white:23,whitespac:[3,12],whom:23,wiki:29,wikipedia:[14,28,33,36,37],wikisql:[4,5,12,15,28,31],wikisql_offici:12,wikisqldataset:4,wikisqlread:5,wikisqltokenembedd:15,winograd:5,wise:21,within:[13,14,15,19,20,21,22,24,26],without:[2,15,23,27,28,33],wmt:23,wmtlstm:29,wnli:[5,28,34],wnli_bert:34,wnli_bert_bas:[],wnli_roberta:34,wnli_roberta_bas:[],wnlibertread:5,word2vec:[29,30],word:[3,5,6,10,11,14,23,24,25,26,27,29,30,33],word_embed:[23,24],word_index:25,word_input:23,word_token:[3,10,11,27,30],word_typ:23,wordembed:[23,24],wordindex:[23,25],wordpiec:[27,30],wordtoken:[23,25,27,30],wordtokenmak:23,work:28,work_of_art:23,world:[23,30],would:21,wrapper:[8,23],write_confusion_matrix_to_csv:13,write_predict:[13,14,16,17],wx_i:19,x_i:19,x_mask:19,x_size:19,xception:20,xiaojun:33,xiong:33,y_j:19,y_mask:19,y_size:19,yoon:33,you:[3,19,21,23,33],yuntian:33,zero:[21,24],zettlemoy:33,zhang:33,zhao:33,zhong:33},titles:["claf package","claf.config package","claf.config.factory package","claf.data package","claf.data.dataset package","claf.data.reader package","claf.data.reader.bert package","claf.decorator package","claf.learn package","claf.machine package","claf.machine.components package","claf.machine.components.retrieval package","claf.metric package","claf.model package","claf.model.reading_comprehension package","claf.model.semantic_parsing package","claf.model.sequence_classification package","claf.model.token_classification package","claf.modules package","claf.modules.attention package","claf.modules.conv package","claf.modules.encoder package","claf.modules.layer package","claf.tokens package","claf.tokens.embedding package","claf.tokens.indexer package","claf.tokens.token_embedder package","claf.tokens.tokenizer package","Dataset and Model","Pretrained Vector","Tokens","CLaF documentation","claf","References","GLUE","HistoryQA","KorQuAD","SQuAD","WikiSQL","Reading Comprehension"],titleterms:{attent:19,bert:6,claf:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,31,32],classif:28,compon:[10,11],comprehens:[28,39],config:[1,2],content:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],conv:20,data:[3,4,5,6],dataset:[4,28],decor:7,dev:34,document:31,embed:24,encod:21,english:29,factori:2,glue:34,historyqa:35,index:25,indic:31,korean:29,korquad:36,layer:22,learn:8,machin:[9,10,11],maker:30,metric:12,model:[13,14,15,16,17,28],modul:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],multi:28,packag:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],pars:28,plot:39,pretrain:29,read:[28,39],reader:[5,6],reading_comprehens:14,refer:33,regress:28,result:[34,35,36,37,38],retriev:11,semant:28,semantic_pars:15,sequenc:28,sequence_classif:16,set:34,squad:[37,39],submodul:[0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],subpackag:[0,1,3,5,9,10,13,18,23],tabl:31,task:28,token:[23,24,25,26,27,28,30],token_classif:17,token_embedd:26,vector:29,wikisql:38}}) ================================================ FILE: docs/_build/html/summary/reading_comprehension.html ================================================ Reading Comprehension — CLaF 0.2.0 documentation

Reading Comprehension

Focus on Service orientied metrics (eg. 1-example inference latency)

  • Exists samples in reports/summary/ directory

SQuAD v1.1

Model Inference Latency
(1-example/ms)
F1 (SQuAD) BaseConfig Note
BiDAF 142.644 cpu / 32.545 gpu 77.747 squad/bidaf.json -
BiDAF + ELMo - cpu / - gpu 82.288 squad/bidaf+elmo.json -
DrQA - cpu / - gpu 77.049 squad/drqa.json -
DocQA - cpu / - gpu 80.635 squad/docqa.json -
DocQA + ELMo - cpu / - gpu 84.372 squad/docqa+elmo.json -
QANet - cpu / - gpu 79.800 squad/qanet.json -
BERT - cpu / - gpu 87.130 squad/bert_base-_uncased.json -

Plot

  • Inference Latency (1-example)

images

================================================ FILE: docs/_static/theme_overrides.css ================================================ /* override table width restrictions */ @media screen and (min-width: 767px) { .wy-table-responsive table td { /* !important prevents the common CSS stylesheets from overriding this as on RTD they are loaded after this stylesheet */ white-space: normal !important; } .wy-table-responsive { overflow: visible !important; } } ================================================ FILE: docs/_templates/modules.rst ================================================ {# The :autogenerated: tag is picked up by breadcrumbs.html to suppress "Edit on Github" link #} :autogenerated: {{ fullname }} module {% for item in range(7 + fullname|length) -%}={%- endfor %} .. currentmodule:: {{ fullname }} .. automodule:: {{ fullname }} {% if members -%} :members: {{ members|join(", ") }} :undoc-members: :show-inheritance: :member-order: bysource Summary ------- {%- if exceptions %} Exceptions: .. autosummary:: :nosignatures: {% for item in exceptions %} {{ item }} {%- endfor %} {%- endif %} {%- if classes %} Classes: .. autosummary:: :nosignatures: {% for item in classes %} {{ item }} {%- endfor %} {%- endif %} {%- if functions %} Functions: .. autosummary:: :nosignatures: {% for item in functions %} {{ item }} {%- endfor %} {%- endif %} {%- endif %} {% set data = get_members(typ='data', in_list='__all__') %} {%- if data %} Data: .. autosummary:: :nosignatures: {% for item in data %} {{ item }} {%- endfor %} {%- endif %} {% set all_refs = get_members(in_list='__all__', include_imported=True, out_format='refs') %} {% if all_refs %} ``__all__``: {{ all_refs|join(", ") }} {%- endif %} {% if members %} Reference --------- {%- endif %} ================================================ FILE: docs/_templates/package.rst ================================================ {# The :autogenerated: tag is picked up by breadcrumbs.html to suppress "Edit on Github" link #} :autogenerated: {{ fullname }} package {% for item in range(8 + fullname|length) -%}={%- endfor %} .. automodule:: {{ fullname }} {% if members -%} :members: {{ members|join(", ") }} :undoc-members: :show-inheritance: {%- endif %} {% if submodules %} Submodules: .. toctree:: :maxdepth: 1 {% for item in submodules %} {{ fullname }}.{{ item }} {%- endfor %} {%- endif -%} {% if subpackages %} Subpackages: .. toctree:: :maxdepth: 1 {% for item in subpackages %} {{ fullname }}.{{ item }} {%- endfor %} {%- endif %} {% set all = get_members(in_list='__all__', include_imported=True) %} {% if members or all %} Summary ------- {%- set exceptions = get_members(typ='exception', in_list='__all__', include_imported=True, out_format='table') -%} {%- set classes = get_members(typ='class', in_list='__all__', include_imported=True, out_format='table') -%} {%- set functions = get_members(typ='function', in_list='__all__', include_imported=True, out_format='table') -%} {%- set data = get_members(typ='data', in_list='__all__', include_imported=True, out_format='table') -%} {%- set private_exceptions = get_members(typ='exception', in_list='__private__', out_format='table') -%} {%- set private_classes = get_members(typ='class', in_list='__private__', out_format='table') -%} {%- set private_functions = get_members(typ='function', in_list='__private__', out_format='table') -%} {%- if exceptions %} ``__all__`` Exceptions: {% for line in exceptions %} {{ line }} {%- endfor %} {%- endif %} {%- if private_exceptions %} Private Exceptions: {% for line in private_exceptions %} {{ line }} {%- endfor %} {%- endif %} {%- if classes %} ``__all__`` Classes: {% for line in classes %} {{ line }} {%- endfor %} {%- endif %} {%- if private_classes %} Private Classes: {% for line in private_classes %} {{ line }} {%- endfor %} {%- endif %} {%- if functions %} ``__all__`` Functions: {% for line in functions %} {{ line }} {%- endfor %} {%- endif %} {%- if private_functions %} Private Functions: {% for line in private_functions %} {{ line }} {%- endfor %} {%- endif %} {%- if data %} ``__all__`` Data: {% for line in data %} {{ line }} {%- endfor %} {%- endif %} {%- endif %} {% if members %} Reference --------- {%- endif %} ================================================ FILE: docs/claf.config.factory.rst ================================================ claf.config.factory package =========================== Submodules ---------- .. automodule:: claf.config.factory.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.data_loader :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.data_reader :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.model :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.optimizer :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.factory.tokens :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.config.factory :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.config.rst ================================================ claf.config package =================== Subpackages ----------- .. toctree:: claf.config.factory Submodules ---------- .. automodule:: claf.config.args :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.namespace :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.pattern :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.registry :members: :undoc-members: :show-inheritance: .. automodule:: claf.config.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.config :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.data.dataset.rst ================================================ claf.data.dataset package ========================= Submodules ---------- .. automodule:: claf.data.dataset.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.seq_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.seq_cls_bert :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.squad :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.squad_bert :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.tok_cls_bert :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.dataset.wikisql :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.data.dataset :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.data.reader.bert.rst ================================================ claf.data.reader.bert package ============================= Submodules ---------- .. automodule:: claf.data.reader.bert.cola :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.bert.conll2003 :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.bert.seq_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.bert.squad :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.bert.tok_cls :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.data.reader.bert :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.data.reader.rst ================================================ claf.data.reader package ======================== Subpackages ----------- .. toctree:: claf.data.reader.bert Submodules ---------- .. automodule:: claf.data.reader.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.cola :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.seq_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.squad :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.reader.wikisql :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.data.reader :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.data.rst ================================================ claf.data package ================= Subpackages ----------- .. toctree:: claf.data.dataset claf.data.reader Submodules ---------- .. automodule:: claf.data.batch :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.collate :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.data_handler :members: :undoc-members: :show-inheritance: .. automodule:: claf.data.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.data :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.decorator.rst ================================================ claf.decorator package ====================== Submodules ---------- .. automodule:: claf.decorator.arguments :members: :undoc-members: :show-inheritance: .. automodule:: claf.decorator.register :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.decorator :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.learn.rst ================================================ claf.learn package ================== Submodules ---------- .. automodule:: claf.learn.experiment :members: :undoc-members: :show-inheritance: .. automodule:: claf.learn.mode :members: :undoc-members: :show-inheritance: .. automodule:: claf.learn.tensorboard :members: :undoc-members: :show-inheritance: .. automodule:: claf.learn.trainer :members: :undoc-members: :show-inheritance: .. automodule:: claf.learn.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.learn :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.machine.components.retrieval.rst ================================================ claf.machine.components.retrieval package ========================================= Submodules ---------- .. automodule:: claf.machine.components.retrieval.tfidf :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.machine.components.retrieval :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.machine.components.rst ================================================ claf.machine.components package =============================== Subpackages ----------- .. toctree:: claf.machine.components.retrieval Module contents --------------- .. automodule:: claf.machine.components :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.machine.rst ================================================ claf.machine package ==================== Subpackages ----------- .. toctree:: claf.machine.components Submodules ---------- .. automodule:: claf.machine.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.machine.module :members: :undoc-members: :show-inheritance: .. automodule:: claf.machine.nlu :members: :undoc-members: :show-inheritance: .. automodule:: claf.machine.open_qa :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.machine :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.metric.rst ================================================ claf.metric package =================== Submodules ---------- .. automodule:: claf.metric.classification :members: :undoc-members: :show-inheritance: .. automodule:: claf.metric.squad_v1_official :members: :undoc-members: :show-inheritance: .. automodule:: claf.metric.squad_v2_official :members: :undoc-members: :show-inheritance: .. automodule:: claf.metric.wikisql_official :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.metric :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.model.reading_comprehension.rst ================================================ claf.model.reading\_comprehension package ========================================= Submodules ---------- .. automodule:: claf.model.reading_comprehension.bert_for_qa :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.bidaf :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.bidaf_no_answer :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.docqa :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.docqa_no_answer :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.drqa :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.mixin :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.reading_comprehension.qanet :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model.reading_comprehension :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.model.rst ================================================ claf.model package ================== Subpackages ----------- .. toctree:: claf.model.reading_comprehension claf.model.semantic_parsing claf.model.sequence_classification claf.model.token_classification Submodules ---------- .. automodule:: claf.model.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.cls_utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.model.semantic_parsing.rst ================================================ claf.model.semantic\_parsing package ==================================== Submodules ---------- .. automodule:: claf.model.semantic_parsing.mixin :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.semantic_parsing.sqlnet :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.semantic_parsing.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model.semantic_parsing :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.model.sequence_classification.rst ================================================ claf.model.sequence\_classification package =========================================== Submodules ---------- .. automodule:: claf.model.sequence_classification.bert_for_seq_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.sequence_classification.mixin :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.sequence_classification.structured_self_attention :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model.sequence_classification :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.model.token_classification.rst ================================================ claf.model.token\_classification package ======================================== Submodules ---------- .. automodule:: claf.model.token_classification.bert_for_tok_cls :members: :undoc-members: :show-inheritance: .. automodule:: claf.model.token_classification.mixin :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.model.token_classification :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.modules.attention.rst ================================================ claf.modules.attention package ============================== Submodules ---------- .. automodule:: claf.modules.attention.bi_attention :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.attention.co_attention :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.attention.docqa_attention :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.attention.multi_head_attention :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.attention.seq_attention :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules.attention :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.modules.conv.rst ================================================ claf.modules.conv package ========================= Submodules ---------- .. automodule:: claf.modules.conv.depthwise_separable_conv :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.conv.pointwise_conv :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules.conv :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.modules.encoder.rst ================================================ claf.modules.encoder package ============================ Submodules ---------- .. automodule:: claf.modules.encoder.lstm_cell_with_projection :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.encoder.positional :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules.encoder :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.modules.layer.rst ================================================ claf.modules.layer package ========================== Submodules ---------- .. automodule:: claf.modules.layer.highway :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.layer.normalization :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.layer.positionwise :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.layer.residual :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.layer.scalar_mix :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules.layer :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.modules.rst ================================================ claf.modules package ==================== Subpackages ----------- .. toctree:: claf.modules.attention claf.modules.conv claf.modules.encoder claf.modules.layer Submodules ---------- .. automodule:: claf.modules.activation :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.functional :members: :undoc-members: :show-inheritance: .. automodule:: claf.modules.initializer :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.modules :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.rst ================================================ claf package ============ Subpackages ----------- .. toctree:: claf.config claf.data claf.decorator claf.learn claf.machine claf.metric claf.model claf.modules claf.tokens Submodules ---------- .. automodule:: claf.utils :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.tokens.embedding.rst ================================================ claf.tokens.embedding package ============================= Submodules ---------- .. automodule:: claf.tokens.embedding.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.bert_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.char_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.cove_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.elmo_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.frequent_word_embedding :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.sparse_feature :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.embedding.word_embedding :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens.embedding :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.tokens.indexer.rst ================================================ claf.tokens.indexer package =========================== Submodules ---------- .. automodule:: claf.tokens.indexer.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.bert_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.char_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.elmo_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.exact_match_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.linguistic_indexer :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.indexer.word_indexer :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens.indexer :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.tokens.rst ================================================ claf.tokens package =================== Subpackages ----------- .. toctree:: claf.tokens.embedding claf.tokens.indexer claf.tokens.token_embedder claf.tokens.tokenizer Submodules ---------- .. automodule:: claf.tokens.cove :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.elmo :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.hangul :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.linguistic :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.text_handler :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.token_maker :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.vocabulary :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.tokens.token_embedder.rst ================================================ claf.tokens.token\_embedder package =================================== Submodules ---------- .. automodule:: claf.tokens.token_embedder.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.token_embedder.basic_embedder :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.token_embedder.reading_comprehension_embedder :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens.token_embedder :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/claf.tokens.tokenizer.rst ================================================ claf.tokens.tokenizer package ============================= Submodules ---------- .. automodule:: claf.tokens.tokenizer.base :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.char :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.pass_text :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.sent :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.subword :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.utils :members: :undoc-members: :show-inheritance: .. automodule:: claf.tokens.tokenizer.word :members: :undoc-members: :show-inheritance: Module contents --------------- .. automodule:: claf.tokens.tokenizer :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/conf.py ================================================ # -*- coding: utf-8 -*- # # Configuration file for the Sphinx documentation builder. # # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) import os import sys sys.path.insert(0, os.path.abspath('..')) from claf import __version__ as VERSION # -- Project information ----------------------------------------------------- project = 'CLaF' copyright = '2019, Dongjun Lee' author = 'Dongjun Lee' # The short X.Y version version = VERSION.__version__ # The full version, including alpha/beta/rc tags release = VERSION.__version__ # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', 'sphinx.ext.githubpages', 'recommonmark', 'sphinx_markdown_tables', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_parsers = { # '.md': 'recommonmark.parser.CommonMarkParser', } source_suffix = ['.rst', '.md'] # The master toctree document. master_doc = 'index' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path . exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} html_theme_options = { 'logo_only': True, } # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] html_context = { 'css_files': [ '_static/theme_overrides.css', # override wide tables in RTD theme ], } # Custom sidebar templates, must be a dictionary that maps document names # to template names. # # The default sidebars (for documents that don't match any pattern) are # defined by theme itself. Builtin themes are using these templates by # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', # 'searchbox.html']``. # # html_sidebars = {} html_logo = "../images/logo.png" html_favicon = "../images/favicon.ico" # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = 'CLaFdoc' # -- Options for LaTeX output ------------------------------------------------ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'CLaF.tex', 'CLaF Documentation', 'Dongjun Lee', 'manual'), ] # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'CLaF', 'CLaF Documentation', [author], 1) ] # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'CLaF', 'CLaF Documentation', author, 'CLaF', 'One line description of project.', 'Miscellaneous'), ] # -- Extension configuration ------------------------------------------------- # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None} ================================================ FILE: docs/contents/dataset_and_model.md ================================================ # Dataset and Model **Table of Contents** - [Multi Task](#multi-task) - [Reading Comprehension](#reading-comprehension) - [Regression](#regression) - [Semantic Parsing](#semantic-parsing) - [Sequence Classification](#sequence-classification) - [Token Classification](#token-classification) --- ## Multi-Task ### Dataset - [GLUE Benchmark](https://gluebenchmark.com/): The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems. - CoLA, MNLI, MRPC, QNLI, QQP, RTE, SST-2, STS-B, WNLI ### Model - [Multi-Task Deep Neural Networks for Natural Language Understanding](https://arxiv.org/abs/1901.11504) ## Reading Comprehension ### Dataset - [HistoryQA](https://oss.navercorp.com/ClovaAI-PJT/HistoryQA): Joseon History Question Answering Dataset (SQuAD Style) - [KorQuAD](https://korquad.github.io/): KorQuAD는 한국어 Machine Reading Comprehension을 위해 만든 데이터셋입니다. 모든 질의에 대한 답변은 해당 Wikipedia 아티클 문단의 일부 하위 영역으로 이루어집니다. Stanford Question Answering Dataset(SQuAD) v1.0과 동일한 방식으로 구성되었습니다. - [SQuAD](https://rajpurkar.github.io/SQuAD-explorer/): **S**tanford **Qu**estion **A**nswering **D**ataset is a reading comprehension dataset, consisting of questions posed by crowdworkers on a set of Wikipedia articles, where the answer to every question is a segment of text, or span, from the corresponding reading passage, or the question might be unanswerable. ### Model - BiDAF: [Birectional Attention Flow for Machine Comprehension](https://arxiv.org/abs/1611.01603) + `No Answer` - [A Structured Self-attentive Sentence Embedding](https://arxiv.org/abs/1703.03130) - DrQA: [Reading Wikipedia to Answer Open-Domain Questions](https://arxiv.org/abs/1704.00051) - DocQA: [Simple and Effective Multi-Paragraph Reading Comprehension](https://arxiv.org/abs/1710.10723) + `No Answer` - [QANet: Combining Local Convolution with Global Self-Attention for Reading Comprehension ](https://arxiv.org/abs/1804.09541) - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) --- ## Regression - [GLUE Benchmark](https://gluebenchmark.com/): The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems. - STS-B ### Model - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) - [RoBERTa: A Robustly Optimized BERT Pretraining Approach](https://arxiv.org/abs/1907.11692) --- ## Semantic Parsing ### Dataset - [WikiSQL](https://github.com/salesforce/WikiSQL): A large crowd-sourced dataset for developing natural language interfaces for relational databases. WikiSQL is the dataset released along with our work [Seq2SQL: Generating Structured Queries from Natural Language using Reinforcement Learning](http://arxiv.org/abs/1709.00103). ### Model - SQLNet: [SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning](https://arxiv.org/abs/1711.04436) --- ## Sequence Classification ### Dataset - [GLUE Benchmark](https://gluebenchmark.com/): The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems. - CoLA, MNLI, MRPC, QNLI, QQP, RTE, SST-2, WNLI ### Model - [A Structured Self-attentive Sentence Embedding](https://arxiv.org/abs/1703.03130) - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) - [RoBERTa: A Robustly Optimized BERT Pretraining Approach](https://arxiv.org/abs/1907.11692) --- ## Token Classification ### Dataset - [NER - CoNLL 2013](https://www.clips.uantwerpen.be/conll2003/ner/): The shared task of CoNLL-2003 concerns language-independent named entity recognition. Named entities are phrases that contain the names of persons, organizations, locations, times and quantities. ### Model - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) ================================================ FILE: docs/contents/pretrained_vector.md ================================================ # Pretrained Vector - List on [DataServer](http://dev-reasoning-qa-data-ncl.nfra.io:7778/) ## English - `Counter Fitting`: [Counter-fitting Word Vectors to Linguistic Constraints](http://mi.eng.cam.ac.uk/~nm480/naaclhlt2016.pdf) - counter\_fitted\_glove.300d.txt - `Cove`: [Learned in Translation: Contextualized Word Vectors (McCann et. al. 2017)](https://github.com/salesforce/cove) - wmtlstm-b142a7f2.pth - `fastText`: [Enriching Word Vectors with Subword Information](https://github.com/facebookresearch/fastText) - fasttext.wiki.en.300d.txt - `GloVe`: [GloVe: Global Vectors for Word Representation](https://nlp.stanford.edu/projects/glove/) - glove.6B.50d.txt - glove.6B.100d.txt - glove.6B.200d.txt - glove.6B.300d.txt - glove.840B.300d.txt - `ELMo`: [Deep contextualized word representations](https://github.com/allenai/allennlp/blob/master/allennlp/modules/elmo.py) - elmo\_2x4096\_512\_2048cnn\_2xhighway\_weights.hdf5 - elmo\_2x4096\_512\_2048cnn\_2xhighway\_options - `Word2Vec`: [Distributed Representations of Words and Phrases and their Compositionality](https://code.google.com/archive/p/word2vec/) - GoogleNews-vectors-negative300.txt ## Korean - `fastText`: [Enriching Word Vectors with Subword Information](https://github.com/facebookresearch/fastText) - fasttext.wiki.ko.300d.txt ================================================ FILE: docs/contents/tokens.md ================================================ # Tokens TokenMakers consists of Tokenizer, Indexer, Vocabulary, and Embedding Modules. `TokenMaker` is responsible for the indexing of text and the generation of the tensors through the embedding module. ## Tokenizers - Tokenizer Design ![images](../../images/tokenizers_design.png) ``` class SentTokenizer(name, config): ... class WordTokenizer(name, sent_tokenizer, config) ... class SubwordTokenizer(name, word_tokenizer, config) ... class CharTokenizer(name, word_tokenizer, config) ... ``` The Tokenizer has a dependency with the other unit's tokenizer and the `tokenize()` function takes the input of text units. (* unit: unit of input e.g. 'text', 'sentence' and 'word') - `tokenizer()` example ``` >>> text = "Hello World.This is tokenizer example code." >>> word_tokenizer.tokenize(text, unit="text") # text -> sentences -> words >>> ['Hello', 'World', '.', 'This', 'is', 'tokenizer', 'example', 'code', '.'] >>> word_tokenizer.tokenize(text, unit="sentence") # text -> words >>> ['Hello', 'World.This', 'is', 'tokenizer', 'example', 'code', '.'] ``` Several tensors in a sub-level text unit can be combined into a single tensor of higher level via a vector operation. For example, subword level tensors can be averaged to represent a word level tensor. e.g.) concatenate \[word; subword\] (subword tokens --average--> word token) * The list of pre-defined `Tokenizers`: | Text Unit | Language | Name | Example | | ---- | ---- | --- | --- | | BPE | All (depend on vocab) | **roberta** | Hello World
-> ["ĠHello", "ĠWorld"] | | Char | All | **character** | Hello World
-> ["Hello", "World"]
-> [["H", "e", "l", "l", "o"], ["W", "o", "r", "l", "d"]] | | Char | Korean | [**jamo_ko**](https://github.com/rhobot/Hangulpy) | "안녕 세상"
-> ["안녕", "세상"]
-> [["ㅇ", "ㅏ", "ㄴ", "ㄴ", "ㅕ", "ㅇ"], ["ㅅ", "ㅔ", "ㅅ", "ㅏ", "ㅇ"]] | | Subword | All (but, need vocab.txt) | [**wordpiece**](https://github.com/huggingface/pytorch-pretrained-BERT/blob/master/pytorch_pretrained_bert/tokenization.py) | "expectancy of anyone"
-> ["expectancy", "of", "anyone"]
-> ["expect", "##ancy", "of", "anyone"] | | Word | English | [**nltk_en**](http://www.nltk.org/api/nltk.tokenize.html) | - | | Word | English | [**spacy_en**](https://spacy.io/api/tokenizer) | - | | Word | Korean | [**mecab_ko**](https://bitbucket.org/eunjeon/mecab-ko) | - | | Word | All | **bert_basic** | - | | Word | All | **space_all** | "Hello World"
-> ["Hello", "World"] | | Sent | All | [**punkt**](http://www.nltk.org/api/nltk.tokenize.html) | "Hello World. This is punkt tokenizer."
-> ["Hello World.", "This is punkt tokenizer."] | ## Token Maker * The list of pre-defined `Token Maker`: | Type | Description | Category | Notes | | ---- | ---- | --- | --- | | **char** | character -> convolution -> maxpool | `CharCNN` | - | | **cove** | Embeddings from Neural Machine Translation | `NMT` | - From [Salesforce](https://github.com/salesforce/cove) | | **feature** | Do not use embedding function, just pass feature | `Feature` | - | | **word** | word -> Embedding (+pretrained) | `Word2Vec` | - | | **frequent_word** | word token + pre-trained word embeddings fixed and only fine-tune the N most frequent | `Word2Vec` + `Fine-tune` | - | | **exact_match** | Three simple binary features, indicating whether p_i can be exactly matched to one question word in q, either in its original, lowercase or lemma form. | `Feature` | - Sparse or Embedding
- Only for RC| | **elmo** | Embeddings from Language Models | `LM` | From [Allennlp](https://github.com/allenai/allennlp) | | **linguistic** | Linguistic Features like POS Tagging, NER and Dependency Parser | `Feature` | - Sparse or Embedding | - Example of tokens in [BaseConfig](#baseconfig) ``` "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { # Define the tokenizer in each unit. "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { # token_name "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { # token_name "indexer": { "lowercase": true }, "embedding": { "embed_dim": 100, "pretrained_path": ", "trainable": false, "dropout": 0.2 } } }, # Tokens process # Text -> Indexed Featrues -> Tensor -> TokenEmbedder -> Model # Visualization # - Text: Hello World # - Indexed Feature: {'char': [[2, 3, 4, 4, 5], [6, 7, 8, 4, 9]], 'glove': [2, 3]} # - Tensor: {'char': tensor, 'glove': tensor} # - TokenEmbedder: [char; glove] (default: concatenate) # - Model: use embedded_value ``` ================================================ FILE: docs/index.rst ================================================ .. CLaF documentation master file, created by sphinx-quickstart on Wed Aug 22 16:14:25 2018. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. :github_url: https://github.com/naver/claf CLaF documentation =================================== CLaF: Clova Language Framework .. toctree:: :glob: :maxdepth: 1 :caption: Contents contents/* .. toctree:: :maxdepth: 1 :caption: Package Reference config data learn metric model modules tokens .. toctree:: :glob: :maxdepth: 1 :caption: Reports reports/* .. toctree:: :glob: :maxdepth: 1 :caption: Summary summary/* .. toctree:: :maxdepth: 1 :caption: Appendix References Indices and tables ================== * :ref:`genindex` * :ref:`modindex` ================================================ FILE: docs/make.bat ================================================ @ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=_build set SPHINXPROJ=rqa if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% :end popd ================================================ FILE: docs/modules.rst ================================================ claf ==== .. toctree:: :maxdepth: 4 claf ================================================ FILE: docs/references.md ================================================ # References - **Dataset** - Pranav Rajpurkar, Jian Zhang, Konstantin Lopyrev and Percy Liang. 2016, [SQuAD: 100,000+ Questions for Machine Comprehension of Text](https://arxiv.org/abs/1606.05250) - Pranav Rajpurkar, Robin Jia and Percy Liang. 2018, [Know What You Don't Know: Unanswerable Questions for SQuAD](https://arxiv.org/abs/1806.03822) - Victor Zhong, Caiming Xiong, and Richard Socher. 2017, [Seq2SQL: Generating Structured Queries from Natural Language using Reinforcement Learning](http://arxiv.org/abs/1709.00103) - **Model** - Minjoon Seo, Aniruddha Kembhavi, Ali Farhadi and Hannaneh Hajishirzi. 2016, [Bidirectional Attention Flow for Machine Comprehension](https://arxiv.org/abs/1611.01603) - Danqi Chen, Adam Fisch, Jason Weston and Antoine Bordes. 2017, [Reading Wikipedia to Answer Open-Domain Questions](https://arxiv.org/abs/1704.00051) - Christopher Clark and Matt Gardner. 2017, [Simple and Effective Multi-Paragraph Reading Comprehension](https://arxiv.org/abs/1710.10723) - Adams Wei Yu, David Dohan, Minh-Thang Luong, Rui Zhao, Kai Chen, Mohammad Norouzi and Quoc V. Le. 2018, [QANet: Combining Local Convolution with Global Self-Attention for Reading Comprehension](https://arxiv.org/abs/1804.09541) - Jacob Devlin, Ming-Wei Chang, Kenton Lee and Kristina Toutanova. 2018, [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805) - Xiaojun Xu, Chang Liu and Dawn Song. 2017, [SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning](https://arxiv.org/abs/1711.04436) - **Token** - Yoon Kim,. 2014, [Convolutional Neural Networks for Sentence Classification](https://arxiv.org/abs/1408.5882) - B. McCann, J. Bradbury, C. Xiong, R. Socher, [Learned in Translation: Contextualized Word Vectors](http://papers.nips.cc/paper/7209-learned-in-translation-contextualized-word-vectors.pdf) - P. Bojanowski, E. Grave, A. Joulin, T. Mikolov, [Enriching Word Vectors with Subword Information](https://arxiv.org/abs/1607.04606) - Matthew E. Peters, Mark Neumann, Mohit Iyyer, Matt Gardner, Christopher Clark, Kenton Lee and Luke Zettlemoyer. 2018, [Deep contextualized word representations](https://arxiv.org/abs/1802.05365) - **Other Framework** - Matt Gardner, Joel Grus, Mark Neumann, Oyvind Tafjord, Pradeep Dasigi, Nelson F. Liu, Matthew Peters, Michael Schmitz and Luke S. Zettlemoyer. 2017, [AllenNLP: A Deep Semantic Natural Language Processing Platform](https://www.semanticscholar.org/paper/AllenNLP%3A-A-Deep-Semantic-Natural-Language-Platform-Gardner-Grus/a5502187140cdd98d76ae711973dbcdaf1fef46d) - Guillaume Klein, Yoon Kim, Yuntian Deng, Vincent Nguyen, Jean Senellart and Alexander M. Rush [OpenNMT: Neural Machine Translation Toolkit](https://arxiv.org/pdf/1805.11462) ================================================ FILE: docs/reports/glue.md ================================================ # GLUE - [`GLUE`](https://gluebenchmark.com/): The General Language Understanding Evaluation (GLUE) benchmark is a collection of resources for training, evaluating, and analyzing natural language understanding systems. --- ## Results ### Dev Set - **Base** Size : 12-layer, 768-hidden, 12-heads, 110M parameters | Task (Metric) | Model | CLaF Result | Official Result | BaseConfig | | ------------- | ----- | ----- | -------- | ---------- | | **CoLA** (**Matthew's Corr**) | BERT-Base | 59.393 | 52.1 (Test set) | glue/cola_bert.json | | | MT-DNN (BERT) Base | 54.658 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 64.828 | 63.6 | glue/cola_roberta.json | | **MNLI m/mm** (**Accuracy**) | BERT-Base | 83.923/84.306 | 84.6/83.4 (Test set) | glue/mnli{m/mm}_bert.json | | | MT-DNN (BERT) Base | 84.452/84.225 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 87.305/87.236 | 87.6/- | glue/mnli{m/mm}_roberta.json | | **MRPC** (**Accuracy/F1**) | BERT-Base | 87.5/91.282 | 88.9 (Test set) | glue/mrpc_bert.json | | | MT-DNN (BERT) Base | 87.5/91.005 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 88.480/91.681 | 90.2 | glue/mrpc_roberta.json | | **QNLI** (**Accuracy**) | BERT-Base | 88.521 | 90.5 (Test set) | glue/qnli_bert.json | | | MT-DNN (BERT) Base | - | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 90.823 | 92.8 | glue/qnli_roberta.json | | **QQP** (**Accuracy/F1**) | BERT-Base | 90.378/87.171 | 71.2 (Test set) | glue/qqp_bert.json | | | MT-DNN (BERT) Base | 91.261/88.219 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 91.541/88.768 | 91.9 | glue/qqp_roberta.json | | **RTE** (**Accuracy**) | BERT-Base | 69.314 | 66.4 (Test set) | glue/rte_bert.json | | | MT-DNN (BERT) Base | 79.422 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 73.646 | 78.7 | glue/rte_roberta.json | | **SST-2** (**Accuracy**) | BERT-Base | 92.546 | 93.5 (Test set) | glue/sst_bert.json | | | MT-DNN (BERT) Base | 93.005 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 94.495 | 94.8 | glue/sst_roberta.json | | **STS-B** (**Pearson/Spearman**) | BERT-Base | 88.070/87.881 | 85.8 (Test set) | glue/stsb_bert.json | | | MT-DNN (BERT) Base | 88.444/88.807 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 89.003/89.094 | 91.2 | glue/stsb_roberta.json | | **WNLI** (**Accuracy**) | BERT-Base | 56.338 | 65.1 (Test set) | glue/wnli_bert.json | | | MT-DNN (BERT) Base | 57.746 | - | 1. multi_task/bert_base_glue.json
2. `fine-fune` | | | RoBERTa-Base | 60.563 | - | glue/wnli_roberta.json | - **Large** Size : 24-layer, 1024-hidden, 16-heads, 340M parameters | Task (Metric) | Model | CLaF Result | Official Result | BaseConfig | | ------------- | ----- | ----- | -------- | ---------- | | **CoLA** (**Matthew's Corr**) | BERT-Large | 61.151 | 60.6 | glue/cola_bert.json | | | MT-DNN (BERT) Large | - | 63.5 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | - | 68.0 | glue/cola_roberta.json | | **MNLI m/mm** (**Accuracy**) | BERT-Large | - | 86.6/- | glue/mnli{m/mm}_bert.json | | | MT-DNN (BERT) Large | - | 87.1/86.7 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | - | 90.2/90.2 | glue/mnli{m/mm}_roberta.json | | **MRPC** (**Accuracy/F1**) | BERT-Large | 87.255/90.845 | 88.0 | glue/mrpc_bert.json | | | MT-DNN (BERT) Large | - | 91.0/87.5 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 90.686/93.214 | 90.9 | glue/mrpc_roberta.json | | **QNLI** (**Accuracy**) | BERT-Large | 90.440 | 92.3 | glue/qnli_bert.json | | | MT-DNN (BERT) Large | - | 87.1/86.7 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | - | 94.7 | glue/qnli_roberta.json | | **QQP** (**Accuracy/F1**) | BERT-Large | 91.640/88.745 | 91.3 | glue/qqp_bert.json | | | MT-DNN (BERT) Large | - | 87.1/86.7 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 91.848/89.031 | 92.2 | glue/qqp_roberta.json | | **RTE** (**Accuracy**) | BERT-Large | 69.675 | 70.4 | glue/rte_bert.json | | | MT-DNN (BERT) Large | - | 83.4 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 84.838 | 86.6 | glue/rte_roberta.json | | **SST-2** (**Accuracy**) | BERT-Large | 93.349 | 93.2 | glue/sst_bert.json | | | MT-DNN (BERT) Large | - | 94.3 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 95.642 | 96.4 | glue/sst_roberta.json | | **STS-B** (**Pearson/Spearman**) | BERT-Large | 90.041/89735 | 90.0 | glue/stsb_bert.json | | | MT-DNN (BERT) Large | - | 90.7/90.6 | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | 91.980/91.764 | 92.4 | glue/stsb_roberta.json | | **WNLI** (**Accuracy**) | BERT-Large | 59.155 | - | glue/wnli_bert.json | | | MT-DNN (BERT) Large | - | - | 1. multi_task/bert_large_glue.json
2. `fine-fune` | | | RoBERTa-Large | - | 91.3 | - | ================================================ FILE: docs/reports/historyqa.md ================================================ # HistoryQA `Span Detector` - `HistoryQA`: Joseon History Question Answering Dataset - Train: 31901 / Dev: 3067 --- ## Results - Dev Set | Model | EM | F1 | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 81.709 | 84.743 | history/bidaf.json | - | | **DocQA** | 85.099 | 87.789 | history/docqa.json | - | ================================================ FILE: docs/reports/korquad.md ================================================ # KorQuAD `Span Detector` - [`KorQuAD`](https://korquad.github.io/): KorQuAD는 한국어 Machine Reading Comprehension을 위해 만든 데이터셋입니다. 모든 질의에 대한 답변은 해당 Wikipedia 아티클 문단의 일부 하위 영역으로 이루어집니다. Stanford Question Answering Dataset(SQuAD) v1.0과 동일한 방식으로 구성되었습니다. - v1.0 - Train: 60359 / Dev: 5774 --- ## Results - Dev Set | Model | EM | F1 | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 75.476 | 85.915 | korquad/bidaf.json | - | | **DocQA** | 77.693 | 88.115 | korquad/docqa.json | - | | **BERT**-Base, Multilingual Uncased | 81.573 | 90.679 | korquad/bert_base_multilingual_uncased.json | - | | **BERT**-Base, Multilingual Cased | 82.542 | 91.692 | korquad/bert_base_multilingual_cased.json | - | ================================================ FILE: docs/reports/squad.md ================================================ # SQuAD `Span Detector`, `No Answer` - [`SQuAD`](https://rajpurkar.github.io/SQuAD-explorer/): Stanford Question Answering Dataset (SQuAD), a new reading comprehension dataset consisting of 100,000+ questions posed by crowdworkers on a set of Wikipedia articles, where the answer to each question is a segment of text from the corresponding reading passage. - v1.1 - Train: 87599 / Dev: 10570 / Test: 9533 - v2.0 + no_answer - Train : 130319 / Dev: 11873 / Test: 8862 --- ## Results (v1.1) - Dev Set | Model | EM (official) | F1 (official) | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 68.108 (67.7) | 77.780 (77.3) | squad/bidaf.json | - | | **BiDAF + ELMo** | 74.295 | 82.727 | squad/bidaf+elmo.json | - | | **DrQA** | 68.316 (68.8) | 77.493 (78.0) | squad/drqa.json | - | | **DocQA** | 71.760 (71.513) | 80.635 (80.422) | squad/docqa.json | - | | **DocQA + ELMo** | 76.244 (77.5) | 84.372 (84.5) | squad/docqa+elmo.json | - | | **QANet** | 70.918 (73.6) | 79.800 (82.7) | squad/qanet.json | - | | **BERT**-Base Uncased | 79.508 (80.8) | 87.642 (88.5) | squad/bert_base_uncased.json | - | | **BERT**-Large Uncased | 83.254 (84.1) | 90.440 (90.9) | squad/bert_large_uncased.json | - | | **RoBERTa**-Base | 82.980 | 90.459 | roberta_base.json/bert_base_uncased.json | - | | **RoBERTa**-Large | 88.061 (88.9) | 94.034 (94.6) | squad/roberta_large.json | - | --- ## Results (v2.0) - Dev Set | Model | EM (official) | F1 (official) | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 62.570 | 65.461 | squad/bidaf_no_answer.json | - | | **DocQA** | 61.728 | 64.489 | squad/docqa_no_answer.json | - | ================================================ FILE: docs/reports/wikisql.md ================================================ # WikiSQL `Semantic Parsing`, `NL2SQL` - `WikiSQL`: A large crowd-sourced dataset for developing natural language interfaces for relational databases. --- ## Results - Column details * Agg: Aggregator * Sel: SELECT Column * Cond: Where clause * LF: Logical Form * EX: Execution * (): Paper result | Model | Agg | Sel | Cond | LF | EX | BaseConfig | | --- | --- | --- | --- | --- | --- | --- | | **SQLNet** | (90.1) | (91.1) | (72.1) | - | (69.8) | wikisql/sqlnet.json | ================================================ FILE: docs/requirements.txt ================================================ # Documentation Sphinx recommonmark sphinx_markdown_tables git+https://github.com/DongjunLee/sphinx_rtd_theme.git ================================================ FILE: docs/summary/reading_comprehension.md ================================================ # Reading Comprehension Focus on Service orientied metrics (eg. 1-example inference latency) - Exists samples in `reports/summary/` directory ## SQuAD v1.1 | Model | Inference Latency
(1-example/ms) | F1 (SQuAD) | BaseConfig | Note | | --- | --- | --- | --- | --- | | **BiDAF** | 142.644 `cpu` / 32.545 `gpu` | 77.747 | squad/bidaf.json | - | | **BiDAF + ELMo** | - `cpu` / - `gpu` | 82.288 | squad/bidaf+elmo.json | - | | **DrQA** | - `cpu` / - `gpu` | 77.049 | squad/drqa.json | - | | **DocQA** | - `cpu` / - `gpu` | 80.635 | squad/docqa.json | - | | **DocQA + ELMo** | - `cpu` / - `gpu` | 84.372 | squad/docqa+elmo.json | - | | **QANet** | - `cpu` / - `gpu` | 79.800 | squad/qanet.json | - | | **BERT** | - `cpu` / - `gpu` | 87.130 | squad/bert\_base-_uncased.json | - | ### Plot - Inference Latency (1-example) ![images](../../images/inference_latency_chart-1000.png) ================================================ FILE: eval.py ================================================ # -*- coding: utf-8 -*- from claf.config import args from claf.learn.experiment import Experiment from claf.learn.mode import Mode if __name__ == "__main__": config = args.config(mode=Mode.EVAL) mode = Mode.EVAL if config.inference_latency: # evaluate inference_latency mode = Mode.INFER_EVAL experiment = Experiment(mode, config) experiment() ================================================ FILE: index.html ================================================ ================================================ FILE: machine.py ================================================ # -*- coding: utf-8 -*- import json from claf.config import args from claf.config.registry import Registry from claf.learn.mode import Mode from claf import utils as common_utils if __name__ == "__main__": registry = Registry() machine_config = args.config(mode=Mode.MACHINE) machine_name = machine_config.name config = getattr(machine_config, machine_name, {}) claf_machine = registry.get(f"machine:{machine_name}")(config) while True: question = common_utils.get_user_input(f"{getattr(machine_config, 'user_input', 'Question')}") answer = claf_machine(question) answer = json.dumps(answer, indent=4, ensure_ascii=False) print(f"{getattr(machine_config, 'system_response', 'Answer')}: {answer}") ================================================ FILE: machine_config/ko_wiki.json ================================================ { "name": "open_qa", "user_input": "Question", "system_response": "Answer", "open_qa": { "tokenizers": { "sent": { "name": "punkt" }, "word": { "name": "mecab_ko", "split_with_regex": true } }, "knowledge_base": { "wiki": "" }, "reasoning": { "document_retrieval": { "type": "component", "name": "tfidf", "tfidf": { "k": 5 } }, "reading_comprehension": { "type": "experiment", "checkpoint_path": "" } } } } ================================================ FILE: machine_config/nlu.json ================================================ { "name": "nlu", "user_input": "Utterance", "system_response": "NLU Result", "nlu": { "tokenizers": { "sent": { "name": "punkt" }, "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased-vocab.txt" } } }, "nlu": { "intent": { "name": "intent", "type": "experiment", "checkpoint_path": "", "cuda_devices": [0] }, "slots": { "name": "slots", "type": "experiment", "checkpoint_path": "", "cuda_devices": [1] } } } } ================================================ FILE: predict.py ================================================ # -*- coding: utf-8 -*- from claf.config import args from claf.learn.experiment import Experiment from claf.learn.mode import Mode if __name__ == "__main__": experiment = Experiment(Mode.PREDICT, args.config(mode=Mode.PREDICT)) result = experiment() print(f"Predict: {result}") ================================================ FILE: pyproject.toml ================================================ # Example configuration for Black. # NOTE: you have to use single-quoted strings in TOML for regular expressions. # It's the equivalent of r-strings in Python. Multiline strings are treated as # verbose regular expressions by Black. Use [ ] to denote a significant space # character. [tool.black] line-length = 100 py36 = true include = '\.pyi?$' exclude = ''' /( \.git | \.hg | \.mypy_cache | \.tox | \.venv | _build | buck-out | build | dist # specific to claf | setup.py | __pycache__ | data | images | inference_result | logs | notebooks | model_config | script | summary # The following are specific to Black, you probably don't want those. | blib2to3 | tests/data | profiling )/ ''' ================================================ FILE: reports/inference_result/bert_for_qa-cpu.json ================================================ { "average_raw_to_tensor": 0.7418926316078263, "average_tensor_to_predict": 85.4424991992989, "average_end_to_end": 86.18439183090672, "tensor_to_predicts": [ { "elapsed_time": 165.971040725708, "token_count": 10 }, { "elapsed_time": 136.68274879455566, "token_count": 11 }, { "elapsed_time": 154.79207038879395, "token_count": 12 }, { "elapsed_time": 173.23875427246094, "token_count": 13 }, { "elapsed_time": 190.60564041137695, "token_count": 14 }, { "elapsed_time": 207.2291374206543, "token_count": 15 }, { "elapsed_time": 177.94513702392578, "token_count": 16 }, { "elapsed_time": 169.35205459594727, "token_count": 17 }, { "elapsed_time": 178.36904525756836, "token_count": 18 }, { "elapsed_time": 230.90004920959473, "token_count": 19 }, { "elapsed_time": 186.1860752105713, "token_count": 20 }, { "elapsed_time": 205.7051658630371, "token_count": 21 }, { "elapsed_time": 188.7838840484619, "token_count": 22 }, { "elapsed_time": 199.5537281036377, "token_count": 23 }, { "elapsed_time": 202.04710960388184, "token_count": 24 }, { "elapsed_time": 198.06313514709473, "token_count": 25 }, { "elapsed_time": 194.227933883667, "token_count": 26 }, { "elapsed_time": 197.78108596801758, "token_count": 27 }, { "elapsed_time": 213.79780769348145, "token_count": 28 }, { "elapsed_time": 206.5870761871338, "token_count": 29 }, { "elapsed_time": 205.718994140625, "token_count": 30 }, { "elapsed_time": 208.95838737487793, "token_count": 31 }, { "elapsed_time": 222.90372848510742, "token_count": 32 }, { "elapsed_time": 227.0190715789795, "token_count": 33 }, { "elapsed_time": 221.44794464111328, "token_count": 34 }, { "elapsed_time": 241.27793312072754, "token_count": 35 }, { "elapsed_time": 225.35395622253418, "token_count": 36 }, { "elapsed_time": 269.5138454437256, "token_count": 37 }, { "elapsed_time": 295.05324363708496, "token_count": 38 }, { "elapsed_time": 254.86993789672852, "token_count": 39 }, { "elapsed_time": 307.0361614227295, "token_count": 40 }, { "elapsed_time": 245.2218532562256, "token_count": 41 }, { "elapsed_time": 259.52911376953125, "token_count": 42 }, { "elapsed_time": 286.4530086517334, "token_count": 43 }, { "elapsed_time": 249.1142749786377, "token_count": 44 }, { "elapsed_time": 287.2958183288574, "token_count": 45 }, { "elapsed_time": 274.45220947265625, "token_count": 46 }, { "elapsed_time": 306.7820072174072, "token_count": 47 }, { "elapsed_time": 300.2350330352783, "token_count": 48 }, { "elapsed_time": 303.76482009887695, "token_count": 49 }, { "elapsed_time": 258.76712799072266, "token_count": 50 }, { "elapsed_time": 287.23716735839844, "token_count": 51 }, { "elapsed_time": 306.8361282348633, "token_count": 52 }, { "elapsed_time": 312.97898292541504, "token_count": 53 }, { "elapsed_time": 319.52977180480957, "token_count": 54 }, { "elapsed_time": 316.7433738708496, "token_count": 55 }, { "elapsed_time": 296.46778106689453, "token_count": 56 }, { "elapsed_time": 328.6020755767822, "token_count": 57 }, { "elapsed_time": 335.73198318481445, "token_count": 58 }, { "elapsed_time": 356.5230369567871, "token_count": 59 }, { "elapsed_time": 371.95277214050293, "token_count": 60 }, { "elapsed_time": 349.3800163269043, "token_count": 61 }, { "elapsed_time": 344.71607208251953, "token_count": 62 }, { "elapsed_time": 340.18468856811523, "token_count": 63 }, { "elapsed_time": 356.83298110961914, "token_count": 64 }, { "elapsed_time": 348.0079174041748, "token_count": 65 }, { "elapsed_time": 390.51079750061035, "token_count": 66 }, { "elapsed_time": 386.43813133239746, "token_count": 67 }, { "elapsed_time": 391.3700580596924, "token_count": 68 }, { "elapsed_time": 383.5337162017822, "token_count": 69 }, { "elapsed_time": 348.6979007720947, "token_count": 70 }, { "elapsed_time": 388.57293128967285, "token_count": 71 }, { "elapsed_time": 379.19116020202637, "token_count": 72 }, { "elapsed_time": 426.4483451843262, "token_count": 73 }, { "elapsed_time": 381.3300132751465, "token_count": 74 }, { "elapsed_time": 400.34985542297363, "token_count": 75 }, { "elapsed_time": 403.1178951263428, "token_count": 76 }, { "elapsed_time": 395.18213272094727, "token_count": 77 }, { "elapsed_time": 413.30909729003906, "token_count": 78 }, { "elapsed_time": 404.61111068725586, "token_count": 79 }, { "elapsed_time": 429.3079376220703, "token_count": 80 }, { "elapsed_time": 454.20193672180176, "token_count": 81 }, { "elapsed_time": 448.97985458374023, "token_count": 82 }, { "elapsed_time": 428.3151626586914, "token_count": 83 }, { "elapsed_time": 474.23505783081055, "token_count": 84 }, { "elapsed_time": 484.2970371246338, "token_count": 85 }, { "elapsed_time": 470.9022045135498, "token_count": 86 }, { "elapsed_time": 488.6510372161865, "token_count": 87 }, { "elapsed_time": 477.9789447784424, "token_count": 88 }, { "elapsed_time": 520.4360485076904, "token_count": 89 }, { "elapsed_time": 478.06596755981445, "token_count": 90 }, { "elapsed_time": 538.3880138397217, "token_count": 91 }, { "elapsed_time": 519.0162658691406, "token_count": 92 }, { "elapsed_time": 537.1859073638916, "token_count": 93 }, { "elapsed_time": 489.7441864013672, "token_count": 94 }, { "elapsed_time": 507.720947265625, "token_count": 95 }, { "elapsed_time": 547.6353168487549, "token_count": 96 }, { "elapsed_time": 517.4188613891602, "token_count": 97 }, { "elapsed_time": 522.0952033996582, "token_count": 98 }, { "elapsed_time": 527.1692276000977, "token_count": 99 }, { "elapsed_time": 513.253927230835, "token_count": 100 }, { "elapsed_time": 527.54807472229, "token_count": 101 }, { "elapsed_time": 549.8991012573242, "token_count": 102 }, { "elapsed_time": 600.9378433227539, "token_count": 103 }, { "elapsed_time": 585.5910778045654, "token_count": 104 }, { "elapsed_time": 616.5471076965332, "token_count": 105 }, { "elapsed_time": 541.7020320892334, "token_count": 106 }, { "elapsed_time": 532.3741436004639, "token_count": 107 }, { "elapsed_time": 532.3798656463623, "token_count": 108 }, { "elapsed_time": 603.1248569488525, "token_count": 109 }, { "elapsed_time": 603.3599376678467, "token_count": 110 }, { "elapsed_time": 583.3499431610107, "token_count": 111 }, { "elapsed_time": 579.2579650878906, "token_count": 112 }, { "elapsed_time": 621.3488578796387, "token_count": 113 }, { "elapsed_time": 636.3058090209961, "token_count": 114 }, { "elapsed_time": 567.2318935394287, "token_count": 115 }, { "elapsed_time": 585.3190422058105, "token_count": 116 }, { "elapsed_time": 609.0958118438721, "token_count": 117 }, { "elapsed_time": 640.0949954986572, "token_count": 118 }, { "elapsed_time": 621.1788654327393, "token_count": 119 }, { "elapsed_time": 620.668888092041, "token_count": 120 }, { "elapsed_time": 620.9800243377686, "token_count": 121 }, { "elapsed_time": 660.9649658203125, "token_count": 122 }, { "elapsed_time": 604.9530506134033, "token_count": 123 }, { "elapsed_time": 598.1481075286865, "token_count": 124 }, { "elapsed_time": 679.0461540222168, "token_count": 125 }, { "elapsed_time": 607.1128845214844, "token_count": 126 }, { "elapsed_time": 645.9732055664062, "token_count": 127 }, { "elapsed_time": 646.8539237976074, "token_count": 128 }, { "elapsed_time": 637.1009349822998, "token_count": 129 }, { "elapsed_time": 679.2159080505371, "token_count": 130 }, { "elapsed_time": 649.979829788208, "token_count": 131 }, { "elapsed_time": 654.9172401428223, "token_count": 132 }, { "elapsed_time": 684.7538948059082, "token_count": 133 }, { "elapsed_time": 710.5560302734375, "token_count": 134 }, { "elapsed_time": 750.6282329559326, "token_count": 135 }, { "elapsed_time": 703.193187713623, "token_count": 136 }, { "elapsed_time": 764.772891998291, "token_count": 137 }, { "elapsed_time": 719.7620868682861, "token_count": 138 }, { "elapsed_time": 709.5608711242676, "token_count": 139 }, { "elapsed_time": 697.6878643035889, "token_count": 140 }, { "elapsed_time": 718.1949615478516, "token_count": 141 }, { "elapsed_time": 785.1710319519043, "token_count": 142 }, { "elapsed_time": 790.3251647949219, "token_count": 143 }, { "elapsed_time": 707.4730396270752, "token_count": 144 }, { "elapsed_time": 673.3918190002441, "token_count": 145 }, { "elapsed_time": 719.782829284668, "token_count": 146 }, { "elapsed_time": 749.7279644012451, "token_count": 147 }, { "elapsed_time": 780.7950973510742, "token_count": 148 }, { "elapsed_time": 771.7950344085693, "token_count": 149 }, { "elapsed_time": 727.4320125579834, "token_count": 150 }, { "elapsed_time": 833.5781097412109, "token_count": 151 }, { "elapsed_time": 798.9060878753662, "token_count": 152 }, { "elapsed_time": 758.4891319274902, "token_count": 153 }, { "elapsed_time": 789.5581722259521, "token_count": 154 }, { "elapsed_time": 859.1389656066895, "token_count": 155 }, { "elapsed_time": 824.2921829223633, "token_count": 156 }, { "elapsed_time": 847.944974899292, "token_count": 157 }, { "elapsed_time": 809.7872734069824, "token_count": 158 }, { "elapsed_time": 809.3380928039551, "token_count": 159 }, { "elapsed_time": 788.1348133087158, "token_count": 160 }, { "elapsed_time": 827.103853225708, "token_count": 161 }, { "elapsed_time": 813.5678768157959, "token_count": 162 }, { "elapsed_time": 981.788158416748, "token_count": 163 }, { "elapsed_time": 894.0699100494385, "token_count": 164 }, { "elapsed_time": 834.8019123077393, "token_count": 165 }, { "elapsed_time": 845.6692695617676, "token_count": 166 }, { "elapsed_time": 823.1420516967773, "token_count": 167 }, { "elapsed_time": 891.5278911590576, "token_count": 168 }, { "elapsed_time": 834.7651958465576, "token_count": 169 }, { "elapsed_time": 845.1728820800781, "token_count": 170 }, { "elapsed_time": 866.7709827423096, "token_count": 171 }, { "elapsed_time": 860.828161239624, "token_count": 172 }, { "elapsed_time": 834.5828056335449, "token_count": 173 }, { "elapsed_time": 2639.5750045776367, "token_count": 174 } ], "max_token_count_per_time": { "200": 27, "300": 56, "400": 77, "500": 94, "600": 124, "700": 145, "800": 160, "900": 173, "1000": 173, "1100": 173, "1200": 173, "1300": 173, "1400": 173, "1500": 173 } } ================================================ FILE: reports/inference_result/bidaf+elmo-cpu.json ================================================ { "average_raw_to_tensor": 0.08636821400035512, "average_tensor_to_predict": 35.91229337634462, "average_end_to_end": 35.99866159034498, "tensor_to_predicts": [ { "elapsed_time": 409.0240001678467, "token_count": 10 }, { "elapsed_time": 424.2978096008301, "token_count": 11 }, { "elapsed_time": 453.9320468902588, "token_count": 12 }, { "elapsed_time": 484.1651916503906, "token_count": 13 }, { "elapsed_time": 516.8399810791016, "token_count": 14 }, { "elapsed_time": 553.3709526062012, "token_count": 15 }, { "elapsed_time": 577.5477886199951, "token_count": 16 }, { "elapsed_time": 614.0329837799072, "token_count": 17 }, { "elapsed_time": 651.1709690093994, "token_count": 18 }, { "elapsed_time": 670.1388359069824, "token_count": 19 }, { "elapsed_time": 749.9408721923828, "token_count": 20 }, { "elapsed_time": 765.0890350341797, "token_count": 21 }, { "elapsed_time": 735.0962162017822, "token_count": 22 }, { "elapsed_time": 782.1478843688965, "token_count": 23 }, { "elapsed_time": 796.2613105773926, "token_count": 24 }, { "elapsed_time": 839.2610549926758, "token_count": 25 }, { "elapsed_time": 824.5720863342285, "token_count": 26 }, { "elapsed_time": 854.9871444702148, "token_count": 27 }, { "elapsed_time": 906.904935836792, "token_count": 28 }, { "elapsed_time": 916.7580604553223, "token_count": 29 }, { "elapsed_time": 956.9301605224609, "token_count": 30 }, { "elapsed_time": 1003.1847953796387, "token_count": 31 }, { "elapsed_time": 1117.8290843963623, "token_count": 32 }, { "elapsed_time": 1066.0440921783447, "token_count": 33 }, { "elapsed_time": 1074.455976486206, "token_count": 34 }, { "elapsed_time": 1105.8878898620605, "token_count": 35 }, { "elapsed_time": 1122.76291847229, "token_count": 36 }, { "elapsed_time": 1168.5528755187988, "token_count": 37 }, { "elapsed_time": 1191.5271282196045, "token_count": 38 }, { "elapsed_time": 1234.421968460083, "token_count": 39 }, { "elapsed_time": 1255.2640438079834, "token_count": 40 }, { "elapsed_time": 1317.5408840179443, "token_count": 41 }, { "elapsed_time": 1329.1430473327637, "token_count": 42 }, { "elapsed_time": 1338.5398387908936, "token_count": 43 }, { "elapsed_time": 1363.4569644927979, "token_count": 44 }, { "elapsed_time": 1412.2247695922852, "token_count": 45 }, { "elapsed_time": 1462.920904159546, "token_count": 46 }, { "elapsed_time": 1506.943941116333, "token_count": 47 } ], "max_token_count_per_time": { "500": 13, "600": 16, "700": 19, "800": 24, "900": 27, "1000": 30, "1100": 34, "1200": 38, "1300": 40, "1400": 44, "1500": 46 } } ================================================ FILE: reports/inference_result/bidaf-cpu.json ================================================ { "average_raw_to_tensor": 5.867820315890842, "average_tensor_to_predict": 335.21361013855596, "average_end_to_end": 341.08143045444683, "tensor_to_predicts": [ { "elapsed_time": 62.13784217834473, "token_count": 10 }, { "elapsed_time": 16.222238540649414, "token_count": 11 }, { "elapsed_time": 16.011953353881836, "token_count": 12 }, { "elapsed_time": 17.163991928100586, "token_count": 13 }, { "elapsed_time": 18.846988677978516, "token_count": 14 }, { "elapsed_time": 19.0279483795166, "token_count": 15 }, { "elapsed_time": 19.305944442749023, "token_count": 16 }, { "elapsed_time": 20.991086959838867, "token_count": 17 }, { "elapsed_time": 21.973133087158203, "token_count": 18 }, { "elapsed_time": 24.37877655029297, "token_count": 19 }, { "elapsed_time": 23.483991622924805, "token_count": 20 }, { "elapsed_time": 25.213956832885742, "token_count": 21 }, { "elapsed_time": 25.713205337524414, "token_count": 22 }, { "elapsed_time": 27.135133743286133, "token_count": 23 }, { "elapsed_time": 27.87923812866211, "token_count": 24 }, { "elapsed_time": 29.041290283203125, "token_count": 25 }, { "elapsed_time": 31.92901611328125, "token_count": 26 }, { "elapsed_time": 35.86316108703613, "token_count": 27 }, { "elapsed_time": 32.334089279174805, "token_count": 28 }, { "elapsed_time": 33.53714942932129, "token_count": 29 }, { "elapsed_time": 35.82119941711426, "token_count": 30 }, { "elapsed_time": 38.6960506439209, "token_count": 31 }, { "elapsed_time": 37.36686706542969, "token_count": 32 }, { "elapsed_time": 41.869163513183594, "token_count": 33 }, { "elapsed_time": 39.75200653076172, "token_count": 34 }, { "elapsed_time": 40.361881256103516, "token_count": 35 }, { "elapsed_time": 42.598724365234375, "token_count": 36 }, { "elapsed_time": 43.7779426574707, "token_count": 37 }, { "elapsed_time": 44.051170349121094, "token_count": 38 }, { "elapsed_time": 48.08402061462402, "token_count": 39 }, { "elapsed_time": 46.10419273376465, "token_count": 40 }, { "elapsed_time": 49.285888671875, "token_count": 41 }, { "elapsed_time": 54.31175231933594, "token_count": 42 }, { "elapsed_time": 51.783084869384766, "token_count": 43 }, { "elapsed_time": 54.353952407836914, "token_count": 44 }, { "elapsed_time": 59.13496017456055, "token_count": 45 }, { "elapsed_time": 56.42294883728027, "token_count": 46 }, { "elapsed_time": 58.589935302734375, "token_count": 47 }, { "elapsed_time": 57.83200263977051, "token_count": 48 }, { "elapsed_time": 58.294057846069336, "token_count": 49 }, { "elapsed_time": 58.44879150390625, "token_count": 50 }, { "elapsed_time": 62.30425834655762, "token_count": 51 }, { "elapsed_time": 62.01767921447754, "token_count": 52 }, { "elapsed_time": 63.64321708679199, "token_count": 53 }, { "elapsed_time": 65.79303741455078, "token_count": 54 }, { "elapsed_time": 66.87211990356445, "token_count": 55 }, { "elapsed_time": 68.1452751159668, "token_count": 56 }, { "elapsed_time": 67.0778751373291, "token_count": 57 }, { "elapsed_time": 67.70110130310059, "token_count": 58 }, { "elapsed_time": 71.57492637634277, "token_count": 59 }, { "elapsed_time": 71.33722305297852, "token_count": 60 }, { "elapsed_time": 74.10407066345215, "token_count": 61 }, { "elapsed_time": 78.57704162597656, "token_count": 62 }, { "elapsed_time": 78.96971702575684, "token_count": 63 }, { "elapsed_time": 78.47476005554199, "token_count": 64 }, { "elapsed_time": 82.55791664123535, "token_count": 65 }, { "elapsed_time": 83.16898345947266, "token_count": 66 }, { "elapsed_time": 85.07394790649414, "token_count": 67 }, { "elapsed_time": 84.61689949035645, "token_count": 68 }, { "elapsed_time": 87.51821517944336, "token_count": 69 }, { "elapsed_time": 86.29393577575684, "token_count": 70 }, { "elapsed_time": 87.97216415405273, "token_count": 71 }, { "elapsed_time": 87.57925033569336, "token_count": 72 }, { "elapsed_time": 90.8820629119873, "token_count": 73 }, { "elapsed_time": 93.00613403320312, "token_count": 74 }, { "elapsed_time": 94.38586235046387, "token_count": 75 }, { "elapsed_time": 98.09422492980957, "token_count": 76 }, { "elapsed_time": 98.31595420837402, "token_count": 77 }, { "elapsed_time": 97.38397598266602, "token_count": 78 }, { "elapsed_time": 100.89397430419922, "token_count": 79 }, { "elapsed_time": 99.67780113220215, "token_count": 80 }, { "elapsed_time": 101.14288330078125, "token_count": 81 }, { "elapsed_time": 111.35220527648926, "token_count": 82 }, { "elapsed_time": 108.67094993591309, "token_count": 83 }, { "elapsed_time": 107.03277587890625, "token_count": 84 }, { "elapsed_time": 110.61596870422363, "token_count": 85 }, { "elapsed_time": 114.74990844726562, "token_count": 86 }, { "elapsed_time": 113.78312110900879, "token_count": 87 }, { "elapsed_time": 114.03489112854004, "token_count": 88 }, { "elapsed_time": 119.4310188293457, "token_count": 89 }, { "elapsed_time": 118.51787567138672, "token_count": 90 }, { "elapsed_time": 117.49768257141113, "token_count": 91 }, { "elapsed_time": 118.64495277404785, "token_count": 92 }, { "elapsed_time": 121.5522289276123, "token_count": 93 }, { "elapsed_time": 127.58016586303711, "token_count": 94 }, { "elapsed_time": 123.76904487609863, "token_count": 95 }, { "elapsed_time": 128.75604629516602, "token_count": 96 }, { "elapsed_time": 128.5421848297119, "token_count": 97 }, { "elapsed_time": 129.12487983703613, "token_count": 98 }, { "elapsed_time": 130.34701347351074, "token_count": 99 }, { "elapsed_time": 137.50696182250977, "token_count": 100 }, { "elapsed_time": 134.9341869354248, "token_count": 101 }, { "elapsed_time": 138.17977905273438, "token_count": 102 }, { "elapsed_time": 140.9752368927002, "token_count": 103 }, { "elapsed_time": 139.86802101135254, "token_count": 104 }, { "elapsed_time": 139.07098770141602, "token_count": 105 }, { "elapsed_time": 142.47798919677734, "token_count": 106 }, { "elapsed_time": 146.39711380004883, "token_count": 107 }, { "elapsed_time": 147.14717864990234, "token_count": 108 }, { "elapsed_time": 151.0782241821289, "token_count": 109 }, { "elapsed_time": 150.7718563079834, "token_count": 110 }, { "elapsed_time": 149.71375465393066, "token_count": 111 }, { "elapsed_time": 152.82392501831055, "token_count": 112 }, { "elapsed_time": 152.84490585327148, "token_count": 113 }, { "elapsed_time": 156.4350128173828, "token_count": 114 }, { "elapsed_time": 165.1589870452881, "token_count": 115 }, { "elapsed_time": 155.11083602905273, "token_count": 116 }, { "elapsed_time": 156.81791305541992, "token_count": 117 }, { "elapsed_time": 185.23025512695312, "token_count": 118 }, { "elapsed_time": 189.79501724243164, "token_count": 119 }, { "elapsed_time": 166.3830280303955, "token_count": 120 }, { "elapsed_time": 167.36197471618652, "token_count": 121 }, { "elapsed_time": 168.60198974609375, "token_count": 122 }, { "elapsed_time": 169.20924186706543, "token_count": 123 }, { "elapsed_time": 165.70186614990234, "token_count": 124 }, { "elapsed_time": 168.40124130249023, "token_count": 125 }, { "elapsed_time": 169.97289657592773, "token_count": 126 }, { "elapsed_time": 174.9289035797119, "token_count": 127 }, { "elapsed_time": 177.9332160949707, "token_count": 128 }, { "elapsed_time": 186.9361400604248, "token_count": 129 }, { "elapsed_time": 181.50711059570312, "token_count": 130 }, { "elapsed_time": 185.3930950164795, "token_count": 131 }, { "elapsed_time": 187.3338222503662, "token_count": 132 }, { "elapsed_time": 188.9479160308838, "token_count": 133 }, { "elapsed_time": 185.4879856109619, "token_count": 134 }, { "elapsed_time": 193.09210777282715, "token_count": 135 }, { "elapsed_time": 194.12469863891602, "token_count": 136 }, { "elapsed_time": 193.20178031921387, "token_count": 137 }, { "elapsed_time": 202.51083374023438, "token_count": 138 }, { "elapsed_time": 197.56317138671875, "token_count": 139 }, { "elapsed_time": 197.5119113922119, "token_count": 140 }, { "elapsed_time": 204.29611206054688, "token_count": 141 }, { "elapsed_time": 211.94195747375488, "token_count": 142 }, { "elapsed_time": 224.75862503051758, "token_count": 143 }, { "elapsed_time": 220.66712379455566, "token_count": 144 }, { "elapsed_time": 212.80717849731445, "token_count": 145 }, { "elapsed_time": 216.4897918701172, "token_count": 146 }, { "elapsed_time": 224.39289093017578, "token_count": 147 }, { "elapsed_time": 225.4958152770996, "token_count": 148 }, { "elapsed_time": 223.88195991516113, "token_count": 149 }, { "elapsed_time": 222.53894805908203, "token_count": 150 }, { "elapsed_time": 227.2341251373291, "token_count": 151 }, { "elapsed_time": 234.94195938110352, "token_count": 152 }, { "elapsed_time": 230.147123336792, "token_count": 153 }, { "elapsed_time": 230.87072372436523, "token_count": 154 }, { "elapsed_time": 232.12695121765137, "token_count": 155 }, { "elapsed_time": 241.40596389770508, "token_count": 156 }, { "elapsed_time": 242.41209030151367, "token_count": 157 }, { "elapsed_time": 239.9299144744873, "token_count": 158 }, { "elapsed_time": 237.17188835144043, "token_count": 159 }, { "elapsed_time": 245.01991271972656, "token_count": 160 }, { "elapsed_time": 238.65079879760742, "token_count": 161 }, { "elapsed_time": 242.27476119995117, "token_count": 162 }, { "elapsed_time": 254.75788116455078, "token_count": 163 }, { "elapsed_time": 254.15706634521484, "token_count": 164 }, { "elapsed_time": 252.48408317565918, "token_count": 165 }, { "elapsed_time": 286.1020565032959, "token_count": 166 }, { "elapsed_time": 264.57810401916504, "token_count": 167 }, { "elapsed_time": 254.62985038757324, "token_count": 168 }, { "elapsed_time": 254.70685958862305, "token_count": 169 }, { "elapsed_time": 257.9371929168701, "token_count": 170 }, { "elapsed_time": 257.0948600769043, "token_count": 171 }, { "elapsed_time": 264.62578773498535, "token_count": 172 }, { "elapsed_time": 263.8969421386719, "token_count": 173 }, { "elapsed_time": 266.603946685791, "token_count": 174 }, { "elapsed_time": 277.7128219604492, "token_count": 175 }, { "elapsed_time": 271.49009704589844, "token_count": 176 }, { "elapsed_time": 274.8551368713379, "token_count": 177 }, { "elapsed_time": 276.7610549926758, "token_count": 178 }, { "elapsed_time": 281.4028263092041, "token_count": 179 }, { "elapsed_time": 285.02702713012695, "token_count": 180 }, { "elapsed_time": 280.03525733947754, "token_count": 181 }, { "elapsed_time": 286.7908477783203, "token_count": 182 }, { "elapsed_time": 288.87200355529785, "token_count": 183 }, { "elapsed_time": 292.6919460296631, "token_count": 184 }, { "elapsed_time": 289.304256439209, "token_count": 185 }, { "elapsed_time": 293.3039665222168, "token_count": 186 }, { "elapsed_time": 293.20597648620605, "token_count": 187 }, { "elapsed_time": 300.9510040283203, "token_count": 188 }, { "elapsed_time": 305.8469295501709, "token_count": 189 }, { "elapsed_time": 302.00982093811035, "token_count": 190 }, { "elapsed_time": 306.7891597747803, "token_count": 191 }, { "elapsed_time": 316.4820671081543, "token_count": 192 }, { "elapsed_time": 304.14319038391113, "token_count": 193 }, { "elapsed_time": 310.38689613342285, "token_count": 194 }, { "elapsed_time": 313.3249282836914, "token_count": 195 }, { "elapsed_time": 315.26994705200195, "token_count": 196 }, { "elapsed_time": 311.63501739501953, "token_count": 197 }, { "elapsed_time": 315.57703018188477, "token_count": 198 }, { "elapsed_time": 331.58397674560547, "token_count": 199 }, { "elapsed_time": 336.7290496826172, "token_count": 200 }, { "elapsed_time": 344.620943069458, "token_count": 201 }, { "elapsed_time": 329.3278217315674, "token_count": 202 }, { "elapsed_time": 325.6492614746094, "token_count": 203 }, { "elapsed_time": 333.97507667541504, "token_count": 204 }, { "elapsed_time": 335.9990119934082, "token_count": 205 }, { "elapsed_time": 340.33703804016113, "token_count": 206 }, { "elapsed_time": 344.44308280944824, "token_count": 207 }, { "elapsed_time": 344.1309928894043, "token_count": 208 }, { "elapsed_time": 345.3068733215332, "token_count": 209 }, { "elapsed_time": 355.1821708679199, "token_count": 210 }, { "elapsed_time": 374.6027946472168, "token_count": 211 }, { "elapsed_time": 361.3901138305664, "token_count": 212 }, { "elapsed_time": 358.11495780944824, "token_count": 213 }, { "elapsed_time": 355.5760383605957, "token_count": 214 }, { "elapsed_time": 366.69421195983887, "token_count": 215 }, { "elapsed_time": 359.8208427429199, "token_count": 216 }, { "elapsed_time": 365.8251762390137, "token_count": 217 }, { "elapsed_time": 365.8897876739502, "token_count": 218 }, { "elapsed_time": 369.11797523498535, "token_count": 219 }, { "elapsed_time": 365.0979995727539, "token_count": 220 }, { "elapsed_time": 371.0436820983887, "token_count": 221 }, { "elapsed_time": 378.57794761657715, "token_count": 222 }, { "elapsed_time": 380.0618648529053, "token_count": 223 }, { "elapsed_time": 380.5208206176758, "token_count": 224 }, { "elapsed_time": 396.2109088897705, "token_count": 225 }, { "elapsed_time": 378.8738250732422, "token_count": 226 }, { "elapsed_time": 392.53902435302734, "token_count": 227 }, { "elapsed_time": 412.625789642334, "token_count": 228 }, { "elapsed_time": 400.84385871887207, "token_count": 229 }, { "elapsed_time": 395.24197578430176, "token_count": 230 }, { "elapsed_time": 399.5180130004883, "token_count": 231 }, { "elapsed_time": 402.25720405578613, "token_count": 232 }, { "elapsed_time": 403.2571315765381, "token_count": 233 }, { "elapsed_time": 401.79920196533203, "token_count": 234 }, { "elapsed_time": 401.5331268310547, "token_count": 235 }, { "elapsed_time": 399.3878364562988, "token_count": 236 }, { "elapsed_time": 425.7321357727051, "token_count": 237 }, { "elapsed_time": 407.9318046569824, "token_count": 238 }, { "elapsed_time": 417.72007942199707, "token_count": 239 }, { "elapsed_time": 415.2061939239502, "token_count": 240 }, { "elapsed_time": 418.8380241394043, "token_count": 241 }, { "elapsed_time": 425.85301399230957, "token_count": 242 }, { "elapsed_time": 420.6819534301758, "token_count": 243 }, { "elapsed_time": 417.0877933502197, "token_count": 244 }, { "elapsed_time": 426.131010055542, "token_count": 245 }, { "elapsed_time": 420.92084884643555, "token_count": 246 }, { "elapsed_time": 426.50508880615234, "token_count": 247 }, { "elapsed_time": 429.9001693725586, "token_count": 248 }, { "elapsed_time": 435.1069927215576, "token_count": 249 }, { "elapsed_time": 429.72278594970703, "token_count": 250 }, { "elapsed_time": 446.80023193359375, "token_count": 251 }, { "elapsed_time": 494.2159652709961, "token_count": 252 }, { "elapsed_time": 455.03783226013184, "token_count": 253 }, { "elapsed_time": 451.8866539001465, "token_count": 254 }, { "elapsed_time": 452.4967670440674, "token_count": 255 }, { "elapsed_time": 448.06694984436035, "token_count": 256 }, { "elapsed_time": 450.3498077392578, "token_count": 257 }, { "elapsed_time": 462.3229503631592, "token_count": 258 }, { "elapsed_time": 450.897216796875, "token_count": 259 }, { "elapsed_time": 463.34099769592285, "token_count": 260 }, { "elapsed_time": 468.00875663757324, "token_count": 261 }, { "elapsed_time": 462.4669551849365, "token_count": 262 }, { "elapsed_time": 466.43567085266113, "token_count": 263 }, { "elapsed_time": 465.5437469482422, "token_count": 264 }, { "elapsed_time": 473.7050533294678, "token_count": 265 }, { "elapsed_time": 480.4959297180176, "token_count": 266 }, { "elapsed_time": 484.72118377685547, "token_count": 267 }, { "elapsed_time": 477.4348735809326, "token_count": 268 }, { "elapsed_time": 478.02090644836426, "token_count": 269 }, { "elapsed_time": 491.2538528442383, "token_count": 270 }, { "elapsed_time": 499.15480613708496, "token_count": 271 }, { "elapsed_time": 492.2609329223633, "token_count": 272 }, { "elapsed_time": 502.20274925231934, "token_count": 273 }, { "elapsed_time": 547.1611022949219, "token_count": 274 }, { "elapsed_time": 505.0802230834961, "token_count": 275 }, { "elapsed_time": 498.05593490600586, "token_count": 276 }, { "elapsed_time": 508.85009765625, "token_count": 277 }, { "elapsed_time": 504.1229724884033, "token_count": 278 }, { "elapsed_time": 499.7239112854004, "token_count": 279 }, { "elapsed_time": 508.44502449035645, "token_count": 280 }, { "elapsed_time": 511.9926929473877, "token_count": 281 }, { "elapsed_time": 523.6489772796631, "token_count": 282 }, { "elapsed_time": 523.4718322753906, "token_count": 283 }, { "elapsed_time": 519.3850994110107, "token_count": 284 }, { "elapsed_time": 525.7408618927002, "token_count": 285 }, { "elapsed_time": 527.3730754852295, "token_count": 286 }, { "elapsed_time": 524.1899490356445, "token_count": 287 }, { "elapsed_time": 529.7901630401611, "token_count": 288 }, { "elapsed_time": 536.9760990142822, "token_count": 289 }, { "elapsed_time": 539.2229557037354, "token_count": 290 }, { "elapsed_time": 539.2158031463623, "token_count": 291 }, { "elapsed_time": 542.9210662841797, "token_count": 292 }, { "elapsed_time": 581.6259384155273, "token_count": 293 }, { "elapsed_time": 564.2130374908447, "token_count": 294 }, { "elapsed_time": 550.5759716033936, "token_count": 295 }, { "elapsed_time": 553.462028503418, "token_count": 296 }, { "elapsed_time": 551.6600608825684, "token_count": 297 }, { "elapsed_time": 558.5448741912842, "token_count": 298 }, { "elapsed_time": 554.3992519378662, "token_count": 299 }, { "elapsed_time": 563.8749599456787, "token_count": 300 }, { "elapsed_time": 571.8111991882324, "token_count": 301 }, { "elapsed_time": 565.9127235412598, "token_count": 302 }, { "elapsed_time": 575.6180286407471, "token_count": 303 }, { "elapsed_time": 578.5820484161377, "token_count": 304 }, { "elapsed_time": 575.4501819610596, "token_count": 305 }, { "elapsed_time": 573.8921165466309, "token_count": 306 }, { "elapsed_time": 588.1481170654297, "token_count": 307 }, { "elapsed_time": 584.0880870819092, "token_count": 308 }, { "elapsed_time": 586.5657329559326, "token_count": 309 }, { "elapsed_time": 595.5183506011963, "token_count": 310 }, { "elapsed_time": 637.9220485687256, "token_count": 311 }, { "elapsed_time": 600.0270843505859, "token_count": 312 }, { "elapsed_time": 605.3450107574463, "token_count": 313 }, { "elapsed_time": 599.0078449249268, "token_count": 314 }, { "elapsed_time": 598.7069606781006, "token_count": 315 }, { "elapsed_time": 597.0721244812012, "token_count": 316 }, { "elapsed_time": 607.7761650085449, "token_count": 317 }, { "elapsed_time": 613.6441230773926, "token_count": 318 }, { "elapsed_time": 612.2570037841797, "token_count": 319 }, { "elapsed_time": 612.6351356506348, "token_count": 320 }, { "elapsed_time": 624.769926071167, "token_count": 321 }, { "elapsed_time": 621.1049556732178, "token_count": 322 }, { "elapsed_time": 625.6289482116699, "token_count": 323 }, { "elapsed_time": 649.1332054138184, "token_count": 324 }, { "elapsed_time": 632.9991817474365, "token_count": 325 }, { "elapsed_time": 631.7660808563232, "token_count": 326 }, { "elapsed_time": 672.1367835998535, "token_count": 327 }, { "elapsed_time": 644.9418067932129, "token_count": 328 }, { "elapsed_time": 640.0299072265625, "token_count": 329 }, { "elapsed_time": 637.0010375976562, "token_count": 330 }, { "elapsed_time": 641.8001651763916, "token_count": 331 }, { "elapsed_time": 654.6058654785156, "token_count": 332 }, { "elapsed_time": 666.7661666870117, "token_count": 333 }, { "elapsed_time": 659.5032215118408, "token_count": 334 }, { "elapsed_time": 665.7872200012207, "token_count": 335 }, { "elapsed_time": 665.0857925415039, "token_count": 336 }, { "elapsed_time": 668.2066917419434, "token_count": 337 }, { "elapsed_time": 673.3362674713135, "token_count": 338 }, { "elapsed_time": 677.4981021881104, "token_count": 339 }, { "elapsed_time": 677.1011352539062, "token_count": 340 }, { "elapsed_time": 676.5961647033691, "token_count": 341 }, { "elapsed_time": 709.9220752716064, "token_count": 342 }, { "elapsed_time": 715.717077255249, "token_count": 343 }, { "elapsed_time": 688.7779235839844, "token_count": 344 }, { "elapsed_time": 688.8248920440674, "token_count": 345 }, { "elapsed_time": 704.2229175567627, "token_count": 346 }, { "elapsed_time": 694.2873001098633, "token_count": 347 }, { "elapsed_time": 698.40407371521, "token_count": 348 }, { "elapsed_time": 699.6040344238281, "token_count": 349 }, { "elapsed_time": 722.3861217498779, "token_count": 350 }, { "elapsed_time": 697.0219612121582, "token_count": 351 }, { "elapsed_time": 712.6810550689697, "token_count": 352 }, { "elapsed_time": 709.8731994628906, "token_count": 353 }, { "elapsed_time": 734.27414894104, "token_count": 354 }, { "elapsed_time": 724.8461246490479, "token_count": 355 }, { "elapsed_time": 725.2058982849121, "token_count": 356 }, { "elapsed_time": 777.3990631103516, "token_count": 357 }, { "elapsed_time": 733.6368560791016, "token_count": 358 }, { "elapsed_time": 732.6760292053223, "token_count": 359 }, { "elapsed_time": 735.4631423950195, "token_count": 360 }, { "elapsed_time": 738.9090061187744, "token_count": 361 }, { "elapsed_time": 739.6328449249268, "token_count": 362 }, { "elapsed_time": 742.6891326904297, "token_count": 363 }, { "elapsed_time": 754.1179656982422, "token_count": 364 }, { "elapsed_time": 754.0450096130371, "token_count": 365 }, { "elapsed_time": 767.8468227386475, "token_count": 366 }, { "elapsed_time": 771.4192867279053, "token_count": 367 }, { "elapsed_time": 785.4800224304199, "token_count": 368 }, { "elapsed_time": 797.9602813720703, "token_count": 369 }, { "elapsed_time": 817.5239562988281, "token_count": 370 }, { "elapsed_time": 767.4849033355713, "token_count": 371 }, { "elapsed_time": 787.7838611602783, "token_count": 372 }, { "elapsed_time": 782.1598052978516, "token_count": 373 }, { "elapsed_time": 794.9643135070801, "token_count": 374 }, { "elapsed_time": 783.6089134216309, "token_count": 375 }, { "elapsed_time": 811.6679191589355, "token_count": 376 }, { "elapsed_time": 794.8837280273438, "token_count": 377 }, { "elapsed_time": 801.6860485076904, "token_count": 378 }, { "elapsed_time": 795.116662979126, "token_count": 379 }, { "elapsed_time": 799.0620136260986, "token_count": 380 }, { "elapsed_time": 811.8622303009033, "token_count": 381 }, { "elapsed_time": 814.7976398468018, "token_count": 382 }, { "elapsed_time": 858.6070537567139, "token_count": 383 }, { "elapsed_time": 831.3829898834229, "token_count": 384 }, { "elapsed_time": 829.2961120605469, "token_count": 385 }, { "elapsed_time": 853.9199829101562, "token_count": 386 }, { "elapsed_time": 824.6307373046875, "token_count": 387 }, { "elapsed_time": 834.3989849090576, "token_count": 388 }, { "elapsed_time": 826.8558979034424, "token_count": 389 }, { "elapsed_time": 832.2029113769531, "token_count": 390 }, { "elapsed_time": 850.4238128662109, "token_count": 391 }, { "elapsed_time": 829.322099685669, "token_count": 392 }, { "elapsed_time": 845.3800678253174, "token_count": 393 }, { "elapsed_time": 855.89599609375, "token_count": 394 }, { "elapsed_time": 882.4560642242432, "token_count": 395 }, { "elapsed_time": 853.701114654541, "token_count": 396 }, { "elapsed_time": 856.7061424255371, "token_count": 397 }, { "elapsed_time": 859.3971729278564, "token_count": 398 }, { "elapsed_time": 857.6898574829102, "token_count": 399 }, { "elapsed_time": 866.3430213928223, "token_count": 400 }, { "elapsed_time": 871.574878692627, "token_count": 401 }, { "elapsed_time": 869.5089817047119, "token_count": 402 }, { "elapsed_time": 873.8663196563721, "token_count": 403 }, { "elapsed_time": 875.709056854248, "token_count": 404 }, { "elapsed_time": 872.5948333740234, "token_count": 405 }, { "elapsed_time": 921.6487407684326, "token_count": 406 }, { "elapsed_time": 857.60498046875, "token_count": 407 }, { "elapsed_time": 850.5361080169678, "token_count": 408 }, { "elapsed_time": 856.9450378417969, "token_count": 409 }, { "elapsed_time": 876.5008449554443, "token_count": 410 }, { "elapsed_time": 865.0968074798584, "token_count": 411 }, { "elapsed_time": 866.1119937896729, "token_count": 412 }, { "elapsed_time": 918.0610179901123, "token_count": 413 }, { "elapsed_time": 908.1909656524658, "token_count": 414 }, { "elapsed_time": 904.60205078125, "token_count": 415 }, { "elapsed_time": 932.1341514587402, "token_count": 416 }, { "elapsed_time": 930.2082061767578, "token_count": 417 }, { "elapsed_time": 947.8180408477783, "token_count": 418 }, { "elapsed_time": 914.9999618530273, "token_count": 419 }, { "elapsed_time": 892.1658992767334, "token_count": 420 }, { "elapsed_time": 903.8169384002686, "token_count": 421 }, { "elapsed_time": 892.0462131500244, "token_count": 422 }, { "elapsed_time": 907.1600437164307, "token_count": 423 }, { "elapsed_time": 917.8471565246582, "token_count": 424 }, { "elapsed_time": 925.3268241882324, "token_count": 425 }, { "elapsed_time": 908.4153175354004, "token_count": 426 }, { "elapsed_time": 943.4559345245361, "token_count": 427 }, { "elapsed_time": 910.0527763366699, "token_count": 428 }, { "elapsed_time": 958.9219093322754, "token_count": 429 }, { "elapsed_time": 937.086820602417, "token_count": 430 }, { "elapsed_time": 921.4839935302734, "token_count": 431 }, { "elapsed_time": 921.7789173126221, "token_count": 432 }, { "elapsed_time": 949.0938186645508, "token_count": 433 }, { "elapsed_time": 933.8688850402832, "token_count": 434 }, { "elapsed_time": 932.9617023468018, "token_count": 435 }, { "elapsed_time": 942.4290657043457, "token_count": 436 }, { "elapsed_time": 958.8119983673096, "token_count": 437 }, { "elapsed_time": 973.6158847808838, "token_count": 438 }, { "elapsed_time": 987.7569675445557, "token_count": 439 }, { "elapsed_time": 982.8140735626221, "token_count": 440 }, { "elapsed_time": 966.7000770568848, "token_count": 441 }, { "elapsed_time": 962.3968601226807, "token_count": 442 }, { "elapsed_time": 1024.6531963348389, "token_count": 443 }, { "elapsed_time": 1018.359899520874, "token_count": 444 }, { "elapsed_time": 1047.145128250122, "token_count": 445 }, { "elapsed_time": 1052.8199672698975, "token_count": 446 }, { "elapsed_time": 1054.7068119049072, "token_count": 447 }, { "elapsed_time": 1080.5950164794922, "token_count": 448 }, { "elapsed_time": 1061.5050792694092, "token_count": 449 }, { "elapsed_time": 1031.270980834961, "token_count": 450 }, { "elapsed_time": 1032.196044921875, "token_count": 451 }, { "elapsed_time": 1065.216064453125, "token_count": 452 }, { "elapsed_time": 1094.2878723144531, "token_count": 453 }, { "elapsed_time": 1073.3230113983154, "token_count": 454 }, { "elapsed_time": 1071.3698863983154, "token_count": 455 }, { "elapsed_time": 1057.5852394104004, "token_count": 456 }, { "elapsed_time": 1107.8059673309326, "token_count": 457 }, { "elapsed_time": 1127.4433135986328, "token_count": 458 }, { "elapsed_time": 1143.3451175689697, "token_count": 459 }, { "elapsed_time": 1123.2619285583496, "token_count": 460 }, { "elapsed_time": 1148.8351821899414, "token_count": 461 }, { "elapsed_time": 1138.772964477539, "token_count": 462 }, { "elapsed_time": 1167.6979064941406, "token_count": 463 }, { "elapsed_time": 1132.261037826538, "token_count": 464 }, { "elapsed_time": 1194.6890354156494, "token_count": 465 }, { "elapsed_time": 1432.2509765625, "token_count": 466 }, { "elapsed_time": 1198.3931064605713, "token_count": 467 }, { "elapsed_time": 1233.3378791809082, "token_count": 468 }, { "elapsed_time": 1266.793966293335, "token_count": 469 }, { "elapsed_time": 1271.022081375122, "token_count": 470 }, { "elapsed_time": 1214.1079902648926, "token_count": 471 }, { "elapsed_time": 1184.654951095581, "token_count": 472 }, { "elapsed_time": 1153.2421112060547, "token_count": 473 }, { "elapsed_time": 1178.3607006072998, "token_count": 474 }, { "elapsed_time": 1214.2219543457031, "token_count": 475 }, { "elapsed_time": 1210.4589939117432, "token_count": 476 }, { "elapsed_time": 1219.1529273986816, "token_count": 477 }, { "elapsed_time": 1241.7538166046143, "token_count": 478 }, { "elapsed_time": 1210.547924041748, "token_count": 479 }, { "elapsed_time": 1197.5979804992676, "token_count": 480 }, { "elapsed_time": 1188.7669563293457, "token_count": 481 }, { "elapsed_time": 1217.8168296813965, "token_count": 482 }, { "elapsed_time": 1164.4926071166992, "token_count": 483 }, { "elapsed_time": 1176.1510372161865, "token_count": 484 }, { "elapsed_time": 1107.550859451294, "token_count": 485 }, { "elapsed_time": 1131.697177886963, "token_count": 486 }, { "elapsed_time": 1123.6543655395508, "token_count": 487 }, { "elapsed_time": 1133.2111358642578, "token_count": 488 }, { "elapsed_time": 1137.9001140594482, "token_count": 489 }, { "elapsed_time": 1174.6058464050293, "token_count": 490 }, { "elapsed_time": 1131.3810348510742, "token_count": 491 }, { "elapsed_time": 1181.5741062164307, "token_count": 492 }, { "elapsed_time": 1147.5169658660889, "token_count": 493 }, { "elapsed_time": 1164.6482944488525, "token_count": 494 }, { "elapsed_time": 1161.9091033935547, "token_count": 495 }, { "elapsed_time": 1195.410966873169, "token_count": 496 }, { "elapsed_time": 1156.3117504119873, "token_count": 497 }, { "elapsed_time": 1169.6851253509521, "token_count": 498 }, { "elapsed_time": 1188.3528232574463, "token_count": 499 }, { "elapsed_time": 1292.7989959716797, "token_count": 500 }, { "elapsed_time": 1279.282808303833, "token_count": 501 }, { "elapsed_time": 1291.952133178711, "token_count": 502 }, { "elapsed_time": 1195.1370239257812, "token_count": 503 }, { "elapsed_time": 1183.1729412078857, "token_count": 504 }, { "elapsed_time": 1198.080062866211, "token_count": 505 }, { "elapsed_time": 1285.5160236358643, "token_count": 506 }, { "elapsed_time": 1305.0501346588135, "token_count": 507 }, { "elapsed_time": 1299.062967300415, "token_count": 508 }, { "elapsed_time": 1315.5882358551025, "token_count": 509 }, { "elapsed_time": 1279.1218757629395, "token_count": 510 }, { "elapsed_time": 1215.500831604004, "token_count": 511 }, { "elapsed_time": 1238.5451793670654, "token_count": 512 }, { "elapsed_time": 1254.9030780792236, "token_count": 513 }, { "elapsed_time": 1304.1479587554932, "token_count": 514 }, { "elapsed_time": 1275.6831645965576, "token_count": 515 }, { "elapsed_time": 1230.5200099945068, "token_count": 516 }, { "elapsed_time": 1297.7912425994873, "token_count": 517 }, { "elapsed_time": 1331.8791389465332, "token_count": 518 }, { "elapsed_time": 1304.5508861541748, "token_count": 519 }, { "elapsed_time": 1338.1831645965576, "token_count": 520 }, { "elapsed_time": 1294.1901683807373, "token_count": 521 }, { "elapsed_time": 1304.9578666687012, "token_count": 522 }, { "elapsed_time": 1263.8070583343506, "token_count": 523 }, { "elapsed_time": 1287.3060703277588, "token_count": 524 }, { "elapsed_time": 1266.0417556762695, "token_count": 525 }, { "elapsed_time": 1349.0638732910156, "token_count": 526 }, { "elapsed_time": 1363.2400035858154, "token_count": 527 }, { "elapsed_time": 1316.6241645812988, "token_count": 528 }, { "elapsed_time": 1336.1079692840576, "token_count": 529 }, { "elapsed_time": 1408.46586227417, "token_count": 530 }, { "elapsed_time": 1351.6149520874023, "token_count": 531 }, { "elapsed_time": 1389.7731304168701, "token_count": 532 }, { "elapsed_time": 1391.4060592651367, "token_count": 533 }, { "elapsed_time": 1353.4770011901855, "token_count": 534 }, { "elapsed_time": 1348.2348918914795, "token_count": 535 }, { "elapsed_time": 1355.9558391571045, "token_count": 536 }, { "elapsed_time": 1384.7899436950684, "token_count": 537 }, { "elapsed_time": 1400.4020690917969, "token_count": 538 }, { "elapsed_time": 1424.4599342346191, "token_count": 539 }, { "elapsed_time": 1400.9671211242676, "token_count": 540 }, { "elapsed_time": 1414.28804397583, "token_count": 541 }, { "elapsed_time": 1394.6771621704102, "token_count": 542 }, { "elapsed_time": 1399.5170593261719, "token_count": 543 }, { "elapsed_time": 1408.1230163574219, "token_count": 544 }, { "elapsed_time": 1413.0239486694336, "token_count": 545 }, { "elapsed_time": 1456.8629264831543, "token_count": 546 }, { "elapsed_time": 1413.060188293457, "token_count": 547 }, { "elapsed_time": 1438.474178314209, "token_count": 548 }, { "elapsed_time": 1461.0569477081299, "token_count": 549 }, { "elapsed_time": 1424.1957664489746, "token_count": 550 }, { "elapsed_time": 1457.3068618774414, "token_count": 551 }, { "elapsed_time": 1439.4941329956055, "token_count": 552 }, { "elapsed_time": 1476.3391017913818, "token_count": 553 }, { "elapsed_time": 1464.7092819213867, "token_count": 554 }, { "elapsed_time": 1460.942029953003, "token_count": 555 }, { "elapsed_time": 1454.3590545654297, "token_count": 556 }, { "elapsed_time": 1452.3730278015137, "token_count": 557 }, { "elapsed_time": 1474.50590133667, "token_count": 558 }, { "elapsed_time": 1486.8419170379639, "token_count": 559 }, { "elapsed_time": 1672.7290153503418, "token_count": 560 } ], "max_token_count_per_time": { "100": 80, "200": 140, "300": 187, "400": 236, "500": 279, "600": 316, "700": 351, "800": 380, "900": 422, "1000": 442, "1100": 456, "1200": 505, "1300": 525, "1400": 543, "1500": 559 } } ================================================ FILE: reports/inference_result/docqa+elmo-cpu.json ================================================ { "average_raw_to_tensor": 0.07495759713529336, "average_tensor_to_predict": 29.947829728174693, "average_end_to_end": 30.022787325309984, "tensor_to_predicts": [ { "elapsed_time": 444.81778144836426, "token_count": 10 }, { "elapsed_time": 450.63209533691406, "token_count": 11 }, { "elapsed_time": 596.3921546936035, "token_count": 12 }, { "elapsed_time": 516.448974609375, "token_count": 13 }, { "elapsed_time": 548.5560894012451, "token_count": 14 }, { "elapsed_time": 592.1571254730225, "token_count": 15 }, { "elapsed_time": 632.4970722198486, "token_count": 16 }, { "elapsed_time": 637.9246711730957, "token_count": 17 }, { "elapsed_time": 678.7707805633545, "token_count": 18 }, { "elapsed_time": 695.0058937072754, "token_count": 19 }, { "elapsed_time": 710.7388973236084, "token_count": 20 }, { "elapsed_time": 734.1299057006836, "token_count": 21 }, { "elapsed_time": 756.6919326782227, "token_count": 22 }, { "elapsed_time": 773.4048366546631, "token_count": 23 }, { "elapsed_time": 891.1871910095215, "token_count": 24 }, { "elapsed_time": 893.3582305908203, "token_count": 25 }, { "elapsed_time": 905.0338268280029, "token_count": 26 }, { "elapsed_time": 1026.8008708953857, "token_count": 27 }, { "elapsed_time": 1394.300937652588, "token_count": 28 }, { "elapsed_time": 1192.229986190796, "token_count": 29 }, { "elapsed_time": 1254.958152770996, "token_count": 30 }, { "elapsed_time": 1283.6709022521973, "token_count": 31 }, { "elapsed_time": 1169.0359115600586, "token_count": 32 }, { "elapsed_time": 1295.1133251190186, "token_count": 33 }, { "elapsed_time": 1141.5653228759766, "token_count": 34 }, { "elapsed_time": 1361.8967533111572, "token_count": 35 }, { "elapsed_time": 1390.589952468872, "token_count": 36 }, { "elapsed_time": 1358.548879623413, "token_count": 37 }, { "elapsed_time": 1374.4440078735352, "token_count": 38 }, { "elapsed_time": 1428.9610385894775, "token_count": 39 }, { "elapsed_time": 1518.4879302978516, "token_count": 40 } ], "max_token_count_per_time": { "500": 11, "600": 15, "700": 19, "800": 23, "900": 25, "1000": 26, "1100": 27, "1200": 34, "1300": 34, "1400": 38, "1500": 39 } } ================================================ FILE: reports/inference_result/docqa-cpu.json ================================================ { "average_raw_to_tensor": 18.26483384527341, "average_tensor_to_predict": 513.9520310392284, "average_end_to_end": 532.2168648845018, "tensor_to_predicts": [ { "elapsed_time": 22.011995315551758, "token_count": 10 }, { "elapsed_time": 15.34271240234375, "token_count": 11 }, { "elapsed_time": 14.614105224609375, "token_count": 12 }, { "elapsed_time": 15.957117080688477, "token_count": 13 }, { "elapsed_time": 18.05901527404785, "token_count": 14 }, { "elapsed_time": 18.22209358215332, "token_count": 15 }, { "elapsed_time": 19.58298683166504, "token_count": 16 }, { "elapsed_time": 20.28179168701172, "token_count": 17 }, { "elapsed_time": 20.82514762878418, "token_count": 18 }, { "elapsed_time": 21.533966064453125, "token_count": 19 }, { "elapsed_time": 23.40412139892578, "token_count": 20 }, { "elapsed_time": 24.00684356689453, "token_count": 21 }, { "elapsed_time": 23.82373809814453, "token_count": 22 }, { "elapsed_time": 25.18606185913086, "token_count": 23 }, { "elapsed_time": 26.07893943786621, "token_count": 24 }, { "elapsed_time": 26.406049728393555, "token_count": 25 }, { "elapsed_time": 27.061939239501953, "token_count": 26 }, { "elapsed_time": 28.91087532043457, "token_count": 27 }, { "elapsed_time": 30.031919479370117, "token_count": 28 }, { "elapsed_time": 30.4567813873291, "token_count": 29 }, { "elapsed_time": 30.633926391601562, "token_count": 30 }, { "elapsed_time": 31.593799591064453, "token_count": 31 }, { "elapsed_time": 32.19199180603027, "token_count": 32 }, { "elapsed_time": 33.66994857788086, "token_count": 33 }, { "elapsed_time": 35.0039005279541, "token_count": 34 }, { "elapsed_time": 36.3619327545166, "token_count": 35 }, { "elapsed_time": 37.146806716918945, "token_count": 36 }, { "elapsed_time": 38.95378112792969, "token_count": 37 }, { "elapsed_time": 38.66982460021973, "token_count": 38 }, { "elapsed_time": 39.273977279663086, "token_count": 39 }, { "elapsed_time": 40.8329963684082, "token_count": 40 }, { "elapsed_time": 41.92209243774414, "token_count": 41 }, { "elapsed_time": 43.81895065307617, "token_count": 42 }, { "elapsed_time": 44.09003257751465, "token_count": 43 }, { "elapsed_time": 44.90208625793457, "token_count": 44 }, { "elapsed_time": 45.2120304107666, "token_count": 45 }, { "elapsed_time": 46.88310623168945, "token_count": 46 }, { "elapsed_time": 47.926902770996094, "token_count": 47 }, { "elapsed_time": 48.39491844177246, "token_count": 48 }, { "elapsed_time": 49.23868179321289, "token_count": 49 }, { "elapsed_time": 51.863670349121094, "token_count": 50 }, { "elapsed_time": 51.2080192565918, "token_count": 51 }, { "elapsed_time": 51.53608322143555, "token_count": 52 }, { "elapsed_time": 53.71212959289551, "token_count": 53 }, { "elapsed_time": 53.76410484313965, "token_count": 54 }, { "elapsed_time": 55.06777763366699, "token_count": 55 }, { "elapsed_time": 56.52594566345215, "token_count": 56 }, { "elapsed_time": 57.60693550109863, "token_count": 57 }, { "elapsed_time": 58.896780014038086, "token_count": 58 }, { "elapsed_time": 58.7918758392334, "token_count": 59 }, { "elapsed_time": 59.01002883911133, "token_count": 60 }, { "elapsed_time": 67.39282608032227, "token_count": 61 }, { "elapsed_time": 61.95783615112305, "token_count": 62 }, { "elapsed_time": 63.0640983581543, "token_count": 63 }, { "elapsed_time": 63.09008598327637, "token_count": 64 }, { "elapsed_time": 63.7509822845459, "token_count": 65 }, { "elapsed_time": 65.15789031982422, "token_count": 66 }, { "elapsed_time": 66.28894805908203, "token_count": 67 }, { "elapsed_time": 67.36111640930176, "token_count": 68 }, { "elapsed_time": 70.6949234008789, "token_count": 69 }, { "elapsed_time": 70.15132904052734, "token_count": 70 }, { "elapsed_time": 69.6871280670166, "token_count": 71 }, { "elapsed_time": 71.19488716125488, "token_count": 72 }, { "elapsed_time": 71.08712196350098, "token_count": 73 }, { "elapsed_time": 71.746826171875, "token_count": 74 }, { "elapsed_time": 73.26412200927734, "token_count": 75 }, { "elapsed_time": 73.58002662658691, "token_count": 76 }, { "elapsed_time": 75.87504386901855, "token_count": 77 }, { "elapsed_time": 75.714111328125, "token_count": 78 }, { "elapsed_time": 77.69608497619629, "token_count": 79 }, { "elapsed_time": 78.66907119750977, "token_count": 80 }, { "elapsed_time": 79.22911643981934, "token_count": 81 }, { "elapsed_time": 79.54883575439453, "token_count": 82 }, { "elapsed_time": 84.93208885192871, "token_count": 83 }, { "elapsed_time": 85.33787727355957, "token_count": 84 }, { "elapsed_time": 82.7798843383789, "token_count": 85 }, { "elapsed_time": 83.96220207214355, "token_count": 86 }, { "elapsed_time": 84.62190628051758, "token_count": 87 }, { "elapsed_time": 85.68811416625977, "token_count": 88 }, { "elapsed_time": 89.02716636657715, "token_count": 89 }, { "elapsed_time": 87.21113204956055, "token_count": 90 }, { "elapsed_time": 88.7598991394043, "token_count": 91 }, { "elapsed_time": 91.01486206054688, "token_count": 92 }, { "elapsed_time": 93.02711486816406, "token_count": 93 }, { "elapsed_time": 94.0561294555664, "token_count": 94 }, { "elapsed_time": 95.55602073669434, "token_count": 95 }, { "elapsed_time": 97.86295890808105, "token_count": 96 }, { "elapsed_time": 94.36583518981934, "token_count": 97 }, { "elapsed_time": 97.54300117492676, "token_count": 98 }, { "elapsed_time": 94.78235244750977, "token_count": 99 }, { "elapsed_time": 99.12705421447754, "token_count": 100 }, { "elapsed_time": 100.07214546203613, "token_count": 101 }, { "elapsed_time": 101.99403762817383, "token_count": 102 }, { "elapsed_time": 106.48012161254883, "token_count": 103 }, { "elapsed_time": 124.58515167236328, "token_count": 104 }, { "elapsed_time": 109.36999320983887, "token_count": 105 }, { "elapsed_time": 105.76009750366211, "token_count": 106 }, { "elapsed_time": 103.45792770385742, "token_count": 107 }, { "elapsed_time": 105.90291023254395, "token_count": 108 }, { "elapsed_time": 106.58884048461914, "token_count": 109 }, { "elapsed_time": 106.76193237304688, "token_count": 110 }, { "elapsed_time": 106.87065124511719, "token_count": 111 }, { "elapsed_time": 108.45398902893066, "token_count": 112 }, { "elapsed_time": 109.87401008605957, "token_count": 113 }, { "elapsed_time": 110.44788360595703, "token_count": 114 }, { "elapsed_time": 112.53595352172852, "token_count": 115 }, { "elapsed_time": 110.50796508789062, "token_count": 116 }, { "elapsed_time": 113.97099494934082, "token_count": 117 }, { "elapsed_time": 113.83390426635742, "token_count": 118 }, { "elapsed_time": 115.86475372314453, "token_count": 119 }, { "elapsed_time": 116.42813682556152, "token_count": 120 }, { "elapsed_time": 117.83814430236816, "token_count": 121 }, { "elapsed_time": 120.54610252380371, "token_count": 122 }, { "elapsed_time": 125.65398216247559, "token_count": 123 }, { "elapsed_time": 120.2549934387207, "token_count": 124 }, { "elapsed_time": 121.26612663269043, "token_count": 125 }, { "elapsed_time": 121.81591987609863, "token_count": 126 }, { "elapsed_time": 122.53618240356445, "token_count": 127 }, { "elapsed_time": 124.64213371276855, "token_count": 128 }, { "elapsed_time": 126.0077953338623, "token_count": 129 }, { "elapsed_time": 127.73990631103516, "token_count": 130 }, { "elapsed_time": 128.8909912109375, "token_count": 131 }, { "elapsed_time": 129.9278736114502, "token_count": 132 }, { "elapsed_time": 129.02402877807617, "token_count": 133 }, { "elapsed_time": 137.800931930542, "token_count": 134 }, { "elapsed_time": 130.20682334899902, "token_count": 135 }, { "elapsed_time": 132.05504417419434, "token_count": 136 }, { "elapsed_time": 133.74996185302734, "token_count": 137 }, { "elapsed_time": 137.07804679870605, "token_count": 138 }, { "elapsed_time": 141.59417152404785, "token_count": 139 }, { "elapsed_time": 135.6191635131836, "token_count": 140 }, { "elapsed_time": 136.65318489074707, "token_count": 141 }, { "elapsed_time": 139.1921043395996, "token_count": 142 }, { "elapsed_time": 140.13981819152832, "token_count": 143 }, { "elapsed_time": 147.78804779052734, "token_count": 144 }, { "elapsed_time": 139.05811309814453, "token_count": 145 }, { "elapsed_time": 142.84396171569824, "token_count": 146 }, { "elapsed_time": 142.8511142730713, "token_count": 147 }, { "elapsed_time": 143.6331272125244, "token_count": 148 }, { "elapsed_time": 143.76306533813477, "token_count": 149 }, { "elapsed_time": 146.1501121520996, "token_count": 150 }, { "elapsed_time": 146.4681625366211, "token_count": 151 }, { "elapsed_time": 147.2008228302002, "token_count": 152 }, { "elapsed_time": 149.45411682128906, "token_count": 153 }, { "elapsed_time": 149.65486526489258, "token_count": 154 }, { "elapsed_time": 149.91497993469238, "token_count": 155 }, { "elapsed_time": 152.17995643615723, "token_count": 156 }, { "elapsed_time": 152.4820327758789, "token_count": 157 }, { "elapsed_time": 153.93686294555664, "token_count": 158 }, { "elapsed_time": 152.94909477233887, "token_count": 159 }, { "elapsed_time": 155.75075149536133, "token_count": 160 }, { "elapsed_time": 155.472993850708, "token_count": 161 }, { "elapsed_time": 157.5329303741455, "token_count": 162 }, { "elapsed_time": 159.93118286132812, "token_count": 163 }, { "elapsed_time": 160.44068336486816, "token_count": 164 }, { "elapsed_time": 161.9699001312256, "token_count": 165 }, { "elapsed_time": 162.0180606842041, "token_count": 166 }, { "elapsed_time": 169.98004913330078, "token_count": 167 }, { "elapsed_time": 169.62718963623047, "token_count": 168 }, { "elapsed_time": 172.4081039428711, "token_count": 169 }, { "elapsed_time": 167.62924194335938, "token_count": 170 }, { "elapsed_time": 165.4222011566162, "token_count": 171 }, { "elapsed_time": 169.46816444396973, "token_count": 172 }, { "elapsed_time": 171.33402824401855, "token_count": 173 }, { "elapsed_time": 174.0267276763916, "token_count": 174 }, { "elapsed_time": 180.15813827514648, "token_count": 175 }, { "elapsed_time": 189.7289752960205, "token_count": 176 }, { "elapsed_time": 173.56109619140625, "token_count": 177 }, { "elapsed_time": 180.6657314300537, "token_count": 178 }, { "elapsed_time": 176.8949031829834, "token_count": 179 }, { "elapsed_time": 181.01811408996582, "token_count": 180 }, { "elapsed_time": 183.05277824401855, "token_count": 181 }, { "elapsed_time": 178.84278297424316, "token_count": 182 }, { "elapsed_time": 180.0861358642578, "token_count": 183 }, { "elapsed_time": 181.08391761779785, "token_count": 184 }, { "elapsed_time": 181.99491500854492, "token_count": 185 }, { "elapsed_time": 184.15284156799316, "token_count": 186 }, { "elapsed_time": 181.884765625, "token_count": 187 }, { "elapsed_time": 185.75572967529297, "token_count": 188 }, { "elapsed_time": 188.20905685424805, "token_count": 189 }, { "elapsed_time": 191.9088363647461, "token_count": 190 }, { "elapsed_time": 187.09182739257812, "token_count": 191 }, { "elapsed_time": 190.31500816345215, "token_count": 192 }, { "elapsed_time": 192.9159164428711, "token_count": 193 }, { "elapsed_time": 192.80099868774414, "token_count": 194 }, { "elapsed_time": 191.5581226348877, "token_count": 195 }, { "elapsed_time": 195.5549716949463, "token_count": 196 }, { "elapsed_time": 193.76707077026367, "token_count": 197 }, { "elapsed_time": 200.6840705871582, "token_count": 198 }, { "elapsed_time": 199.9228000640869, "token_count": 199 }, { "elapsed_time": 209.4428539276123, "token_count": 200 }, { "elapsed_time": 201.25389099121094, "token_count": 201 }, { "elapsed_time": 200.6399631500244, "token_count": 202 }, { "elapsed_time": 203.0961513519287, "token_count": 203 }, { "elapsed_time": 202.65698432922363, "token_count": 204 }, { "elapsed_time": 206.27999305725098, "token_count": 205 }, { "elapsed_time": 206.88104629516602, "token_count": 206 }, { "elapsed_time": 206.74610137939453, "token_count": 207 }, { "elapsed_time": 211.15708351135254, "token_count": 208 }, { "elapsed_time": 210.56890487670898, "token_count": 209 }, { "elapsed_time": 212.08500862121582, "token_count": 210 }, { "elapsed_time": 211.35282516479492, "token_count": 211 }, { "elapsed_time": 211.63296699523926, "token_count": 212 }, { "elapsed_time": 213.029146194458, "token_count": 213 }, { "elapsed_time": 216.0940170288086, "token_count": 214 }, { "elapsed_time": 217.95082092285156, "token_count": 215 }, { "elapsed_time": 218.28603744506836, "token_count": 216 }, { "elapsed_time": 214.7970199584961, "token_count": 217 }, { "elapsed_time": 217.0848846435547, "token_count": 218 }, { "elapsed_time": 217.3750400543213, "token_count": 219 }, { "elapsed_time": 217.29612350463867, "token_count": 220 }, { "elapsed_time": 219.35296058654785, "token_count": 221 }, { "elapsed_time": 223.18291664123535, "token_count": 222 }, { "elapsed_time": 223.61207008361816, "token_count": 223 }, { "elapsed_time": 226.52292251586914, "token_count": 224 }, { "elapsed_time": 251.3289451599121, "token_count": 225 }, { "elapsed_time": 237.1211051940918, "token_count": 226 }, { "elapsed_time": 226.90272331237793, "token_count": 227 }, { "elapsed_time": 228.54876518249512, "token_count": 228 }, { "elapsed_time": 229.6581268310547, "token_count": 229 }, { "elapsed_time": 230.0422191619873, "token_count": 230 }, { "elapsed_time": 232.0230007171631, "token_count": 231 }, { "elapsed_time": 232.41662979125977, "token_count": 232 }, { "elapsed_time": 232.2678565979004, "token_count": 233 }, { "elapsed_time": 237.60628700256348, "token_count": 234 }, { "elapsed_time": 236.23085021972656, "token_count": 235 }, { "elapsed_time": 234.2069149017334, "token_count": 236 }, { "elapsed_time": 235.7008457183838, "token_count": 237 }, { "elapsed_time": 239.45307731628418, "token_count": 238 }, { "elapsed_time": 242.93971061706543, "token_count": 239 }, { "elapsed_time": 244.95601654052734, "token_count": 240 }, { "elapsed_time": 241.8079376220703, "token_count": 241 }, { "elapsed_time": 240.94080924987793, "token_count": 242 }, { "elapsed_time": 244.82202529907227, "token_count": 243 }, { "elapsed_time": 245.06211280822754, "token_count": 244 }, { "elapsed_time": 244.06790733337402, "token_count": 245 }, { "elapsed_time": 245.23377418518066, "token_count": 246 }, { "elapsed_time": 256.270170211792, "token_count": 247 }, { "elapsed_time": 246.08302116394043, "token_count": 248 }, { "elapsed_time": 248.3201026916504, "token_count": 249 }, { "elapsed_time": 249.11212921142578, "token_count": 250 }, { "elapsed_time": 252.63500213623047, "token_count": 251 }, { "elapsed_time": 249.87483024597168, "token_count": 252 }, { "elapsed_time": 255.54418563842773, "token_count": 253 }, { "elapsed_time": 255.4757595062256, "token_count": 254 }, { "elapsed_time": 260.9391212463379, "token_count": 255 }, { "elapsed_time": 255.35821914672852, "token_count": 256 }, { "elapsed_time": 256.80017471313477, "token_count": 257 }, { "elapsed_time": 259.36388969421387, "token_count": 258 }, { "elapsed_time": 259.14669036865234, "token_count": 259 }, { "elapsed_time": 261.04092597961426, "token_count": 260 }, { "elapsed_time": 259.45401191711426, "token_count": 261 }, { "elapsed_time": 263.9880180358887, "token_count": 262 }, { "elapsed_time": 266.3249969482422, "token_count": 263 }, { "elapsed_time": 261.3518238067627, "token_count": 264 }, { "elapsed_time": 285.16578674316406, "token_count": 265 }, { "elapsed_time": 275.4840850830078, "token_count": 266 }, { "elapsed_time": 269.2747116088867, "token_count": 267 }, { "elapsed_time": 270.69687843322754, "token_count": 268 }, { "elapsed_time": 268.9981460571289, "token_count": 269 }, { "elapsed_time": 270.0989246368408, "token_count": 270 }, { "elapsed_time": 269.75274085998535, "token_count": 271 }, { "elapsed_time": 272.9229927062988, "token_count": 272 }, { "elapsed_time": 274.64795112609863, "token_count": 273 }, { "elapsed_time": 273.0908393859863, "token_count": 274 }, { "elapsed_time": 273.9260196685791, "token_count": 275 }, { "elapsed_time": 276.1831283569336, "token_count": 276 }, { "elapsed_time": 275.8491039276123, "token_count": 277 }, { "elapsed_time": 281.0189723968506, "token_count": 278 }, { "elapsed_time": 277.0402431488037, "token_count": 279 }, { "elapsed_time": 282.0549011230469, "token_count": 280 }, { "elapsed_time": 282.088041305542, "token_count": 281 }, { "elapsed_time": 283.22625160217285, "token_count": 282 }, { "elapsed_time": 282.2577953338623, "token_count": 283 }, { "elapsed_time": 286.6480350494385, "token_count": 284 }, { "elapsed_time": 283.0181121826172, "token_count": 285 }, { "elapsed_time": 285.9029769897461, "token_count": 286 }, { "elapsed_time": 286.91601753234863, "token_count": 287 }, { "elapsed_time": 292.94419288635254, "token_count": 288 }, { "elapsed_time": 290.74621200561523, "token_count": 289 }, { "elapsed_time": 293.95198822021484, "token_count": 290 }, { "elapsed_time": 296.2679862976074, "token_count": 291 }, { "elapsed_time": 295.318603515625, "token_count": 292 }, { "elapsed_time": 304.0449619293213, "token_count": 293 }, { "elapsed_time": 292.1290397644043, "token_count": 294 }, { "elapsed_time": 295.4821586608887, "token_count": 295 }, { "elapsed_time": 295.5801486968994, "token_count": 296 }, { "elapsed_time": 300.42386054992676, "token_count": 297 }, { "elapsed_time": 297.5497245788574, "token_count": 298 }, { "elapsed_time": 299.1049289703369, "token_count": 299 }, { "elapsed_time": 336.3640308380127, "token_count": 300 }, { "elapsed_time": 301.8522262573242, "token_count": 301 }, { "elapsed_time": 305.1719665527344, "token_count": 302 }, { "elapsed_time": 302.45208740234375, "token_count": 303 }, { "elapsed_time": 301.4500141143799, "token_count": 304 }, { "elapsed_time": 306.7131042480469, "token_count": 305 }, { "elapsed_time": 306.4439296722412, "token_count": 306 }, { "elapsed_time": 310.29391288757324, "token_count": 307 }, { "elapsed_time": 311.42568588256836, "token_count": 308 }, { "elapsed_time": 308.07995796203613, "token_count": 309 }, { "elapsed_time": 307.58094787597656, "token_count": 310 }, { "elapsed_time": 336.6107940673828, "token_count": 311 }, { "elapsed_time": 317.2111511230469, "token_count": 312 }, { "elapsed_time": 313.53282928466797, "token_count": 313 }, { "elapsed_time": 315.57297706604004, "token_count": 314 }, { "elapsed_time": 312.15786933898926, "token_count": 315 }, { "elapsed_time": 313.7197494506836, "token_count": 316 }, { "elapsed_time": 320.8651542663574, "token_count": 317 }, { "elapsed_time": 318.77899169921875, "token_count": 318 }, { "elapsed_time": 317.7759647369385, "token_count": 319 }, { "elapsed_time": 326.6417980194092, "token_count": 320 }, { "elapsed_time": 318.8762664794922, "token_count": 321 }, { "elapsed_time": 318.10998916625977, "token_count": 322 }, { "elapsed_time": 319.2269802093506, "token_count": 323 }, { "elapsed_time": 321.7320442199707, "token_count": 324 }, { "elapsed_time": 324.4171142578125, "token_count": 325 }, { "elapsed_time": 332.5479030609131, "token_count": 326 }, { "elapsed_time": 333.04882049560547, "token_count": 327 }, { "elapsed_time": 329.4830322265625, "token_count": 328 }, { "elapsed_time": 328.9341926574707, "token_count": 329 }, { "elapsed_time": 329.0398120880127, "token_count": 330 }, { "elapsed_time": 354.0470600128174, "token_count": 331 }, { "elapsed_time": 332.73983001708984, "token_count": 332 }, { "elapsed_time": 331.91895484924316, "token_count": 333 }, { "elapsed_time": 334.2170715332031, "token_count": 334 }, { "elapsed_time": 337.3422622680664, "token_count": 335 }, { "elapsed_time": 334.5921039581299, "token_count": 336 }, { "elapsed_time": 335.7560634613037, "token_count": 337 }, { "elapsed_time": 341.005802154541, "token_count": 338 }, { "elapsed_time": 334.8731994628906, "token_count": 339 }, { "elapsed_time": 341.9320583343506, "token_count": 340 }, { "elapsed_time": 344.0670967102051, "token_count": 341 }, { "elapsed_time": 343.70899200439453, "token_count": 342 }, { "elapsed_time": 341.3829803466797, "token_count": 343 }, { "elapsed_time": 348.93107414245605, "token_count": 344 }, { "elapsed_time": 344.174861907959, "token_count": 345 }, { "elapsed_time": 345.81995010375977, "token_count": 346 }, { "elapsed_time": 348.7520217895508, "token_count": 347 }, { "elapsed_time": 348.3738899230957, "token_count": 348 }, { "elapsed_time": 345.8671569824219, "token_count": 349 }, { "elapsed_time": 350.0561714172363, "token_count": 350 }, { "elapsed_time": 347.4860191345215, "token_count": 351 }, { "elapsed_time": 352.05078125, "token_count": 352 }, { "elapsed_time": 350.1091003417969, "token_count": 353 }, { "elapsed_time": 355.0229072570801, "token_count": 354 }, { "elapsed_time": 357.105016708374, "token_count": 355 }, { "elapsed_time": 359.464168548584, "token_count": 356 }, { "elapsed_time": 358.7932586669922, "token_count": 357 }, { "elapsed_time": 363.2500171661377, "token_count": 358 }, { "elapsed_time": 369.2049980163574, "token_count": 359 }, { "elapsed_time": 384.37819480895996, "token_count": 360 }, { "elapsed_time": 365.94080924987793, "token_count": 361 }, { "elapsed_time": 363.8288974761963, "token_count": 362 }, { "elapsed_time": 365.9951686859131, "token_count": 363 }, { "elapsed_time": 365.1881217956543, "token_count": 364 }, { "elapsed_time": 370.5451488494873, "token_count": 365 }, { "elapsed_time": 367.04421043395996, "token_count": 366 }, { "elapsed_time": 366.15896224975586, "token_count": 367 }, { "elapsed_time": 370.7408905029297, "token_count": 368 }, { "elapsed_time": 374.71723556518555, "token_count": 369 }, { "elapsed_time": 370.95093727111816, "token_count": 370 }, { "elapsed_time": 368.5319423675537, "token_count": 371 }, { "elapsed_time": 371.4439868927002, "token_count": 372 }, { "elapsed_time": 372.1799850463867, "token_count": 373 }, { "elapsed_time": 376.2097358703613, "token_count": 374 }, { "elapsed_time": 375.87904930114746, "token_count": 375 }, { "elapsed_time": 378.0653476715088, "token_count": 376 }, { "elapsed_time": 377.11501121520996, "token_count": 377 }, { "elapsed_time": 384.5939636230469, "token_count": 378 }, { "elapsed_time": 385.43009757995605, "token_count": 379 }, { "elapsed_time": 378.277063369751, "token_count": 380 }, { "elapsed_time": 383.90398025512695, "token_count": 381 }, { "elapsed_time": 383.8071823120117, "token_count": 382 }, { "elapsed_time": 384.5667839050293, "token_count": 383 }, { "elapsed_time": 387.7251148223877, "token_count": 384 }, { "elapsed_time": 409.31105613708496, "token_count": 385 }, { "elapsed_time": 417.7131652832031, "token_count": 386 }, { "elapsed_time": 400.2389907836914, "token_count": 387 }, { "elapsed_time": 408.91075134277344, "token_count": 388 }, { "elapsed_time": 416.3250923156738, "token_count": 389 }, { "elapsed_time": 426.1159896850586, "token_count": 390 }, { "elapsed_time": 408.397912979126, "token_count": 391 }, { "elapsed_time": 388.1049156188965, "token_count": 392 }, { "elapsed_time": 383.00490379333496, "token_count": 393 }, { "elapsed_time": 424.3659973144531, "token_count": 394 }, { "elapsed_time": 398.3330726623535, "token_count": 395 }, { "elapsed_time": 392.54307746887207, "token_count": 396 }, { "elapsed_time": 477.85496711730957, "token_count": 397 }, { "elapsed_time": 440.6557083129883, "token_count": 398 }, { "elapsed_time": 441.8160915374756, "token_count": 399 }, { "elapsed_time": 456.50315284729004, "token_count": 400 }, { "elapsed_time": 411.6809368133545, "token_count": 401 }, { "elapsed_time": 417.77896881103516, "token_count": 402 }, { "elapsed_time": 407.74011611938477, "token_count": 403 }, { "elapsed_time": 406.7211151123047, "token_count": 404 }, { "elapsed_time": 407.82904624938965, "token_count": 405 }, { "elapsed_time": 424.335241317749, "token_count": 406 }, { "elapsed_time": 445.2629089355469, "token_count": 407 }, { "elapsed_time": 428.9829730987549, "token_count": 408 }, { "elapsed_time": 467.9739475250244, "token_count": 409 }, { "elapsed_time": 427.49881744384766, "token_count": 410 }, { "elapsed_time": 447.6337432861328, "token_count": 411 }, { "elapsed_time": 417.7069664001465, "token_count": 412 }, { "elapsed_time": 426.30887031555176, "token_count": 413 }, { "elapsed_time": 434.2389106750488, "token_count": 414 }, { "elapsed_time": 428.8160800933838, "token_count": 415 }, { "elapsed_time": 506.3459873199463, "token_count": 416 }, { "elapsed_time": 438.31396102905273, "token_count": 417 }, { "elapsed_time": 428.0991554260254, "token_count": 418 }, { "elapsed_time": 424.893856048584, "token_count": 419 }, { "elapsed_time": 433.1321716308594, "token_count": 420 }, { "elapsed_time": 430.67121505737305, "token_count": 421 }, { "elapsed_time": 438.9798641204834, "token_count": 422 }, { "elapsed_time": 421.0679531097412, "token_count": 423 }, { "elapsed_time": 426.4037609100342, "token_count": 424 }, { "elapsed_time": 416.1832332611084, "token_count": 425 }, { "elapsed_time": 409.7311496734619, "token_count": 426 }, { "elapsed_time": 417.1748161315918, "token_count": 427 }, { "elapsed_time": 448.0559825897217, "token_count": 428 }, { "elapsed_time": 437.2999668121338, "token_count": 429 }, { "elapsed_time": 421.44274711608887, "token_count": 430 }, { "elapsed_time": 425.0040054321289, "token_count": 431 }, { "elapsed_time": 441.12682342529297, "token_count": 432 }, { "elapsed_time": 435.57095527648926, "token_count": 433 }, { "elapsed_time": 416.2321090698242, "token_count": 434 }, { "elapsed_time": 419.2769527435303, "token_count": 435 }, { "elapsed_time": 429.2941093444824, "token_count": 436 }, { "elapsed_time": 461.21907234191895, "token_count": 437 }, { "elapsed_time": 466.1281108856201, "token_count": 438 }, { "elapsed_time": 465.40212631225586, "token_count": 439 }, { "elapsed_time": 488.9678955078125, "token_count": 440 }, { "elapsed_time": 464.59197998046875, "token_count": 441 }, { "elapsed_time": 460.94799041748047, "token_count": 442 }, { "elapsed_time": 445.404052734375, "token_count": 443 }, { "elapsed_time": 453.6876678466797, "token_count": 444 }, { "elapsed_time": 445.02782821655273, "token_count": 445 }, { "elapsed_time": 490.4487133026123, "token_count": 446 }, { "elapsed_time": 436.722993850708, "token_count": 447 }, { "elapsed_time": 434.948205947876, "token_count": 448 }, { "elapsed_time": 437.9758834838867, "token_count": 449 }, { "elapsed_time": 434.99112129211426, "token_count": 450 }, { "elapsed_time": 444.4091320037842, "token_count": 451 }, { "elapsed_time": 436.3710880279541, "token_count": 452 }, { "elapsed_time": 437.76512145996094, "token_count": 453 }, { "elapsed_time": 469.7380065917969, "token_count": 454 }, { "elapsed_time": 450.8390426635742, "token_count": 455 }, { "elapsed_time": 445.85394859313965, "token_count": 456 }, { "elapsed_time": 444.27490234375, "token_count": 457 }, { "elapsed_time": 453.5098075866699, "token_count": 458 }, { "elapsed_time": 449.1729736328125, "token_count": 459 }, { "elapsed_time": 499.47404861450195, "token_count": 460 }, { "elapsed_time": 570.4200267791748, "token_count": 461 }, { "elapsed_time": 493.44801902770996, "token_count": 462 }, { "elapsed_time": 496.5167045593262, "token_count": 463 }, { "elapsed_time": 461.5209102630615, "token_count": 464 }, { "elapsed_time": 459.2139720916748, "token_count": 465 }, { "elapsed_time": 453.20606231689453, "token_count": 466 }, { "elapsed_time": 462.4667167663574, "token_count": 467 }, { "elapsed_time": 461.4448547363281, "token_count": 468 }, { "elapsed_time": 456.1190605163574, "token_count": 469 }, { "elapsed_time": 458.65917205810547, "token_count": 470 }, { "elapsed_time": 470.3030586242676, "token_count": 471 }, { "elapsed_time": 461.6281986236572, "token_count": 472 }, { "elapsed_time": 461.8861675262451, "token_count": 473 }, { "elapsed_time": 456.89916610717773, "token_count": 474 }, { "elapsed_time": 494.52710151672363, "token_count": 475 }, { "elapsed_time": 465.670108795166, "token_count": 476 }, { "elapsed_time": 473.36769104003906, "token_count": 477 }, { "elapsed_time": 460.8421325683594, "token_count": 478 }, { "elapsed_time": 462.3439311981201, "token_count": 479 }, { "elapsed_time": 485.84604263305664, "token_count": 480 }, { "elapsed_time": 493.72410774230957, "token_count": 481 }, { "elapsed_time": 507.74502754211426, "token_count": 482 }, { "elapsed_time": 484.48801040649414, "token_count": 483 }, { "elapsed_time": 474.3969440460205, "token_count": 484 }, { "elapsed_time": 472.7020263671875, "token_count": 485 }, { "elapsed_time": 472.1040725708008, "token_count": 486 }, { "elapsed_time": 475.95906257629395, "token_count": 487 }, { "elapsed_time": 477.8859615325928, "token_count": 488 }, { "elapsed_time": 477.327823638916, "token_count": 489 }, { "elapsed_time": 477.26988792419434, "token_count": 490 }, { "elapsed_time": 478.53803634643555, "token_count": 491 }, { "elapsed_time": 496.6771602630615, "token_count": 492 }, { "elapsed_time": 556.1008453369141, "token_count": 493 }, { "elapsed_time": 490.1928901672363, "token_count": 494 }, { "elapsed_time": 500.03623962402344, "token_count": 495 }, { "elapsed_time": 486.71889305114746, "token_count": 496 }, { "elapsed_time": 480.3178310394287, "token_count": 497 }, { "elapsed_time": 484.6360683441162, "token_count": 498 }, { "elapsed_time": 482.41186141967773, "token_count": 499 }, { "elapsed_time": 521.5590000152588, "token_count": 500 }, { "elapsed_time": 519.4799900054932, "token_count": 501 }, { "elapsed_time": 512.2461318969727, "token_count": 502 }, { "elapsed_time": 497.71976470947266, "token_count": 503 }, { "elapsed_time": 490.63587188720703, "token_count": 504 }, { "elapsed_time": 495.24617195129395, "token_count": 505 }, { "elapsed_time": 491.3179874420166, "token_count": 506 }, { "elapsed_time": 510.59579849243164, "token_count": 507 }, { "elapsed_time": 495.6858158111572, "token_count": 508 }, { "elapsed_time": 502.8700828552246, "token_count": 509 }, { "elapsed_time": 514.8937702178955, "token_count": 510 }, { "elapsed_time": 496.0649013519287, "token_count": 511 }, { "elapsed_time": 497.32112884521484, "token_count": 512 }, { "elapsed_time": 501.6951560974121, "token_count": 513 }, { "elapsed_time": 499.5579719543457, "token_count": 514 }, { "elapsed_time": 525.2909660339355, "token_count": 515 }, { "elapsed_time": 508.52203369140625, "token_count": 516 }, { "elapsed_time": 500.12803077697754, "token_count": 517 }, { "elapsed_time": 503.83782386779785, "token_count": 518 }, { "elapsed_time": 533.4410667419434, "token_count": 519 }, { "elapsed_time": 559.0431690216064, "token_count": 520 }, { "elapsed_time": 559.8242282867432, "token_count": 521 }, { "elapsed_time": 521.9700336456299, "token_count": 522 }, { "elapsed_time": 526.6900062561035, "token_count": 523 }, { "elapsed_time": 511.0049247741699, "token_count": 524 }, { "elapsed_time": 514.5778656005859, "token_count": 525 }, { "elapsed_time": 514.1708850860596, "token_count": 526 }, { "elapsed_time": 516.7269706726074, "token_count": 527 }, { "elapsed_time": 525.9373188018799, "token_count": 528 }, { "elapsed_time": 525.1889228820801, "token_count": 529 }, { "elapsed_time": 518.6707973480225, "token_count": 530 }, { "elapsed_time": 528.0117988586426, "token_count": 531 }, { "elapsed_time": 519.6027755737305, "token_count": 532 }, { "elapsed_time": 525.0160694122314, "token_count": 533 }, { "elapsed_time": 550.6200790405273, "token_count": 534 }, { "elapsed_time": 522.7260589599609, "token_count": 535 }, { "elapsed_time": 517.3521041870117, "token_count": 536 }, { "elapsed_time": 535.7329845428467, "token_count": 537 }, { "elapsed_time": 549.4029521942139, "token_count": 538 }, { "elapsed_time": 568.2649612426758, "token_count": 539 }, { "elapsed_time": 539.3872261047363, "token_count": 540 }, { "elapsed_time": 535.4480743408203, "token_count": 541 }, { "elapsed_time": 527.4639129638672, "token_count": 542 }, { "elapsed_time": 528.648853302002, "token_count": 543 }, { "elapsed_time": 523.05006980896, "token_count": 544 }, { "elapsed_time": 540.1520729064941, "token_count": 545 }, { "elapsed_time": 539.6311283111572, "token_count": 546 }, { "elapsed_time": 548.1328964233398, "token_count": 547 }, { "elapsed_time": 561.5191459655762, "token_count": 548 }, { "elapsed_time": 534.7428321838379, "token_count": 549 }, { "elapsed_time": 539.0269756317139, "token_count": 550 }, { "elapsed_time": 537.045955657959, "token_count": 551 }, { "elapsed_time": 563.9400482177734, "token_count": 552 }, { "elapsed_time": 539.4518375396729, "token_count": 553 }, { "elapsed_time": 540.3928756713867, "token_count": 554 }, { "elapsed_time": 565.2949810028076, "token_count": 555 }, { "elapsed_time": 559.8609447479248, "token_count": 556 }, { "elapsed_time": 564.2290115356445, "token_count": 557 }, { "elapsed_time": 554.7668933868408, "token_count": 558 }, { "elapsed_time": 543.7991619110107, "token_count": 559 }, { "elapsed_time": 548.3779907226562, "token_count": 560 }, { "elapsed_time": 554.896354675293, "token_count": 561 }, { "elapsed_time": 549.4740009307861, "token_count": 562 }, { "elapsed_time": 548.583984375, "token_count": 563 }, { "elapsed_time": 548.9439964294434, "token_count": 564 }, { "elapsed_time": 561.2199306488037, "token_count": 565 }, { "elapsed_time": 550.1072406768799, "token_count": 566 }, { "elapsed_time": 550.8038997650146, "token_count": 567 }, { "elapsed_time": 554.7902584075928, "token_count": 568 }, { "elapsed_time": 559.8747730255127, "token_count": 569 }, { "elapsed_time": 578.2039165496826, "token_count": 570 }, { "elapsed_time": 560.9710216522217, "token_count": 571 }, { "elapsed_time": 561.2380504608154, "token_count": 572 }, { "elapsed_time": 586.9040489196777, "token_count": 573 }, { "elapsed_time": 605.8380603790283, "token_count": 574 }, { "elapsed_time": 583.1217765808105, "token_count": 575 }, { "elapsed_time": 564.8770332336426, "token_count": 576 }, { "elapsed_time": 564.9909973144531, "token_count": 577 }, { "elapsed_time": 562.7660751342773, "token_count": 578 }, { "elapsed_time": 567.4760341644287, "token_count": 579 }, { "elapsed_time": 570.4531669616699, "token_count": 580 }, { "elapsed_time": 570.8537101745605, "token_count": 581 }, { "elapsed_time": 570.5368518829346, "token_count": 582 }, { "elapsed_time": 569.8349475860596, "token_count": 583 }, { "elapsed_time": 571.5010166168213, "token_count": 584 }, { "elapsed_time": 579.1959762573242, "token_count": 585 }, { "elapsed_time": 572.4055767059326, "token_count": 586 }, { "elapsed_time": 592.7660465240479, "token_count": 587 }, { "elapsed_time": 582.8151702880859, "token_count": 588 }, { "elapsed_time": 581.9079875946045, "token_count": 589 }, { "elapsed_time": 597.4950790405273, "token_count": 590 }, { "elapsed_time": 612.7002239227295, "token_count": 591 }, { "elapsed_time": 590.4951095581055, "token_count": 592 }, { "elapsed_time": 580.7859897613525, "token_count": 593 }, { "elapsed_time": 597.8291034698486, "token_count": 594 }, { "elapsed_time": 605.043888092041, "token_count": 595 }, { "elapsed_time": 619.1518306732178, "token_count": 596 }, { "elapsed_time": 583.9929580688477, "token_count": 597 }, { "elapsed_time": 591.2821292877197, "token_count": 598 }, { "elapsed_time": 613.26003074646, "token_count": 599 }, { "elapsed_time": 592.9069519042969, "token_count": 600 }, { "elapsed_time": 596.6241359710693, "token_count": 601 }, { "elapsed_time": 599.308967590332, "token_count": 602 }, { "elapsed_time": 601.0639667510986, "token_count": 603 }, { "elapsed_time": 623.3329772949219, "token_count": 604 }, { "elapsed_time": 598.0930328369141, "token_count": 605 }, { "elapsed_time": 632.274866104126, "token_count": 606 }, { "elapsed_time": 645.4660892486572, "token_count": 607 }, { "elapsed_time": 609.9510192871094, "token_count": 608 }, { "elapsed_time": 597.5987911224365, "token_count": 609 }, { "elapsed_time": 600.2588272094727, "token_count": 610 }, { "elapsed_time": 610.1539134979248, "token_count": 611 }, { "elapsed_time": 604.8843860626221, "token_count": 612 }, { "elapsed_time": 594.1450595855713, "token_count": 613 }, { "elapsed_time": 600.4259586334229, "token_count": 614 }, { "elapsed_time": 611.975908279419, "token_count": 615 }, { "elapsed_time": 611.6209030151367, "token_count": 616 }, { "elapsed_time": 640.1662826538086, "token_count": 617 }, { "elapsed_time": 618.4589862823486, "token_count": 618 }, { "elapsed_time": 620.1009750366211, "token_count": 619 }, { "elapsed_time": 646.6770172119141, "token_count": 620 }, { "elapsed_time": 621.64306640625, "token_count": 621 }, { "elapsed_time": 726.8228530883789, "token_count": 622 }, { "elapsed_time": 710.4299068450928, "token_count": 623 }, { "elapsed_time": 628.183126449585, "token_count": 624 }, { "elapsed_time": 619.276762008667, "token_count": 625 }, { "elapsed_time": 613.8589382171631, "token_count": 626 }, { "elapsed_time": 620.3219890594482, "token_count": 627 }, { "elapsed_time": 649.1000652313232, "token_count": 628 }, { "elapsed_time": 617.3152923583984, "token_count": 629 }, { "elapsed_time": 643.151044845581, "token_count": 630 }, { "elapsed_time": 643.4428691864014, "token_count": 631 }, { "elapsed_time": 641.9332027435303, "token_count": 632 }, { "elapsed_time": 644.2077159881592, "token_count": 633 }, { "elapsed_time": 648.3910083770752, "token_count": 634 }, { "elapsed_time": 681.6592216491699, "token_count": 635 }, { "elapsed_time": 651.1030197143555, "token_count": 636 }, { "elapsed_time": 661.7991924285889, "token_count": 637 }, { "elapsed_time": 667.7999496459961, "token_count": 638 }, { "elapsed_time": 684.6127510070801, "token_count": 639 }, { "elapsed_time": 660.477876663208, "token_count": 640 }, { "elapsed_time": 649.94215965271, "token_count": 641 }, { "elapsed_time": 655.6398868560791, "token_count": 642 }, { "elapsed_time": 654.2057991027832, "token_count": 643 }, { "elapsed_time": 651.4029502868652, "token_count": 644 }, { "elapsed_time": 654.1929244995117, "token_count": 645 }, { "elapsed_time": 656.9077968597412, "token_count": 646 }, { "elapsed_time": 658.581018447876, "token_count": 647 }, { "elapsed_time": 661.2038612365723, "token_count": 648 }, { "elapsed_time": 667.8159236907959, "token_count": 649 }, { "elapsed_time": 708.7538242340088, "token_count": 650 }, { "elapsed_time": 712.4860286712646, "token_count": 651 }, { "elapsed_time": 684.7560405731201, "token_count": 652 }, { "elapsed_time": 685.575008392334, "token_count": 653 }, { "elapsed_time": 679.354190826416, "token_count": 654 }, { "elapsed_time": 665.9941673278809, "token_count": 655 }, { "elapsed_time": 671.2608337402344, "token_count": 656 }, { "elapsed_time": 665.4930114746094, "token_count": 657 }, { "elapsed_time": 665.9131050109863, "token_count": 658 }, { "elapsed_time": 669.295072555542, "token_count": 659 }, { "elapsed_time": 662.956953048706, "token_count": 660 }, { "elapsed_time": 670.1853275299072, "token_count": 661 }, { "elapsed_time": 668.8430309295654, "token_count": 662 }, { "elapsed_time": 668.4768199920654, "token_count": 663 }, { "elapsed_time": 674.0128993988037, "token_count": 664 }, { "elapsed_time": 720.0701236724854, "token_count": 665 }, { "elapsed_time": 681.542158126831, "token_count": 666 }, { "elapsed_time": 677.8302192687988, "token_count": 667 }, { "elapsed_time": 673.5413074493408, "token_count": 668 }, { "elapsed_time": 673.1760501861572, "token_count": 669 }, { "elapsed_time": 677.3147583007812, "token_count": 670 }, { "elapsed_time": 680.4599761962891, "token_count": 671 }, { "elapsed_time": 685.36376953125, "token_count": 672 }, { "elapsed_time": 684.7589015960693, "token_count": 673 }, { "elapsed_time": 685.128927230835, "token_count": 674 }, { "elapsed_time": 685.4660511016846, "token_count": 675 }, { "elapsed_time": 687.8349781036377, "token_count": 676 }, { "elapsed_time": 692.0487880706787, "token_count": 677 }, { "elapsed_time": 688.1997585296631, "token_count": 678 }, { "elapsed_time": 712.3813629150391, "token_count": 679 }, { "elapsed_time": 696.4809894561768, "token_count": 680 }, { "elapsed_time": 693.6180591583252, "token_count": 681 }, { "elapsed_time": 693.9289569854736, "token_count": 682 }, { "elapsed_time": 695.7530975341797, "token_count": 683 }, { "elapsed_time": 692.4891471862793, "token_count": 684 }, { "elapsed_time": 691.3399696350098, "token_count": 685 }, { "elapsed_time": 697.0570087432861, "token_count": 686 }, { "elapsed_time": 700.7420063018799, "token_count": 687 }, { "elapsed_time": 698.5862255096436, "token_count": 688 }, { "elapsed_time": 703.6690711975098, "token_count": 689 }, { "elapsed_time": 697.3750591278076, "token_count": 690 }, { "elapsed_time": 698.9147663116455, "token_count": 691 }, { "elapsed_time": 707.2639465332031, "token_count": 692 }, { "elapsed_time": 725.6231307983398, "token_count": 693 }, { "elapsed_time": 719.4039821624756, "token_count": 694 }, { "elapsed_time": 704.409122467041, "token_count": 695 }, { "elapsed_time": 721.0156917572021, "token_count": 696 }, { "elapsed_time": 711.9140625, "token_count": 697 }, { "elapsed_time": 712.2728824615479, "token_count": 698 }, { "elapsed_time": 711.4911079406738, "token_count": 699 }, { "elapsed_time": 715.2609825134277, "token_count": 700 }, { "elapsed_time": 720.6470966339111, "token_count": 701 }, { "elapsed_time": 713.7801647186279, "token_count": 702 }, { "elapsed_time": 715.9850597381592, "token_count": 703 }, { "elapsed_time": 714.390754699707, "token_count": 704 }, { "elapsed_time": 713.7837409973145, "token_count": 705 }, { "elapsed_time": 717.2880172729492, "token_count": 706 }, { "elapsed_time": 737.3449802398682, "token_count": 707 }, { "elapsed_time": 730.7889461517334, "token_count": 708 }, { "elapsed_time": 719.6478843688965, "token_count": 709 }, { "elapsed_time": 724.1098880767822, "token_count": 710 }, { "elapsed_time": 725.2438068389893, "token_count": 711 }, { "elapsed_time": 730.7620048522949, "token_count": 712 }, { "elapsed_time": 728.5861968994141, "token_count": 713 }, { "elapsed_time": 742.5169944763184, "token_count": 714 }, { "elapsed_time": 736.163854598999, "token_count": 715 }, { "elapsed_time": 734.220027923584, "token_count": 716 }, { "elapsed_time": 733.9432239532471, "token_count": 717 }, { "elapsed_time": 735.5148792266846, "token_count": 718 }, { "elapsed_time": 733.6602210998535, "token_count": 719 }, { "elapsed_time": 734.2422008514404, "token_count": 720 }, { "elapsed_time": 767.967939376831, "token_count": 721 }, { "elapsed_time": 735.7251644134521, "token_count": 722 }, { "elapsed_time": 738.9769554138184, "token_count": 723 }, { "elapsed_time": 739.2199039459229, "token_count": 724 }, { "elapsed_time": 741.0118579864502, "token_count": 725 }, { "elapsed_time": 740.6919002532959, "token_count": 726 }, { "elapsed_time": 745.7780838012695, "token_count": 727 }, { "elapsed_time": 747.3618984222412, "token_count": 728 }, { "elapsed_time": 746.2027072906494, "token_count": 729 }, { "elapsed_time": 742.2547340393066, "token_count": 730 }, { "elapsed_time": 745.9189891815186, "token_count": 731 }, { "elapsed_time": 747.0359802246094, "token_count": 732 }, { "elapsed_time": 754.8000812530518, "token_count": 733 }, { "elapsed_time": 775.6679058074951, "token_count": 734 }, { "elapsed_time": 749.5479583740234, "token_count": 735 }, { "elapsed_time": 751.3370513916016, "token_count": 736 }, { "elapsed_time": 753.5991668701172, "token_count": 737 }, { "elapsed_time": 754.227876663208, "token_count": 738 }, { "elapsed_time": 757.7621936798096, "token_count": 739 }, { "elapsed_time": 753.3740997314453, "token_count": 740 }, { "elapsed_time": 752.4957656860352, "token_count": 741 }, { "elapsed_time": 757.5850486755371, "token_count": 742 }, { "elapsed_time": 760.0550651550293, "token_count": 743 }, { "elapsed_time": 753.9660930633545, "token_count": 744 }, { "elapsed_time": 760.3912353515625, "token_count": 745 }, { "elapsed_time": 774.3439674377441, "token_count": 746 }, { "elapsed_time": 787.5418663024902, "token_count": 747 }, { "elapsed_time": 763.9012336730957, "token_count": 748 }, { "elapsed_time": 770.7409858703613, "token_count": 749 }, { "elapsed_time": 765.8088207244873, "token_count": 750 }, { "elapsed_time": 767.3029899597168, "token_count": 751 }, { "elapsed_time": 764.509916305542, "token_count": 752 }, { "elapsed_time": 770.989179611206, "token_count": 753 }, { "elapsed_time": 774.7378349304199, "token_count": 754 }, { "elapsed_time": 767.3690319061279, "token_count": 755 }, { "elapsed_time": 769.9542045593262, "token_count": 756 }, { "elapsed_time": 771.7411518096924, "token_count": 757 }, { "elapsed_time": 779.0279388427734, "token_count": 758 }, { "elapsed_time": 775.0191688537598, "token_count": 759 }, { "elapsed_time": 812.2591972351074, "token_count": 760 }, { "elapsed_time": 785.9430313110352, "token_count": 761 }, { "elapsed_time": 780.771017074585, "token_count": 762 }, { "elapsed_time": 787.1949672698975, "token_count": 763 }, { "elapsed_time": 786.5152359008789, "token_count": 764 }, { "elapsed_time": 786.3969802856445, "token_count": 765 }, { "elapsed_time": 781.8841934204102, "token_count": 766 }, { "elapsed_time": 789.1049385070801, "token_count": 767 }, { "elapsed_time": 785.1972579956055, "token_count": 768 }, { "elapsed_time": 784.1329574584961, "token_count": 769 }, { "elapsed_time": 805.1390647888184, "token_count": 770 }, { "elapsed_time": 789.8290157318115, "token_count": 771 }, { "elapsed_time": 787.5981330871582, "token_count": 772 }, { "elapsed_time": 811.0649585723877, "token_count": 773 }, { "elapsed_time": 789.9961471557617, "token_count": 774 }, { "elapsed_time": 793.0312156677246, "token_count": 775 }, { "elapsed_time": 793.9772605895996, "token_count": 776 }, { "elapsed_time": 791.9681072235107, "token_count": 777 }, { "elapsed_time": 795.7291603088379, "token_count": 778 }, { "elapsed_time": 797.3158359527588, "token_count": 779 }, { "elapsed_time": 801.2428283691406, "token_count": 780 }, { "elapsed_time": 794.370174407959, "token_count": 781 }, { "elapsed_time": 799.8051643371582, "token_count": 782 }, { "elapsed_time": 799.5131015777588, "token_count": 783 }, { "elapsed_time": 805.4378032684326, "token_count": 784 }, { "elapsed_time": 856.1458587646484, "token_count": 785 }, { "elapsed_time": 808.8986873626709, "token_count": 786 }, { "elapsed_time": 803.6859035491943, "token_count": 787 }, { "elapsed_time": 808.4800243377686, "token_count": 788 }, { "elapsed_time": 803.056001663208, "token_count": 789 }, { "elapsed_time": 821.5560913085938, "token_count": 790 }, { "elapsed_time": 813.9939308166504, "token_count": 791 }, { "elapsed_time": 813.8620853424072, "token_count": 792 }, { "elapsed_time": 815.8199787139893, "token_count": 793 }, { "elapsed_time": 816.1683082580566, "token_count": 794 }, { "elapsed_time": 813.5509490966797, "token_count": 795 }, { "elapsed_time": 819.0748691558838, "token_count": 796 }, { "elapsed_time": 856.4291000366211, "token_count": 797 }, { "elapsed_time": 845.2358245849609, "token_count": 798 }, { "elapsed_time": 820.0631141662598, "token_count": 799 }, { "elapsed_time": 819.8158740997314, "token_count": 800 }, { "elapsed_time": 817.5492286682129, "token_count": 801 }, { "elapsed_time": 818.6848163604736, "token_count": 802 }, { "elapsed_time": 824.7551918029785, "token_count": 803 }, { "elapsed_time": 823.0190277099609, "token_count": 804 }, { "elapsed_time": 832.5469493865967, "token_count": 805 }, { "elapsed_time": 826.9658088684082, "token_count": 806 }, { "elapsed_time": 832.2749137878418, "token_count": 807 }, { "elapsed_time": 828.4199237823486, "token_count": 808 }, { "elapsed_time": 913.9750003814697, "token_count": 809 }, { "elapsed_time": 895.2701091766357, "token_count": 810 }, { "elapsed_time": 881.6509246826172, "token_count": 811 }, { "elapsed_time": 842.1778678894043, "token_count": 812 }, { "elapsed_time": 833.503246307373, "token_count": 813 }, { "elapsed_time": 834.2037200927734, "token_count": 814 }, { "elapsed_time": 839.7300243377686, "token_count": 815 }, { "elapsed_time": 849.506139755249, "token_count": 816 }, { "elapsed_time": 826.6851902008057, "token_count": 817 }, { "elapsed_time": 830.7459354400635, "token_count": 818 }, { "elapsed_time": 849.5919704437256, "token_count": 819 }, { "elapsed_time": 849.2252826690674, "token_count": 820 }, { "elapsed_time": 860.3720664978027, "token_count": 821 }, { "elapsed_time": 851.8869876861572, "token_count": 822 }, { "elapsed_time": 844.3551063537598, "token_count": 823 }, { "elapsed_time": 925.57692527771, "token_count": 824 }, { "elapsed_time": 926.642894744873, "token_count": 825 }, { "elapsed_time": 907.4020385742188, "token_count": 826 }, { "elapsed_time": 886.6698741912842, "token_count": 827 }, { "elapsed_time": 857.795238494873, "token_count": 828 }, { "elapsed_time": 833.5812091827393, "token_count": 829 }, { "elapsed_time": 842.2620296478271, "token_count": 830 }, { "elapsed_time": 912.5587940216064, "token_count": 831 }, { "elapsed_time": 863.8632297515869, "token_count": 832 }, { "elapsed_time": 822.3171234130859, "token_count": 833 }, { "elapsed_time": 829.0932178497314, "token_count": 834 }, { "elapsed_time": 833.9681625366211, "token_count": 835 }, { "elapsed_time": 825.6399631500244, "token_count": 836 }, { "elapsed_time": 827.8646469116211, "token_count": 837 }, { "elapsed_time": 835.8430862426758, "token_count": 838 }, { "elapsed_time": 834.8791599273682, "token_count": 839 }, { "elapsed_time": 858.1340312957764, "token_count": 840 }, { "elapsed_time": 837.9640579223633, "token_count": 841 }, { "elapsed_time": 860.4061603546143, "token_count": 842 }, { "elapsed_time": 866.912841796875, "token_count": 843 }, { "elapsed_time": 875.4920959472656, "token_count": 844 }, { "elapsed_time": 843.4748649597168, "token_count": 845 }, { "elapsed_time": 853.7468910217285, "token_count": 846 }, { "elapsed_time": 847.9480743408203, "token_count": 847 }, { "elapsed_time": 859.097957611084, "token_count": 848 }, { "elapsed_time": 841.4080142974854, "token_count": 849 }, { "elapsed_time": 857.2111129760742, "token_count": 850 }, { "elapsed_time": 848.5860824584961, "token_count": 851 }, { "elapsed_time": 862.8449440002441, "token_count": 852 }, { "elapsed_time": 878.9939880371094, "token_count": 853 }, { "elapsed_time": 949.5830535888672, "token_count": 854 }, { "elapsed_time": 895.77317237854, "token_count": 855 }, { "elapsed_time": 855.1888465881348, "token_count": 856 }, { "elapsed_time": 858.1619262695312, "token_count": 857 }, { "elapsed_time": 860.8441352844238, "token_count": 858 }, { "elapsed_time": 859.2650890350342, "token_count": 859 }, { "elapsed_time": 857.6781749725342, "token_count": 860 }, { "elapsed_time": 875.4050731658936, "token_count": 861 }, { "elapsed_time": 859.2300415039062, "token_count": 862 }, { "elapsed_time": 853.8417816162109, "token_count": 863 }, { "elapsed_time": 911.3221168518066, "token_count": 864 }, { "elapsed_time": 894.9120044708252, "token_count": 865 }, { "elapsed_time": 892.2209739685059, "token_count": 866 }, { "elapsed_time": 897.29905128479, "token_count": 867 }, { "elapsed_time": 867.1579360961914, "token_count": 868 }, { "elapsed_time": 975.5196571350098, "token_count": 869 }, { "elapsed_time": 891.6261196136475, "token_count": 870 }, { "elapsed_time": 889.4851207733154, "token_count": 871 }, { "elapsed_time": 869.3656921386719, "token_count": 872 }, { "elapsed_time": 865.4229640960693, "token_count": 873 }, { "elapsed_time": 871.258020401001, "token_count": 874 }, { "elapsed_time": 894.4530487060547, "token_count": 875 }, { "elapsed_time": 920.490026473999, "token_count": 876 }, { "elapsed_time": 894.4039344787598, "token_count": 877 }, { "elapsed_time": 884.7861289978027, "token_count": 878 }, { "elapsed_time": 868.5309886932373, "token_count": 879 }, { "elapsed_time": 870.2540397644043, "token_count": 880 }, { "elapsed_time": 882.0631504058838, "token_count": 881 }, { "elapsed_time": 885.4029178619385, "token_count": 882 }, { "elapsed_time": 890.2831077575684, "token_count": 883 }, { "elapsed_time": 917.949914932251, "token_count": 884 }, { "elapsed_time": 904.9878120422363, "token_count": 885 }, { "elapsed_time": 932.6300621032715, "token_count": 886 }, { "elapsed_time": 949.6340751647949, "token_count": 887 }, { "elapsed_time": 978.4488677978516, "token_count": 888 }, { "elapsed_time": 913.9950275421143, "token_count": 889 }, { "elapsed_time": 892.6239013671875, "token_count": 890 }, { "elapsed_time": 894.8051929473877, "token_count": 891 }, { "elapsed_time": 890.2859687805176, "token_count": 892 }, { "elapsed_time": 884.2830657958984, "token_count": 893 }, { "elapsed_time": 892.6887512207031, "token_count": 894 }, { "elapsed_time": 884.1209411621094, "token_count": 895 }, { "elapsed_time": 899.036169052124, "token_count": 896 }, { "elapsed_time": 927.5510311126709, "token_count": 897 }, { "elapsed_time": 917.4659252166748, "token_count": 898 }, { "elapsed_time": 935.1351261138916, "token_count": 899 }, { "elapsed_time": 903.4619331359863, "token_count": 900 }, { "elapsed_time": 900.1138210296631, "token_count": 901 }, { "elapsed_time": 933.4406852722168, "token_count": 902 }, { "elapsed_time": 940.9232139587402, "token_count": 903 }, { "elapsed_time": 914.560079574585, "token_count": 904 }, { "elapsed_time": 920.4709529876709, "token_count": 905 }, { "elapsed_time": 914.2270088195801, "token_count": 906 }, { "elapsed_time": 942.2147274017334, "token_count": 907 }, { "elapsed_time": 950.7451057434082, "token_count": 908 }, { "elapsed_time": 906.6321849822998, "token_count": 909 }, { "elapsed_time": 937.2189044952393, "token_count": 910 }, { "elapsed_time": 916.1841869354248, "token_count": 911 }, { "elapsed_time": 914.405107498169, "token_count": 912 }, { "elapsed_time": 923.6910343170166, "token_count": 913 }, { "elapsed_time": 903.8498401641846, "token_count": 914 }, { "elapsed_time": 907.7188968658447, "token_count": 915 }, { "elapsed_time": 921.4489459991455, "token_count": 916 }, { "elapsed_time": 951.4951705932617, "token_count": 917 }, { "elapsed_time": 1097.7373123168945, "token_count": 918 }, { "elapsed_time": 979.5041084289551, "token_count": 919 }, { "elapsed_time": 934.563159942627, "token_count": 920 }, { "elapsed_time": 942.4681663513184, "token_count": 921 }, { "elapsed_time": 937.0431900024414, "token_count": 922 }, { "elapsed_time": 940.4652118682861, "token_count": 923 }, { "elapsed_time": 927.6463985443115, "token_count": 924 }, { "elapsed_time": 917.3150062561035, "token_count": 925 }, { "elapsed_time": 921.212911605835, "token_count": 926 }, { "elapsed_time": 926.3668060302734, "token_count": 927 }, { "elapsed_time": 985.6488704681396, "token_count": 928 }, { "elapsed_time": 953.5841941833496, "token_count": 929 }, { "elapsed_time": 959.791898727417, "token_count": 930 }, { "elapsed_time": 967.120885848999, "token_count": 931 }, { "elapsed_time": 940.6309127807617, "token_count": 932 }, { "elapsed_time": 978.1241416931152, "token_count": 933 }, { "elapsed_time": 965.5249118804932, "token_count": 934 }, { "elapsed_time": 955.1191329956055, "token_count": 935 }, { "elapsed_time": 1009.2718601226807, "token_count": 936 }, { "elapsed_time": 949.9356746673584, "token_count": 937 }, { "elapsed_time": 979.8638820648193, "token_count": 938 }, { "elapsed_time": 984.0288162231445, "token_count": 939 }, { "elapsed_time": 966.0861492156982, "token_count": 940 }, { "elapsed_time": 974.7872352600098, "token_count": 941 }, { "elapsed_time": 936.2180233001709, "token_count": 942 }, { "elapsed_time": 963.4943008422852, "token_count": 943 }, { "elapsed_time": 959.0239524841309, "token_count": 944 }, { "elapsed_time": 954.8361301422119, "token_count": 945 }, { "elapsed_time": 949.6219158172607, "token_count": 946 }, { "elapsed_time": 948.7991333007812, "token_count": 947 }, { "elapsed_time": 989.1409873962402, "token_count": 948 }, { "elapsed_time": 1001.5542507171631, "token_count": 949 }, { "elapsed_time": 947.2270011901855, "token_count": 950 }, { "elapsed_time": 981.112003326416, "token_count": 951 }, { "elapsed_time": 952.0020484924316, "token_count": 952 }, { "elapsed_time": 972.4569320678711, "token_count": 953 }, { "elapsed_time": 960.968017578125, "token_count": 954 }, { "elapsed_time": 958.507776260376, "token_count": 955 }, { "elapsed_time": 948.6229419708252, "token_count": 956 }, { "elapsed_time": 956.0608863830566, "token_count": 957 }, { "elapsed_time": 1043.2829856872559, "token_count": 958 }, { "elapsed_time": 1078.1879425048828, "token_count": 959 }, { "elapsed_time": 999.6969699859619, "token_count": 960 }, { "elapsed_time": 979.5680046081543, "token_count": 961 }, { "elapsed_time": 972.0108509063721, "token_count": 962 }, { "elapsed_time": 993.9279556274414, "token_count": 963 }, { "elapsed_time": 1017.1148777008057, "token_count": 964 }, { "elapsed_time": 958.6939811706543, "token_count": 965 }, { "elapsed_time": 973.0429649353027, "token_count": 966 }, { "elapsed_time": 968.5530662536621, "token_count": 967 }, { "elapsed_time": 1016.1139965057373, "token_count": 968 }, { "elapsed_time": 1020.1249122619629, "token_count": 969 }, { "elapsed_time": 972.2130298614502, "token_count": 970 }, { "elapsed_time": 1019.0231800079346, "token_count": 971 }, { "elapsed_time": 983.159065246582, "token_count": 972 }, { "elapsed_time": 988.9998435974121, "token_count": 973 }, { "elapsed_time": 973.0901718139648, "token_count": 974 }, { "elapsed_time": 971.3859558105469, "token_count": 975 }, { "elapsed_time": 982.0280075073242, "token_count": 976 }, { "elapsed_time": 985.7861995697021, "token_count": 977 }, { "elapsed_time": 1031.9018363952637, "token_count": 978 }, { "elapsed_time": 1067.1050548553467, "token_count": 979 }, { "elapsed_time": 982.450008392334, "token_count": 980 }, { "elapsed_time": 1042.5522327423096, "token_count": 981 }, { "elapsed_time": 1031.4853191375732, "token_count": 982 }, { "elapsed_time": 1033.1158638000488, "token_count": 983 }, { "elapsed_time": 1033.4279537200928, "token_count": 984 }, { "elapsed_time": 1029.088020324707, "token_count": 985 }, { "elapsed_time": 1016.071081161499, "token_count": 986 }, { "elapsed_time": 1032.0429801940918, "token_count": 987 }, { "elapsed_time": 1027.3950099945068, "token_count": 988 }, { "elapsed_time": 1072.1111297607422, "token_count": 989 }, { "elapsed_time": 1084.6278667449951, "token_count": 990 }, { "elapsed_time": 1051.6648292541504, "token_count": 991 }, { "elapsed_time": 1033.2810878753662, "token_count": 992 }, { "elapsed_time": 1027.7941226959229, "token_count": 993 }, { "elapsed_time": 1037.5773906707764, "token_count": 994 }, { "elapsed_time": 1037.9290580749512, "token_count": 995 }, { "elapsed_time": 1037.017822265625, "token_count": 996 }, { "elapsed_time": 1052.016019821167, "token_count": 997 }, { "elapsed_time": 1032.4182510375977, "token_count": 998 }, { "elapsed_time": 1047.070026397705, "token_count": 999 } ], "max_token_count_per_time": { "100": 100, "200": 199, "300": 299, "400": 396, "500": 514, "600": 613, "700": 691, "800": 783, "900": 896, "1000": 980, "1100": 999, "1200": 999, "1300": 999, "1400": 999, "1500": 999 } } ================================================ FILE: reports/inference_result/drqa-cpu.json ================================================ { "average_raw_to_tensor": 32.9001364081797, "average_tensor_to_predict": 641.9128160284023, "average_end_to_end": 674.812952436582, "tensor_to_predicts": [ { "elapsed_time": 21.235227584838867, "token_count": 10 }, { "elapsed_time": 16.850709915161133, "token_count": 11 }, { "elapsed_time": 17.00878143310547, "token_count": 12 }, { "elapsed_time": 18.548965454101562, "token_count": 13 }, { "elapsed_time": 21.88277244567871, "token_count": 14 }, { "elapsed_time": 21.05093002319336, "token_count": 15 }, { "elapsed_time": 22.473812103271484, "token_count": 16 }, { "elapsed_time": 22.981882095336914, "token_count": 17 }, { "elapsed_time": 25.272130966186523, "token_count": 18 }, { "elapsed_time": 25.201082229614258, "token_count": 19 }, { "elapsed_time": 26.571035385131836, "token_count": 20 }, { "elapsed_time": 28.10215950012207, "token_count": 21 }, { "elapsed_time": 30.492067337036133, "token_count": 22 }, { "elapsed_time": 31.450748443603516, "token_count": 23 }, { "elapsed_time": 32.26184844970703, "token_count": 24 }, { "elapsed_time": 34.14177894592285, "token_count": 25 }, { "elapsed_time": 35.87222099304199, "token_count": 26 }, { "elapsed_time": 35.156965255737305, "token_count": 27 }, { "elapsed_time": 37.405967712402344, "token_count": 28 }, { "elapsed_time": 38.398027420043945, "token_count": 29 }, { "elapsed_time": 40.621042251586914, "token_count": 30 }, { "elapsed_time": 42.3130989074707, "token_count": 31 }, { "elapsed_time": 41.590213775634766, "token_count": 32 }, { "elapsed_time": 43.280839920043945, "token_count": 33 }, { "elapsed_time": 45.42899131774902, "token_count": 34 }, { "elapsed_time": 46.02503776550293, "token_count": 35 }, { "elapsed_time": 46.67782783508301, "token_count": 36 }, { "elapsed_time": 48.43711853027344, "token_count": 37 }, { "elapsed_time": 49.037933349609375, "token_count": 38 }, { "elapsed_time": 50.63199996948242, "token_count": 39 }, { "elapsed_time": 51.650047302246094, "token_count": 40 }, { "elapsed_time": 52.427053451538086, "token_count": 41 }, { "elapsed_time": 53.91883850097656, "token_count": 42 }, { "elapsed_time": 54.63695526123047, "token_count": 43 }, { "elapsed_time": 56.98394775390625, "token_count": 44 }, { "elapsed_time": 58.67195129394531, "token_count": 45 }, { "elapsed_time": 59.92412567138672, "token_count": 46 }, { "elapsed_time": 60.537099838256836, "token_count": 47 }, { "elapsed_time": 62.37220764160156, "token_count": 48 }, { "elapsed_time": 63.94219398498535, "token_count": 49 }, { "elapsed_time": 64.08119201660156, "token_count": 50 }, { "elapsed_time": 65.05918502807617, "token_count": 51 }, { "elapsed_time": 66.68901443481445, "token_count": 52 }, { "elapsed_time": 70.2981948852539, "token_count": 53 }, { "elapsed_time": 68.56298446655273, "token_count": 54 }, { "elapsed_time": 72.21508026123047, "token_count": 55 }, { "elapsed_time": 72.13592529296875, "token_count": 56 }, { "elapsed_time": 72.58796691894531, "token_count": 57 }, { "elapsed_time": 73.41790199279785, "token_count": 58 }, { "elapsed_time": 81.53414726257324, "token_count": 59 }, { "elapsed_time": 75.82592964172363, "token_count": 60 }, { "elapsed_time": 77.42500305175781, "token_count": 61 }, { "elapsed_time": 80.19804954528809, "token_count": 62 }, { "elapsed_time": 81.69412612915039, "token_count": 63 }, { "elapsed_time": 97.87607192993164, "token_count": 64 }, { "elapsed_time": 84.8398208618164, "token_count": 65 }, { "elapsed_time": 88.93585205078125, "token_count": 66 }, { "elapsed_time": 90.28816223144531, "token_count": 67 }, { "elapsed_time": 89.13803100585938, "token_count": 68 }, { "elapsed_time": 88.60278129577637, "token_count": 69 }, { "elapsed_time": 93.69111061096191, "token_count": 70 }, { "elapsed_time": 91.4311408996582, "token_count": 71 }, { "elapsed_time": 95.53885459899902, "token_count": 72 }, { "elapsed_time": 96.96698188781738, "token_count": 73 }, { "elapsed_time": 97.97501564025879, "token_count": 74 }, { "elapsed_time": 100.7380485534668, "token_count": 75 }, { "elapsed_time": 99.43819046020508, "token_count": 76 }, { "elapsed_time": 101.49669647216797, "token_count": 77 }, { "elapsed_time": 99.32088851928711, "token_count": 78 }, { "elapsed_time": 100.79097747802734, "token_count": 79 }, { "elapsed_time": 104.67314720153809, "token_count": 80 }, { "elapsed_time": 104.24280166625977, "token_count": 81 }, { "elapsed_time": 104.84910011291504, "token_count": 82 }, { "elapsed_time": 106.05168342590332, "token_count": 83 }, { "elapsed_time": 107.30123519897461, "token_count": 84 }, { "elapsed_time": 110.1682186126709, "token_count": 85 }, { "elapsed_time": 112.25771903991699, "token_count": 86 }, { "elapsed_time": 111.44614219665527, "token_count": 87 }, { "elapsed_time": 109.50303077697754, "token_count": 88 }, { "elapsed_time": 114.6087646484375, "token_count": 89 }, { "elapsed_time": 119.31300163269043, "token_count": 90 }, { "elapsed_time": 131.72483444213867, "token_count": 91 }, { "elapsed_time": 148.66304397583008, "token_count": 92 }, { "elapsed_time": 126.63102149963379, "token_count": 93 }, { "elapsed_time": 128.92603874206543, "token_count": 94 }, { "elapsed_time": 124.58586692810059, "token_count": 95 }, { "elapsed_time": 126.44696235656738, "token_count": 96 }, { "elapsed_time": 127.31695175170898, "token_count": 97 }, { "elapsed_time": 129.10699844360352, "token_count": 98 }, { "elapsed_time": 133.61310958862305, "token_count": 99 }, { "elapsed_time": 130.8581829071045, "token_count": 100 }, { "elapsed_time": 135.90312004089355, "token_count": 101 }, { "elapsed_time": 138.10205459594727, "token_count": 102 }, { "elapsed_time": 134.85217094421387, "token_count": 103 }, { "elapsed_time": 140.6550407409668, "token_count": 104 }, { "elapsed_time": 138.90886306762695, "token_count": 105 }, { "elapsed_time": 142.84110069274902, "token_count": 106 }, { "elapsed_time": 142.38595962524414, "token_count": 107 }, { "elapsed_time": 143.7680721282959, "token_count": 108 }, { "elapsed_time": 149.71494674682617, "token_count": 109 }, { "elapsed_time": 141.53790473937988, "token_count": 110 }, { "elapsed_time": 146.33822441101074, "token_count": 111 }, { "elapsed_time": 146.11482620239258, "token_count": 112 }, { "elapsed_time": 149.85322952270508, "token_count": 113 }, { "elapsed_time": 150.6969928741455, "token_count": 114 }, { "elapsed_time": 148.1606960296631, "token_count": 115 }, { "elapsed_time": 150.8629322052002, "token_count": 116 }, { "elapsed_time": 150.91395378112793, "token_count": 117 }, { "elapsed_time": 151.21102333068848, "token_count": 118 }, { "elapsed_time": 151.2470245361328, "token_count": 119 }, { "elapsed_time": 151.4723300933838, "token_count": 120 }, { "elapsed_time": 153.92613410949707, "token_count": 121 }, { "elapsed_time": 156.28433227539062, "token_count": 122 }, { "elapsed_time": 157.0448875427246, "token_count": 123 }, { "elapsed_time": 161.1959934234619, "token_count": 124 }, { "elapsed_time": 162.94288635253906, "token_count": 125 }, { "elapsed_time": 164.23702239990234, "token_count": 126 }, { "elapsed_time": 163.02013397216797, "token_count": 127 }, { "elapsed_time": 161.6988182067871, "token_count": 128 }, { "elapsed_time": 162.79292106628418, "token_count": 129 }, { "elapsed_time": 164.68286514282227, "token_count": 130 }, { "elapsed_time": 165.54880142211914, "token_count": 131 }, { "elapsed_time": 162.8117561340332, "token_count": 132 }, { "elapsed_time": 169.98887062072754, "token_count": 133 }, { "elapsed_time": 169.6298122406006, "token_count": 134 }, { "elapsed_time": 172.78480529785156, "token_count": 135 }, { "elapsed_time": 177.93703079223633, "token_count": 136 }, { "elapsed_time": 180.9530258178711, "token_count": 137 }, { "elapsed_time": 180.16505241394043, "token_count": 138 }, { "elapsed_time": 184.3719482421875, "token_count": 139 }, { "elapsed_time": 182.49988555908203, "token_count": 140 }, { "elapsed_time": 179.67915534973145, "token_count": 141 }, { "elapsed_time": 182.02495574951172, "token_count": 142 }, { "elapsed_time": 183.53509902954102, "token_count": 143 }, { "elapsed_time": 184.18622016906738, "token_count": 144 }, { "elapsed_time": 190.11783599853516, "token_count": 145 }, { "elapsed_time": 199.3999481201172, "token_count": 146 }, { "elapsed_time": 193.17913055419922, "token_count": 147 }, { "elapsed_time": 198.6408233642578, "token_count": 148 }, { "elapsed_time": 197.88122177124023, "token_count": 149 }, { "elapsed_time": 199.5859146118164, "token_count": 150 }, { "elapsed_time": 191.51711463928223, "token_count": 151 }, { "elapsed_time": 209.42211151123047, "token_count": 152 }, { "elapsed_time": 223.0069637298584, "token_count": 153 }, { "elapsed_time": 206.34889602661133, "token_count": 154 }, { "elapsed_time": 199.17702674865723, "token_count": 155 }, { "elapsed_time": 200.1659870147705, "token_count": 156 }, { "elapsed_time": 209.14602279663086, "token_count": 157 }, { "elapsed_time": 207.89408683776855, "token_count": 158 }, { "elapsed_time": 208.94408226013184, "token_count": 159 }, { "elapsed_time": 204.49495315551758, "token_count": 160 }, { "elapsed_time": 209.86700057983398, "token_count": 161 }, { "elapsed_time": 204.6191692352295, "token_count": 162 }, { "elapsed_time": 205.53302764892578, "token_count": 163 }, { "elapsed_time": 206.77709579467773, "token_count": 164 }, { "elapsed_time": 206.35175704956055, "token_count": 165 }, { "elapsed_time": 216.96090698242188, "token_count": 166 }, { "elapsed_time": 219.75421905517578, "token_count": 167 }, { "elapsed_time": 221.16804122924805, "token_count": 168 }, { "elapsed_time": 215.25216102600098, "token_count": 169 }, { "elapsed_time": 226.14502906799316, "token_count": 170 }, { "elapsed_time": 222.70512580871582, "token_count": 171 }, { "elapsed_time": 225.27098655700684, "token_count": 172 }, { "elapsed_time": 232.76281356811523, "token_count": 173 }, { "elapsed_time": 228.22999954223633, "token_count": 174 }, { "elapsed_time": 223.4060764312744, "token_count": 175 }, { "elapsed_time": 224.07007217407227, "token_count": 176 }, { "elapsed_time": 224.9429225921631, "token_count": 177 }, { "elapsed_time": 226.7131805419922, "token_count": 178 }, { "elapsed_time": 225.0978946685791, "token_count": 179 }, { "elapsed_time": 226.1679172515869, "token_count": 180 }, { "elapsed_time": 240.675687789917, "token_count": 181 }, { "elapsed_time": 238.19804191589355, "token_count": 182 }, { "elapsed_time": 242.16985702514648, "token_count": 183 }, { "elapsed_time": 231.72688484191895, "token_count": 184 }, { "elapsed_time": 240.99111557006836, "token_count": 185 }, { "elapsed_time": 237.86377906799316, "token_count": 186 }, { "elapsed_time": 234.9720001220703, "token_count": 187 }, { "elapsed_time": 236.8319034576416, "token_count": 188 }, { "elapsed_time": 249.2218017578125, "token_count": 189 }, { "elapsed_time": 247.66898155212402, "token_count": 190 }, { "elapsed_time": 249.01485443115234, "token_count": 191 }, { "elapsed_time": 254.64487075805664, "token_count": 192 }, { "elapsed_time": 254.76789474487305, "token_count": 193 }, { "elapsed_time": 254.06599044799805, "token_count": 194 }, { "elapsed_time": 249.6318817138672, "token_count": 195 }, { "elapsed_time": 272.6602554321289, "token_count": 196 }, { "elapsed_time": 246.50001525878906, "token_count": 197 }, { "elapsed_time": 253.18503379821777, "token_count": 198 }, { "elapsed_time": 258.9449882507324, "token_count": 199 }, { "elapsed_time": 265.0489807128906, "token_count": 200 }, { "elapsed_time": 258.6369514465332, "token_count": 201 }, { "elapsed_time": 269.52314376831055, "token_count": 202 }, { "elapsed_time": 263.75675201416016, "token_count": 203 }, { "elapsed_time": 263.5519504547119, "token_count": 204 }, { "elapsed_time": 269.8650360107422, "token_count": 205 }, { "elapsed_time": 258.23473930358887, "token_count": 206 }, { "elapsed_time": 267.2140598297119, "token_count": 207 }, { "elapsed_time": 273.04697036743164, "token_count": 208 }, { "elapsed_time": 270.2140808105469, "token_count": 209 }, { "elapsed_time": 270.5862522125244, "token_count": 210 }, { "elapsed_time": 262.315034866333, "token_count": 211 }, { "elapsed_time": 266.8459415435791, "token_count": 212 }, { "elapsed_time": 270.81799507141113, "token_count": 213 }, { "elapsed_time": 274.77002143859863, "token_count": 214 }, { "elapsed_time": 271.32582664489746, "token_count": 215 }, { "elapsed_time": 274.8448848724365, "token_count": 216 }, { "elapsed_time": 276.7951488494873, "token_count": 217 }, { "elapsed_time": 275.0129699707031, "token_count": 218 }, { "elapsed_time": 277.68898010253906, "token_count": 219 }, { "elapsed_time": 277.188777923584, "token_count": 220 }, { "elapsed_time": 278.28192710876465, "token_count": 221 }, { "elapsed_time": 279.2022228240967, "token_count": 222 }, { "elapsed_time": 284.99484062194824, "token_count": 223 }, { "elapsed_time": 279.93083000183105, "token_count": 224 }, { "elapsed_time": 283.3220958709717, "token_count": 225 }, { "elapsed_time": 287.16015815734863, "token_count": 226 }, { "elapsed_time": 282.96923637390137, "token_count": 227 }, { "elapsed_time": 301.10788345336914, "token_count": 228 }, { "elapsed_time": 296.9090938568115, "token_count": 229 }, { "elapsed_time": 287.08720207214355, "token_count": 230 }, { "elapsed_time": 307.6517581939697, "token_count": 231 }, { "elapsed_time": 319.35906410217285, "token_count": 232 }, { "elapsed_time": 298.20704460144043, "token_count": 233 }, { "elapsed_time": 297.8029251098633, "token_count": 234 }, { "elapsed_time": 299.62778091430664, "token_count": 235 }, { "elapsed_time": 313.31896781921387, "token_count": 236 }, { "elapsed_time": 305.4490089416504, "token_count": 237 }, { "elapsed_time": 303.8027286529541, "token_count": 238 }, { "elapsed_time": 308.48002433776855, "token_count": 239 }, { "elapsed_time": 301.3441562652588, "token_count": 240 }, { "elapsed_time": 303.1141757965088, "token_count": 241 }, { "elapsed_time": 304.6698570251465, "token_count": 242 }, { "elapsed_time": 304.70991134643555, "token_count": 243 }, { "elapsed_time": 313.25721740722656, "token_count": 244 }, { "elapsed_time": 319.0479278564453, "token_count": 245 }, { "elapsed_time": 330.8117389678955, "token_count": 246 }, { "elapsed_time": 319.4901943206787, "token_count": 247 }, { "elapsed_time": 321.64597511291504, "token_count": 248 }, { "elapsed_time": 328.10378074645996, "token_count": 249 }, { "elapsed_time": 315.84906578063965, "token_count": 250 }, { "elapsed_time": 325.0696659088135, "token_count": 251 }, { "elapsed_time": 329.10799980163574, "token_count": 252 }, { "elapsed_time": 320.6460475921631, "token_count": 253 }, { "elapsed_time": 321.29883766174316, "token_count": 254 }, { "elapsed_time": 331.3019275665283, "token_count": 255 }, { "elapsed_time": 369.59099769592285, "token_count": 256 }, { "elapsed_time": 333.0421447753906, "token_count": 257 }, { "elapsed_time": 330.17802238464355, "token_count": 258 }, { "elapsed_time": 333.1298828125, "token_count": 259 }, { "elapsed_time": 339.60771560668945, "token_count": 260 }, { "elapsed_time": 341.50195121765137, "token_count": 261 }, { "elapsed_time": 405.4131507873535, "token_count": 262 }, { "elapsed_time": 349.4572639465332, "token_count": 263 }, { "elapsed_time": 342.61393547058105, "token_count": 264 }, { "elapsed_time": 357.5749397277832, "token_count": 265 }, { "elapsed_time": 363.0189895629883, "token_count": 266 }, { "elapsed_time": 370.37110328674316, "token_count": 267 }, { "elapsed_time": 347.33104705810547, "token_count": 268 }, { "elapsed_time": 381.98304176330566, "token_count": 269 }, { "elapsed_time": 344.5413112640381, "token_count": 270 }, { "elapsed_time": 341.98904037475586, "token_count": 271 }, { "elapsed_time": 358.1976890563965, "token_count": 272 }, { "elapsed_time": 341.8850898742676, "token_count": 273 }, { "elapsed_time": 370.9218502044678, "token_count": 274 }, { "elapsed_time": 366.4538860321045, "token_count": 275 }, { "elapsed_time": 364.4399642944336, "token_count": 276 }, { "elapsed_time": 405.6661128997803, "token_count": 277 }, { "elapsed_time": 384.0980529785156, "token_count": 278 }, { "elapsed_time": 357.59711265563965, "token_count": 279 }, { "elapsed_time": 355.09490966796875, "token_count": 280 }, { "elapsed_time": 345.89219093322754, "token_count": 281 }, { "elapsed_time": 363.65628242492676, "token_count": 282 }, { "elapsed_time": 361.42516136169434, "token_count": 283 }, { "elapsed_time": 378.66902351379395, "token_count": 284 }, { "elapsed_time": 360.7301712036133, "token_count": 285 }, { "elapsed_time": 355.8981418609619, "token_count": 286 }, { "elapsed_time": 355.6239604949951, "token_count": 287 }, { "elapsed_time": 355.76868057250977, "token_count": 288 }, { "elapsed_time": 386.7230415344238, "token_count": 289 }, { "elapsed_time": 368.90101432800293, "token_count": 290 }, { "elapsed_time": 374.33695793151855, "token_count": 291 }, { "elapsed_time": 376.48797035217285, "token_count": 292 }, { "elapsed_time": 371.5019226074219, "token_count": 293 }, { "elapsed_time": 383.8391304016113, "token_count": 294 }, { "elapsed_time": 401.80015563964844, "token_count": 295 }, { "elapsed_time": 424.42893981933594, "token_count": 296 }, { "elapsed_time": 405.18712997436523, "token_count": 297 }, { "elapsed_time": 417.70410537719727, "token_count": 298 }, { "elapsed_time": 406.4829349517822, "token_count": 299 }, { "elapsed_time": 382.47084617614746, "token_count": 300 }, { "elapsed_time": 438.6329650878906, "token_count": 301 }, { "elapsed_time": 438.4799003601074, "token_count": 302 }, { "elapsed_time": 411.7240905761719, "token_count": 303 }, { "elapsed_time": 393.0470943450928, "token_count": 304 }, { "elapsed_time": 368.09802055358887, "token_count": 305 }, { "elapsed_time": 366.03713035583496, "token_count": 306 }, { "elapsed_time": 392.1840190887451, "token_count": 307 }, { "elapsed_time": 404.2072296142578, "token_count": 308 }, { "elapsed_time": 379.47607040405273, "token_count": 309 }, { "elapsed_time": 388.1187438964844, "token_count": 310 }, { "elapsed_time": 372.114896774292, "token_count": 311 }, { "elapsed_time": 380.60736656188965, "token_count": 312 }, { "elapsed_time": 394.8078155517578, "token_count": 313 }, { "elapsed_time": 411.2508296966553, "token_count": 314 }, { "elapsed_time": 375.54097175598145, "token_count": 315 }, { "elapsed_time": 393.65196228027344, "token_count": 316 }, { "elapsed_time": 393.5661315917969, "token_count": 317 }, { "elapsed_time": 396.85583114624023, "token_count": 318 }, { "elapsed_time": 391.5691375732422, "token_count": 319 }, { "elapsed_time": 395.2949047088623, "token_count": 320 }, { "elapsed_time": 382.0798397064209, "token_count": 321 }, { "elapsed_time": 381.85811042785645, "token_count": 322 }, { "elapsed_time": 383.55112075805664, "token_count": 323 }, { "elapsed_time": 383.6100101470947, "token_count": 324 }, { "elapsed_time": 391.6490077972412, "token_count": 325 }, { "elapsed_time": 395.0479030609131, "token_count": 326 }, { "elapsed_time": 386.962890625, "token_count": 327 }, { "elapsed_time": 388.9341354370117, "token_count": 328 }, { "elapsed_time": 395.72715759277344, "token_count": 329 }, { "elapsed_time": 401.1709690093994, "token_count": 330 }, { "elapsed_time": 410.4199409484863, "token_count": 331 }, { "elapsed_time": 397.2170352935791, "token_count": 332 }, { "elapsed_time": 420.46594619750977, "token_count": 333 }, { "elapsed_time": 402.5919437408447, "token_count": 334 }, { "elapsed_time": 399.5680809020996, "token_count": 335 }, { "elapsed_time": 402.1608829498291, "token_count": 336 }, { "elapsed_time": 406.94499015808105, "token_count": 337 }, { "elapsed_time": 408.87999534606934, "token_count": 338 }, { "elapsed_time": 426.9752502441406, "token_count": 339 }, { "elapsed_time": 425.264835357666, "token_count": 340 }, { "elapsed_time": 430.42588233947754, "token_count": 341 }, { "elapsed_time": 428.51781845092773, "token_count": 342 }, { "elapsed_time": 426.39732360839844, "token_count": 343 }, { "elapsed_time": 413.8641357421875, "token_count": 344 }, { "elapsed_time": 423.59280586242676, "token_count": 345 }, { "elapsed_time": 421.95916175842285, "token_count": 346 }, { "elapsed_time": 452.4531364440918, "token_count": 347 }, { "elapsed_time": 458.12201499938965, "token_count": 348 }, { "elapsed_time": 437.08205223083496, "token_count": 349 }, { "elapsed_time": 417.94800758361816, "token_count": 350 }, { "elapsed_time": 420.98498344421387, "token_count": 351 }, { "elapsed_time": 415.4808521270752, "token_count": 352 }, { "elapsed_time": 438.62199783325195, "token_count": 353 }, { "elapsed_time": 430.9496879577637, "token_count": 354 }, { "elapsed_time": 423.8128662109375, "token_count": 355 }, { "elapsed_time": 429.7680854797363, "token_count": 356 }, { "elapsed_time": 425.86398124694824, "token_count": 357 }, { "elapsed_time": 430.0990104675293, "token_count": 358 }, { "elapsed_time": 424.62801933288574, "token_count": 359 }, { "elapsed_time": 436.72704696655273, "token_count": 360 }, { "elapsed_time": 450.2379894256592, "token_count": 361 }, { "elapsed_time": 444.7751045227051, "token_count": 362 }, { "elapsed_time": 447.9401111602783, "token_count": 363 }, { "elapsed_time": 469.2549705505371, "token_count": 364 }, { "elapsed_time": 471.3430404663086, "token_count": 365 }, { "elapsed_time": 445.82676887512207, "token_count": 366 }, { "elapsed_time": 437.3350143432617, "token_count": 367 }, { "elapsed_time": 437.4651908874512, "token_count": 368 }, { "elapsed_time": 441.770076751709, "token_count": 369 }, { "elapsed_time": 440.0827884674072, "token_count": 370 }, { "elapsed_time": 446.2592601776123, "token_count": 371 }, { "elapsed_time": 444.3342685699463, "token_count": 372 }, { "elapsed_time": 448.8110542297363, "token_count": 373 }, { "elapsed_time": 455.72686195373535, "token_count": 374 }, { "elapsed_time": 460.0188732147217, "token_count": 375 }, { "elapsed_time": 461.1189365386963, "token_count": 376 }, { "elapsed_time": 456.42709732055664, "token_count": 377 }, { "elapsed_time": 455.1968574523926, "token_count": 378 }, { "elapsed_time": 467.7407741546631, "token_count": 379 }, { "elapsed_time": 462.24403381347656, "token_count": 380 }, { "elapsed_time": 457.9331874847412, "token_count": 381 }, { "elapsed_time": 455.8260440826416, "token_count": 382 }, { "elapsed_time": 500.5779266357422, "token_count": 383 }, { "elapsed_time": 477.83493995666504, "token_count": 384 }, { "elapsed_time": 483.74414443969727, "token_count": 385 }, { "elapsed_time": 493.92175674438477, "token_count": 386 }, { "elapsed_time": 467.6229953765869, "token_count": 387 }, { "elapsed_time": 464.3230438232422, "token_count": 388 }, { "elapsed_time": 459.5651626586914, "token_count": 389 }, { "elapsed_time": 473.94514083862305, "token_count": 390 }, { "elapsed_time": 480.85594177246094, "token_count": 391 }, { "elapsed_time": 477.57792472839355, "token_count": 392 }, { "elapsed_time": 470.9620475769043, "token_count": 393 }, { "elapsed_time": 476.17602348327637, "token_count": 394 }, { "elapsed_time": 470.3092575073242, "token_count": 395 }, { "elapsed_time": 481.6150665283203, "token_count": 396 }, { "elapsed_time": 474.3647575378418, "token_count": 397 }, { "elapsed_time": 479.86578941345215, "token_count": 398 }, { "elapsed_time": 470.1519012451172, "token_count": 399 }, { "elapsed_time": 474.22194480895996, "token_count": 400 }, { "elapsed_time": 475.50106048583984, "token_count": 401 }, { "elapsed_time": 474.49707984924316, "token_count": 402 }, { "elapsed_time": 522.1829414367676, "token_count": 403 }, { "elapsed_time": 541.0339832305908, "token_count": 404 }, { "elapsed_time": 501.1169910430908, "token_count": 405 }, { "elapsed_time": 507.5850486755371, "token_count": 406 }, { "elapsed_time": 488.3460998535156, "token_count": 407 }, { "elapsed_time": 486.4037036895752, "token_count": 408 }, { "elapsed_time": 490.5858039855957, "token_count": 409 }, { "elapsed_time": 492.5687313079834, "token_count": 410 }, { "elapsed_time": 497.1649646759033, "token_count": 411 }, { "elapsed_time": 499.0870952606201, "token_count": 412 }, { "elapsed_time": 503.0250549316406, "token_count": 413 }, { "elapsed_time": 534.904956817627, "token_count": 414 }, { "elapsed_time": 499.3762969970703, "token_count": 415 }, { "elapsed_time": 497.18523025512695, "token_count": 416 }, { "elapsed_time": 499.50504302978516, "token_count": 417 }, { "elapsed_time": 498.7812042236328, "token_count": 418 }, { "elapsed_time": 493.2868480682373, "token_count": 419 }, { "elapsed_time": 499.82595443725586, "token_count": 420 }, { "elapsed_time": 512.3200416564941, "token_count": 421 }, { "elapsed_time": 521.1179256439209, "token_count": 422 }, { "elapsed_time": 530.1470756530762, "token_count": 423 }, { "elapsed_time": 533.043384552002, "token_count": 424 }, { "elapsed_time": 524.9018669128418, "token_count": 425 }, { "elapsed_time": 522.5439071655273, "token_count": 426 }, { "elapsed_time": 518.9979076385498, "token_count": 427 }, { "elapsed_time": 505.85007667541504, "token_count": 428 }, { "elapsed_time": 507.72976875305176, "token_count": 429 }, { "elapsed_time": 516.0698890686035, "token_count": 430 }, { "elapsed_time": 521.0089683532715, "token_count": 431 }, { "elapsed_time": 529.0801525115967, "token_count": 432 }, { "elapsed_time": 514.279842376709, "token_count": 433 }, { "elapsed_time": 522.3121643066406, "token_count": 434 }, { "elapsed_time": 535.7871055603027, "token_count": 435 }, { "elapsed_time": 519.5579528808594, "token_count": 436 }, { "elapsed_time": 519.4869041442871, "token_count": 437 }, { "elapsed_time": 517.8229808807373, "token_count": 438 }, { "elapsed_time": 536.3140106201172, "token_count": 439 }, { "elapsed_time": 525.0308513641357, "token_count": 440 }, { "elapsed_time": 562.8988742828369, "token_count": 441 }, { "elapsed_time": 548.3510494232178, "token_count": 442 }, { "elapsed_time": 573.5812187194824, "token_count": 443 }, { "elapsed_time": 535.2597236633301, "token_count": 444 }, { "elapsed_time": 524.8911380767822, "token_count": 445 }, { "elapsed_time": 530.8239459991455, "token_count": 446 }, { "elapsed_time": 541.2678718566895, "token_count": 447 }, { "elapsed_time": 540.2400493621826, "token_count": 448 }, { "elapsed_time": 536.1719131469727, "token_count": 449 }, { "elapsed_time": 543.5659885406494, "token_count": 450 }, { "elapsed_time": 547.9080677032471, "token_count": 451 }, { "elapsed_time": 548.9180088043213, "token_count": 452 }, { "elapsed_time": 543.4980392456055, "token_count": 453 }, { "elapsed_time": 564.439058303833, "token_count": 454 }, { "elapsed_time": 589.4920825958252, "token_count": 455 }, { "elapsed_time": 569.5738792419434, "token_count": 456 }, { "elapsed_time": 560.067892074585, "token_count": 457 }, { "elapsed_time": 559.4067573547363, "token_count": 458 }, { "elapsed_time": 598.0770587921143, "token_count": 459 }, { "elapsed_time": 574.9740600585938, "token_count": 460 }, { "elapsed_time": 558.6040019989014, "token_count": 461 }, { "elapsed_time": 547.7950572967529, "token_count": 462 }, { "elapsed_time": 549.2150783538818, "token_count": 463 }, { "elapsed_time": 560.9450340270996, "token_count": 464 }, { "elapsed_time": 565.2029514312744, "token_count": 465 }, { "elapsed_time": 552.4501800537109, "token_count": 466 }, { "elapsed_time": 568.5896873474121, "token_count": 467 }, { "elapsed_time": 566.5137767791748, "token_count": 468 }, { "elapsed_time": 569.6001052856445, "token_count": 469 }, { "elapsed_time": 575.512170791626, "token_count": 470 }, { "elapsed_time": 570.3291893005371, "token_count": 471 }, { "elapsed_time": 566.9059753417969, "token_count": 472 }, { "elapsed_time": 576.9941806793213, "token_count": 473 }, { "elapsed_time": 600.7211208343506, "token_count": 474 }, { "elapsed_time": 631.7639350891113, "token_count": 475 }, { "elapsed_time": 658.998966217041, "token_count": 476 }, { "elapsed_time": 590.1567935943604, "token_count": 477 }, { "elapsed_time": 576.9021511077881, "token_count": 478 }, { "elapsed_time": 599.0431308746338, "token_count": 479 }, { "elapsed_time": 580.496072769165, "token_count": 480 }, { "elapsed_time": 583.2288265228271, "token_count": 481 }, { "elapsed_time": 573.9006996154785, "token_count": 482 }, { "elapsed_time": 585.7679843902588, "token_count": 483 }, { "elapsed_time": 598.0160236358643, "token_count": 484 }, { "elapsed_time": 593.1191444396973, "token_count": 485 }, { "elapsed_time": 592.8990840911865, "token_count": 486 }, { "elapsed_time": 578.7680149078369, "token_count": 487 }, { "elapsed_time": 582.4229717254639, "token_count": 488 }, { "elapsed_time": 585.7851505279541, "token_count": 489 }, { "elapsed_time": 582.3900699615479, "token_count": 490 }, { "elapsed_time": 592.8120613098145, "token_count": 491 }, { "elapsed_time": 651.3097286224365, "token_count": 492 }, { "elapsed_time": 615.5147552490234, "token_count": 493 }, { "elapsed_time": 629.3089389801025, "token_count": 494 }, { "elapsed_time": 623.4490871429443, "token_count": 495 }, { "elapsed_time": 631.4830780029297, "token_count": 496 }, { "elapsed_time": 659.9578857421875, "token_count": 497 }, { "elapsed_time": 639.3358707427979, "token_count": 498 }, { "elapsed_time": 623.0559349060059, "token_count": 499 }, { "elapsed_time": 636.1188888549805, "token_count": 500 }, { "elapsed_time": 633.0299377441406, "token_count": 501 }, { "elapsed_time": 632.1699619293213, "token_count": 502 }, { "elapsed_time": 657.872200012207, "token_count": 503 }, { "elapsed_time": 635.4598999023438, "token_count": 504 }, { "elapsed_time": 643.1519985198975, "token_count": 505 }, { "elapsed_time": 663.3169651031494, "token_count": 506 }, { "elapsed_time": 674.9649047851562, "token_count": 507 }, { "elapsed_time": 662.4579429626465, "token_count": 508 }, { "elapsed_time": 685.9791278839111, "token_count": 509 }, { "elapsed_time": 662.2657775878906, "token_count": 510 }, { "elapsed_time": 654.5212268829346, "token_count": 511 }, { "elapsed_time": 635.5040073394775, "token_count": 512 }, { "elapsed_time": 654.4430255889893, "token_count": 513 }, { "elapsed_time": 682.0330619812012, "token_count": 514 }, { "elapsed_time": 674.5500564575195, "token_count": 515 }, { "elapsed_time": 695.228099822998, "token_count": 516 }, { "elapsed_time": 698.3127593994141, "token_count": 517 }, { "elapsed_time": 670.8939075469971, "token_count": 518 }, { "elapsed_time": 676.3179302215576, "token_count": 519 }, { "elapsed_time": 679.6684265136719, "token_count": 520 }, { "elapsed_time": 657.6039791107178, "token_count": 521 }, { "elapsed_time": 726.8009185791016, "token_count": 522 }, { "elapsed_time": 670.8889007568359, "token_count": 523 }, { "elapsed_time": 676.4800548553467, "token_count": 524 }, { "elapsed_time": 667.2618389129639, "token_count": 525 }, { "elapsed_time": 683.1569671630859, "token_count": 526 }, { "elapsed_time": 663.3946895599365, "token_count": 527 }, { "elapsed_time": 666.9082641601562, "token_count": 528 }, { "elapsed_time": 685.4498386383057, "token_count": 529 }, { "elapsed_time": 672.2099781036377, "token_count": 530 }, { "elapsed_time": 668.503999710083, "token_count": 531 }, { "elapsed_time": 671.9920635223389, "token_count": 532 }, { "elapsed_time": 689.5289421081543, "token_count": 533 }, { "elapsed_time": 670.1021194458008, "token_count": 534 }, { "elapsed_time": 688.9910697937012, "token_count": 535 }, { "elapsed_time": 696.8660354614258, "token_count": 536 }, { "elapsed_time": 707.4930667877197, "token_count": 537 }, { "elapsed_time": 678.4472465515137, "token_count": 538 }, { "elapsed_time": 695.976972579956, "token_count": 539 }, { "elapsed_time": 696.5770721435547, "token_count": 540 }, { "elapsed_time": 685.6579780578613, "token_count": 541 }, { "elapsed_time": 672.3299026489258, "token_count": 542 }, { "elapsed_time": 683.9370727539062, "token_count": 543 }, { "elapsed_time": 713.8378620147705, "token_count": 544 }, { "elapsed_time": 698.4188556671143, "token_count": 545 }, { "elapsed_time": 705.4469585418701, "token_count": 546 }, { "elapsed_time": 700.98876953125, "token_count": 547 }, { "elapsed_time": 683.4759712219238, "token_count": 548 }, { "elapsed_time": 709.6338272094727, "token_count": 549 }, { "elapsed_time": 730.0589084625244, "token_count": 550 }, { "elapsed_time": 733.6788177490234, "token_count": 551 }, { "elapsed_time": 707.6327800750732, "token_count": 552 }, { "elapsed_time": 710.2329730987549, "token_count": 553 }, { "elapsed_time": 703.9999961853027, "token_count": 554 }, { "elapsed_time": 694.6370601654053, "token_count": 555 }, { "elapsed_time": 704.1637897491455, "token_count": 556 }, { "elapsed_time": 737.2739315032959, "token_count": 557 }, { "elapsed_time": 704.2477130889893, "token_count": 558 }, { "elapsed_time": 703.4449577331543, "token_count": 559 }, { "elapsed_time": 728.1410694122314, "token_count": 560 }, { "elapsed_time": 732.0592403411865, "token_count": 561 }, { "elapsed_time": 727.5331020355225, "token_count": 562 }, { "elapsed_time": 730.7801246643066, "token_count": 563 }, { "elapsed_time": 763.9138698577881, "token_count": 564 }, { "elapsed_time": 716.9351577758789, "token_count": 565 }, { "elapsed_time": 741.3778305053711, "token_count": 566 }, { "elapsed_time": 725.5580425262451, "token_count": 567 }, { "elapsed_time": 730.9889793395996, "token_count": 568 }, { "elapsed_time": 734.2398166656494, "token_count": 569 }, { "elapsed_time": 737.8311157226562, "token_count": 570 }, { "elapsed_time": 739.5682334899902, "token_count": 571 }, { "elapsed_time": 734.7161769866943, "token_count": 572 }, { "elapsed_time": 733.2289218902588, "token_count": 573 }, { "elapsed_time": 722.1508026123047, "token_count": 574 }, { "elapsed_time": 757.0569515228271, "token_count": 575 }, { "elapsed_time": 722.6920127868652, "token_count": 576 }, { "elapsed_time": 757.0540904998779, "token_count": 577 }, { "elapsed_time": 750.201940536499, "token_count": 578 }, { "elapsed_time": 739.7613525390625, "token_count": 579 }, { "elapsed_time": 773.3309268951416, "token_count": 580 }, { "elapsed_time": 742.0380115509033, "token_count": 581 }, { "elapsed_time": 744.1351413726807, "token_count": 582 }, { "elapsed_time": 747.5252151489258, "token_count": 583 }, { "elapsed_time": 760.1180076599121, "token_count": 584 }, { "elapsed_time": 735.2437973022461, "token_count": 585 }, { "elapsed_time": 761.2118721008301, "token_count": 586 }, { "elapsed_time": 752.0289421081543, "token_count": 587 }, { "elapsed_time": 766.1268711090088, "token_count": 588 }, { "elapsed_time": 758.620023727417, "token_count": 589 }, { "elapsed_time": 764.6498680114746, "token_count": 590 }, { "elapsed_time": 765.6619548797607, "token_count": 591 }, { "elapsed_time": 747.6279735565186, "token_count": 592 }, { "elapsed_time": 770.9300518035889, "token_count": 593 }, { "elapsed_time": 754.6098232269287, "token_count": 594 }, { "elapsed_time": 760.0240707397461, "token_count": 595 }, { "elapsed_time": 750.9407997131348, "token_count": 596 }, { "elapsed_time": 746.5171813964844, "token_count": 597 }, { "elapsed_time": 756.0529708862305, "token_count": 598 }, { "elapsed_time": 773.8540172576904, "token_count": 599 }, { "elapsed_time": 778.8650989532471, "token_count": 600 }, { "elapsed_time": 783.3890914916992, "token_count": 601 }, { "elapsed_time": 762.1257305145264, "token_count": 602 }, { "elapsed_time": 815.6230449676514, "token_count": 603 }, { "elapsed_time": 817.249059677124, "token_count": 604 }, { "elapsed_time": 794.8858737945557, "token_count": 605 }, { "elapsed_time": 802.0639419555664, "token_count": 606 }, { "elapsed_time": 779.2959213256836, "token_count": 607 }, { "elapsed_time": 788.0909442901611, "token_count": 608 }, { "elapsed_time": 780.2801132202148, "token_count": 609 }, { "elapsed_time": 766.4439678192139, "token_count": 610 }, { "elapsed_time": 781.1987400054932, "token_count": 611 }, { "elapsed_time": 781.2738418579102, "token_count": 612 }, { "elapsed_time": 778.527021408081, "token_count": 613 }, { "elapsed_time": 781.1660766601562, "token_count": 614 }, { "elapsed_time": 790.895938873291, "token_count": 615 }, { "elapsed_time": 823.9378929138184, "token_count": 616 }, { "elapsed_time": 812.0250701904297, "token_count": 617 }, { "elapsed_time": 797.4851131439209, "token_count": 618 }, { "elapsed_time": 800.9231090545654, "token_count": 619 }, { "elapsed_time": 809.5271587371826, "token_count": 620 }, { "elapsed_time": 785.2580547332764, "token_count": 621 }, { "elapsed_time": 806.5638542175293, "token_count": 622 }, { "elapsed_time": 794.2447662353516, "token_count": 623 }, { "elapsed_time": 794.9440479278564, "token_count": 624 }, { "elapsed_time": 806.5979480743408, "token_count": 625 }, { "elapsed_time": 805.2339553833008, "token_count": 626 }, { "elapsed_time": 811.3389015197754, "token_count": 627 }, { "elapsed_time": 868.0908679962158, "token_count": 628 }, { "elapsed_time": 795.1741218566895, "token_count": 629 }, { "elapsed_time": 799.8960018157959, "token_count": 630 }, { "elapsed_time": 812.8938674926758, "token_count": 631 }, { "elapsed_time": 818.8931941986084, "token_count": 632 }, { "elapsed_time": 810.6639385223389, "token_count": 633 }, { "elapsed_time": 810.7247352600098, "token_count": 634 }, { "elapsed_time": 854.0420532226562, "token_count": 635 }, { "elapsed_time": 804.6839237213135, "token_count": 636 }, { "elapsed_time": 821.8157291412354, "token_count": 637 }, { "elapsed_time": 817.0981407165527, "token_count": 638 }, { "elapsed_time": 814.4152164459229, "token_count": 639 }, { "elapsed_time": 855.9751510620117, "token_count": 640 }, { "elapsed_time": 818.0601596832275, "token_count": 641 }, { "elapsed_time": 830.6300640106201, "token_count": 642 }, { "elapsed_time": 836.2441062927246, "token_count": 643 }, { "elapsed_time": 852.9171943664551, "token_count": 644 }, { "elapsed_time": 810.6119632720947, "token_count": 645 }, { "elapsed_time": 819.2219734191895, "token_count": 646 }, { "elapsed_time": 815.9439563751221, "token_count": 647 }, { "elapsed_time": 825.8111476898193, "token_count": 648 }, { "elapsed_time": 833.2102298736572, "token_count": 649 }, { "elapsed_time": 850.0947952270508, "token_count": 650 }, { "elapsed_time": 847.8660583496094, "token_count": 651 }, { "elapsed_time": 873.5368251800537, "token_count": 652 }, { "elapsed_time": 876.4591217041016, "token_count": 653 }, { "elapsed_time": 864.5689487457275, "token_count": 654 }, { "elapsed_time": 841.3457870483398, "token_count": 655 }, { "elapsed_time": 856.8928241729736, "token_count": 656 }, { "elapsed_time": 838.9019966125488, "token_count": 657 }, { "elapsed_time": 845.757007598877, "token_count": 658 }, { "elapsed_time": 863.469123840332, "token_count": 659 }, { "elapsed_time": 845.3171253204346, "token_count": 660 }, { "elapsed_time": 873.6157417297363, "token_count": 661 }, { "elapsed_time": 862.900972366333, "token_count": 662 }, { "elapsed_time": 904.1879177093506, "token_count": 663 }, { "elapsed_time": 911.1380577087402, "token_count": 664 }, { "elapsed_time": 877.5229454040527, "token_count": 665 }, { "elapsed_time": 900.8140563964844, "token_count": 666 }, { "elapsed_time": 856.4369678497314, "token_count": 667 }, { "elapsed_time": 840.4300212860107, "token_count": 668 }, { "elapsed_time": 865.6840324401855, "token_count": 669 }, { "elapsed_time": 871.2441921234131, "token_count": 670 }, { "elapsed_time": 862.3812198638916, "token_count": 671 }, { "elapsed_time": 873.9111423492432, "token_count": 672 }, { "elapsed_time": 868.3099746704102, "token_count": 673 }, { "elapsed_time": 894.7000503540039, "token_count": 674 }, { "elapsed_time": 880.1238536834717, "token_count": 675 }, { "elapsed_time": 850.2810001373291, "token_count": 676 }, { "elapsed_time": 890.4669284820557, "token_count": 677 }, { "elapsed_time": 863.753080368042, "token_count": 678 }, { "elapsed_time": 876.4212131500244, "token_count": 679 }, { "elapsed_time": 881.9088935852051, "token_count": 680 }, { "elapsed_time": 909.4328880310059, "token_count": 681 }, { "elapsed_time": 897.0329761505127, "token_count": 682 }, { "elapsed_time": 884.6838474273682, "token_count": 683 }, { "elapsed_time": 845.451831817627, "token_count": 684 }, { "elapsed_time": 852.2071838378906, "token_count": 685 }, { "elapsed_time": 899.8377323150635, "token_count": 686 }, { "elapsed_time": 938.6401176452637, "token_count": 687 }, { "elapsed_time": 883.1479549407959, "token_count": 688 }, { "elapsed_time": 857.6540946960449, "token_count": 689 }, { "elapsed_time": 875.006914138794, "token_count": 690 }, { "elapsed_time": 905.7869911193848, "token_count": 691 }, { "elapsed_time": 893.326997756958, "token_count": 692 }, { "elapsed_time": 914.0479564666748, "token_count": 693 }, { "elapsed_time": 993.9572811126709, "token_count": 694 }, { "elapsed_time": 835.1140022277832, "token_count": 695 }, { "elapsed_time": 859.8461151123047, "token_count": 696 }, { "elapsed_time": 847.7330207824707, "token_count": 697 }, { "elapsed_time": 853.1429767608643, "token_count": 698 }, { "elapsed_time": 877.3999214172363, "token_count": 699 }, { "elapsed_time": 848.8421440124512, "token_count": 700 }, { "elapsed_time": 872.4002838134766, "token_count": 701 }, { "elapsed_time": 860.4459762573242, "token_count": 702 }, { "elapsed_time": 860.7540130615234, "token_count": 703 }, { "elapsed_time": 901.7531871795654, "token_count": 704 }, { "elapsed_time": 889.6300792694092, "token_count": 705 }, { "elapsed_time": 861.2210750579834, "token_count": 706 }, { "elapsed_time": 877.0627975463867, "token_count": 707 }, { "elapsed_time": 872.2248077392578, "token_count": 708 }, { "elapsed_time": 876.7061233520508, "token_count": 709 }, { "elapsed_time": 874.2232322692871, "token_count": 710 }, { "elapsed_time": 871.6099262237549, "token_count": 711 }, { "elapsed_time": 863.8780117034912, "token_count": 712 }, { "elapsed_time": 861.8829250335693, "token_count": 713 }, { "elapsed_time": 864.997148513794, "token_count": 714 }, { "elapsed_time": 902.3878574371338, "token_count": 715 }, { "elapsed_time": 905.552864074707, "token_count": 716 }, { "elapsed_time": 887.8898620605469, "token_count": 717 }, { "elapsed_time": 865.3512001037598, "token_count": 718 }, { "elapsed_time": 921.2119579315186, "token_count": 719 }, { "elapsed_time": 874.6020793914795, "token_count": 720 }, { "elapsed_time": 886.857271194458, "token_count": 721 }, { "elapsed_time": 890.068769454956, "token_count": 722 }, { "elapsed_time": 870.3858852386475, "token_count": 723 }, { "elapsed_time": 872.4451065063477, "token_count": 724 }, { "elapsed_time": 886.2419128417969, "token_count": 725 }, { "elapsed_time": 915.5311584472656, "token_count": 726 }, { "elapsed_time": 917.3147678375244, "token_count": 727 }, { "elapsed_time": 885.1439952850342, "token_count": 728 }, { "elapsed_time": 885.3046894073486, "token_count": 729 }, { "elapsed_time": 896.1889743804932, "token_count": 730 }, { "elapsed_time": 906.6040515899658, "token_count": 731 }, { "elapsed_time": 905.5318832397461, "token_count": 732 }, { "elapsed_time": 903.0609130859375, "token_count": 733 }, { "elapsed_time": 901.3876914978027, "token_count": 734 }, { "elapsed_time": 903.4957885742188, "token_count": 735 }, { "elapsed_time": 915.194034576416, "token_count": 736 }, { "elapsed_time": 939.079761505127, "token_count": 737 }, { "elapsed_time": 911.5219116210938, "token_count": 738 }, { "elapsed_time": 899.5487689971924, "token_count": 739 }, { "elapsed_time": 955.068826675415, "token_count": 740 }, { "elapsed_time": 955.1289081573486, "token_count": 741 }, { "elapsed_time": 908.9326858520508, "token_count": 742 }, { "elapsed_time": 918.4308052062988, "token_count": 743 }, { "elapsed_time": 894.2909240722656, "token_count": 744 }, { "elapsed_time": 907.5498580932617, "token_count": 745 }, { "elapsed_time": 943.8052177429199, "token_count": 746 }, { "elapsed_time": 945.5070495605469, "token_count": 747 }, { "elapsed_time": 982.8181266784668, "token_count": 748 }, { "elapsed_time": 936.2037181854248, "token_count": 749 }, { "elapsed_time": 934.0300559997559, "token_count": 750 }, { "elapsed_time": 943.8340663909912, "token_count": 751 }, { "elapsed_time": 917.046070098877, "token_count": 752 }, { "elapsed_time": 927.1447658538818, "token_count": 753 }, { "elapsed_time": 911.231279373169, "token_count": 754 }, { "elapsed_time": 934.6013069152832, "token_count": 755 }, { "elapsed_time": 918.3061122894287, "token_count": 756 }, { "elapsed_time": 962.3701572418213, "token_count": 757 }, { "elapsed_time": 956.7220211029053, "token_count": 758 }, { "elapsed_time": 935.4269504547119, "token_count": 759 }, { "elapsed_time": 931.0300350189209, "token_count": 760 }, { "elapsed_time": 951.0829448699951, "token_count": 761 }, { "elapsed_time": 935.6310367584229, "token_count": 762 }, { "elapsed_time": 936.2468719482422, "token_count": 763 }, { "elapsed_time": 945.3997611999512, "token_count": 764 }, { "elapsed_time": 986.7877960205078, "token_count": 765 }, { "elapsed_time": 970.1352119445801, "token_count": 766 }, { "elapsed_time": 968.2466983795166, "token_count": 767 }, { "elapsed_time": 958.2858085632324, "token_count": 768 }, { "elapsed_time": 948.462724685669, "token_count": 769 }, { "elapsed_time": 926.9680976867676, "token_count": 770 }, { "elapsed_time": 937.471866607666, "token_count": 771 }, { "elapsed_time": 966.9280052185059, "token_count": 772 }, { "elapsed_time": 963.468074798584, "token_count": 773 }, { "elapsed_time": 949.52392578125, "token_count": 774 }, { "elapsed_time": 945.0027942657471, "token_count": 775 }, { "elapsed_time": 939.9826526641846, "token_count": 776 }, { "elapsed_time": 973.2320308685303, "token_count": 777 }, { "elapsed_time": 967.3218727111816, "token_count": 778 }, { "elapsed_time": 950.2789974212646, "token_count": 779 }, { "elapsed_time": 944.3318843841553, "token_count": 780 }, { "elapsed_time": 993.9780235290527, "token_count": 781 }, { "elapsed_time": 999.8130798339844, "token_count": 782 }, { "elapsed_time": 964.9229049682617, "token_count": 783 }, { "elapsed_time": 952.286958694458, "token_count": 784 }, { "elapsed_time": 993.4918880462646, "token_count": 785 }, { "elapsed_time": 985.4457378387451, "token_count": 786 }, { "elapsed_time": 996.0262775421143, "token_count": 787 }, { "elapsed_time": 1006.321907043457, "token_count": 788 }, { "elapsed_time": 971.5721607208252, "token_count": 789 }, { "elapsed_time": 1026.247262954712, "token_count": 790 }, { "elapsed_time": 1015.1896476745605, "token_count": 791 }, { "elapsed_time": 1026.4759063720703, "token_count": 792 }, { "elapsed_time": 973.0522632598877, "token_count": 793 }, { "elapsed_time": 965.6057357788086, "token_count": 794 }, { "elapsed_time": 959.61594581604, "token_count": 795 }, { "elapsed_time": 979.7031879425049, "token_count": 796 }, { "elapsed_time": 1026.258945465088, "token_count": 797 }, { "elapsed_time": 999.2351531982422, "token_count": 798 }, { "elapsed_time": 975.5859375, "token_count": 799 }, { "elapsed_time": 976.7377376556396, "token_count": 800 }, { "elapsed_time": 978.5499572753906, "token_count": 801 }, { "elapsed_time": 967.3070907592773, "token_count": 802 }, { "elapsed_time": 969.9997901916504, "token_count": 803 }, { "elapsed_time": 993.0713176727295, "token_count": 804 }, { "elapsed_time": 983.4628105163574, "token_count": 805 }, { "elapsed_time": 1015.6819820404053, "token_count": 806 }, { "elapsed_time": 1019.2279815673828, "token_count": 807 }, { "elapsed_time": 977.2469997406006, "token_count": 808 }, { "elapsed_time": 990.1268482208252, "token_count": 809 }, { "elapsed_time": 996.4280128479004, "token_count": 810 }, { "elapsed_time": 1008.1138610839844, "token_count": 811 }, { "elapsed_time": 1003.528356552124, "token_count": 812 }, { "elapsed_time": 1026.021957397461, "token_count": 813 }, { "elapsed_time": 1011.0671520233154, "token_count": 814 }, { "elapsed_time": 991.1260604858398, "token_count": 815 }, { "elapsed_time": 1036.0009670257568, "token_count": 816 }, { "elapsed_time": 1048.2568740844727, "token_count": 817 }, { "elapsed_time": 1011.5840435028076, "token_count": 818 }, { "elapsed_time": 985.6131076812744, "token_count": 819 }, { "elapsed_time": 992.9828643798828, "token_count": 820 }, { "elapsed_time": 1067.0549869537354, "token_count": 821 }, { "elapsed_time": 1007.9092979431152, "token_count": 822 }, { "elapsed_time": 1007.9989433288574, "token_count": 823 }, { "elapsed_time": 1007.2150230407715, "token_count": 824 }, { "elapsed_time": 1015.7771110534668, "token_count": 825 }, { "elapsed_time": 1049.9351024627686, "token_count": 826 }, { "elapsed_time": 1039.2727851867676, "token_count": 827 }, { "elapsed_time": 1017.758846282959, "token_count": 828 }, { "elapsed_time": 994.2889213562012, "token_count": 829 }, { "elapsed_time": 1044.712781906128, "token_count": 830 }, { "elapsed_time": 1028.6140441894531, "token_count": 831 }, { "elapsed_time": 1027.001142501831, "token_count": 832 }, { "elapsed_time": 1018.5010433197021, "token_count": 833 }, { "elapsed_time": 1045.9837913513184, "token_count": 834 }, { "elapsed_time": 1135.4973316192627, "token_count": 835 }, { "elapsed_time": 1122.6019859313965, "token_count": 836 }, { "elapsed_time": 1071.2230205535889, "token_count": 837 }, { "elapsed_time": 1083.3790302276611, "token_count": 838 }, { "elapsed_time": 1105.510950088501, "token_count": 839 }, { "elapsed_time": 1149.7211456298828, "token_count": 840 }, { "elapsed_time": 1109.7090244293213, "token_count": 841 }, { "elapsed_time": 1082.9010009765625, "token_count": 842 }, { "elapsed_time": 1095.7257747650146, "token_count": 843 }, { "elapsed_time": 1129.899024963379, "token_count": 844 }, { "elapsed_time": 1103.8730144500732, "token_count": 845 }, { "elapsed_time": 1071.2378025054932, "token_count": 846 }, { "elapsed_time": 1074.0838050842285, "token_count": 847 }, { "elapsed_time": 1120.5179691314697, "token_count": 848 }, { "elapsed_time": 1105.125904083252, "token_count": 849 }, { "elapsed_time": 1084.4078063964844, "token_count": 850 }, { "elapsed_time": 1087.7938270568848, "token_count": 851 }, { "elapsed_time": 1128.661870956421, "token_count": 852 }, { "elapsed_time": 1097.870111465454, "token_count": 853 }, { "elapsed_time": 1083.604097366333, "token_count": 854 }, { "elapsed_time": 1110.6181144714355, "token_count": 855 }, { "elapsed_time": 1095.5898761749268, "token_count": 856 }, { "elapsed_time": 1110.3918552398682, "token_count": 857 }, { "elapsed_time": 1111.0508441925049, "token_count": 858 }, { "elapsed_time": 1098.0708599090576, "token_count": 859 }, { "elapsed_time": 1096.4851379394531, "token_count": 860 }, { "elapsed_time": 1098.2930660247803, "token_count": 861 }, { "elapsed_time": 1136.8820667266846, "token_count": 862 }, { "elapsed_time": 1119.2331314086914, "token_count": 863 }, { "elapsed_time": 1127.953052520752, "token_count": 864 }, { "elapsed_time": 1114.31884765625, "token_count": 865 }, { "elapsed_time": 1156.4826965332031, "token_count": 866 }, { "elapsed_time": 1126.6319751739502, "token_count": 867 }, { "elapsed_time": 1133.5039138793945, "token_count": 868 }, { "elapsed_time": 1151.1361598968506, "token_count": 869 }, { "elapsed_time": 1123.8861083984375, "token_count": 870 }, { "elapsed_time": 1143.9900398254395, "token_count": 871 }, { "elapsed_time": 1135.4100704193115, "token_count": 872 }, { "elapsed_time": 1123.4469413757324, "token_count": 873 }, { "elapsed_time": 1140.9378051757812, "token_count": 874 }, { "elapsed_time": 1208.785057067871, "token_count": 875 }, { "elapsed_time": 1124.5441436767578, "token_count": 876 }, { "elapsed_time": 1114.2029762268066, "token_count": 877 }, { "elapsed_time": 1133.707046508789, "token_count": 878 }, { "elapsed_time": 1143.2089805603027, "token_count": 879 }, { "elapsed_time": 1152.3962020874023, "token_count": 880 }, { "elapsed_time": 1121.380090713501, "token_count": 881 }, { "elapsed_time": 1145.4012393951416, "token_count": 882 }, { "elapsed_time": 1152.83203125, "token_count": 883 }, { "elapsed_time": 1130.7189464569092, "token_count": 884 }, { "elapsed_time": 1154.299020767212, "token_count": 885 }, { "elapsed_time": 1165.3642654418945, "token_count": 886 }, { "elapsed_time": 1180.3059577941895, "token_count": 887 }, { "elapsed_time": 1172.1458435058594, "token_count": 888 }, { "elapsed_time": 1155.5912494659424, "token_count": 889 }, { "elapsed_time": 1175.4529476165771, "token_count": 890 }, { "elapsed_time": 1149.8332023620605, "token_count": 891 }, { "elapsed_time": 1221.423864364624, "token_count": 892 }, { "elapsed_time": 1152.7009010314941, "token_count": 893 }, { "elapsed_time": 1169.8229312896729, "token_count": 894 }, { "elapsed_time": 1160.0687503814697, "token_count": 895 }, { "elapsed_time": 1174.3040084838867, "token_count": 896 }, { "elapsed_time": 1173.1488704681396, "token_count": 897 }, { "elapsed_time": 1206.5439224243164, "token_count": 898 }, { "elapsed_time": 1241.407871246338, "token_count": 899 }, { "elapsed_time": 1221.3799953460693, "token_count": 900 }, { "elapsed_time": 1190.492868423462, "token_count": 901 }, { "elapsed_time": 1149.3990421295166, "token_count": 902 }, { "elapsed_time": 1159.740924835205, "token_count": 903 }, { "elapsed_time": 1164.28804397583, "token_count": 904 }, { "elapsed_time": 1170.008897781372, "token_count": 905 }, { "elapsed_time": 1189.5978450775146, "token_count": 906 }, { "elapsed_time": 1165.4701232910156, "token_count": 907 }, { "elapsed_time": 1218.4031009674072, "token_count": 908 }, { "elapsed_time": 1177.2480010986328, "token_count": 909 }, { "elapsed_time": 1181.3089847564697, "token_count": 910 }, { "elapsed_time": 1160.7410907745361, "token_count": 911 }, { "elapsed_time": 1173.095941543579, "token_count": 912 }, { "elapsed_time": 1171.915054321289, "token_count": 913 }, { "elapsed_time": 1191.7622089385986, "token_count": 914 }, { "elapsed_time": 1214.2279148101807, "token_count": 915 }, { "elapsed_time": 1191.1287307739258, "token_count": 916 }, { "elapsed_time": 1208.6169719696045, "token_count": 917 }, { "elapsed_time": 1202.7289867401123, "token_count": 918 }, { "elapsed_time": 1219.2788124084473, "token_count": 919 }, { "elapsed_time": 1225.1660823822021, "token_count": 920 }, { "elapsed_time": 1211.3001346588135, "token_count": 921 }, { "elapsed_time": 1210.280179977417, "token_count": 922 }, { "elapsed_time": 1214.9970531463623, "token_count": 923 }, { "elapsed_time": 1210.345983505249, "token_count": 924 }, { "elapsed_time": 1249.7310638427734, "token_count": 925 }, { "elapsed_time": 1194.2119598388672, "token_count": 926 }, { "elapsed_time": 1210.5278968811035, "token_count": 927 }, { "elapsed_time": 1207.2458267211914, "token_count": 928 }, { "elapsed_time": 1231.3008308410645, "token_count": 929 }, { "elapsed_time": 1190.269947052002, "token_count": 930 }, { "elapsed_time": 1175.7640838623047, "token_count": 931 }, { "elapsed_time": 1195.2240467071533, "token_count": 932 }, { "elapsed_time": 1243.8418865203857, "token_count": 933 }, { "elapsed_time": 1204.4878005981445, "token_count": 934 }, { "elapsed_time": 1192.7618980407715, "token_count": 935 }, { "elapsed_time": 1192.230224609375, "token_count": 936 }, { "elapsed_time": 1226.0360717773438, "token_count": 937 }, { "elapsed_time": 1244.8480129241943, "token_count": 938 }, { "elapsed_time": 1247.600793838501, "token_count": 939 }, { "elapsed_time": 1220.9670543670654, "token_count": 940 }, { "elapsed_time": 1243.8328266143799, "token_count": 941 }, { "elapsed_time": 1248.1279373168945, "token_count": 942 }, { "elapsed_time": 1223.071813583374, "token_count": 943 }, { "elapsed_time": 1223.1440544128418, "token_count": 944 }, { "elapsed_time": 1212.4137878417969, "token_count": 945 }, { "elapsed_time": 1235.2757453918457, "token_count": 946 }, { "elapsed_time": 1265.765905380249, "token_count": 947 }, { "elapsed_time": 1223.6747741699219, "token_count": 948 }, { "elapsed_time": 1276.6129970550537, "token_count": 949 }, { "elapsed_time": 1239.4740581512451, "token_count": 950 }, { "elapsed_time": 1239.2480373382568, "token_count": 951 }, { "elapsed_time": 1227.7781963348389, "token_count": 952 }, { "elapsed_time": 1220.6542491912842, "token_count": 953 }, { "elapsed_time": 1225.4700660705566, "token_count": 954 }, { "elapsed_time": 1217.1416282653809, "token_count": 955 }, { "elapsed_time": 1224.8599529266357, "token_count": 956 }, { "elapsed_time": 1278.2058715820312, "token_count": 957 }, { "elapsed_time": 1241.4240837097168, "token_count": 958 }, { "elapsed_time": 1257.673978805542, "token_count": 959 }, { "elapsed_time": 1245.2747821807861, "token_count": 960 }, { "elapsed_time": 1263.962984085083, "token_count": 961 }, { "elapsed_time": 1286.0841751098633, "token_count": 962 }, { "elapsed_time": 1251.089334487915, "token_count": 963 }, { "elapsed_time": 1229.884147644043, "token_count": 964 }, { "elapsed_time": 1322.2050666809082, "token_count": 965 }, { "elapsed_time": 1275.5608558654785, "token_count": 966 }, { "elapsed_time": 1305.8741092681885, "token_count": 967 }, { "elapsed_time": 1271.662950515747, "token_count": 968 }, { "elapsed_time": 1306.886911392212, "token_count": 969 }, { "elapsed_time": 1319.5970058441162, "token_count": 970 }, { "elapsed_time": 1190.6020641326904, "token_count": 971 }, { "elapsed_time": 1204.8108577728271, "token_count": 972 }, { "elapsed_time": 1216.4289951324463, "token_count": 973 }, { "elapsed_time": 1184.4539642333984, "token_count": 974 }, { "elapsed_time": 1179.732084274292, "token_count": 975 }, { "elapsed_time": 1187.7260208129883, "token_count": 976 }, { "elapsed_time": 1200.4919052124023, "token_count": 977 }, { "elapsed_time": 1189.9049282073975, "token_count": 978 }, { "elapsed_time": 1191.3361549377441, "token_count": 979 }, { "elapsed_time": 1223.3309745788574, "token_count": 980 }, { "elapsed_time": 1244.507074356079, "token_count": 981 }, { "elapsed_time": 1194.288730621338, "token_count": 982 }, { "elapsed_time": 1202.0208835601807, "token_count": 983 }, { "elapsed_time": 1208.789587020874, "token_count": 984 }, { "elapsed_time": 1219.3498611450195, "token_count": 985 }, { "elapsed_time": 1240.9930229187012, "token_count": 986 }, { "elapsed_time": 1211.393117904663, "token_count": 987 }, { "elapsed_time": 1233.4747314453125, "token_count": 988 }, { "elapsed_time": 1236.0661029815674, "token_count": 989 }, { "elapsed_time": 1284.9681377410889, "token_count": 990 }, { "elapsed_time": 1242.8689002990723, "token_count": 991 }, { "elapsed_time": 1215.0537967681885, "token_count": 992 }, { "elapsed_time": 1257.9760551452637, "token_count": 993 }, { "elapsed_time": 1216.5498733520508, "token_count": 994 }, { "elapsed_time": 1213.7219905853271, "token_count": 995 }, { "elapsed_time": 1250.9360313415527, "token_count": 996 }, { "elapsed_time": 1261.4572048187256, "token_count": 997 }, { "elapsed_time": 1249.9299049377441, "token_count": 998 }, { "elapsed_time": 1265.0718688964844, "token_count": 999 } ], "max_token_count_per_time": { "100": 78, "200": 155, "300": 235, "400": 335, "500": 420, "600": 491, "700": 555, "800": 630, "900": 744, "1000": 829, "1100": 861, "1200": 982, "1300": 999, "1400": 999, "1500": 999 } } ================================================ FILE: reports/inference_result/qanet-cpu.json ================================================ { "average_raw_to_tensor": 4.473000343399819, "average_tensor_to_predict": 288.2474863167965, "average_end_to_end": 292.72048666019634, "tensor_to_predicts": [ { "elapsed_time": 55.062055587768555, "token_count": 10 }, { "elapsed_time": 47.39522933959961, "token_count": 11 }, { "elapsed_time": 45.30024528503418, "token_count": 12 }, { "elapsed_time": 49.443960189819336, "token_count": 13 }, { "elapsed_time": 53.22384834289551, "token_count": 14 }, { "elapsed_time": 50.269126892089844, "token_count": 15 }, { "elapsed_time": 48.4468936920166, "token_count": 16 }, { "elapsed_time": 48.007965087890625, "token_count": 17 }, { "elapsed_time": 54.67581748962402, "token_count": 18 }, { "elapsed_time": 54.72612380981445, "token_count": 19 }, { "elapsed_time": 49.44610595703125, "token_count": 20 }, { "elapsed_time": 50.19712448120117, "token_count": 21 }, { "elapsed_time": 50.90618133544922, "token_count": 22 }, { "elapsed_time": 51.69105529785156, "token_count": 23 }, { "elapsed_time": 51.33414268493652, "token_count": 24 }, { "elapsed_time": 57.901859283447266, "token_count": 25 }, { "elapsed_time": 53.57098579406738, "token_count": 26 }, { "elapsed_time": 53.86185646057129, "token_count": 27 }, { "elapsed_time": 53.77602577209473, "token_count": 28 }, { "elapsed_time": 55.60708045959473, "token_count": 29 }, { "elapsed_time": 62.99781799316406, "token_count": 30 }, { "elapsed_time": 65.87004661560059, "token_count": 31 }, { "elapsed_time": 62.61420249938965, "token_count": 32 }, { "elapsed_time": 60.440778732299805, "token_count": 33 }, { "elapsed_time": 64.48221206665039, "token_count": 34 }, { "elapsed_time": 64.99290466308594, "token_count": 35 }, { "elapsed_time": 58.7010383605957, "token_count": 36 }, { "elapsed_time": 60.5158805847168, "token_count": 37 }, { "elapsed_time": 62.348127365112305, "token_count": 38 }, { "elapsed_time": 73.24004173278809, "token_count": 39 }, { "elapsed_time": 81.1319351196289, "token_count": 40 }, { "elapsed_time": 67.34776496887207, "token_count": 41 }, { "elapsed_time": 74.97119903564453, "token_count": 42 }, { "elapsed_time": 65.0181770324707, "token_count": 43 }, { "elapsed_time": 66.66922569274902, "token_count": 44 }, { "elapsed_time": 67.18897819519043, "token_count": 45 }, { "elapsed_time": 67.96789169311523, "token_count": 46 }, { "elapsed_time": 67.64912605285645, "token_count": 47 }, { "elapsed_time": 69.34285163879395, "token_count": 48 }, { "elapsed_time": 69.1080093383789, "token_count": 49 }, { "elapsed_time": 71.76828384399414, "token_count": 50 }, { "elapsed_time": 77.92210578918457, "token_count": 51 }, { "elapsed_time": 72.60894775390625, "token_count": 52 }, { "elapsed_time": 73.33111763000488, "token_count": 53 }, { "elapsed_time": 74.80406761169434, "token_count": 54 }, { "elapsed_time": 75.00600814819336, "token_count": 55 }, { "elapsed_time": 74.03898239135742, "token_count": 56 }, { "elapsed_time": 76.53498649597168, "token_count": 57 }, { "elapsed_time": 78.89223098754883, "token_count": 58 }, { "elapsed_time": 79.6818733215332, "token_count": 59 }, { "elapsed_time": 81.88199996948242, "token_count": 60 }, { "elapsed_time": 87.59903907775879, "token_count": 61 }, { "elapsed_time": 80.70778846740723, "token_count": 62 }, { "elapsed_time": 84.13004875183105, "token_count": 63 }, { "elapsed_time": 93.40691566467285, "token_count": 64 }, { "elapsed_time": 92.47112274169922, "token_count": 65 }, { "elapsed_time": 94.68412399291992, "token_count": 66 }, { "elapsed_time": 95.54195404052734, "token_count": 67 }, { "elapsed_time": 97.12409973144531, "token_count": 68 }, { "elapsed_time": 98.97303581237793, "token_count": 69 }, { "elapsed_time": 99.7309684753418, "token_count": 70 }, { "elapsed_time": 99.81703758239746, "token_count": 71 }, { "elapsed_time": 100.67319869995117, "token_count": 72 }, { "elapsed_time": 103.1348705291748, "token_count": 73 }, { "elapsed_time": 105.5450439453125, "token_count": 74 }, { "elapsed_time": 105.84020614624023, "token_count": 75 }, { "elapsed_time": 105.37600517272949, "token_count": 76 }, { "elapsed_time": 107.0261001586914, "token_count": 77 }, { "elapsed_time": 108.76989364624023, "token_count": 78 }, { "elapsed_time": 111.3741397857666, "token_count": 79 }, { "elapsed_time": 114.97712135314941, "token_count": 80 }, { "elapsed_time": 114.5792007446289, "token_count": 81 }, { "elapsed_time": 118.77608299255371, "token_count": 82 }, { "elapsed_time": 113.48509788513184, "token_count": 83 }, { "elapsed_time": 114.4859790802002, "token_count": 84 }, { "elapsed_time": 117.53702163696289, "token_count": 85 }, { "elapsed_time": 116.38402938842773, "token_count": 86 }, { "elapsed_time": 119.8890209197998, "token_count": 87 }, { "elapsed_time": 118.94774436950684, "token_count": 88 }, { "elapsed_time": 122.1771240234375, "token_count": 89 }, { "elapsed_time": 125.07224082946777, "token_count": 90 }, { "elapsed_time": 124.17101860046387, "token_count": 91 }, { "elapsed_time": 127.5639533996582, "token_count": 92 }, { "elapsed_time": 128.3249855041504, "token_count": 93 }, { "elapsed_time": 128.11803817749023, "token_count": 94 }, { "elapsed_time": 130.85699081420898, "token_count": 95 }, { "elapsed_time": 137.15124130249023, "token_count": 96 }, { "elapsed_time": 137.1171474456787, "token_count": 97 }, { "elapsed_time": 138.80205154418945, "token_count": 98 }, { "elapsed_time": 142.43197441101074, "token_count": 99 }, { "elapsed_time": 136.27076148986816, "token_count": 100 }, { "elapsed_time": 136.8880271911621, "token_count": 101 }, { "elapsed_time": 139.00995254516602, "token_count": 102 }, { "elapsed_time": 141.57700538635254, "token_count": 103 }, { "elapsed_time": 141.88599586486816, "token_count": 104 }, { "elapsed_time": 145.1261043548584, "token_count": 105 }, { "elapsed_time": 143.6312198638916, "token_count": 106 }, { "elapsed_time": 148.15115928649902, "token_count": 107 }, { "elapsed_time": 146.67201042175293, "token_count": 108 }, { "elapsed_time": 148.63991737365723, "token_count": 109 }, { "elapsed_time": 150.4189968109131, "token_count": 110 }, { "elapsed_time": 157.3319435119629, "token_count": 111 }, { "elapsed_time": 155.68900108337402, "token_count": 112 }, { "elapsed_time": 156.26001358032227, "token_count": 113 }, { "elapsed_time": 157.07707405090332, "token_count": 114 }, { "elapsed_time": 159.0712070465088, "token_count": 115 }, { "elapsed_time": 160.63380241394043, "token_count": 116 }, { "elapsed_time": 162.75310516357422, "token_count": 117 }, { "elapsed_time": 163.82479667663574, "token_count": 118 }, { "elapsed_time": 165.4069423675537, "token_count": 119 }, { "elapsed_time": 165.14897346496582, "token_count": 120 }, { "elapsed_time": 180.32479286193848, "token_count": 121 }, { "elapsed_time": 180.51505088806152, "token_count": 122 }, { "elapsed_time": 176.131010055542, "token_count": 123 }, { "elapsed_time": 179.6121597290039, "token_count": 124 }, { "elapsed_time": 183.5489273071289, "token_count": 125 }, { "elapsed_time": 257.2641372680664, "token_count": 126 }, { "elapsed_time": 177.4439811706543, "token_count": 127 }, { "elapsed_time": 178.67207527160645, "token_count": 128 }, { "elapsed_time": 180.65834045410156, "token_count": 129 }, { "elapsed_time": 187.43276596069336, "token_count": 130 }, { "elapsed_time": 185.91022491455078, "token_count": 131 }, { "elapsed_time": 185.11104583740234, "token_count": 132 }, { "elapsed_time": 188.8582706451416, "token_count": 133 }, { "elapsed_time": 191.4539337158203, "token_count": 134 }, { "elapsed_time": 190.59181213378906, "token_count": 135 }, { "elapsed_time": 191.46966934204102, "token_count": 136 }, { "elapsed_time": 193.7851905822754, "token_count": 137 }, { "elapsed_time": 201.46799087524414, "token_count": 138 }, { "elapsed_time": 197.57699966430664, "token_count": 139 }, { "elapsed_time": 198.95219802856445, "token_count": 140 }, { "elapsed_time": 203.3400535583496, "token_count": 141 }, { "elapsed_time": 224.6251106262207, "token_count": 142 }, { "elapsed_time": 223.5720157623291, "token_count": 143 }, { "elapsed_time": 300.95887184143066, "token_count": 144 }, { "elapsed_time": 228.7452220916748, "token_count": 145 }, { "elapsed_time": 218.47224235534668, "token_count": 146 }, { "elapsed_time": 215.18421173095703, "token_count": 147 }, { "elapsed_time": 220.45111656188965, "token_count": 148 }, { "elapsed_time": 221.13418579101562, "token_count": 149 }, { "elapsed_time": 215.20209312438965, "token_count": 150 }, { "elapsed_time": 227.39005088806152, "token_count": 151 }, { "elapsed_time": 217.89813041687012, "token_count": 152 }, { "elapsed_time": 240.37671089172363, "token_count": 153 }, { "elapsed_time": 224.69592094421387, "token_count": 154 }, { "elapsed_time": 227.98967361450195, "token_count": 155 }, { "elapsed_time": 231.3079833984375, "token_count": 156 }, { "elapsed_time": 230.90410232543945, "token_count": 157 }, { "elapsed_time": 232.53393173217773, "token_count": 158 }, { "elapsed_time": 235.5191707611084, "token_count": 159 }, { "elapsed_time": 235.12506484985352, "token_count": 160 }, { "elapsed_time": 244.14324760437012, "token_count": 161 }, { "elapsed_time": 294.5101261138916, "token_count": 162 }, { "elapsed_time": 244.38190460205078, "token_count": 163 }, { "elapsed_time": 250.75101852416992, "token_count": 164 }, { "elapsed_time": 250.74100494384766, "token_count": 165 }, { "elapsed_time": 258.1980228424072, "token_count": 166 }, { "elapsed_time": 261.72685623168945, "token_count": 167 }, { "elapsed_time": 262.62402534484863, "token_count": 168 }, { "elapsed_time": 265.26880264282227, "token_count": 169 }, { "elapsed_time": 317.85106658935547, "token_count": 170 }, { "elapsed_time": 276.0648727416992, "token_count": 171 }, { "elapsed_time": 261.1210346221924, "token_count": 172 }, { "elapsed_time": 276.3221263885498, "token_count": 173 }, { "elapsed_time": 292.6907539367676, "token_count": 174 }, { "elapsed_time": 270.89595794677734, "token_count": 175 }, { "elapsed_time": 276.6141891479492, "token_count": 176 }, { "elapsed_time": 311.65409088134766, "token_count": 177 }, { "elapsed_time": 278.92303466796875, "token_count": 178 }, { "elapsed_time": 288.0749702453613, "token_count": 179 }, { "elapsed_time": 286.6790294647217, "token_count": 180 }, { "elapsed_time": 287.08481788635254, "token_count": 181 }, { "elapsed_time": 284.1620445251465, "token_count": 182 }, { "elapsed_time": 289.7059917449951, "token_count": 183 }, { "elapsed_time": 395.5528736114502, "token_count": 184 }, { "elapsed_time": 289.46995735168457, "token_count": 185 }, { "elapsed_time": 293.7150001525879, "token_count": 186 }, { "elapsed_time": 304.32605743408203, "token_count": 187 }, { "elapsed_time": 308.7160587310791, "token_count": 188 }, { "elapsed_time": 319.80013847351074, "token_count": 189 }, { "elapsed_time": 371.9768524169922, "token_count": 190 }, { "elapsed_time": 308.8412284851074, "token_count": 191 }, { "elapsed_time": 305.3109645843506, "token_count": 192 }, { "elapsed_time": 313.77315521240234, "token_count": 193 }, { "elapsed_time": 311.65385246276855, "token_count": 194 }, { "elapsed_time": 315.809965133667, "token_count": 195 }, { "elapsed_time": 328.16100120544434, "token_count": 196 }, { "elapsed_time": 341.49980545043945, "token_count": 197 }, { "elapsed_time": 321.5939998626709, "token_count": 198 }, { "elapsed_time": 330.7080268859863, "token_count": 199 }, { "elapsed_time": 333.30678939819336, "token_count": 200 }, { "elapsed_time": 329.3938636779785, "token_count": 201 }, { "elapsed_time": 347.00608253479004, "token_count": 202 }, { "elapsed_time": 451.88117027282715, "token_count": 203 }, { "elapsed_time": 338.03391456604004, "token_count": 204 }, { "elapsed_time": 346.75097465515137, "token_count": 205 }, { "elapsed_time": 343.9030647277832, "token_count": 206 }, { "elapsed_time": 345.61800956726074, "token_count": 207 }, { "elapsed_time": 379.5909881591797, "token_count": 208 }, { "elapsed_time": 360.50891876220703, "token_count": 209 }, { "elapsed_time": 351.9749641418457, "token_count": 210 }, { "elapsed_time": 356.98723793029785, "token_count": 211 }, { "elapsed_time": 357.4092388153076, "token_count": 212 }, { "elapsed_time": 366.09578132629395, "token_count": 213 }, { "elapsed_time": 380.6729316711426, "token_count": 214 }, { "elapsed_time": 369.69995498657227, "token_count": 215 }, { "elapsed_time": 373.8381862640381, "token_count": 216 }, { "elapsed_time": 370.1620101928711, "token_count": 217 }, { "elapsed_time": 374.9868869781494, "token_count": 218 }, { "elapsed_time": 385.1027488708496, "token_count": 219 }, { "elapsed_time": 392.5309181213379, "token_count": 220 }, { "elapsed_time": 414.5240783691406, "token_count": 221 }, { "elapsed_time": 412.6248359680176, "token_count": 222 }, { "elapsed_time": 426.8360137939453, "token_count": 223 }, { "elapsed_time": 406.47125244140625, "token_count": 224 }, { "elapsed_time": 430.7851791381836, "token_count": 225 }, { "elapsed_time": 422.7719306945801, "token_count": 226 }, { "elapsed_time": 420.18580436706543, "token_count": 227 }, { "elapsed_time": 441.85328483581543, "token_count": 228 }, { "elapsed_time": 501.4500617980957, "token_count": 229 }, { "elapsed_time": 436.5861415863037, "token_count": 230 }, { "elapsed_time": 439.24403190612793, "token_count": 231 }, { "elapsed_time": 429.5618534088135, "token_count": 232 }, { "elapsed_time": 441.49017333984375, "token_count": 233 }, { "elapsed_time": 446.97070121765137, "token_count": 234 }, { "elapsed_time": 454.7269344329834, "token_count": 235 }, { "elapsed_time": 484.04693603515625, "token_count": 236 }, { "elapsed_time": 467.17166900634766, "token_count": 237 }, { "elapsed_time": 466.3407802581787, "token_count": 238 }, { "elapsed_time": 464.4937515258789, "token_count": 239 }, { "elapsed_time": 462.5508785247803, "token_count": 240 }, { "elapsed_time": 460.11996269226074, "token_count": 241 }, { "elapsed_time": 452.1148204803467, "token_count": 242 }, { "elapsed_time": 459.5298767089844, "token_count": 243 }, { "elapsed_time": 473.2780456542969, "token_count": 244 }, { "elapsed_time": 469.79308128356934, "token_count": 245 }, { "elapsed_time": 461.69590950012207, "token_count": 246 }, { "elapsed_time": 494.9300289154053, "token_count": 247 }, { "elapsed_time": 480.6993007659912, "token_count": 248 }, { "elapsed_time": 485.24999618530273, "token_count": 249 }, { "elapsed_time": 520.6639766693115, "token_count": 250 }, { "elapsed_time": 530.0159454345703, "token_count": 251 }, { "elapsed_time": 496.7031478881836, "token_count": 252 }, { "elapsed_time": 516.455888748169, "token_count": 253 }, { "elapsed_time": 535.3689193725586, "token_count": 254 }, { "elapsed_time": 570.6892013549805, "token_count": 255 }, { "elapsed_time": 576.5459537506104, "token_count": 256 }, { "elapsed_time": 561.7289543151855, "token_count": 257 }, { "elapsed_time": 561.5148544311523, "token_count": 258 }, { "elapsed_time": 564.79811668396, "token_count": 259 }, { "elapsed_time": 568.8509941101074, "token_count": 260 }, { "elapsed_time": 553.2877445220947, "token_count": 261 }, { "elapsed_time": 593.4939384460449, "token_count": 262 }, { "elapsed_time": 553.2639026641846, "token_count": 263 }, { "elapsed_time": 562.5877380371094, "token_count": 264 }, { "elapsed_time": 585.3509902954102, "token_count": 265 }, { "elapsed_time": 588.3030891418457, "token_count": 266 }, { "elapsed_time": 592.9570198059082, "token_count": 267 }, { "elapsed_time": 595.862865447998, "token_count": 268 }, { "elapsed_time": 660.520076751709, "token_count": 269 }, { "elapsed_time": 598.5348224639893, "token_count": 270 }, { "elapsed_time": 596.0509777069092, "token_count": 271 }, { "elapsed_time": 590.155839920044, "token_count": 272 }, { "elapsed_time": 599.8470783233643, "token_count": 273 }, { "elapsed_time": 615.5831813812256, "token_count": 274 }, { "elapsed_time": 609.9987030029297, "token_count": 275 }, { "elapsed_time": 599.606990814209, "token_count": 276 }, { "elapsed_time": 618.9801692962646, "token_count": 277 }, { "elapsed_time": 619.2541122436523, "token_count": 278 }, { "elapsed_time": 626.0509490966797, "token_count": 279 }, { "elapsed_time": 627.6149749755859, "token_count": 280 }, { "elapsed_time": 619.0118789672852, "token_count": 281 }, { "elapsed_time": 645.4310417175293, "token_count": 282 }, { "elapsed_time": 640.023946762085, "token_count": 283 }, { "elapsed_time": 637.0580196380615, "token_count": 284 }, { "elapsed_time": 660.8457565307617, "token_count": 285 }, { "elapsed_time": 630.8290958404541, "token_count": 286 }, { "elapsed_time": 650.3238677978516, "token_count": 287 }, { "elapsed_time": 627.3548603057861, "token_count": 288 }, { "elapsed_time": 679.5840263366699, "token_count": 289 }, { "elapsed_time": 659.1899394989014, "token_count": 290 }, { "elapsed_time": 661.2207889556885, "token_count": 291 }, { "elapsed_time": 668.0889129638672, "token_count": 292 }, { "elapsed_time": 659.8389148712158, "token_count": 293 }, { "elapsed_time": 668.0130958557129, "token_count": 294 }, { "elapsed_time": 657.4878692626953, "token_count": 295 }, { "elapsed_time": 682.366132736206, "token_count": 296 }, { "elapsed_time": 671.1418628692627, "token_count": 297 }, { "elapsed_time": 675.9459972381592, "token_count": 298 }, { "elapsed_time": 683.7213039398193, "token_count": 299 }, { "elapsed_time": 706.0728073120117, "token_count": 300 }, { "elapsed_time": 701.740026473999, "token_count": 301 }, { "elapsed_time": 685.5213642120361, "token_count": 302 }, { "elapsed_time": 709.2888355255127, "token_count": 303 }, { "elapsed_time": 701.0719776153564, "token_count": 304 }, { "elapsed_time": 701.3440132141113, "token_count": 305 }, { "elapsed_time": 716.8080806732178, "token_count": 306 }, { "elapsed_time": 716.8710231781006, "token_count": 307 }, { "elapsed_time": 710.561990737915, "token_count": 308 }, { "elapsed_time": 698.5089778900146, "token_count": 309 }, { "elapsed_time": 718.2919979095459, "token_count": 310 }, { "elapsed_time": 709.306001663208, "token_count": 311 }, { "elapsed_time": 718.2950973510742, "token_count": 312 }, { "elapsed_time": 725.9209156036377, "token_count": 313 }, { "elapsed_time": 728.6982536315918, "token_count": 314 }, { "elapsed_time": 734.9491119384766, "token_count": 315 }, { "elapsed_time": 724.6959209442139, "token_count": 316 }, { "elapsed_time": 749.2809295654297, "token_count": 317 }, { "elapsed_time": 743.2272434234619, "token_count": 318 }, { "elapsed_time": 740.74387550354, "token_count": 319 }, { "elapsed_time": 732.2258949279785, "token_count": 320 }, { "elapsed_time": 747.3270893096924, "token_count": 321 }, { "elapsed_time": 748.6340999603271, "token_count": 322 }, { "elapsed_time": 771.1091041564941, "token_count": 323 }, { "elapsed_time": 774.3332386016846, "token_count": 324 }, { "elapsed_time": 800.0829219818115, "token_count": 325 }, { "elapsed_time": 791.1818027496338, "token_count": 326 }, { "elapsed_time": 767.4610614776611, "token_count": 327 }, { "elapsed_time": 800.2538681030273, "token_count": 328 }, { "elapsed_time": 789.700984954834, "token_count": 329 }, { "elapsed_time": 831.8881988525391, "token_count": 330 }, { "elapsed_time": 786.2792015075684, "token_count": 331 }, { "elapsed_time": 793.8086986541748, "token_count": 332 }, { "elapsed_time": 810.5988502502441, "token_count": 333 }, { "elapsed_time": 798.3238697052002, "token_count": 334 }, { "elapsed_time": 796.8943119049072, "token_count": 335 }, { "elapsed_time": 806.6802024841309, "token_count": 336 }, { "elapsed_time": 816.1449432373047, "token_count": 337 }, { "elapsed_time": 814.2890930175781, "token_count": 338 }, { "elapsed_time": 838.0098342895508, "token_count": 339 }, { "elapsed_time": 857.1949005126953, "token_count": 340 }, { "elapsed_time": 833.9781761169434, "token_count": 341 }, { "elapsed_time": 835.1960182189941, "token_count": 342 }, { "elapsed_time": 838.07373046875, "token_count": 343 }, { "elapsed_time": 837.3382091522217, "token_count": 344 }, { "elapsed_time": 851.7599105834961, "token_count": 345 }, { "elapsed_time": 862.6139163970947, "token_count": 346 }, { "elapsed_time": 854.9811840057373, "token_count": 347 }, { "elapsed_time": 836.2128734588623, "token_count": 348 }, { "elapsed_time": 878.1459331512451, "token_count": 349 }, { "elapsed_time": 848.4652042388916, "token_count": 350 }, { "elapsed_time": 861.5922927856445, "token_count": 351 }, { "elapsed_time": 895.1332569122314, "token_count": 352 }, { "elapsed_time": 868.5016632080078, "token_count": 353 }, { "elapsed_time": 876.3399124145508, "token_count": 354 }, { "elapsed_time": 881.5140724182129, "token_count": 355 }, { "elapsed_time": 885.3049278259277, "token_count": 356 }, { "elapsed_time": 888.6220455169678, "token_count": 357 }, { "elapsed_time": 880.9411525726318, "token_count": 358 }, { "elapsed_time": 895.7779407501221, "token_count": 359 }, { "elapsed_time": 904.1779041290283, "token_count": 360 }, { "elapsed_time": 905.9996604919434, "token_count": 361 }, { "elapsed_time": 901.9708633422852, "token_count": 362 }, { "elapsed_time": 931.8850040435791, "token_count": 363 }, { "elapsed_time": 957.9288959503174, "token_count": 364 }, { "elapsed_time": 926.5198707580566, "token_count": 365 }, { "elapsed_time": 934.1239929199219, "token_count": 366 }, { "elapsed_time": 907.2451591491699, "token_count": 367 }, { "elapsed_time": 929.6219348907471, "token_count": 368 }, { "elapsed_time": 931.9150447845459, "token_count": 369 }, { "elapsed_time": 930.1309585571289, "token_count": 370 }, { "elapsed_time": 940.8419132232666, "token_count": 371 }, { "elapsed_time": 962.4912738800049, "token_count": 372 }, { "elapsed_time": 951.9827365875244, "token_count": 373 }, { "elapsed_time": 975.9402275085449, "token_count": 374 }, { "elapsed_time": 947.0551013946533, "token_count": 375 }, { "elapsed_time": 968.8420295715332, "token_count": 376 }, { "elapsed_time": 987.1189594268799, "token_count": 377 }, { "elapsed_time": 987.825870513916, "token_count": 378 }, { "elapsed_time": 975.7990837097168, "token_count": 379 }, { "elapsed_time": 970.8831310272217, "token_count": 380 }, { "elapsed_time": 983.3378791809082, "token_count": 381 }, { "elapsed_time": 993.5328960418701, "token_count": 382 }, { "elapsed_time": 1007.2898864746094, "token_count": 383 }, { "elapsed_time": 984.3730926513672, "token_count": 384 }, { "elapsed_time": 1024.087905883789, "token_count": 385 }, { "elapsed_time": 1021.9128131866455, "token_count": 386 }, { "elapsed_time": 1013.6210918426514, "token_count": 387 }, { "elapsed_time": 1008.0199241638184, "token_count": 388 }, { "elapsed_time": 1030.1949977874756, "token_count": 389 }, { "elapsed_time": 1033.4501266479492, "token_count": 390 }, { "elapsed_time": 1033.463954925537, "token_count": 391 }, { "elapsed_time": 1014.603853225708, "token_count": 392 }, { "elapsed_time": 1022.3391056060791, "token_count": 393 }, { "elapsed_time": 1028.2039642333984, "token_count": 394 }, { "elapsed_time": 1091.2058353424072, "token_count": 395 }, { "elapsed_time": 1070.9569454193115, "token_count": 396 }, { "elapsed_time": 1037.696123123169, "token_count": 397 }, { "elapsed_time": 1035.9861850738525, "token_count": 398 }, { "elapsed_time": 1047.9118824005127, "token_count": 399 }, { "elapsed_time": 1086.932897567749, "token_count": 400 }, { "elapsed_time": 1134.5102787017822, "token_count": 401 }, { "elapsed_time": 1174.5598316192627, "token_count": 402 }, { "elapsed_time": 1095.1387882232666, "token_count": 403 }, { "elapsed_time": 1107.680082321167, "token_count": 404 }, { "elapsed_time": 1080.6970596313477, "token_count": 405 }, { "elapsed_time": 1071.8271732330322, "token_count": 406 }, { "elapsed_time": 1092.6196575164795, "token_count": 407 }, { "elapsed_time": 1081.3350677490234, "token_count": 408 }, { "elapsed_time": 1098.7889766693115, "token_count": 409 }, { "elapsed_time": 1092.0178890228271, "token_count": 410 }, { "elapsed_time": 1103.9669513702393, "token_count": 411 }, { "elapsed_time": 1115.328073501587, "token_count": 412 }, { "elapsed_time": 1148.010015487671, "token_count": 413 }, { "elapsed_time": 1106.6868305206299, "token_count": 414 }, { "elapsed_time": 1179.4452667236328, "token_count": 415 }, { "elapsed_time": 1122.5628852844238, "token_count": 416 }, { "elapsed_time": 1126.3039112091064, "token_count": 417 }, { "elapsed_time": 1147.0317840576172, "token_count": 418 }, { "elapsed_time": 1134.335994720459, "token_count": 419 }, { "elapsed_time": 1165.2190685272217, "token_count": 420 }, { "elapsed_time": 1155.7650566101074, "token_count": 421 }, { "elapsed_time": 1191.2481784820557, "token_count": 422 }, { "elapsed_time": 1172.7440357208252, "token_count": 423 }, { "elapsed_time": 1125.0512599945068, "token_count": 424 }, { "elapsed_time": 1149.794101715088, "token_count": 425 }, { "elapsed_time": 1126.8959045410156, "token_count": 426 }, { "elapsed_time": 1127.2268295288086, "token_count": 427 }, { "elapsed_time": 1130.3367614746094, "token_count": 428 }, { "elapsed_time": 1160.2697372436523, "token_count": 429 }, { "elapsed_time": 1156.4621925354004, "token_count": 430 }, { "elapsed_time": 1167.252779006958, "token_count": 431 }, { "elapsed_time": 1140.7279968261719, "token_count": 432 }, { "elapsed_time": 1174.4790077209473, "token_count": 433 }, { "elapsed_time": 1152.867078781128, "token_count": 434 }, { "elapsed_time": 1159.2891216278076, "token_count": 435 }, { "elapsed_time": 1162.2331142425537, "token_count": 436 }, { "elapsed_time": 1187.4489784240723, "token_count": 437 }, { "elapsed_time": 1186.1419677734375, "token_count": 438 }, { "elapsed_time": 1209.9151611328125, "token_count": 439 }, { "elapsed_time": 1229.6240329742432, "token_count": 440 }, { "elapsed_time": 1230.764627456665, "token_count": 441 }, { "elapsed_time": 1254.1100978851318, "token_count": 442 }, { "elapsed_time": 1204.930067062378, "token_count": 443 }, { "elapsed_time": 1219.7070121765137, "token_count": 444 }, { "elapsed_time": 1234.1461181640625, "token_count": 445 }, { "elapsed_time": 1204.906940460205, "token_count": 446 }, { "elapsed_time": 1228.996992111206, "token_count": 447 }, { "elapsed_time": 1295.4521179199219, "token_count": 448 }, { "elapsed_time": 1348.1459617614746, "token_count": 449 }, { "elapsed_time": 1275.0210762023926, "token_count": 450 }, { "elapsed_time": 1267.6169872283936, "token_count": 451 }, { "elapsed_time": 1260.3521347045898, "token_count": 452 }, { "elapsed_time": 1309.9231719970703, "token_count": 453 }, { "elapsed_time": 1295.098066329956, "token_count": 454 }, { "elapsed_time": 1289.7379398345947, "token_count": 455 }, { "elapsed_time": 1331.507921218872, "token_count": 456 }, { "elapsed_time": 1290.6358242034912, "token_count": 457 }, { "elapsed_time": 1252.7201175689697, "token_count": 458 }, { "elapsed_time": 1316.3022994995117, "token_count": 459 }, { "elapsed_time": 1258.8050365447998, "token_count": 460 }, { "elapsed_time": 1263.2899284362793, "token_count": 461 }, { "elapsed_time": 1264.9197578430176, "token_count": 462 }, { "elapsed_time": 1275.2928733825684, "token_count": 463 }, { "elapsed_time": 1301.7358779907227, "token_count": 464 }, { "elapsed_time": 1285.0627899169922, "token_count": 465 }, { "elapsed_time": 1287.6639366149902, "token_count": 466 }, { "elapsed_time": 1305.1869869232178, "token_count": 467 }, { "elapsed_time": 1323.3981132507324, "token_count": 468 }, { "elapsed_time": 1342.5891399383545, "token_count": 469 }, { "elapsed_time": 1300.9309768676758, "token_count": 470 }, { "elapsed_time": 1333.5871696472168, "token_count": 471 }, { "elapsed_time": 1321.0220336914062, "token_count": 472 }, { "elapsed_time": 1334.9671363830566, "token_count": 473 }, { "elapsed_time": 1349.3397235870361, "token_count": 474 }, { "elapsed_time": 1335.6122970581055, "token_count": 475 }, { "elapsed_time": 1325.2122402191162, "token_count": 476 }, { "elapsed_time": 1360.4190349578857, "token_count": 477 }, { "elapsed_time": 1384.0408325195312, "token_count": 478 }, { "elapsed_time": 1373.9428520202637, "token_count": 479 }, { "elapsed_time": 1354.4118404388428, "token_count": 480 }, { "elapsed_time": 1366.821050643921, "token_count": 481 }, { "elapsed_time": 1363.2912635803223, "token_count": 482 }, { "elapsed_time": 1422.6531982421875, "token_count": 483 }, { "elapsed_time": 1366.6198253631592, "token_count": 484 }, { "elapsed_time": 1364.2160892486572, "token_count": 485 }, { "elapsed_time": 1403.7902355194092, "token_count": 486 }, { "elapsed_time": 1395.6530094146729, "token_count": 487 }, { "elapsed_time": 1380.1908493041992, "token_count": 488 }, { "elapsed_time": 1450.5088329315186, "token_count": 489 }, { "elapsed_time": 1393.4822082519531, "token_count": 490 }, { "elapsed_time": 1393.7640190124512, "token_count": 491 }, { "elapsed_time": 1426.9161224365234, "token_count": 492 }, { "elapsed_time": 1525.0968933105469, "token_count": 493 } ], "max_token_count_per_time": { "100": 71, "200": 140, "300": 186, "400": 220, "500": 252, "600": 276, "700": 309, "800": 335, "900": 359, "1000": 384, "1100": 410, "1200": 438, "1300": 466, "1400": 491, "1500": 492 } } ================================================ FILE: reports/summary/bert_for_qa.json ================================================ { "config": { "data_reader": { "dataset": "squad_bert", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad_bert": { "lang_code": "en", "max_seq_length": 384, "context_stride": 128, "max_question_length": 64 } }, "iterator": { "batch_size": 48 }, "token": { "names": ["feature"], "types": ["feature"], "tokenizer": { "subword": { "name": "wordpiece", "wordpiece": { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" } }, "word": { "name": "bert_basic", "bert_basic": { "do_lower_case": true } } }, "feature": { "vocab": { "pretrained_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt", "pretrained_token": "all" }, "indexer": { "do_tokenize": false } } }, "model": { "name": "bert_for_qa", "bert_for_qa": { "pretrained_model_name": "bert-base-uncased", "answer_maxlen": 30 } }, "trainer": { "log_dir": "logs/squad_bert", "num_epochs": 5, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": 1000 }, "optimizer": { "op_type": "bert_adam", "learning_rate": 5e-05, "bert_adam": { "warmup": 0.1 } }, "seed_num": 42, "use_gpu": true, "gpu_num": 4 }, "training_logs": { "early_stopping_count": 6, "elapsed_time": ["02:18:10"], "train_dataset": { "name": "squad_bert", "total_count": 87779, "HasAns_count": 87779, "NoAns_count": 0 }, "valid_dataset": { "name": "squad_bert", "total_count": 10646, "HasAns_count": 10646, "NoAns_count": 0 } }, "metrics": { "best_epoch": 2, "best_global_step": 0, "best": { "valid/loss": 0.8889339666914295, "valid/epoch_time": 53.34748435020447, "valid/em": 78.67549668874172, "valid/f1": 86.58346875203304 }, "best_score": 86.58346875203304, "valid/loss": [0.9415906336124953, 0.9108352352370013, 0.8889339666914295, 1.0355482176617459, 1.0540606967500739, 1.1880523226819597, 1.1383471519828916, 1.351632583114478, 1.3381704858562968], "valid/epoch_time": [56.80781602859497, 53.31908941268921, 53.34748435020447, 56.13729381561279, 53.40209174156189, 56.136420249938965, 53.31478691101074, 56.12194752693176, 53.169355630874634], "valid/em": [76.9914853358562, 78.15515610217597, 78.67549668874172, 77.44560075685904, 77.17123935666982, 76.75496688741723, 76.3197729422895, 77.02932828760643, 76.49952696310312], "valid/f1": [84.95112042771974, 86.23856546381289, 86.58346875203304, 85.55421931957414, 85.89519153631547, 85.44916850325487, 85.25391484030878, 85.72639448425241, 85.4407206832876], "best_step": 3000 }, "inferency_latency": { "cpu": { "max_token_count_per_time": { "200": 27, "300": 56, "400": 77, "500": 94, "600": 124, "700": 145, "800": 160, "900": 173, "1000": 173, "1100": 173, "1200": 173, "1300": 173, "1400": 173, "1500": 173 } }, "gpu": { } } } ================================================ FILE: reports/summary/bidaf+elmo.json ================================================ { "config": { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json" }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove", "elmo"], "types": ["char", "word", "elmo"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": true }, "embedding": { "embed_dim": 100, "pretrained_path": "data/glove.6B.100d.txt", "trainable": false, "dropout": 0.2 } }, "elmo": { "embedding": { "options_file": "data/elmo_2x4096_512_2048cnn_2xhighway_options.json", "weight_file": "data/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5", "trainable": false, "dropout": 0.5 } } }, "model": { "name": "bidaf", "bidaf": { "model_dim": 200, "dropout": 0.3 } }, "trainer": { "log_dir": "logs/squad_bidaf+elmo", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "adam": { "betas": [0.9, 0.9] }, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 31, "use_gpu": true, "gpu_num": 1 }, "training_logs": { "early_stopping_count": 10, "early_stopping": true, "elapsed_time": ["20:07:04"], "train_dataset": { "name": "squad", "total_count": 87599, "HasAns_count": 87599, "NoAns_count": 0, "context_maxlen": 846, "question_maxlen": 60 }, "valid_dataset": { "name": "squad", "total_count": 10570, "HasAns_count": 10570, "NoAns_count": 0, "context_maxlen": 708, "question_maxlen": 36 } }, "metrics": { "best_epoch": 19, "best_global_step": 0, "best": { "train/loss": 0.8802273391131679, "train/epoch_time": 5151.87109541893, "train/start_acc": 82.51920684026074, "train/end_acc": 87.06149613580064, "train/span_acc": 75.27597347001678, "train/em": 80.97809335723011, "train/f1": 90.74583008084164, "valid/loss": 2.626493739667616, "valid/epoch_time": 371.3416645526886, "valid/start_acc": 67.62535477767265, "valid/end_acc": 71.26773888363293, "valid/span_acc": 59.11069063386944, "valid/em": 74.29517502365185, "valid/f1": 82.72662782854266 }, "best_score": 82.72662782854266, "train/loss": [5.199321151128035, 3.2426543711222724, 2.7508464762988623, 2.4840693453352674, 2.278940136868907, 2.1065649907244133, 1.9677384493340533, 1.8301174992884572, 1.7133333797303318, 1.6135036105261482, 1.5180674711660018, 1.3173119416521621, 1.2235544464442745, 1.1530149076174785, 1.097825859316167, 1.0446735754053988, 0.957186687871041, 0.913848308738868, 0.8802273391131679, 0.8539335568230721, 0.8255233902938615, 0.8052649012527995, 0.7617339534022409, 0.7471291374842384, 0.7284036813000417, 0.7035484345857029, 0.7000005541871376, 0.6894140941185443, 0.6820922573447402], "train/epoch_time": [5474.6565499305725, 4979.730434417725, 4964.404814720154, 4977.647702217102, 4963.868552207947, 4973.586528301239, 4975.978181362152, 4979.218969106674, 4990.829063177109, 4970.988567113876, 4978.851436853409, 4977.866499662399, 4982.926045179367, 5002.937310934067, 5285.927149772644, 5205.089644193649, 5130.486099720001, 5166.29741024971, 5151.87109541893, 5158.328686237335, 5132.487548828125, 5152.464540481567, 5132.208809375763, 5145.624874353409, 5144.96672129631, 5127.451770544052, 5141.1182289123535, 5140.675534486771, 5139.1023206710815], "train/start_acc": [30.09623397527369, 52.3944337264124, 58.49952625029966, 61.60915078939257, 64.2084955307709, 66.01102752314524, 67.7484902795694, 69.6172330734369, 70.8992111782098, 72.02479480359365, 73.52024566490485, 76.06022899804792, 77.35590588933664, 78.33536912521832, 79.19154328245756, 80.01803673557917, 81.26805100514846, 82.03518305003482, 82.51920684026074, 83.01350472037352, 83.39250448064476, 83.88680236075754, 84.26922681765774, 84.5192296715716, 84.83544332697862, 85.362846607838, 85.42106645053026, 85.57974406100526, 85.52609048048494], "train/end_acc": [32.472973435769816, 56.563431089396, 62.700487448486854, 65.88773844450279, 68.36493567278166, 70.64920832429594, 72.14237605452116, 73.92892612929371, 75.45862395689448, 76.64356899051359, 77.94267057843126, 80.52831653329376, 81.87308074293085, 83.13907693010194, 83.67104647313326, 84.58201577643581, 85.72814758159339, 86.43249352161554, 87.06149613580064, 87.37200196349274, 87.92566125184078, 88.04780876494024, 88.8548956038311, 89.16768456260917, 89.42453680978093, 89.81723535656799, 89.76700647267663, 89.84805762622861, 90.214500165527], "train/span_acc": [21.84157353394445, 42.51075925524264, 48.564481329695546, 51.80995216840375, 54.36363428806265, 56.5314672541924, 58.154773456318, 60.1034258381945, 61.592027306247786, 62.8717222799347, 64.51671822737703, 67.25419239945661, 68.8854895603831, 70.19258210710169, 71.05446409205585, 72.11383691594654, 73.72001963492734, 74.6538202490896, 75.27597347001678, 75.97347001678101, 76.5705087957625, 76.9928880466672, 77.7725773125264, 78.16870055594242, 78.56482379935844, 79.20980833114534, 79.2280733798331, 79.38560942476512, 79.6104978367333], "train/em": [24.685213301521706, 48.01995456569139, 54.574823913515, 58.05545725407824, 60.72900375575064, 63.02697519378075, 64.66512174796516, 66.65258735830318, 68.05557141063254, 69.31357663900273, 70.90035274375278, 73.71431180721241, 75.09674767976803, 76.34333725270837, 77.167547574744, 78.13331202410987, 79.59679905021747, 80.36050639847487, 80.97809335723011, 81.54773456317994, 82.03518305003482, 82.38792680281739, 83.10939622598431, 83.39592917727371, 83.86282948435485, 84.31488943937717, 84.22128106485233, 84.41648877270289, 84.64822657792897], "train/f1": [36.081805902200124, 62.256687310922864, 68.79747652976971, 72.01592592596222, 74.54823397427586, 76.54656945307397, 78.0749588626154, 79.84475624140384, 81.04883125005381, 82.18241326097673, 83.234597479496, 85.66653647222941, 86.75640467761987, 87.59982726857889, 88.25205327127513, 88.80302223991147, 89.77693590987325, 90.32219441701788, 90.74583008084164, 90.99030982547735, 91.24850897403488, 91.46237203842257, 91.95796286683243, 92.075923964645, 92.37982660291567, 92.57360772115761, 92.62741445698998, 92.71939533714819, 92.8358291897603], "valid/loss": [3.1358324537824647, 2.462308123032492, 2.26361395026982, 2.1426335310287707, 2.130673690324824, 2.112841031522549, 2.073477884433781, 2.125299881232109, 2.115961379335006, 2.1840251048526014, 2.1877216370804433, 2.2746186195183378, 2.303641164590945, 2.3522322186890685, 2.411913618850564, 2.4464716475535737, 2.562021914025448, 2.6151650555184243, 2.626493739667616, 2.7094725381211573, 2.751489603087261, 2.7427400102968305, 2.808030868224867, 2.8389116403199393, 2.898545431226402, 2.9101907281357, 2.931594036857167, 2.9568752257485404, 2.9598750104716895], "valid/epoch_time": [397.5357277393341, 354.3016209602356, 354.2125337123871, 354.8656098842621, 354.83954215049744, 354.5988097190857, 355.3075087070465, 355.19523334503174, 355.18815422058105, 355.1181824207306, 355.3709852695465, 354.5889689922333, 355.16985297203064, 374.96937012672424, 381.7922697067261, 369.42103838920593, 370.18241143226624, 370.13810300827026, 371.3416645526886, 370.67670726776123, 369.77847123146057, 366.278751373291, 367.56112146377563, 359.98594427108765, 368.54997873306274, 367.8412208557129, 368.14005970954895, 369.04835271835327, 362.66716599464417], "valid/start_acc": [53.87890255439925, 62.61116367076632, 65.01419110690634, 67.11447492904446, 66.84011352885526, 67.74834437086092, 67.85241248817408, 67.88079470198676, 67.80510879848629, 67.81456953642385, 67.43614001892148, 67.99432355723746, 68.09839167455061, 68.02270577105014, 67.44560075685904, 67.69157994323557, 67.65373699148533, 68.0321665089877, 67.62535477767265, 67.64427625354777, 67.5685903500473, 67.14285714285714, 67.55912961210974, 67.7294228949858, 67.36991485335857, 67.33207190160833, 67.360454115421, 67.52128666035951, 67.31315042573321], "valid/end_acc": [57.530747398297066, 66.10217596972564, 68.78902554399244, 70.12298959318827, 70.39735099337749, 71.36234626300852, 71.11636707663197, 71.36234626300852, 71.30558183538317, 71.35288552507096, 71.38126773888364, 71.2961210974456, 71.40018921475875, 71.47587511825922, 71.33396404919584, 71.48533585619678, 71.2488174077578, 71.31504257332072, 71.26773888363293, 71.02175969725639, 70.78524124881741, 70.84200567644277, 71.30558183538317, 71.22989593188268, 70.88930936613056, 70.88930936613056, 70.51087984862819, 70.70009460737937, 70.7663197729423], "valid/span_acc": [44.49385052034059, 53.065279091769156, 56.62251655629139, 57.80510879848628, 58.09839167455061, 59.77294228949858, 59.3755912961211, 59.40397350993378, 59.54588457899716, 59.17691579943236, 58.73226111636708, 59.44181646168401, 59.593188268684955, 59.57426679280984, 59.195837275307476, 59.120151371807, 59.0728476821192, 59.55534531693472, 59.11069063386944, 59.17691579943236, 58.978240302743615, 58.57142857142857, 59.17691579943236, 59.24314096499527, 58.741721854304636, 58.760643330179754, 58.38221381267739, 58.7038789025544, 58.62819299905393], "valid/em": [56.385998107852416, 66.62251655629139, 69.89593188268685, 72.21381267738883, 72.28003784295176, 73.78429517502366, 73.81267738883633, 73.80321665089878, 74.03973509933775, 73.71807000946073, 73.66130558183538, 74.18164616840113, 74.48438978240303, 74.25733207190162, 74.0964995269631, 73.96404919583728, 73.87890255439925, 74.37086092715232, 74.29517502365185, 74.18164616840113, 74.0964995269631, 73.89782403027436, 74.19110690633869, 74.2100283822138, 73.85052034058657, 73.89782403027436, 73.64238410596026, 73.7748344370861, 73.92620624408704], "valid/f1": [67.3041368772203, 76.62706615904294, 78.83509809179301, 81.00528880703403, 80.90156879146838, 81.77321188017719, 82.11160303527237, 82.24011294202107, 82.03716696557396, 82.11519150244165, 82.23375635679048, 82.58431637358657, 82.67790929614387, 82.61403458750335, 82.40268727546746, 82.50648656754376, 82.50090325321402, 82.68915589879413, 82.72662782854266, 82.50404724093217, 82.46038638435557, 82.42655348570055, 82.59671887078092, 82.67566678598348, 82.49401156249223, 82.4828737404366, 82.35408272883042, 82.37103880032886, 82.47274214105332], "best_step": 52022 }, "inferency_latency": { "cpu": { "max_token_count_per_time": { "500": 13, "600": 16, "700": 19, "800": 24, "900": 27, "1000": 30, "1100": 34, "1200": 38, "1300": 40, "1400": 44, "1500": 46 } }, "gpu": { } } } ================================================ FILE: reports/summary/bidaf.json ================================================ { "config": { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json" }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "start_token": "", "end_token": "", "max_vocab_size": 260 }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 16, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "vocab": { "pretrained_path": "http://dev-reasoning-qa-data-ncl.nfra.io:7778/data/glove.6B.vocab.txt", "pretrained_token": "intersect" }, "indexer": { "lowercase": true }, "embedding": { "embed_dim": 100, "pretrained_path": "http://dev-reasoning-qa-data-ncl.nfra.io:7778/data/glove.6B.100d.txt", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "bidaf", "bidaf": { "model_dim": 100, "contextual_rnn_num_layer": 1, "modeling_rnn_num_layer": 2, "predict_rnn_num_layer": 1, "dropout": 0.2 } }, "trainer": { "log_dir": "logs/squad_bidaf", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adadelta", "learning_rate": 0.5, "exponential_moving_average": 0.999 }, "seed_num": 2, "slack": false, "use_gpu": true, "gpu_num": 1 }, "training_logs": { "early_stopping_count": 10, "early_stopping": true, "elapsed_time": ["13:35:37"], "train_dataset": { "name": "squad", "total_count": 87599, "HasAns_count": 87599, "NoAns_count": 0, "context_maxlen": 846, "question_maxlen": 60 }, "valid_dataset": { "name": "squad", "total_count": 10570, "HasAns_count": 10570, "NoAns_count": 0, "context_maxlen": 708, "question_maxlen": 36 } }, "metrics": { "best_epoch": 21, "best_global_step": 0, "best": { "train/loss": 1.8804193112191012, "train/epoch_time": 1488.8830120563507, "train/start_acc": 68.78845648922933, "train/end_acc": 73.70061302069658, "train/span_acc": 59.47670635509538, "train/em": 65.63659402504595, "train/f1": 78.98644094318335, "valid/loss": 2.59111491665019, "valid/epoch_time": 60.7434446811676, "valid/start_acc": 63.17880794701987, "valid/end_acc": 67.19016083254493, "valid/span_acc": 54.45600756859035, "valid/em": 68.10785241248817, "valid/f1": 77.77963381714842 }, "best_score": 77.77963381714842, "train/loss": [6.802488770077401, 4.205627956209259, 3.505901032594802, 3.195407586083785, 2.994199373758649, 2.8403854832934847, 2.713508145621086, 2.616165210854145, 2.5216083436921357, 2.4369467883714364, 2.364499175740124, 2.292416350152738, 2.232062298551452, 2.1831376637482487, 2.131602263803287, 2.072337622077383, 2.029501295551233, 1.998490737553841, 1.9576764812079375, 1.9282494203029017, 1.8804193112191012, 1.85559536587417, 1.8236318133755092, 1.800804827424886, 1.776197946206595, 1.7496464839375219, 1.7319859258008752, 1.7110994695267423, 1.6878932957844286, 1.6624671622425036, 1.637791820148032], "train/epoch_time": [2006.0850911140442, 1485.6879358291626, 1475.598529100418, 1478.4869632720947, 1482.2096199989319, 1486.2473270893097, 1472.47771525383, 1482.7782707214355, 1479.5967094898224, 1485.5918855667114, 1474.6913664340973, 1480.9212946891785, 1481.4111742973328, 1485.9645612239838, 1473.1698570251465, 1483.397302865982, 1488.9916093349457, 1483.4742772579193, 1480.3435850143433, 1486.24049782753, 1488.8830120563507, 1486.1977095603943, 1476.0061762332916, 1481.454964876175, 1488.7305047512054, 1485.6676778793335, 1473.8961174488068, 1479.606299161911, 1479.1073908805847, 1479.5758039951324, 1477.463410615921], "train/start_acc": [16.583522642952545, 42.4422653226635, 50.25742302994326, 53.80198404091371, 55.96525074487152, 57.68901471477985, 59.18789027272001, 60.26096188312652, 61.43449126131577, 62.52696948595304, 63.33405632484389, 64.15712508133655, 64.78270299889269, 65.5053139876026, 65.85234991267023, 66.52701514857476, 67.02930398748845, 67.33866824963755, 67.8923275379856, 68.2416465941392, 68.78845648922933, 68.99622141805271, 69.44942293861801, 69.60467585246407, 69.81015765020149, 70.13664539549538, 70.3181543168301, 70.67888902841356, 70.92889188232742, 71.17204534298337, 71.47912647404651], "train/end_acc": [17.532163609173622, 46.669482528339366, 54.49148962887704, 58.047466295277346, 60.42078105914451, 62.275825066496196, 63.71305608511513, 65.01444080411876, 66.19481957556593, 66.9539606616514, 68.12520690875466, 68.80900466900307, 69.36152239180812, 70.08984120823297, 70.75651548533659, 71.64921973995136, 71.95173460884257, 72.3307343691138, 72.82731538031256, 73.23485427915844, 73.70061302069658, 74.14239888583204, 74.76911836893115, 74.89354901311658, 75.16980787451912, 75.6800876722337, 75.77141291567256, 76.17895181451843, 76.32735533510656, 76.87758992682565, 77.34905649607872], "train/span_acc": [10.059475564789553, 32.62137695635795, 40.09292343519903, 43.784746401214626, 45.98340163700499, 47.85100286532951, 49.271110400803664, 50.517699973743994, 51.73346727702371, 52.773433486683636, 53.75061359147936, 54.48920649779107, 54.992636902247746, 55.82597974862727, 56.348816767314695, 57.10795785340015, 57.61252982339981, 57.887647119259356, 58.413908834575736, 58.91163141131748, 59.47670635509538, 59.758673044212834, 60.40251601045674, 60.48356716400872, 60.74955193552438, 61.201611890546694, 61.32604253473213, 61.751846482265776, 62.018972819324425, 62.46989120880375, 62.78382173312481], "train/em": [11.201041107775202, 36.92622061895684, 45.28133882806881, 49.20033333713855, 51.54168426580212, 53.638740168266764, 55.09880249774541, 56.441283576296534, 57.651343051861325, 58.70386648249409, 59.852281418737654, 60.51324786812635, 61.144533613397414, 61.93563853468647, 62.48130686423361, 63.256429867920865, 63.76214340346351, 64.10803776298816, 64.57722120115527, 64.9562209614265, 65.63659402504595, 66.00988595760225, 66.5235904519458, 66.66856927590497, 66.826105320837, 67.30556284889097, 67.36606582266921, 67.85008961289512, 67.8923275379856, 68.5361705042295, 68.84439320083563], "train/f1": [19.97468549873792, 51.34196880784591, 60.08754900566428, 63.93039993057552, 66.25848527221643, 68.159784095871, 69.55288259311627, 70.77210151946028, 71.85804457432974, 72.74239831484314, 73.82220251022059, 74.4477480036949, 75.12548563093274, 75.82249693925081, 76.30668814749853, 76.985685281905, 77.42865253978103, 77.62549431865827, 78.15147865774858, 78.39996484486177, 78.98644094318335, 79.28245614472341, 79.70279469474156, 79.90194637491457, 80.06043674987653, 80.29938451692719, 80.41705882967047, 80.83001291157164, 80.86903855211925, 81.27039805834508, 81.60764566928177], "valid/loss": [4.7435729885389435, 3.18698846213407, 2.9136927451972157, 2.720595936580727, 2.6256603928130917, 2.5950503596006205, 2.509827042454319, 2.5278977413191894, 2.5180999204471393, 2.486862433100755, 2.5041553129602416, 2.4991234886682285, 2.4887624843963323, 2.511779291662205, 2.4878336310026508, 2.5245973305759835, 2.5873427063316736, 2.5393245362443144, 2.579380591830458, 2.5648889905376375, 2.59111491665019, 2.5946989243124188, 2.6353404403093, 2.645616871892866, 2.6574283924707833, 2.6868798694941933, 2.7441978377157827, 2.713041145635876, 2.688760362182859, 2.742932821148472, 2.755753375972506], "valid/epoch_time": [101.57139825820923, 60.02541184425354, 60.92531633377075, 60.83312249183655, 59.99517583847046, 60.126864194869995, 60.92917728424072, 67.57362794876099, 60.27321743965149, 60.59219217300415, 60.95810270309448, 60.571919679641724, 60.45670247077942, 60.42324709892273, 60.31264591217041, 60.76713800430298, 60.29240608215332, 59.75893235206604, 60.75028729438782, 60.91915845870972, 60.7434446811676, 60.262728452682495, 60.26231932640076, 60.294543504714966, 60.88165044784546, 60.55802631378174, 60.503045082092285, 60.411009311676025, 59.75921869277954, 60.26841878890991, 60.91560435295105], "valid/start_acc": [37.19016083254494, 54.16272469252602, 57.455061494796595, 59.75402081362346, 61.37180700094607, 61.485335856196784, 62.88552507095554, 62.40302743614002, 63.2639545884579, 63.19772942289499, 63.443708609271525, 63.03689687795648, 63.28287606433302, 63.80321665089877, 63.16934720908231, 63.084200567644274, 63.746452223273415, 62.79091769157994, 63.15042573320719, 63.38694418164617, 63.17880794701987, 63.16934720908231, 62.639545884579, 63.27341532639546, 62.97067171239357, 63.33964049195837, 62.838221381267736, 62.64900662251656, 63.11258278145695, 62.80983916745506, 62.49763481551561], "valid/end_acc": [40.23651844843898, 57.80510879848628, 61.01229895931883, 63.36802270577105, 64.61684011352885, 65.45884578997162, 66.04541154210028, 65.98864711447493, 66.88741721854305, 66.20624408703878, 67.00094607379376, 66.91579943235573, 67.09555345316934, 66.69820245979186, 66.92526017029329, 66.76442762535478, 66.84957426679281, 66.26300851466415, 66.82119205298014, 67.08609271523179, 67.19016083254493, 66.80227057710502, 66.08325449385052, 66.14001892147587, 66.56575212866603, 67.2942289498581, 66.20624408703878, 66.81173131504258, 66.34815515610218, 66.55629139072848, 66.07379375591296], "valid/span_acc": [28.060548722800377, 44.3046357615894, 48.25922421948912, 50.53926206244087, 51.95837275307474, 52.8949858088931, 53.25449385052034, 53.16934720908231, 54.437086092715234, 53.831598864711445, 54.62630085146642, 54.68306527909177, 54.70198675496689, 54.24787133396405, 54.427625354777675, 54.370860927152314, 54.77767265846736, 53.59508041627247, 54.38978240302744, 54.45600756859035, 54.45600756859035, 54.21948912015137, 53.528855250709555, 54.058656575212865, 54.12488174077578, 55.07095553453169, 53.63292336802271, 53.53831598864711, 54.16272469252602, 53.95458845789972, 53.15988647114475], "valid/em": [34.45600756859035, 56.017029328287606, 59.44181646168401, 62.78145695364238, 64.399243140965, 64.93850520340587, 66.1778618732261, 66.26300851466415, 67.21854304635761, 67.12393566698202, 67.46452223273415, 67.55912961210974, 67.53074739829707, 67.62535477767265, 67.39829706717124, 67.57805108798486, 67.90917691579943, 66.86849574266793, 67.68211920529801, 67.80510879848629, 68.10785241248817, 67.66319772942289, 67.06717123935667, 67.36991485335857, 67.65373699148533, 68.01324503311258, 67.02932828760643, 66.61305581835383, 67.2942289498581, 67.4077578051088, 66.5279091769158], "valid/f1": [47.11793993142203, 67.62064966725356, 70.43505363398312, 73.3648573373103, 74.65367863205222, 75.01986741588263, 76.22554585944229, 76.229074438378, 76.86040318995676, 76.64349340625128, 76.94548374612968, 76.77342438746693, 76.99280462085946, 77.48774268182495, 77.07897215760607, 77.06606888717221, 77.4321479503029, 76.94813176230305, 77.44460779629544, 77.61593675600862, 77.77963381714842, 77.38312592532897, 76.8725362267208, 77.09486060768172, 77.17977821122052, 77.4367462196794, 76.95349394175246, 76.67467144835067, 76.84060825277712, 77.23149291511744, 76.84772426585663], "best_step": 57498 }, "inferency_latency": { "cpu": { "max_token_count_per_time": { "100": 80, "200": 140, "300": 187, "400": 236, "500": 279, "600": 316, "700": 351, "800": 380, "900": 422, "1000": 442, "1100": 456, "1200": 505, "1300": 525, "1400": 543, "1500": 559 } }, "gpu": { } } } ================================================ FILE: reports/summary/docqa+elmo.json ================================================ { "config": { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json" }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove", "elmo"], "types": ["char", "word", "elmo"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "data/glove.840B.300d.txt", "trainable": false } }, "elmo": { "embedding": { "options_file": "data/elmo_2x4096_512_2048cnn_2xhighway_options.json", "weight_file": "data/elmo_2x4096_512_2048cnn_2xhighway_weights.hdf5", "trainable": false, "dropout": 0.5 } } }, "model": { "name": "docqa", "docqa": { "rnn_dim": 200, "linear_dim": 400, "dropout": 0.25, "weight_init": true } }, "trainer": { "log_dir": "logs/squad_docqa+elmo", "num_epochs": 30, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 2, "use_gpu": true, "gpu_num": 1 }, "training_logs": { "early_stopping_count": 9, "elapsed_time": ["23:55:12"], "train_dataset": { "name": "squad", "total_count": 87599, "HasAns_count": 87599, "NoAns_count": 0, "context_maxlen": 846, "question_maxlen": 60 }, "valid_dataset": { "name": "squad", "total_count": 10570, "HasAns_count": 10570, "NoAns_count": 0, "context_maxlen": 708, "question_maxlen": 36 } }, "metrics": { "best_epoch": 21, "best_global_step": 0, "best": { "train/loss": 1.439864479391744, "train/epoch_time": 5993.168662786484, "train/start_acc": 74.20518499069624, "train/end_acc": 78.46664916266167, "train/span_acc": 65.07608534344, "train/em": 71.53848788228176, "train/f1": 84.62785307755999, "valid/loss": 2.080861333813912, "valid/epoch_time": 479.3675630092621, "valid/start_acc": 69.30936613055819, "valid/end_acc": 73.01797540208136, "valid/span_acc": 61.44749290444655, "valid/em": 76.45222327341533, "valid/f1": 84.11094186682244 }, "best_score": 84.11094186682244, "train/loss": [5.079814058572729, 3.2275339316677405, 2.8251574592402244, 2.6195111416873487, 2.4645420738691133, 2.3375994696113818, 2.2441998273460775, 2.153036293319928, 2.076495324655377, 2.0178244998630945, 1.9499604054791289, 1.894998986151551, 1.766365717652943, 1.6965989512496833, 1.655730398599034, 1.6212873319320387, 1.5427740310516733, 1.5107103774066908, 1.4867077688608317, 1.460878933538391, 1.439864479391744, 1.4177687963140193, 1.4082762137588747, 1.3824653881931932, 1.3560050226328928, 1.3370496482418956, 1.3229278716577764, 1.3051053639460515, 1.291628007789961, 1.2855351840909857], "train/epoch_time": [5241.659848213196, 4748.942885637283, 4745.987740516663, 4743.398574113846, 4725.667029619217, 4740.133901357651, 4726.168287754059, 4744.704974651337, 4728.299903869629, 4737.382742881775, 4740.728321313858, 4735.4657237529755, 4742.2038497924805, 4737.14636349678, 5863.12846493721, 5230.826290607452, 5954.650916814804, 5947.938965082169, 5953.572997093201, 5921.744880437851, 5993.168662786484, 5895.05787229538, 6060.5481877326965, 5996.288537025452, 6012.955463647842, 5990.060202360153, 5975.012909889221, 5807.853344678879, 5025.293034076691, 5041.438595294952], "train/start_acc": [33.11225013984178, 53.04284295482825, 57.920752520005934, 60.28950102170116, 62.16509320882658, 63.44935444468544, 64.59434468430005, 65.59549766549847, 66.5783855980091, 67.32154476649276, 68.0270322720579, 68.77818239934246, 69.9597027363326, 71.02135869130926, 71.56246075868447, 71.91634607701, 72.95631228666994, 73.2862247285928, 73.51339627164694, 73.96431466112627, 74.20518499069624, 74.52824803936117, 74.61614858617108, 74.78281715544698, 75.24629276589916, 75.44264203929269, 75.6321419194283, 75.94949714037831, 76.10817475085332, 76.12415666845511], "train/end_acc": [36.291510177056814, 57.11709037774404, 62.05093665452802, 64.39000445210561, 66.29071108117672, 67.6845626091622, 68.74051073642393, 69.8409799198621, 70.73368417447688, 71.33757234671629, 72.156074841037, 72.69032751515428, 74.28166988207627, 75.14012717040148, 75.63670818160024, 75.98146097558191, 77.11617712530965, 77.5739449080469, 77.79540862338611, 78.08308314021849, 78.46664916266167, 78.6310346008516, 78.74404958960719, 78.9015856345392, 79.45638648843023, 79.84451877304535, 79.87305791162, 80.11621137227594, 80.36050639847487, 80.4050274546513], "train/span_acc": [25.563077204077672, 43.68428863343189, 48.50740305254626, 50.87158529206955, 52.84991837806368, 54.05997785362847, 55.17186269249649, 56.265482482676745, 57.219831276612744, 57.99837897692896, 58.671902647290494, 59.24496854986929, 60.706172444890925, 61.68221098414365, 62.28381602529709, 62.62971038482174, 63.740453658146784, 64.09091427984337, 64.38657975547666, 64.8603294558157, 65.07608534344, 65.36033516364343, 65.49275676662975, 65.63659402504595, 66.22564184522655, 66.5703946392082, 66.63432230961541, 66.95738535828035, 67.20168038447927, 67.19711412230733], "train/em": [29.25946643226521, 49.58389935958173, 54.55199260265528, 57.07713558373954, 59.18446557609105, 60.52466352355621, 61.69933446728844, 62.77925547095286, 63.729038002716926, 64.61945912624573, 65.19366659436751, 65.82495233963859, 67.3672073882122, 68.36493567278166, 68.84439320083563, 69.18229660155937, 70.40148860146806, 70.71998538796105, 70.96428041415997, 71.30104224934074, 71.53848788228176, 71.79534012945354, 71.94602678112764, 72.10470439160264, 72.52822520805032, 72.98142672861562, 73.01909839153414, 73.29649881847966, 73.50426374730306, 73.48257400198632], "train/f1": [41.823210076567165, 64.04439607349838, 68.96454499193852, 71.38109999644747, 73.26550154910214, 74.67687827370719, 75.72286084886255, 76.7442846826793, 77.60396260583099, 78.29910018311244, 78.95895148974826, 79.57258898355508, 80.85222068237327, 81.85572763701992, 82.23764080679737, 82.51173221452157, 83.5567821531103, 83.9109659772286, 84.04452704844486, 84.33425528835996, 84.62785307755999, 84.87435268422722, 84.88500124763733, 85.07580479166042, 85.38736816765336, 85.6982155518823, 85.87633529241451, 86.04517807639093, 86.15535877515501, 86.15685151665427], "valid/loss": [2.7543403014675727, 2.3885570840172896, 2.251079231770737, 2.1365918373053168, 2.0704233495130278, 2.052785878635245, 2.0243880656910807, 1.995103694881197, 2.036385576170377, 2.010665632446727, 2.029187322563275, 1.9823158302335941, 2.030617795501951, 2.0456596283394046, 2.026606950334912, 2.0517768854461047, 2.0770177837585035, 2.0823803038035273, 2.0933495162116795, 2.1015306077334817, 2.080861333813912, 2.127328137796811, 2.1290761077512066, 2.1883657828558607, 2.177603616815319, 2.1813284672819235, 2.1603564943251654, 2.193939955392993, 2.2064665964722994, 2.2040130128673194], "valid/epoch_time": [398.0897767543793, 364.0841760635376, 364.6475431919098, 364.73658061027527, 365.0627250671387, 364.43452525138855, 364.4353904724121, 365.03809237480164, 364.5749924182892, 364.6512653827667, 364.92579984664917, 365.4912221431732, 364.74781131744385, 365.2856652736664, 430.99648451805115, 503.08322763442993, 389.6020042896271, 444.917387008667, 467.61401438713074, 482.1286108493805, 479.3675630092621, 403.44353556632996, 455.83782386779785, 433.4075622558594, 466.4834966659546, 421.3050284385681, 423.5893306732178, 420.13208866119385, 417.5079028606415, 382.99699330329895], "valid/start_acc": [59.120151371807, 63.443708609271525, 65.4399243140965, 66.93472090823084, 67.80510879848629, 67.92809839167455, 68.53358561967833, 68.18353831598864, 68.57142857142857, 68.25922421948913, 69.00662251655629, 69.05392620624409, 69.120151371807, 68.94039735099338, 68.90255439924314, 68.43897824030275, 69.33774834437087, 69.09176915799432, 69.10122989593188, 69.33774834437087, 69.30936613055819, 69.2336802270577, 69.12961210974456, 68.89309366130558, 69.34720908230842, 69.19583727530747, 69.45127719962157, 69.3282876064333, 69.4228949858089, 69.33774834437087], "valid/end_acc": [62.60170293282876, 67.36991485335857, 68.67549668874172, 70.22705771050141, 70.95553453169347, 71.2961210974456, 71.759697256386, 71.82592242194892, 72.02459791863765, 72.20435193945127, 71.98675496688742, 72.34626300851467, 72.79091769157995, 72.26111636707664, 72.65846736045411, 72.58278145695364, 72.73415326395458, 72.55439924314096, 72.75307473982971, 72.78145695364239, 73.01797540208136, 72.46925260170293, 72.45979186376537, 72.39356669820246, 72.639545884579, 72.51655629139073, 72.3841059602649, 72.33680227057711, 72.45979186376537, 72.47871333964049], "valid/span_acc": [50.09460737937559, 55.06149479659413, 56.9441816461684, 58.978240302743615, 59.08230842005676, 59.91485335856197, 60.45411542100284, 59.83916745506149, 60.32166508987701, 60.586565752128664, 60.633869441816465, 60.9271523178808, 61.31504257332072, 60.59602649006622, 60.936613055818356, 60.6717123935667, 61.324503311258276, 60.86092715231788, 61.22989593188269, 61.2961210974456, 61.44749290444655, 60.85146641438032, 61.0879848628193, 60.567644276253546, 61.173131504257334, 60.88930936613056, 60.97445600756859, 60.98391674550615, 61.19205298013245, 61.00283822138127], "valid/em": [63.207190160832546, 68.59981078524125, 71.14474929044465, 73.18826868495742, 73.90728476821192, 74.29517502365185, 74.89120151371807, 74.52223273415326, 75.12771996215704, 75.26963103122044, 75.16556291390728, 75.26963103122044, 75.93188268684958, 75.62913907284768, 75.8561967833491, 75.68590350047303, 75.9508041627247, 75.83727530747399, 76.3197729422895, 76.21570482497634, 76.45222327341533, 76.04541154210028, 76.09271523178808, 75.78051087984863, 76.3670766319773, 75.97918637653737, 76.05487228003784, 76.18732261116367, 76.15894039735099, 76.18732261116367], "valid/f1": [73.63899777129646, 78.07477719953904, 79.88712087808636, 81.27290750190173, 82.4028846891031, 82.2366015873866, 82.79291500485648, 83.0706694667876, 83.30933603410722, 83.08599055072762, 83.08029879894835, 83.17156421119037, 83.72038512545765, 83.57372872139884, 83.68574466681565, 83.57760476086574, 83.76355651811551, 83.74346993139304, 83.90126410509757, 84.02309811707664, 84.11094186682244, 83.87333403602042, 83.84284476902984, 83.8307092817778, 84.09020433360895, 83.92002772620177, 84.01457182368458, 83.94613454081411, 83.94902773917838, 84.01561276132168], "best_step": 57498 }, "inferency_latency": { "cpu": { "max_token_count_per_time": { "500": 11, "600": 15, "700": 19, "800": 23, "900": 25, "1000": 26, "1100": 27, "1200": 34, "1300": 34, "1400": 38, "1500": 39 } }, "gpu": { } } } ================================================ FILE: reports/summary/docqa.json ================================================ { "config": { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json" }, "iterator": { "batch_size": 32 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 20, "kernel_sizes": [5], "num_filter": 100, "activation": "relu", "dropout": 0.2 } }, "glove": { "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "http://dev-reasoning-qa-data-ncl.nfra.io:7778/data/glove.840B.300d.txt", "trainable": false, "dropout": 0.2 } } }, "model": { "name": "docqa", "docqa": { "answer_maxlen": 17, "rnn_dim": 100, "linear_dim": 200, "preprocess_rnn_num_layer": 1, "modeling_rnn_num_layer": 1, "predict_rnn_num_layer": 1, "dropout": 0.2, "weight_init": true } }, "trainer": { "log_dir": "logs/squad_docqa", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.001, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 2, "slack": true, "use_gpu": true, "nsml": { "dataset_path": "/data/rqa_squad" }, "gpu_num": 1 }, "training_logs": { "early_stopping_count": 10, "early_stopping": true, "elapsed_time": ["17:45:49"], "train_dataset": { "name": "squad", "total_count": 87599, "HasAns_count": 87599, "NoAns_count": 0, "context_maxlen": 846, "question_maxlen": 60 }, "valid_dataset": { "name": "squad", "total_count": 10570, "HasAns_count": 10570, "NoAns_count": 0, "context_maxlen": 708, "question_maxlen": 36 } }, "metrics": { "best_epoch": 36, "best_global_step": 0, "best": { "train/loss": 2.0024796845792765, "train/epoch_time": 1305.2128376960754, "train/start_acc": 67.36149956049726, "train/end_acc": 71.60013242160299, "train/span_acc": 58.0588819507072, "train/em": 64.28612198769392, "train/f1": 78.08381782352954, "valid/loss": 2.315428913359916, "valid/epoch_time": 54.355202436447144, "valid/start_acc": 65.80889309366131, "valid/end_acc": 69.45127719962157, "valid/span_acc": 57.8240302743614, "valid/em": 71.70293282876064, "valid/f1": 80.30594840422914 }, "best_score": 80.30594840422914, "train/loss": [5.818612085022658, 3.937010064187757, 3.512418350178974, 3.2931603383983115, 3.146366418235227, 3.020703520846245, 2.9343829691801915, 2.855480711811907, 2.7907345838752255, 2.721842828155696, 2.674787028938249, 2.625751250847314, 2.5884839667727078, 2.542313673685205, 2.5029476590187905, 2.478994732294055, 2.4431232058105024, 2.4099183318125585, 2.379493480272063, 2.368589064515882, 2.336758820265205, 2.2467474233416245, 2.2265513101749126, 2.1981466996182135, 2.175110972019074, 2.1597982208340425, 2.143637337764743, 2.099299894230831, 2.0832237069888913, 2.0711371807219603, 2.0655367378556355, 2.0611205305863334, 2.035011407317168, 2.0221054804986895, 2.0124819927445463, 2.0024796845792765, 2.004889547694243, 1.9917108297696333, 1.9854124109617892, 1.9879058681542723, 1.9850256016560939, 1.9814429832819693, 1.98769978735898, 1.9869677119441411, 1.9802090744845096, 1.972371397726374], "train/epoch_time": [1756.2093238830566, 1316.4014723300934, 1317.7358529567719, 1317.4981582164764, 1319.6687710285187, 1311.2953672409058, 1313.9999244213104, 1323.0991418361664, 1313.743307352066, 1312.1007041931152, 1306.5723552703857, 1305.0280554294586, 1304.2646160125732, 1305.101998090744, 1305.0865998268127, 1307.065759897232, 1312.506501674652, 1305.7742664813995, 1301.0485985279083, 1302.7703099250793, 1304.4089150428772, 1302.5827214717865, 1305.076423406601, 1305.9158294200897, 1308.109647512436, 1304.6278502941132, 1303.51096701622, 1306.9799551963806, 1305.2228252887726, 1304.5719447135925, 1303.1180980205536, 1303.124599456787, 1306.586990594864, 1312.1639318466187, 1307.5126221179962, 1305.2128376960754, 1300.9613127708435, 1304.874558210373, 1302.824146747589, 1305.8176651000977, 1306.3275363445282, 1309.6138033866882, 1305.2054679393768, 1304.3916850090027, 1307.717455625534, 1309.7977273464203], "train/start_acc": [26.958070297606138, 45.77791983926757, 50.218609801481755, 52.824803936117995, 54.4469685727006, 55.73807920181737, 56.936723021952304, 57.781481523761684, 58.38194499937214, 59.23926072215436, 59.58058881950707, 60.088585486135685, 60.5965821527643, 61.21759380814849, 61.64225619013916, 61.993858377378736, 62.256418452265436, 62.80665304398452, 63.090902864187946, 63.10916791287572, 63.5326887293234, 64.48132969554447, 64.72334159065743, 65.0601034258382, 65.2667267891186, 65.41969657187867, 65.57951574789666, 66.20851836208176, 66.45167182273771, 66.45852121599562, 66.59779221223987, 66.67199397253394, 66.90487334330301, 66.84322880398179, 66.94711126839347, 67.36149956049726, 67.25990022717154, 67.49277959794061, 67.55214100617587, 67.33638511855158, 67.50305368782749, 67.59437893126633, 67.31697850432083, 67.28158997248828, 67.50647838445644, 67.69483669904908], "train/end_acc": [30.020890649436637, 49.88755579401592, 54.39559812326625, 57.039463920821014, 58.50066781584265, 59.942465096633526, 60.8751241452528, 61.97787645977694, 62.668523613283256, 63.488167673146954, 63.84205299147251, 64.56923024235437, 64.97791070674323, 65.50417242205961, 65.90828662427653, 66.2850032534618, 66.66628614481901, 67.02587929085948, 67.40830374775967, 67.55099944063288, 67.83410769529333, 68.94485096861837, 69.10695327572232, 69.62636559778079, 69.64577221201155, 69.91289854907019, 70.13664539549538, 70.74053356773479, 71.03049121565314, 70.86039794974829, 70.9471569310152, 71.11610863137707, 71.39693375495155, 71.56360232422745, 71.54533727553968, 71.60013242160299, 71.89123163506433, 72.00424662381991, 72.00196349273394, 72.06474959759815, 72.16064110320895, 72.00424662381991, 71.88209911072045, 71.9894062717611, 72.0533339421683, 72.17662302081074], "train/span_acc": [19.95456569138917, 36.527814244454845, 41.04384753250608, 43.58268930010617, 45.11695338987888, 46.48226577928972, 47.62953914999029, 48.514252445804175, 49.126131576844486, 49.93435998127833, 50.357880797726004, 50.84532928458088, 51.36131691001039, 51.85447322458019, 52.35447893240791, 52.69466546421763, 53.07594835557484, 53.55997214580075, 53.83737257274626, 53.76773707462414, 54.144453703809404, 55.246064452790556, 55.446979988356034, 55.816847224283386, 55.99607301453213, 56.16388314935102, 56.39105469240516, 57.0246235687622, 57.369376362743864, 57.15818673729152, 57.28832520919189, 57.39449080468955, 57.66504183837715, 57.84084293199694, 57.69129784586582, 58.0588819507072, 58.12737588328634, 58.31459263233599, 58.37052934394228, 58.296327583648214, 58.44244797315038, 58.30203541136314, 58.280345666046415, 58.17874633272069, 58.310026370164046, 58.433315448806496], "train/em": [22.662359159351134, 41.364627450085045, 46.216281007774064, 49.05421294763639, 50.614733044897775, 52.13301521706869, 53.304261464171965, 54.31112227308531, 54.892179134465, 55.86821767371774, 56.165024714894, 56.76777132159043, 57.40019863240448, 57.7963218758205, 58.383086564915125, 58.71642370346694, 59.04861927647576, 59.57488099179214, 59.829450107877946, 59.87853742622632, 60.242696834438746, 61.34773228004886, 61.514400849324765, 61.91851505154168, 62.065777006586835, 62.3466021301613, 62.585189328645306, 63.14912270688021, 63.55095377801116, 63.25528830237788, 63.52127307389354, 63.585200744300735, 63.83292046712862, 64.0258450438932, 63.9699083322869, 64.28612198769392, 64.1765316955673, 64.52470918617793, 64.54525736595167, 64.43566707382504, 64.53612484160779, 64.46991404011462, 64.35004965810111, 64.36260687907397, 64.47333873674357, 64.75530542586102], "train/f1": [34.51665745792339, 55.96283280809833, 60.82320165645106, 63.63061596631879, 65.17485231431245, 66.64568001646025, 67.64169795101888, 68.73308628110989, 69.28069431706629, 70.21271447481666, 70.54703360121063, 71.19162133184672, 71.6819499810439, 72.13588895733164, 72.66614584868276, 72.900612658929, 73.22490967894906, 73.63541695638129, 74.01887599030012, 74.18845060303182, 74.43589645954991, 75.39396181643032, 75.61005385994422, 76.11364356166689, 76.19438467871556, 76.40991137212013, 76.60393875909631, 77.0916370135873, 77.37343348429118, 77.31739948326253, 77.46668390851623, 77.55081584829301, 77.740727156274, 77.84463712652615, 77.95601209237195, 78.08381782352954, 78.1411374778047, 78.3281561841061, 78.32106385611733, 78.30993029624211, 78.4085983439505, 78.3298353702733, 78.16075301294741, 78.26459775068054, 78.37941623824787, 78.57573145533343], "valid/loss": [3.4869210010568903, 2.9881206001760017, 2.786508514621827, 2.667641931250016, 2.603000451971037, 2.536243675878761, 2.4856419484060694, 2.4491564145261067, 2.450293586513427, 2.3857613187902285, 2.4012758238438034, 2.390632554663632, 2.3743403143392947, 2.3420211186581867, 2.362375890200232, 2.3368675526895553, 2.3347333815522786, 2.3056936638592953, 2.339246654078319, 2.3097513512542243, 2.299276483563138, 2.304530702688903, 2.289493453286566, 2.2624936852930535, 2.2946915707559383, 2.319118372803368, 2.3110386475335436, 2.2981555944483087, 2.3032014364562365, 2.3110423495042, 2.305257016798521, 2.310691530790934, 2.3049456558198727, 2.3115620616699633, 2.305059173856257, 2.315428913359916, 2.309111459377669, 2.304927429583858, 2.307107508002451, 2.313411759465843, 2.314569900763359, 2.317394887932838, 2.3121195779466195, 2.3131560251071734, 2.313246792176699, 2.3126730434483993], "valid/epoch_time": [91.11087465286255, 55.417484283447266, 55.66261267662048, 55.26226997375488, 55.44231724739075, 55.15640068054199, 55.226255655288696, 55.333287954330444, 55.09399700164795, 54.859079122543335, 54.51596140861511, 54.523744344711304, 54.57809925079346, 54.51284646987915, 54.53284311294556, 54.46537971496582, 54.57931470870972, 54.63344359397888, 54.45877027511597, 54.27037239074707, 54.39240479469299, 54.63644528388977, 54.53509068489075, 54.34073352813721, 54.60284972190857, 54.62445068359375, 54.627192735672, 54.77781081199646, 54.56430721282959, 54.37482237815857, 54.62762641906738, 54.46081566810608, 54.664390563964844, 54.65615272521973, 54.440516233444214, 54.355202436447144, 54.60070729255676, 54.28603959083557, 54.679141998291016, 54.64013314247131, 54.4134566783905, 54.36632299423218, 54.66620182991028, 54.603073835372925, 54.53094506263733, 54.339805603027344], "valid/start_acc": [50.350047303689685, 56.868495742667925, 58.84578997161778, 60.21759697256386, 60.91769157994324, 61.91106906338695, 62.1759697256386, 62.639545884579, 62.980132450331126, 63.53831598864711, 63.78429517502365, 63.7275307473983, 64.1438032166509, 64.22894985808892, 64.66414380321665, 64.94796594134343, 64.94796594134343, 65.29801324503312, 64.9763481551561, 65.1371807000946, 65.29801324503312, 65.50614947965941, 65.46830652790918, 65.8561967833491, 65.72374645222327, 65.69536423841059, 65.6480605487228, 65.65752128666036, 65.71428571428571, 65.45884578997162, 65.65752128666036, 65.94134342478714, 65.68590350047303, 65.71428571428571, 65.84673604541155, 65.80889309366131, 65.73320719016083, 65.81835383159887, 65.83727530747399, 65.78051087984863, 65.80889309366131, 65.80889309366131, 65.7899716177862, 65.77105014191108, 65.73320719016083, 65.83727530747399], "valid/end_acc": [54.427625354777675, 60.08514664143803, 62.47871333964049, 63.897824030274364, 64.83443708609272, 65.77105014191108, 66.16840113528855, 66.66982024597918, 67.17123935666982, 67.54020813623463, 67.76726584673605, 67.60643330179754, 68.36329233680227, 68.05108798486282, 68.29706717123936, 68.240302743614, 68.87417218543047, 68.6565752128666, 68.46736045411542, 68.87417218543047, 68.6565752128666, 68.84578997161779, 69.35666982024598, 69.47019867549669, 69.31882686849575, 69.120151371807, 69.06338694418164, 69.3282876064333, 69.19583727530747, 69.10122989593188, 69.10122989593188, 69.0728476821192, 69.35666982024598, 69.17691579943235, 69.47019867549669, 69.45127719962157, 69.15799432355723, 69.22421948912014, 69.31882686849575, 69.34720908230842, 69.3282876064333, 69.2620624408704, 69.29990539262063, 69.30936613055819, 69.21475875118259, 69.29044465468307], "valid/span_acc": [41.14474929044466, 47.757805108798486, 50.23651844843898, 52.015137180700094, 52.384105960264904, 53.03689687795648, 53.70860927152318, 54.645222327341536, 55.08041627246925, 55.53453169347209, 55.96972563859981, 55.30747398297067, 56.45222327341533, 56.14947965941344, 56.65089877010407, 56.688741721854306, 57.07663197729423, 57.19016083254494, 56.688741721854306, 57.05771050141911, 56.9441816461684, 57.05771050141911, 57.39829706717124, 57.89025543992432, 57.60643330179754, 57.63481551561022, 57.379375591296125, 57.672658467360456, 57.530747398297066, 57.360454115421, 57.58751182592242, 57.549668874172184, 57.70104068117313, 57.72942289498581, 57.88079470198676, 57.8240302743614, 57.58751182592242, 57.71996215704825, 57.74834437086093, 57.842951750236516, 57.81456953642384, 57.776726584673604, 57.757805108798486, 57.73888363292337, 57.682119205298015, 57.83349101229896], "valid/em": [51.333964049195835, 59.25260170293283, 62.21381267738884, 64.58845789971618, 65.17502365184484, 65.99810785241249, 67.20908230842005, 67.52128666035951, 68.34437086092716, 69.02554399243141, 69.46073793755913, 69.09176915799432, 69.70671712393566, 69.62157048249763, 70.02838221381268, 70.08514664143803, 70.7663197729423, 70.82308420056765, 70.52980132450331, 70.65279091769158, 70.64333017975402, 70.86092715231788, 71.14474929044465, 71.58940397350993, 71.46641438032167, 71.45695364238411, 71.14474929044465, 71.44749290444655, 71.62724692526017, 71.47587511825922, 71.40018921475875, 71.53263954588458, 71.60832544938505, 71.42857142857143, 71.65562913907284, 71.70293282876064, 71.52317880794702, 71.5042573320719, 71.53263954588458, 71.7123935666982, 71.6650898770104, 71.56102175969725, 71.61778618732261, 71.62724692526017, 71.57048249763481, 71.64616840113528], "valid/f1": [63.716542159677566, 70.2960210003769, 72.81607190395042, 74.53190422631644, 75.421681157565, 76.4135897143571, 76.7579247718018, 77.03410374591463, 77.60157205795711, 78.21744573295402, 78.26873914903332, 78.43110519558583, 78.60525536373322, 78.65916247196188, 78.89507681858818, 79.07286072680064, 79.51470974793064, 79.54524082213555, 79.5191310520532, 79.51313633887004, 79.46815034744174, 79.82266775185798, 80.02195952906334, 80.20059574109268, 80.1112083954039, 79.94827592836825, 79.95972844746196, 80.14069016501246, 80.28698213417988, 80.13359507471047, 80.0382166591011, 80.25549700005551, 80.20409907785661, 80.07606205259867, 80.27331973669013, 80.30594840422914, 80.11729620028403, 80.08637267538136, 80.16562101733193, 80.187354927146, 80.18693311368027, 80.15784949751684, 80.14505358124059, 80.15866527496513, 80.10717593451717, 80.15877032876196], "best_step": 98568 }, "inferency_latency": { "cpu": { "max_token_count_per_time": { "100": 100, "200": 199, "300": 299, "400": 396, "500": 514, "600": 613, "700": 691, "800": 783, "900": 896, "1000": 980, "1100": 999, "1200": 999, "1300": 999, "1400": 999, "1500": 999 } }, "gpu": { } } } ================================================ FILE: reports/summary/drqa.json ================================================ { "config": { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json" }, "iterator": { "batch_size": 32 }, "token": { "names": ["frequent_glove", "exact_match", "linguistic"], "types": ["frequent_word", "exact_match", "linguistic"], "tokenizer": { "word": { "name": "spacy_en", "split_with_regex": true } }, "frequent_glove": { "vocab": { "frequent_count": 1000 }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "data/glove.840B.300d.txt", "dropout": 0.3 } }, "exact_match": { "indexer": { "lower": true, "lemma": true }, "embedding": { "type": "sparse" } }, "linguistic": { "indexer": { "pos_tag": true, "ner": true }, "embedding": { "type": "sparse" } } }, "model": { "name": "drqa", "drqa": { "aligned_query_embedding": true, "answer_maxlen": 15, "model_dim": 128, "dropout": 0.3 } }, "trainer": { "log_dir": "logs/squad_drqa_paper", "num_epochs": 50, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.003, "adamax": { "betas": [0.9, 0.999], "eps": 1e-08, "weight_decay": 0 }, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 21, "use_gpu": true, "gpu_num": 1 }, "training_logs": { "early_stopping_count": 10, "early_stopping": true, "elapsed_time": ["13:23:56"], "train_dataset": { "name": "squad", "total_count": 87599, "HasAns_count": 87599, "NoAns_count": 0, "context_maxlen": 841, "question_maxlen": 60 }, "valid_dataset": { "name": "squad", "total_count": 10570, "HasAns_count": 10570, "NoAns_count": 0, "context_maxlen": 706, "question_maxlen": 34 } }, "metrics": { "best_epoch": 17, "best_global_step": 0, "best": { "train/loss": 1.61940172236274, "train/epoch_time": 5187.572727203369, "train/start_acc": 72.40836082603683, "train/end_acc": 76.46662633135081, "train/span_acc": 63.38656833982123, "train/em": 69.1971369536182, "train/f1": 82.23221248606394, "valid/loss": 8.654243107648774, "valid/epoch_time": 198.70182490348816, "valid/start_acc": 63.40586565752129, "valid/end_acc": 66.59413434247871, "valid/span_acc": 55.16556291390729, "valid/em": 68.31598864711448, "valid/f1": 77.4926689298344 }, "best_score": 77.4926689298344, "train/loss": [4.60658250959186, 3.504659719498511, 3.123943943190174, 2.8921950323639165, 2.711123498753965, 2.5738340889214597, 2.4436522412247865, 2.33488081083235, 2.2465767058645225, 2.1464829364556133, 2.0868621060367567, 2.0080187161139453, 1.9401038473674728, 1.8752335216156142, 1.8369758235572289, 1.6853253674646465, 1.61940172236274, 1.5688945004067516, 1.5298081311955776, 1.4967625302346281, 1.4212235773541442, 1.3916269571699305, 1.3672968858650254, 1.3256880727299292, 1.3106557530173426, 1.298210813985679, 1.2784150778115275], "train/epoch_time": [8640.480652332306, 3039.2762203216553, 2967.1172726154327, 3045.9760546684265, 2952.516592979431, 2966.4932758808136, 3048.574713230133, 2953.297121286392, 3017.3895716667175, 3028.043808698654, 4921.801164865494, 5170.423162698746, 5179.85888671875, 5174.736956357956, 5181.168378829956, 5196.217725515366, 5187.572727203369, 5615.094452857971, 5767.616916179657, 5789.34668636322, 5759.392116069794, 5751.3127381801605, 5734.911474227905, 5749.742757558823, 5754.053142309189, 5592.814163446426, 5202.744418144226], "train/start_acc": [39.44223107569721, 50.45719699996575, 54.70496238541536, 57.29859929907876, 59.44131782326282, 61.07033185310335, 62.621719426020846, 63.77812532106531, 64.57607963561227, 65.93910889393715, 66.69140058676469, 67.4471169762212, 68.48137535816619, 69.22681765773582, 69.52590782999806, 71.59214146280209, 72.40836082603683, 73.06476101325357, 73.58988116302697, 74.10244409182754, 75.01113026404411, 75.26569938012992, 75.62072626399845, 76.293108368817, 76.37415952236897, 76.5876322789073, 76.7622918069841], "train/end_acc": [43.09638237879428, 54.65473350152399, 58.97213438509572, 61.49956049726595, 63.66625189785272, 65.1308804895033, 66.66057831710408, 67.90945102113038, 69.06357378508888, 70.21313028687543, 70.99852738044954, 71.73027089350335, 72.55105651891003, 73.44261920798182, 73.85586593454263, 75.7280334250391, 76.46662633135081, 77.11731869085264, 77.69380929006039, 77.98262537243576, 78.9814952225482, 79.63903697530793, 79.72122969440291, 80.35251543967397, 80.52717496775077, 80.53402436100869, 80.8913343759632], "train/span_acc": [30.878206372218862, 41.4959074875284, 45.624950056507494, 48.13411111998995, 50.280254340802976, 51.83849130697839, 53.28143015331225, 54.56340825808514, 55.40017580109362, 56.684437036952474, 57.6136713889428, 58.300893845820156, 59.22670350118152, 60.088585486135685, 60.54178700670099, 62.57948150093038, 63.38656833982123, 64.19936300642702, 64.65256452699232, 65.17768467676572, 66.23363280402744, 66.71651502871038, 67.00761424217171, 67.85693900615304, 67.89118597244261, 67.9471226840489, 68.18913457916186], "train/em": [34.93989657416181, 46.63637712759278, 51.12843753924132, 53.81454126188655, 56.06913320928321, 57.74380986084316, 59.21300471466569, 60.60114841493624, 61.53723216018448, 62.76783981552301, 63.64912841470793, 64.38657975547666, 65.26558522357561, 66.06011484149363, 66.52587358303177, 68.46881813719335, 69.1971369536182, 70.08527494606103, 70.56929873628694, 71.01336773250836, 71.99739723056199, 72.47000536535805, 72.61840888594618, 73.30106508065161, 73.46202582221258, 73.49513122295916, 73.92321830157879], "train/f1": [48.50907262116509, 60.765045197662275, 65.33317809003307, 67.99144869099675, 70.14312976671866, 71.8124061884322, 73.2439380277194, 74.42822285361672, 75.44229199600885, 76.48428687371036, 77.21201568350556, 77.93745800998794, 78.80769543744253, 79.51781682786827, 79.83912968505147, 81.55126317962365, 82.23221248606394, 82.87567185774346, 83.29790277374553, 83.62127823426802, 84.45655843981444, 84.8716303752159, 84.94624146974907, 85.3940965811925, 85.57905551986542, 85.70510085888766, 85.93909958584186], "valid/loss": [9.00497546440885, 8.884206907266577, 8.810493067312096, 8.787639697152683, 8.777150423505155, 8.735577976595598, 8.725793743421663, 8.71934508557046, 8.711208483243636, 8.709731617722987, 8.695330253900718, 8.690546114999362, 8.671222137900637, 8.675527650424002, 8.692196104101544, 8.640968986868499, 8.654243107648774, 8.646484069593724, 8.658190711387334, 8.64464476749616, 8.63754986276079, 8.635264432682371, 8.639671476946136, 8.629355259172145, 8.6297872995682, 8.63080207674885, 8.630225940773494], "valid/epoch_time": [849.218492269516, 127.3110020160675, 126.12082743644714, 126.01026105880737, 125.38758969306946, 127.1003749370575, 124.92033886909485, 127.7095730304718, 83.75935649871826, 127.01851630210876, 200.48730492591858, 189.13106560707092, 200.52873182296753, 199.95279550552368, 199.04243564605713, 192.7031126022339, 198.70182490348816, 216.21145462989807, 171.93388772010803, 215.22909307479858, 218.55399131774902, 216.11700892448425, 212.8858299255371, 217.22716164588928, 215.74384808540344, 199.73770761489868, 188.1731538772583], "valid/start_acc": [53.69914853358562, 57.70104068117313, 59.744560075685904, 61.22043519394513, 62.05298013245033, 62.157048249763484, 62.5922421948912, 62.28003784295175, 62.8949858088931, 62.47871333964049, 63.18826868495743, 63.19772942289499, 62.771996215704824, 62.686849574266795, 61.88268684957427, 63.12204351939451, 63.40586565752129, 62.847682119205295, 62.35572374645222, 62.71523178807947, 62.82876064333018, 62.686849574266795, 62.79091769157994, 62.79091769157994, 62.75307473982971, 62.81929990539262, 62.52601702932829], "valid/end_acc": [57.161778618732264, 61.68401135288553, 63.973509933774835, 64.38978240302744, 65.28855250709556, 65.77105014191108, 66.02649006622516, 66.02649006622516, 66.19678334910122, 65.26963103122044, 66.12109744560075, 66.66982024597918, 66.30085146641439, 66.13055818353831, 65.55345316934721, 66.46168401135289, 66.59413434247871, 66.30085146641439, 65.77105014191108, 66.24408703878902, 66.26300851466415, 66.05487228003784, 65.92242194891202, 65.94134342478714, 66.05487228003784, 66.0170293282876, 65.89403973509934], "valid/span_acc": [45.2317880794702, 50.00946073793756, 51.73131504257332, 53.11258278145695, 53.964049195837276, 53.85052034058656, 54.276253547776726, 54.418164616840116, 54.55061494796594, 53.64238410596027, 54.63576158940398, 54.91958372753075, 54.7682119205298, 54.31409649952696, 53.59508041627247, 54.966887417218544, 55.16556291390729, 54.25733207190161, 53.57615894039735, 54.38032166508988, 54.33301797540208, 54.11542100283822, 54.02081362346263, 54.03027436140019, 54.15326395458846, 54.13434247871334, 53.77483443708609], "valid/em": [56.14001892147588, 61.66508987701041, 63.80321665089877, 64.99526963103122, 66.21570482497634, 66.25354777672659, 67.20908230842005, 67.02932828760643, 67.4550614947966, 67.16177861873226, 67.70104068117313, 68.10785241248817, 67.74834437086092, 67.81456953642385, 67.16177861873226, 68.18353831598864, 68.31598864711448, 67.67265846736045, 67.30368968779565, 67.92809839167455, 67.97540208136235, 67.78618732261117, 67.9848628192999, 67.97540208136235, 67.81456953642385, 67.78618732261117, 67.66319772942289], "valid/f1": [66.89296464147222, 71.42020468405755, 73.78136022851302, 74.3754233617323, 75.25886347567096, 75.95991010879098, 76.31073571334775, 76.22517118040842, 76.72587837225083, 76.59299099682524, 76.85032903593398, 77.15654402217363, 76.78704335228713, 76.91471910369974, 76.5554205523628, 77.12696613053616, 77.4926689298344, 77.24874236993564, 77.00283628952356, 77.21012521283004, 77.24411498477711, 77.25184051667006, 77.35801026562912, 77.33955319833585, 77.12135440028722, 77.1612906473848, 77.13617405192754], "best_step": 46546 }, "inferency_latency": { "cpu": { "max_token_count_per_time": { "100": 78, "200": 155, "300": 235, "400": 335, "500": 420, "600": 491, "700": 555, "800": 630, "900": 744, "1000": 829, "1100": 861, "1200": 982, "1300": 999, "1400": 999, "1500": 999 } }, "gpu": { } } } ================================================ FILE: reports/summary/qanet.json ================================================ { "config": { "data_reader": { "dataset": "squad", "train_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json", "valid_file_path": "https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json", "squad": { "context_max_length": 400 } }, "iterator": { "batch_size": 24 }, "token": { "names": ["char", "glove"], "types": ["char", "word"], "tokenizer": { "char": { "name": "character" }, "word": { "name": "treebank_en", "split_with_regex": true } }, "char": { "vocab": { "max_vocab_size": 260, "start_token": "", "end_token": "" }, "indexer": { "insert_char_start": true, "insert_char_end": true }, "embedding": { "embed_dim": 64, "kernel_sizes": [5], "num_filter": 200, "activation": "relu", "dropout": 0.05 } }, "glove": { "vocab": { "pretrained_path": "data/glove.840B.vocab.txt", "pretrained_token": "intersect" }, "indexer": { "lowercase": false }, "embedding": { "embed_dim": 300, "pretrained_path": "data/glove.840B.300d.txt", "trainable": false, "dropout": 0.1 } } }, "model": { "name": "qanet", "qanet": { "answer_maxlen": 30, "model_dim": 128, "kernel_size_in_embedding": 7, "num_head_in_embedding": 8, "num_conv_block_in_embedding": 4, "num_embedding_encoder_block": 1, "kernel_size_in_modeling": 5, "num_head_in_modeling": 8, "num_conv_block_in_modeling": 2, "num_modeling_encoder_block": 7, "layer_dropout": 0.9, "dropout": 0.1 } }, "trainer": { "log_dir": "logs/squad_qanet", "num_epochs": 100, "early_stopping_threshold": 10, "metric_key": "f1", "verbose_step_count": 100, "eval_and_save_step_count": "epoch" }, "optimizer": { "op_type": "adamax", "learning_rate": 0.002, "lr_scheduler_type": "reduce_on_plateau", "reduce_on_plateau": { "factor": 0.5, "mode": "max", "patience": 2 } }, "seed_num": 2, "use_gpu": true, "gpu_num": 4 }, "training_logs": { "early_stopping_count": 10, "early_stopping": true, "elapsed_time": ["18:50:02"], "train_dataset": { "name": "squad", "total_count": 87338, "HasAns_count": 87338, "NoAns_count": 0, "context_maxlen": 400, "question_maxlen": 60 }, "valid_dataset": { "name": "squad", "total_count": 10570, "HasAns_count": 10570, "NoAns_count": 0, "context_maxlen": 708, "question_maxlen": 36 } }, "metrics": { "best_epoch": 55, "best_global_step": 0, "best": { "train/loss": 1.8296265312521667, "train/epoch_time": 2923.537817955017, "train/start_acc": 70.34967597151297, "train/end_acc": 74.25175753967345, "train/span_acc": 60.74904394421672, "train/em": 66.74391260174203, "train/f1": 80.28687106237878, "valid/loss": 3.077031190027726, "valid/epoch_time": 174.152925491333, "valid/start_acc": 62.63008514664144, "valid/end_acc": 66.26300851466415, "valid/span_acc": 54.0964995269631, "valid/em": 67.83349101229896, "valid/f1": 77.13077790254637 }, "best_score": 77.13077790254637, "train/loss": [15.488234868940417, 7.086183975031088, 6.088968063055814, 5.210119113162324, 4.451079359748861, 4.088897859591704, 3.874833091012724, 3.7179631613768063, 3.5771984939719292, 3.460189548429552, 3.3689059971125572, 3.2848737781846915, 3.203482925433379, 3.150210040414726, 3.078502645335355, 3.0158281381968615, 2.989606374305683, 2.941913167166186, 2.9079444455903967, 2.82684417452131, 2.8017081719669665, 2.7582939096368277, 2.714333850800336, 2.506440755905031, 2.4188369879928917, 2.383003100703706, 2.3444873504422525, 2.3108870263774315, 2.287744827568531, 2.167220318366538, 2.1375067864964294, 2.107174483252751, 2.0835232992584887, 2.066835755732033, 2.003879681606214, 1.9922781422570512, 1.966677693072911, 1.9619674635703093, 1.9436703464323348, 1.9370005422568584, 1.9062095401542527, 1.90440199055842, 1.8926173113122746, 1.8847115559401093, 1.8826755651733378, 1.8712462813153372, 1.8606046057173184, 1.8536939557273309, 1.847323245546975, 1.8556774545993124, 1.8493036387222155, 1.8427186589810876, 1.8316330748108718, 1.8370130183768796, 1.8296265312521667, 1.8304680805612397, 1.831867292195886, 1.8246009549269309, 1.823964442541966, 1.8222635420632887, 1.8235378652483551, 1.820832459735019, 1.8225761726089231, 1.8155118651114976, 1.823007430938574], "train/epoch_time": [4296.78471827507, 3628.3298971652985, 3696.4495577812195, 3715.0882000923157, 3701.7543013095856, 3697.767979621887, 3716.3892545700073, 3706.149761199951, 3705.2665474414825, 3721.388156414032, 3708.758844614029, 3716.7224357128143, 3719.79412984848, 3715.805262565613, 3730.085188627243, 3735.406765937805, 3736.960794210434, 3738.1067128181458, 3721.5864198207855, 3727.7481503486633, 3725.5567350387573, 3730.4315271377563, 3736.385180950165, 3728.862630367279, 3731.2970473766327, 3715.3351254463196, 3707.4656279087067, 3702.9816896915436, 3700.1895813941956, 3703.805330991745, 3695.1101365089417, 3697.978477716446, 3701.3173661231995, 3687.6701006889343, 3610.503224134445, 3591.565302848816, 3604.3066127300262, 3602.3776235580444, 3601.5347332954407, 3613.2096066474915, 3450.535410642624, 3397.07058262825, 3396.484432220459, 3384.921397447586, 3308.4173386096954, 3345.625899553299, 3166.124237060547, 3147.206519126892, 3254.1261310577393, 3174.810401201248, 3073.9619607925415, 3039.8876259326935, 2974.9580183029175, 3024.4925615787506, 2923.537817955017, 3019.033987045288, 3017.864396095276, 3088.1552584171295, 3004.0221095085144, 3011.139225959778, 2949.2352333068848, 2803.4796018600464, 2785.6616218090057, 2788.4025688171387, 2775.26225733757], "train/start_acc": [3.327303121207264, 13.663010373491494, 21.929744212141337, 32.393688886853376, 41.41152762829467, 45.47619592846184, 47.70317616615906, 49.283244406787425, 50.90224186493852, 51.838833039455906, 53.069683299365686, 53.82651308708695, 54.61082232247132, 55.242849618722666, 56.00883922233163, 56.64888135748471, 57.102292243925895, 57.48929446518125, 58.03315853351348, 58.660605921820974, 58.943415237353726, 59.399116077766834, 59.72886944972406, 62.491698916851774, 63.3137923927729, 63.8187272435824, 64.28473287686917, 64.80340745151022, 64.76676818795943, 66.21974398314593, 66.63079072110651, 67.00863312647415, 67.22503377682109, 67.47807369071882, 68.09865121711054, 68.29215232773821, 68.72037372048821, 68.79823215553367, 68.83945132702833, 68.90128008427031, 69.46346378437794, 69.32492156907647, 69.53903226545147, 69.70276397444411, 69.76344775470012, 69.9603837962857, 69.95809384231377, 69.94549909546818, 70.10923080446084, 70.03595227735923, 69.8836703382262, 70.04740204721885, 70.25922278962193, 70.26151274359385, 70.34967597151297, 70.5168426114635, 70.33937117863931, 70.23975818086056, 70.41150472875495, 70.59126611555108, 70.38173532711993, 70.54432205912661, 70.34624104055509, 70.53745219721084, 70.52600242735122], "train/end_acc": [3.439510865831597, 14.418695184226797, 23.245322769012343, 34.78669078751517, 44.6174631889899, 48.86876273786897, 51.252604822643065, 53.04105887471662, 54.55128351920126, 55.98479470562642, 57.22022487348004, 57.76981382674208, 58.612516888410546, 59.539948247040236, 60.12617646385308, 61.13375621150015, 61.27115344981566, 61.781813185554974, 62.13561107421741, 63.091666857496165, 63.23364400375552, 63.651560603631864, 64.17138015525887, 66.35714122146145, 67.54219240193272, 67.78378254597082, 68.37115573976963, 68.79479722457579, 69.0695917012068, 70.09434610364332, 70.7435480546841, 71.17978428633585, 71.3675605120337, 71.43053424626164, 72.17934919508117, 72.3808651446106, 72.6865739998626, 72.90869953513935, 72.89037990336394, 73.06556138221622, 73.36096544459457, 73.4514186264856, 73.51782729167144, 73.58996084178708, 73.68842886257987, 73.90368453594083, 74.0330669353546, 74.00673246467746, 74.06627126794751, 73.93917882250567, 74.05825642904577, 74.2254230689963, 74.21282832215073, 74.20481348324898, 74.25175753967345, 74.23916279282787, 74.27580205637867, 74.42235911058188, 74.40060454784859, 74.42121413359591, 74.21626325310861, 74.4338088804415, 74.29984657308388, 74.66394925461998, 74.43037394948361], "train/span_acc": [0.8896471180929263, 7.191600448830979, 14.019098216125856, 23.41706931690673, 31.412443609883443, 35.280175868465044, 37.36632393688887, 39.001351072843434, 40.58370926744372, 41.56151961345577, 42.76718037967437, 43.44615173235018, 44.12855801598388, 44.86019831001397, 45.47047104353202, 46.36927797751265, 46.70704618837161, 47.13984748906547, 47.71691588999061, 48.31802880762097, 48.573358675490624, 49.00387002221255, 49.402322013327534, 52.10790263115712, 53.18647095193386, 53.45439556664911, 54.13336691932492, 54.76882914653415, 54.82951292679017, 56.165701069408506, 56.80688818154755, 57.106872151869744, 57.469829856419885, 57.54654331447938, 58.23238452907096, 58.55984794705626, 58.97661956994664, 59.101422061416564, 59.112871831276195, 59.21935469097071, 59.772378575190636, 59.67047562343997, 59.88458631981497, 59.96702466280428, 60.024273512102404, 60.26700863312647, 60.37463646980696, 60.41356568732969, 60.501728915248805, 60.38608623966658, 60.284183287915916, 60.471959513613776, 60.72385445052554, 60.66775057821338, 60.74904394421672, 60.82575740227622, 60.71354965765188, 60.77652339187982, 60.82232247131833, 61.06276763837047, 60.741029105314986, 60.988344134282904, 60.83720717213584, 61.04673796056699, 60.98032929538116], "train/em": [1.0342583819449993, 7.986392538727611, 15.882601399559356, 26.695510222719438, 35.6248358999532, 39.97762531535748, 42.27331362230162, 44.233381659607986, 45.76193792166577, 47.050765419696575, 48.255117067546436, 49.055354513179374, 49.74942636331465, 50.68322697747691, 51.24716035571182, 52.03940684254386, 52.4823342732223, 52.89900569641206, 53.572529366773594, 54.08623386111714, 54.540576947225425, 54.892179134465, 55.42300711195333, 58.0349090743045, 59.32716126896426, 59.49725453486912, 60.13653123894108, 60.75069350106737, 60.8990970216555, 62.209614265003026, 62.8397584447311, 63.24158951586205, 63.488167673146954, 63.67652598773959, 64.28498042215094, 64.52014292400598, 65.0601034258382, 65.13658831721823, 65.27015148574755, 65.25987739586068, 65.76444936586034, 65.7678740624893, 66.00760282651629, 65.95623237708193, 66.01559378531718, 66.2998436055206, 66.40144293884633, 66.48820192011324, 66.5475633283485, 66.40030137330335, 66.36719597255676, 66.47792783022638, 66.73478007739814, 66.7541866916289, 66.74391260174203, 66.79756618226236, 66.80898183769222, 66.86948481147046, 66.87861733581434, 67.064692519321, 66.77930113357458, 66.99163232456992, 66.86263541821253, 66.98249980022602, 66.9688010137102], "train/f1": [7.150047734105509, 16.63170412613727, 26.19659288961383, 39.08138133061436, 49.84063113001966, 54.61454535767007, 57.143186253227746, 59.10524134986093, 60.71428109373346, 62.059277261947244, 63.21982678680412, 64.07990285325717, 64.87698501573175, 65.74865706973803, 66.32128910373044, 67.12752163349023, 67.50868689352882, 67.89652046625697, 68.41920511572731, 69.18789151532724, 69.42894162261885, 69.89257706785226, 70.3228442925677, 72.67823765403614, 73.82454766784191, 74.04671799090839, 74.6219246838363, 74.91264495078597, 75.18874316384371, 76.34421724432246, 76.88907106368313, 77.30056130121899, 77.50318492937623, 77.6535877815243, 78.33743091127086, 78.38863415983027, 78.81242449181157, 78.86354520575438, 78.96835118472518, 78.97697460642281, 79.39019526946112, 79.48265094902965, 79.58841871505763, 79.64187998228611, 79.62459297787933, 79.9101032860282, 80.02879371097904, 80.01883954391293, 80.09166524686128, 79.9815621415061, 80.03474289505635, 80.12950977457226, 80.23290285604988, 80.26405821264099, 80.28687106237878, 80.22713019725572, 80.28221497366124, 80.34851973450617, 80.40295881187913, 80.40065827498132, 80.34280037019676, 80.43921475619794, 80.32658524341801, 80.50858909402363, 80.39468830408457], "valid/loss": [8.255948972810152, 5.915341379420828, 5.165603543625397, 4.09425747637846, 3.4162629902227666, 3.2846769813507324, 3.205561557324295, 3.1158123729991263, 3.128326172055571, 3.076131648217199, 2.9896649645299327, 2.7874708310817105, 2.921256586807926, 3.0315158992938174, 2.781769103338929, 2.7369340300019367, 2.659010061466234, 2.908389812964701, 3.0148692762229987, 2.9282795726036537, 2.7956396157509076, 2.9713704398159537, 3.062869045537075, 2.773363924756342, 3.011526436492159, 2.9336592405020787, 2.905980131523409, 2.8350266742598174, 2.868667747158042, 2.945699503497472, 2.918121996515192, 3.015675984542656, 2.9449547623831127, 2.9032093983929173, 2.974846825848361, 2.950968151595317, 2.8892771217828437, 2.895898574063567, 3.102883370825493, 2.9213964879647945, 3.0979490190947137, 3.0246552370843434, 3.019246398456513, 3.037102747936638, 3.09164640598016, 3.042913777217303, 3.0085863671064916, 2.9791532334556927, 3.084758754625342, 3.030128677010266, 3.010667343393745, 3.1367937095311222, 3.029783969968895, 3.0280854511423176, 3.077031190027726, 3.0702189928820345, 3.063274392870819, 3.0583306350945887, 3.043750105125834, 3.0566056808646844, 3.059594034202515, 3.0572560739084707, 3.0632660667371856, 3.06162472620032, 3.0489957079865766], "valid/epoch_time": [287.46108889579773, 227.90340781211853, 222.4364550113678, 216.4619071483612, 222.15947246551514, 216.29195261001587, 214.69099068641663, 221.3820288181305, 216.5057213306427, 216.65303802490234, 222.42914581298828, 216.1564326286316, 216.6853802204132, 217.8182852268219, 224.5480830669403, 218.9715609550476, 219.65285968780518, 223.64484643936157, 217.82541251182556, 218.23222827911377, 224.46948266029358, 218.5539779663086, 218.37477159500122, 223.67253923416138, 218.8413109779358, 215.68055748939514, 222.2364730834961, 217.2599310874939, 217.65814018249512, 217.04646611213684, 221.7856466770172, 215.99438333511353, 215.92943477630615, 221.5010108947754, 209.42291712760925, 209.55638647079468, 218.70353651046753, 209.24770426750183, 209.31441521644592, 208.81332969665527, 201.30897331237793, 199.84483170509338, 203.9441864490509, 199.94291138648987, 190.84432768821716, 192.7756884098053, 187.47333455085754, 184.5499279499054, 192.43693470954895, 198.6127965450287, 176.0017011165619, 184.59607195854187, 179.56342768669128, 166.98182225227356, 174.152925491333, 185.67984318733215, 175.0498013496399, 180.09878587722778, 177.73906755447388, 172.00069618225098, 174.74165105819702, 167.67725229263306, 173.81641054153442, 164.90295362472534, 165.88444900512695], "valid/start_acc": [8.429517502365185, 23.273415326395458, 31.28666035950804, 48.99716177861873, 53.746452223273415, 55.808893093661304, 55.96026490066225, 53.7275307473983, 58.48628192999054, 58.675496688741724, 60.047303689687794, 60.61494796594134, 61.248817407757805, 61.343424787133394, 62.35572374645222, 61.788079470198674, 62.57332071901608, 62.52601702932829, 61.98675496688742, 62.384105960264904, 61.44749290444655, 61.28666035950804, 62.11920529801324, 62.56385998107852, 62.63008514664144, 62.42194891201514, 62.93282876064333, 62.70577105014191, 62.327341532639544, 62.44087038789026, 62.58278145695364, 62.57332071901608, 61.66508987701041, 62.39356669820246, 62.75307473982971, 62.73415326395459, 62.48817407757805, 62.47871333964049, 62.639545884579, 62.63008514664144, 62.544938505203405, 62.25165562913907, 62.42194891201514, 61.75023651844844, 62.469252601702934, 62.620624408703875, 62.28003784295175, 62.4314096499527, 62.60170293282876, 62.40302743614002, 62.57332071901608, 62.35572374645222, 62.42194891201514, 62.469252601702934, 62.63008514664144, 62.3368022705771, 62.535477767265846, 62.223273415326396, 62.36518448438978, 62.58278145695364, 62.47871333964049, 62.40302743614002, 62.50709555345317, 62.49763481551561, 62.49763481551561], "valid/end_acc": [9.044465468306528, 24.88174077578051, 33.140964995269634, 52.58278145695364, 57.29422894985809, 58.968779564806056, 60.22705771050142, 61.485335856196784, 62.37464522232734, 63.074739829706715, 63.80321665089877, 63.38694418164617, 64.5600756859035, 65.33585619678335, 65.19394512771996, 64.22894985808892, 65.97918637653737, 65.29801324503312, 64.69252601702932, 65.9508041627247, 64.66414380321665, 65.3926206244087, 65.67644276253547, 65.89403973509934, 65.55345316934721, 66.08325449385052, 65.9508041627247, 65.21286660359507, 65.3263954588458, 65.47776726584674, 66.12109744560075, 66.10217596972564, 65.57237464522233, 66.0170293282876, 65.96972563859981, 65.91296121097446, 66.0643330179754, 65.97918637653737, 66.09271523178808, 66.2251655629139, 66.27246925260171, 65.65752128666036, 66.41438032166509, 65.57237464522233, 65.99810785241249, 66.04541154210028, 66.20624408703878, 65.98864711447493, 66.26300851466415, 66.1116367076632, 66.23462630085146, 66.04541154210028, 66.14947965941343, 66.31031220435194, 66.26300851466415, 66.2251655629139, 66.15894039735099, 66.02649006622516, 66.02649006622516, 66.2251655629139, 66.19678334910122, 66.14001892147587, 66.23462630085146, 66.1116367076632, 66.16840113528855], "valid/span_acc": [3.6896877956480605, 17.95648060548723, 24.720908230842007, 41.248817407757805, 44.32355723746452, 46.859035004730366, 46.84957426679281, 45.47776726584674, 49.14853358561968, 49.422894985808895, 51.333964049195835, 50.87038789025544, 52.51655629139073, 52.989593188268685, 52.93282876064333, 51.97729422894986, 54.26679280983917, 53.50993377483444, 52.4314096499527, 53.226111636707664, 51.854304635761586, 52.48817407757805, 53.32071901608325, 53.528855250709555, 53.17880794701987, 53.36802270577105, 53.69914853358562, 52.94228949858089, 53.226111636707664, 53.2639545884579, 53.897824030274364, 54.40870387890256, 52.980132450331126, 53.62346263008514, 53.85052034058656, 53.86944181646168, 53.841059602649004, 53.614001892147584, 53.888363292336805, 54.03027436140019, 53.99243140964995, 53.53831598864711, 54.049195837275306, 53.140964995269634, 54.03027436140019, 53.973509933774835, 53.81267738883633, 53.661305581835386, 54.049195837275306, 53.85052034058656, 54.07757805108798, 53.92620624408704, 53.964049195837276, 53.95458845789972, 54.0964995269631, 53.888363292336805, 54.02081362346263, 53.64238410596027, 53.77483443708609, 54.07757805108798, 53.92620624408704, 53.897824030274364, 53.973509933774835, 53.94512771996216, 53.982970671712394], "valid/em": [4.370860927152318, 21.97729422894986, 30.321665089877012, 51.551561021759696, 56.177861873226114, 58.893093661305585, 60.24597918637654, 60.586565752128664, 61.82592242194891, 62.88552507095554, 63.73699148533586, 64.11542100283822, 65.49668874172185, 65.80889309366131, 66.00756859035005, 65.0236518448439, 66.92526017029329, 66.27246925260171, 65.71428571428571, 66.49006622516556, 64.78713339640493, 65.7899716177862, 66.50898770104068, 66.82119205298014, 66.47114474929045, 67.01040681173131, 67.13339640491958, 66.03595080416272, 66.32923368022706, 66.49006622516556, 67.55912961210974, 67.65373699148533, 66.53736991485336, 67.18070009460737, 67.4077578051088, 67.24692526017029, 67.62535477767265, 67.11447492904446, 67.4077578051088, 67.33207190160833, 67.41721854304636, 66.84011352885526, 67.67265846736045, 66.84957426679281, 67.46452223273415, 67.6158940397351, 67.49290444654683, 67.34153263954589, 67.7294228949858, 67.54966887417218, 67.67265846736045, 67.59697256385998, 67.63481551561021, 67.63481551561021, 67.83349101229896, 67.55912961210974, 67.71996215704824, 67.41721854304636, 67.51182592242195, 67.76726584673605, 67.57805108798486, 67.57805108798486, 67.67265846736045, 67.63481551561021, 67.71996215704824], "valid/f1": [11.266146019810424, 30.772402372897893, 40.10075805725353, 62.220128029590626, 67.9484941604292, 69.82032376677888, 71.54927060569607, 72.20567648137283, 73.21076038103618, 73.71064584987039, 73.93403603109759, 74.416882277429, 75.3439026970129, 75.62636078290245, 76.0333251040766, 75.18245755711935, 76.19728182025369, 76.00926386634342, 76.03215827514094, 76.37251267962549, 75.56392096319695, 75.79021151369639, 76.13802079198902, 76.65071732165994, 76.40813974097514, 76.80525713720175, 76.6778873725336, 76.17081276576117, 75.96335697004196, 76.27771175633562, 76.9036583840013, 76.69783533879072, 76.18528440702401, 76.60309722540178, 76.6982441344683, 76.58797384373058, 77.01409520956456, 76.8748504664614, 76.79104822097199, 76.86368945830043, 76.81899070543213, 76.3542346457786, 77.0531810950532, 76.42858371934507, 76.71813045388687, 77.01527290444345, 76.85797666378635, 76.88914052002201, 77.06747114046203, 76.85733929273742, 76.9899426388657, 76.8706795549681, 77.02189951127839, 77.08313535436119, 77.13077790254637, 76.94931769174534, 77.05748374460357, 76.87845291687933, 76.86475449258185, 77.02177711332001, 76.92178675214353, 76.9404529198229, 76.99248635694408, 76.93969188857635, 76.9873356935659], "best_step": 200200 }, "inferency_latency": { "cpu": { "max_token_count_per_time": { "100": 71, "200": 140, "300": 186, "400": 220, "500": 252, "600": 276, "700": 309, "800": 335, "900": 359, "1000": 384, "1100": 410, "1200": 438, "1300": 466, "1400": 491, "1500": 492 } }, "gpu": { } } } ================================================ FILE: requirements.txt ================================================ # Python Package pip>=20.0.0 # Backends numpy>=1.15.0 torch>=1.3.1 # Tokenizer konlpy nltk spacy==2.1.8 https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.1.0/en_core_web_sm-2.1.0.tar.gz # BERT transformers==2.11.0 # WikiSQL babel records # Utils h5py jsbeautifier msgpack overrides requests gensim tqdm tensorboardX PyYAML==5.3.1 # Test, CI pytest>=3.6 pytest-cov # Metrics pycm seqeval scikit-learn ================================================ FILE: script/convert_checkpoint_to_bert_model.py ================================================ import sys import os sys.path.append(os.path.join(os.path.dirname(__file__), "..")) import argparse from collections import OrderedDict import torch def convert_checkpoint_to_bert_model(checkpoint_path, output_path): checkpoint = torch.load(checkpoint_path, map_location="cpu") model_weights = checkpoint["weights"] bert_model_weights = OrderedDict() for key, tensor in model_weights.items(): if "_model" in key or "shared_layers" in key: new_key = key.replace("_model", "bert").replace("shared_layers", "bert") bert_model_weights[new_key] = tensor torch.save(bert_model_weights, output_path) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('checkpoint_path', type=str, help="""CLaF Checkpoint Path""") parser.add_argument('output_path', type=str, help="""BERT model output_path""") args = parser.parse_args() convert_checkpoint_to_bert_model(args.checkpoint_path, args.output_path) ================================================ FILE: script/convert_embedding_to_vocab_txt.py ================================================ import argparse def read_embedding_vocabs(file_path): print("Reading vocabs from file") vocabs = [] with open(file_path, "rb") as embeddings_file: for line in embeddings_file: fields = line.decode("utf-8").rstrip().split(" ") word = fields[0] vocabs.append(word) return vocabs def write_vocab(embedding_vocabs, output_path): print("Write vocabs") vocab_texts = "\n".join(embedding_vocabs) with open(output_path, "wb") as vocab_file: vocab_file.write(vocab_texts.encode("utf-8")) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('embed_path', type=str, help='Pretrained embedding txt path') parser.add_argument('output_path', type=str, help='vocab_texts output path') args = parser.parse_args() embedding_vocabs = read_embedding_vocabs(args.embed_path) write_vocab(embedding_vocabs, args.output_path) ================================================ FILE: script/download_wikisql.sh ================================================ mkdir -p data/wikisql cd data/wikisql wget https://github.com/salesforce/WikiSQL/raw/master/data.tar.bz2 tar xvjf data.tar.bz2 mv data/* . rm data.tar.bz2 rm -r data ================================================ FILE: script/install_mecab.sh ================================================ #!/bin/sh OUT_DIR="${1:-./mecab}" mkdir -v -p $OUT_DIR apt-get install git cmake make automake wget wget https://bitbucket.org/eunjeon/mecab-ko/downloads/mecab-0.996-ko-0.9.2.tar.gz wget https://bitbucket.org/eunjeon/mecab-ko-dic/downloads/mecab-ko-dic-2.1.1-20180720.tar.gz mv mecab-0.996-ko-0.9.2.tar.gz "$OUT_DIR/" mv mecab-ko-dic-2.1.1-20180720.tar.gz "$OUT_DIR/" cd "$OUT_DIR" tar -zxvf mecab-0.996-ko-0.9.2.tar.gz cd mecab-0.996-ko-0.9.2 ./configure make make check make install cd ../ ldconfig tar -zxvf mecab-ko-dic-2.1.1-20180720.tar.gz cd mecab-ko-dic-2.1.1-20180720 ./autogen.sh ./configure make make install pip install mecab-python3 ================================================ FILE: script/make_squad_synthetic_data.py ================================================ import argparse import json import os import random import uuid def make_squad_synthetic_data(output_path, max_context_length, question_lengths): ANSWER_TOKEN = "ANSWER" out_squad = {'data': [], 'version': "0.1"} article = { "paragraphs": [], "title": "Synthetic data for test" } for token_count in range(10, max_context_length): qas = [] for question_length in question_lengths: answers = [{"answer_start": 0, "answer_end": 0, "text": ANSWER_TOKEN}] qa = { "id": str(uuid.uuid1()), "answers": answers, "question": make_random_tokens(question_length) } qas.append(qa) paragraph = { "context": make_random_tokens(token_count, answer_token=ANSWER_TOKEN), "qas": qas } article["paragraphs"].append(paragraph) out_squad['data'].append(article) with open(output_path, 'w') as fp: json.dump(out_squad, fp) def make_random_tokens(length, answer_token=""): tokens = ['kox', 'pev', 'hi', 'shemini', 'outvote'] if answer_token: output = [answer_token] else: output = [] for _ in range(length-1): output.append(random.choice(tokens)) return " ".join(output) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('output_path', type=str, help='synthetic data output path') parser.add_argument('--max_context_length', type=int, help='The number of maximum context length') parser.add_argument('--question_lengths', nargs="+", type=int, help='The numbers of question length') args = parser.parse_args() make_squad_synthetic_data(args.output_path, args.max_context_length, args.question_lengths) ================================================ FILE: script/plot.py ================================================ import argparse import json import os from matplotlib import pyplot as plt import numpy as np import seaborn from sklearn import linear_model seaborn.set() seaborn.set_style("whitegrid") def make_inference_latency_plot(result_dir, max_elapsed_time=2000): token_counts = [] # x inference_latencies = [] # y model_names = [] # Legend linear_regr_models = [] # Linear Regression for expect token_counts (SQuAD's context: 50 ~ 700 tokens) for file_path in os.listdir(result_dir): result_path = os.path.join(result_dir, file_path) if not result_path.endswith(".json"): continue with open(result_path, "r") as f: model_name = os.path.basename(result_path).replace(".json", "") model_names.append(model_name) result = json.load(f) token_count = [r["token_count"] for r in result["tensor_to_predicts"]] inference_latency = [r["elapsed_time"] for r in result["tensor_to_predicts"]] token_counts.append(token_count) inference_latencies.append(inference_latency) # Create linear regression for predict token_counts regr = linear_model.LinearRegression() regr.fit( np.array(inference_latency).reshape(-1, 1), np.array(token_count).reshape(-1, 1) ) linear_regr_models.append(regr) f_name = f"inference_latency_chart-{max_elapsed_time}.png" title = "Inference Latency" zipped_data = list(zip(model_names, token_counts, inference_latencies, linear_regr_models)) zipped_data.sort() # get maximum token count for zipped in zipped_data: model_name, token_counts, inference_latencies, linear_regr_model = zipped max_token_count = 0 for token_count, inference_latency in zip(token_counts, inference_latencies): if inference_latency <= max_elapsed_time and max_token_count < token_count: max_token_count = token_count token_logs = f"model_name: {model_name} | " token_logs += f"max_token_count: {max_token_count} " token_logs += f"(predict: {int(linear_regr_model.predict(np.array(max_elapsed_time).reshape(-1, 1)))})" token_logs += f" / {max_elapsed_time} mills" print(token_logs) model_names, token_counts, inference_latencies, linear_regr_models = zip(*zipped_data) make_scatter( token_counts, inference_latencies, f_name, linear_regr_models=linear_regr_models, alpha=0.2, size=[18, 10], s=20, legends=model_names, x_min=0, x_max=800, y_min=0, y_max=max_elapsed_time, x_label="Tokens", y_label="1-example Latency (milliseconds)", title=title, markerscale=5, ) def make_summary_plot(result_dir, max_elapsed_time=100): max_token_counts = [] # x f1_scores = [] # y model_names = [] # Legend for file_path in os.listdir(result_dir): result_path = os.path.join(result_dir, file_path) if not result_path.endswith(".json"): continue with open(result_path, "r") as f: model_name = os.path.basename(result_path).replace(".json", "") result = json.load(f) model_names.append(model_name + "_cpu") model_names.append(model_name + "_gpu") f1_scores.append([result["metrics"]["best"]["valid/f1"]]) f1_scores.append([result["metrics"]["best"]["valid/f1"]]) max_token_counts.append( [result["inferency_latency"]["cpu"]["max_token_count"][str(max_elapsed_time)]] ) max_token_counts.append( [result["inferency_latency"]["gpu"]["max_token_count"][str(max_elapsed_time)]] ) f_name = f"summary.png" title = "Model Summary" zipped_data = list(zip(model_names, f1_scores, max_token_counts)) zipped_data.sort() model_names, f1_scores, max_token_counts = zip(*zipped_data) latency_min, latency_max = 0, 1000 f1_min, f1_max = 60, 80 make_scatter( max_token_counts, f1_scores, f_name, is_env_with_color=True, size=[18, 10], legends=model_names, s=400, alpha=1, y_min=60, y_max=80, x_min=0, x_max=700, x_ticks=list(range(latency_min, latency_max + 1, 100)), y_ticks=list(range(f1_min, f1_max + 1, 5)), x_label=f"Maximum token count ({max_elapsed_time} milliseconds)", y_label="F1 Score", title=title, ) def make_scatter( x, y, f_name, is_env_with_color=False, linear_regr_models=None, size=[10, 14], title=None, legends=None, s=10, alpha=0.6, markerscale=1, x_min=None, y_min=None, x_max=None, y_max=None, x_label=None, y_label=None, x_ticks=None, y_ticks=None, ): fig = plt.figure(figsize=(size[0], size[1])) markers = ["o", "*", "v", "^", "<", ">", "8", "s", "p", "h", "H", "D", "d", "P", "X"] if title is not None: plt.title(title, fontsize=32) if x_label is not None: plt.xlabel(x_label, fontsize=22) if y_label is not None: plt.ylabel(y_label, fontsize=22) if x_min is not None or x_max is not None: plt.xlim(xmin=x_min, xmax=x_max) if y_min is not None or y_max is not None: plt.ylim(ymin=y_min, ymax=y_max) if x_ticks is not None: plt.xticks(x_ticks, x_ticks, fontsize=18) else: plt.xticks(fontsize=18) if y_ticks is not None: plt.yticks(y_ticks, y_ticks, fontsize=18) else: plt.yticks(fontsize=18) if isinstance(x[0], list) and isinstance(y[0], list): for index, (x_item, y_item) in enumerate(zip(x, y)): if is_env_with_color: i = int(index / 2) if index % 2 == 0: plt.scatter(x_item, y_item, s=s, c="b", marker=markers[i], alpha=alpha) else: plt.scatter(x_item, y_item, s=s, c="g", marker=markers[i], alpha=alpha) else: if index % 2 == 0: plt.scatter(x_item, y_item, s=s, marker="o", alpha=alpha) else: plt.scatter(x_item, y_item, s=s, marker="^", alpha=alpha) else: plt.scatter(x, y, s=s, alpha=alpha) if linear_regr_models is not None: ys = np.arange(y_min, y_max) for model in linear_regr_models: xs = [int(model.predict(np.array(y).reshape(-1, 1))) for y in ys] plt.plot(xs, ys) if legends is not None: plt.legend( legends, fontsize=24, fancybox=True, shadow=True, loc=(1.04, 0.3), markerscale=markerscale, ) plt.savefig(f_name, bbox_inches="tight") plt.close(fig) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "plot_type", type=str, default="inference", help="Plot type [inference|summary]" ) parser.add_argument( "--result_dir", type=str, default="inference_result", help="SQuAD official json file path" ) parser.add_argument( "--max_latency", type=int, default=2000, help="The number of maximum latency time. (milliseconds)", ) config = parser.parse_args() if config.plot_type == "inference": make_inference_latency_plot(config.result_dir, max_elapsed_time=config.max_latency) elif config.plot_type == "summary": make_summary_plot(config.result_dir, max_elapsed_time=config.max_latency) else: raise ValueError(f"not supported plot_type: {config.plot_type}") print(f"Complete make {config.plot_type} plot") ================================================ FILE: setup.py ================================================ import io import os import sys from shutil import rmtree from setuptools import find_packages, setup, Command # Package meta-data. NAME = 'claf' DESCRIPTION = 'CLaF: Clova Language Framework' URL = 'https://github.com/naver/claf' EMAIL = 'humanbrain.djlee@gmail.com' AUTHOR = 'Dongjun Lee' REQUIRES_PYTHON = '>=3.6.0' VERSION = None REQUIRED = [ "numpy>=1.15.0", "torch>=1.0.1", # Backends "pytorch-transformers==1.1.0", # BERT "konlpy", "nltk", "spacy", # Tokenizer "babel", "records", # WikiSQL "h5py", "jsbeautifier", "msgpack", "overrides", "requests", "gensim", "tqdm", "tensorboardX", # Utils "pycm", "seqeval", "scikit-learn", # Metrics ] EXTRAS = {} here = os.path.abspath(os.path.dirname(__file__)) # Import the README and use it as the long-description. try: with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f: long_description = '\n' + f.read() except FileNotFoundError: long_description = DESCRIPTION # Load the package's __version__.py module as a dictionary. about = {} if not VERSION: with open(os.path.join(here, NAME, '__version__.py')) as f: exec(f.read(), about) else: about['__version__'] = VERSION class UploadCommand(Command): """Support setup.py upload.""" description = 'Build and publish the package.' user_options = [] @staticmethod def status(s): """Prints things in bold.""" print('\033[1m{0}\033[0m'.format(s)) def initialize_options(self): pass def finalize_options(self): pass def run(self): try: self.status('Removing previous builds…') rmtree(os.path.join(here, 'dist')) except OSError: pass self.status('Building Source and Wheel (universal) distribution…') os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable)) self.status('Uploading the package to PyPI via Twine…') os.system('twine upload dist/*') self.status('Pushing git tags…') os.system('git tag v{0}'.format(about['__version__'])) os.system('git push --tags') sys.exit() setup( name=NAME, version=about['__version__'], description=DESCRIPTION, long_description=long_description, long_description_content_type='text/markdown', author=AUTHOR, author_email=EMAIL, python_requires=REQUIRES_PYTHON, url=URL, packages=find_packages(exclude=('tests',)), install_requires=REQUIRED, extras_require=EXTRAS, include_package_data=True, license='MIT', classifiers=[ # Trove classifiers # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers 'License :: OSI Approved :: MIT License', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy' ], # $ setup.py publish support. cmdclass={ 'upload': UploadCommand, }, ) ================================================ FILE: tests/__init__.py ================================================ ================================================ FILE: tests/claf/data/test_batch.py ================================================ from claf.data.utils import make_batch def test_make_batch(): features = { "f1": 0, "f2": 1, "f3": 3, } labels = { "l1": 0, "l2": 1, "l3": 2, } batch = make_batch(features, labels) assert batch.features == features assert batch.labels == labels def test_batch_sort_by_key(): features = [ {"f1": "long long long"}, {"f1": "short"}, {"f1": "mid mid"} ] labels = [ {"l1": 3}, {"l1": 1}, {"l1": 2}, ] batch = make_batch(features, labels) batch.sort_by_key("f1") assert batch.features == sorted(features, key=lambda x: len(x["f1"])) ================================================ FILE: tests/claf/machine/knowlege_base/test_docs.py ================================================ import json import os from claf.machine.knowlege_base.docs import read_wiki_articles def test_read_wiki_articles(): articles = [ {"id": 0 , "url": "url", "title": "title", "text": "text"}, {"id": 1 , "url": "url", "title": "title", "text": "text"}, {"id": 2 , "url": "url", "title": "title", "text": "text"}, ] file_path = "./wiki_articles.json" with open(file_path, "w", encoding="utf-8") as out_file: for article in articles: out_file.write(json.dumps(article)) articles = read_wiki_articles(file_path) os.remove(file_path) ================================================ FILE: tests/claf/modules/test_functional.py ================================================ import torch import claf.modules.functional as f def test_add_masked_value(): a = torch.rand(3, 5) a_mask = torch.FloatTensor([ [1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 1, 1, 1, 1], ]) tensor = f.add_masked_value(a, a_mask, value=100) assert tensor[0][3] == 100 assert tensor[0][4] == 100 assert tensor[1][2] == 100 assert tensor[1][3] == 100 assert tensor[1][4] == 100 def test_add_masked_value_with_byte_tensor(): a = torch.rand(3, 5) a_mask = torch.ByteTensor([ [1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 1, 1, 1, 1], ]) tensor = f.add_masked_value(a, a_mask, value=100) assert tensor[0][3] == 100 assert tensor[0][4] == 100 assert tensor[1][2] == 100 assert tensor[1][3] == 100 assert tensor[1][4] == 100 def test_get_mask_from_tokens_with_2_dim(): tokens = { "word" : torch.LongTensor([ [1, 1, 1, 0, 0], [1, 1, 0, 0, 0], [1, 1, 1, 1, 1], ]), } mask = f.get_mask_from_tokens(tokens) print(mask) assert mask.equal(tokens["word"]) def test_get_mask_from_tokens_with_3_dim(): tokens = { "char" : torch.LongTensor([ [[4, 2], [3, 6], [0, 0]], [[5, 1], [0, 0], [0, 0]], [[1, 3], [2, 4], [3, 6]], ]), } mask = f.get_mask_from_tokens(tokens) expect_tensor = torch.LongTensor([ [1, 1, 0], [1, 0, 0], [1, 1, 1], ]) assert mask.equal(expect_tensor) def test_last_dim_masked_softmax_with_2_dim(): tensor = torch.FloatTensor([ [2, 3, 1, 0, 0], [4, 1, 0, 0, 0], [1, 5, 2, 4, 1], ]) mask = f.get_mask_from_tokens({"word": tensor}).float() result = f.last_dim_masked_softmax(tensor, mask) assert result.argmax(dim=-1).equal(torch.LongTensor([1, 0, 1])) def test_masked_softmax(): tensor = torch.FloatTensor([ [2, 3, 1, 4, 5], [4, 1, 6, 9, 10], [1, 5, 2, 4, 1], ]) mask = torch.tensor([ [1., 1., 1., 0., 0.], [1., 1., 0., 0., 0.], [1., 1., 1., 1., 1.] ]) result = f.masked_softmax(tensor, mask) assert result.argmax(dim=-1).equal(torch.LongTensor([1, 0, 1])) def test_masked_zero(): tensor = torch.FloatTensor([ [2, 3, 1, 4, 5], [4, 1, 6, 9, 10], [1, 5, 2, 4, 1], ]) mask = torch.tensor([ [1., 1., 1., 0., 0.], [1., 1., 0., 0., 0.], [1., 1., 1., 1., 1.] ]) result = f.masked_zero(tensor, mask) assert result[0][3] == 0 assert result[0][4] == 0 assert result[1][2] == 0 assert result[1][3] == 0 assert result[1][4] == 0 result = f.masked_zero(tensor.long(), mask) assert result[0][3] == 0 assert result[0][4] == 0 assert result[1][2] == 0 assert result[1][3] == 0 assert result[1][4] == 0 result = f.masked_zero(tensor.byte(), mask) assert result[0][3] == 0 assert result[0][4] == 0 assert result[1][2] == 0 assert result[1][3] == 0 assert result[1][4] == 0 def test_get_sorted_seq_config(): tensor = torch.LongTensor([ [2, 3, 1, 0, 0], [4, 1, 0, 0, 0], [1, 5, 2, 4, 1], ]) seq_config = f.get_sorted_seq_config({"word": tensor}) assert seq_config["seq_lengths"].tolist() == [5, 3, 2] assert seq_config["perm_idx"].tolist() == [2, 0, 1] assert seq_config["unperm_idx"].tolist() == [1, 2, 0] def test_forward_rnn_with_pack(): tensor = torch.LongTensor([ [2, 3, 1, 0, 0], [4, 1, 0, 0, 0], [1, 5, 2, 4, 1], ]) matrix = torch.rand(10, 10) embedded_tensor = torch.nn.functional.embedding(tensor, matrix) seq_config = f.get_sorted_seq_config({"word": tensor}) gru = torch.nn.GRU(input_size=10, hidden_size=1, bidirectional=False, batch_first=True) encoded_tensor = f.forward_rnn_with_pack(gru, embedded_tensor, seq_config) assert encoded_tensor[0][3] == 0 assert encoded_tensor[0][4] == 0 assert encoded_tensor[1][2] == 0 assert encoded_tensor[1][3] == 0 assert encoded_tensor[1][4] == 0 ================================================ FILE: tests/claf/tokens/test_vocabulary.py ================================================ from collections import Counter import os from claf.tokens.vocabulary import Vocab def test_init_vocab(): vocab = Vocab("token_name") vocab.init() assert vocab.get_all_tokens() == ["[PAD]", "[UNK]"] def test_init_vocab_with_special_token(): vocab = Vocab("token_name", start_token="", end_token="", cls_token="[CLS]", sep_token="[SEP]") vocab.init() assert vocab.get_all_tokens() == ["[PAD]", "[UNK]", "", "", "[CLS]", "[SEP]"] def test_from_texts(): texts = "A\nB\nC\nD" vocab = Vocab("token_name") vocab.from_texts(texts) assert vocab.get_all_tokens() == ["A", "B", "C", "D", "[PAD]", "[UNK]"] def test_from_texts_with_pad(): texts = "\nA\nB\nC\nD" vocab = Vocab("token_name", pad_token="") vocab.from_texts(texts) assert vocab.get_all_tokens() == ["", "A", "B", "C", "D", "[UNK]"] def test_from_texts_with_pad_but_not_define(): texts = "\nA\nB\nC\nD" vocab = Vocab("token_name") vocab.from_texts(texts) assert vocab.get_all_tokens() == ["", "A", "B", "C", "D", "[PAD]", "[UNK]"] def test_build(): tokens = ["A", "A", "A", "B", "B"] token_counter = Counter(tokens) vocab = Vocab("token_name") vocab.build(token_counter) assert vocab.get_all_tokens() == ["[PAD]", "[UNK]", "A", "B"] def test_build_with_max_vocab_size(): tokens = ["A", "A", "A", "B", "B"] token_counter = Counter(tokens) vocab = Vocab("token_name", max_vocab_size=1) vocab.build(token_counter) assert vocab.get_all_tokens() == ["[PAD]", "[UNK]", "A"] def test_build_with_min_count(): tokens = ["A", "A", "A", "B", "B"] token_counter = Counter(tokens) vocab = Vocab("token_name", min_count=3) vocab.build(token_counter) assert vocab.get_all_tokens() == ["[PAD]", "[UNK]", "A"] def test_get_token(): texts = "A\nB\nC\nD" vocab = Vocab("token_name") vocab.from_texts(texts) assert vocab.get_all_tokens() == ["A", "B", "C", "D", "[PAD]", "[UNK]"] assert vocab.get_token(2) == "C" def test_save_and_load(): texts = "A\nB\nC\nD" vocab = Vocab("token_name") vocab.from_texts(texts) vocab_path = "./test_vocab.txt" vocab.dump(vocab_path) vocab2 = Vocab("token_name") vocab2.load(vocab_path) os.remove(vocab_path) assert vocab.get_all_tokens() == vocab2.get_all_tokens() def test_build_with_pretrained_file_all(): texts = "[PAD]\n[UNK]\nA\nB\nC\nD" vocab_path = "./test_vocab.txt" with open(vocab_path, "w", encoding="utf-8") as out_file: out_file.write(texts) vocab = Vocab("token_name", pretrained_path=vocab_path, pretrained_token=Vocab.PRETRAINED_ALL) token_counter = None vocab.build_with_pretrained_file(token_counter) os.remove(vocab_path) assert vocab.get_all_tokens() == ["[PAD]", "[UNK]", "A", "B", "C", "D"] def test_build_with_pretrained_file_intersect(): texts = "[PAD]\n[UNK]\nA\nB\nC\nD" vocab_path = "./test_vocab.txt" with open(vocab_path, "w", encoding="utf-8") as out_file: out_file.write(texts) vocab = Vocab("token_name", pretrained_path=vocab_path, pretrained_token=Vocab.PRETRAINED_INTERSECT) input_texts = ["B", "C", "D", "E"] token_counter = Counter(input_texts) vocab.build_with_pretrained_file(token_counter) os.remove(vocab_path) assert vocab.get_all_tokens() == ["[PAD]", "[UNK]", "B", "C", "D"] ================================================ FILE: tests/integration/test_config.py ================================================ import json from claf.config import args from claf.config.namespace import NestedNamespace from claf.learn.mode import Mode def test_train_argparse(): train_config = args.config(argv=["--seed_num", "4"], mode=Mode.TRAIN) assert train_config.seed_num == 4 def test_train_base_config_argparse(): train_config = args.config(argv=["--base_config", "test/bidaf"], mode=Mode.TRAIN) config = NestedNamespace() with open("base_config/test/bidaf.json", "r") as f: defined_config = json.load(f) config.load_from_json(defined_config) args.set_gpu_env(config) assert train_config == config def test_eval_argparse(): eval_config = args.config(argv=["data_path", "checkpoint_path"], mode=Mode.EVAL) print(eval_config) def test_predict_argparse(): predict_config = args.config(argv=["checkpoint_path"], mode=Mode.PREDICT) print(predict_config) def test_machine_argparse(): machine_config = args.config(argv=["--machine_config", "ko_wiki"], mode=Mode.MACHINE) print(machine_config) ================================================ FILE: tests/integration/test_machine.py ================================================ import json import os import pytest import shutil from claf.config.args import optimize_config, set_gpu_env from claf.config.namespace import NestedNamespace from claf.config.registry import Registry from claf.learn.experiment import Experiment from claf.learn.mode import Mode import utils TEST_DIR = os.path.join("logs", "test") SQUAD_SYNTHETIC_DATA_PATH= os.path.join(TEST_DIR, "squad_synthetic_data.json") WIKI_SYNTHETIC_DATA_PATH= os.path.join(TEST_DIR, "wiki_articles") @pytest.mark.order1 def test_make_synthetic_data(): if os.path.exists(TEST_DIR): shutil.rmtree(TEST_DIR, ignore_errors=True) os.makedirs(TEST_DIR, exist_ok=True) utils.make_wiki_article_synthetic_data(WIKI_SYNTHETIC_DATA_PATH) utils.make_squad_synthetic_data(SQUAD_SYNTHETIC_DATA_PATH) @pytest.fixture def train_config(request): config_path = request.param config = NestedNamespace() with open(config_path, "r") as f: defined_config = json.load(f) config.load_from_json(defined_config) config.nsml = NestedNamespace() config.nsml.pause = 0 config = optimize_config(config, is_test=True) set_gpu_env(config) config.data_reader.train_file_path = SQUAD_SYNTHETIC_DATA_PATH config.data_reader.valid_file_path = SQUAD_SYNTHETIC_DATA_PATH return config @pytest.mark.order2 @pytest.mark.parametrize("train_config", ["./base_config/test/bidaf.json"], indirect=True) def test_train_squad_bidaf_model(train_config): experiment = Experiment(Mode.TRAIN, train_config) experiment() @pytest.fixture def open_qa_config(request): config_path = request.param machine_config = NestedNamespace() with open(config_path, "r") as f: defined_config = json.load(f) machine_config.load_from_json(defined_config) claf_name = machine_config.name config = getattr(machine_config, claf_name, {}) config.knowledge_base.wiki = WIKI_SYNTHETIC_DATA_PATH config.reasoning.reading_comprehension.checkpoint_path = "./logs/test/bidaf/checkpoint/model_1.pkl" return machine_config @pytest.mark.order3 @pytest.mark.parametrize("open_qa_config", ["./base_config/test/open_qa.json"], indirect=True) def test_open_qa_with_bidaf_model(open_qa_config): claf_name = open_qa_config.name config = getattr(open_qa_config, claf_name, {}) registry = Registry() claf_machine = registry.get(f"machine:{claf_name}")(config) question = utils.make_random_tokens(5) answer = claf_machine(question) answer = json.dumps(answer, indent=4, ensure_ascii=False) @pytest.mark.order4 def test_remove_tested_directory(): test_path = "logs/test" shutil.rmtree(test_path) ================================================ FILE: tests/integration/test_multi_task.py ================================================ import json import os import pytest from claf.config.args import optimize_config, set_gpu_env from claf.config.namespace import NestedNamespace from claf.learn.experiment import Experiment from claf.learn.mode import Mode import utils SYNTHETIC_QA_DATA_PATH = os.path.join("logs", "test", "data", "qa_synthetic_data.json") SYNTHETIC_SEQ_CLS_DATA_PATH = os.path.join("logs", "test", "data", "seq_cls_synthetic_data.json") SYNTHETIC_REG_DATA_PATH = os.path.join("logs", "test", "data", "reg_synthetic_data.json") @pytest.fixture def test_config(request): return load_and_setting(request.param) def load_and_setting(config_path): config = NestedNamespace() with open(config_path, "r") as f: defined_config = json.load(f) config.load_from_json(defined_config) config = optimize_config(config, is_test=True) set_gpu_env(config) config.data_reader.multitask_bert.readers[0]["train_file_path"] = SYNTHETIC_SEQ_CLS_DATA_PATH config.data_reader.multitask_bert.readers[0]["valid_file_path"] = SYNTHETIC_SEQ_CLS_DATA_PATH config.data_reader.multitask_bert.readers[1]["train_file_path"] = SYNTHETIC_REG_DATA_PATH config.data_reader.multitask_bert.readers[1]["valid_file_path"] = SYNTHETIC_REG_DATA_PATH config.data_reader.multitask_bert.readers[2]["train_file_path"] = SYNTHETIC_QA_DATA_PATH config.data_reader.multitask_bert.readers[2]["valid_file_path"] = SYNTHETIC_QA_DATA_PATH return config @pytest.mark.order1 def test_make_multi_task_synthetic_data(): utils.make_bert_seq_cls_synthetic_data(SYNTHETIC_SEQ_CLS_DATA_PATH, remove_exist=False) utils.make_bert_reg_synthetic_data(SYNTHETIC_REG_DATA_PATH, remove_exist=False) utils.make_squad_synthetic_data(SYNTHETIC_QA_DATA_PATH, remove_exist=False) @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/bert_for_multi_task.json"], indirect=True) def test_train_multi_task_bert_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() ================================================ FILE: tests/integration/test_reading_comprehension.py ================================================ import os import pytest import shutil from claf.config.args import optimize_config, set_gpu_env from claf.config.namespace import NestedNamespace from claf.config.utils import add_config_extension, read_config from claf.learn.experiment import Experiment from claf.learn.mode import Mode import utils SYNTHETIC_DATA_PATH = os.path.join("logs", "test", "squad_synthetic_data.json") DUMMY_EMBEDDING_300D_PATH = os.path.join("logs", "test", "dummy_300d.txt") @pytest.fixture def test_config(request): return load_and_setting(request.param) def load_and_setting(config_path): config = NestedNamespace() config_path = add_config_extension(config_path) defined_config = read_config(config_path) config.load_from_json(defined_config) config = optimize_config(config, is_test=True) set_gpu_env(config) config.data_reader.train_file_path = SYNTHETIC_DATA_PATH config.data_reader.valid_file_path = SYNTHETIC_DATA_PATH return config @pytest.mark.order1 def test_make_squad_synthetic_data(): utils.make_squad_synthetic_data(SYNTHETIC_DATA_PATH) utils.write_embedding_txt(DUMMY_EMBEDDING_300D_PATH, 300) @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/bidaf"], indirect=True) def test_train_squad_bidaf_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/bidaf_no_answer.json"], indirect=True) def test_train_squad_bidaf_no_answer_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() # need glove.840B.300d.txt (5.65 GB) # @pytest.mark.order2 # @pytest.mark.parametrize("test_config", ["./base_config/test/bidaf+cove.json"], indirect=True) # def test_train_squad_bidaf_cove_model(test_config): # experiment = Experiment(Mode.TRAIN, test_config) # experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/bidaf+elmo.json"], indirect=True) def test_train_squad_bidaf_elmo_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/drqa.json"], indirect=True) def test_train_squad_drqa_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/drqa_sparse_to_embedding.json"], indirect=True) def test_train_squad_drqa_model_with_sparse_to_embedding(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/docqa.json"], indirect=True) def test_train_squad_docqa_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/docqa_no_answer.json"], indirect=True) def test_train_squad_docqa_no_answer_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/qanet.json"], indirect=True) def test_train_squad_qanet_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/bert_for_qa"], indirect=True) def test_train_squad_bert_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() # TODO: subword ---> word # @pytest.mark.order2 # @pytest.mark.parametrize("test_config", ["./base_config/test/bidaf+bert.json"], indirect=True) # def test_train_squad_bidaf_model_with_bert(test_config): # experiment = Experiment(Mode.TRAIN, test_config) # experiment() @pytest.mark.order2 def test_eval_squad_bidaf(): config = NestedNamespace() config.data_file_path = SYNTHETIC_DATA_PATH config.checkpoint_path = "./logs/test/bidaf/checkpoint/model_1.pkl" config.cude_devices = None set_gpu_env(config) experiment = Experiment(Mode.EVAL, config) experiment() @pytest.mark.order3 def test_eval_infer_squad_bidaf(): config = NestedNamespace() config.data_file_path = SYNTHETIC_DATA_PATH config.checkpoint_path = "./logs/test/bidaf/checkpoint/model_1.pkl" config.cude_devices = None config.inference_latency = 1000 set_gpu_env(config) experiment = Experiment(Mode.INFER_EVAL, config) experiment() @pytest.mark.order3 def test_qa_predict_squad_bidaf_1_example(): config = NestedNamespace() config.checkpoint_path = "./logs/test/bidaf/checkpoint/model_1.pkl" config.cude_devices = None config.interactive = False set_gpu_env(config) config.context = "Westwood One will carry the game throughout North America, with Kevin Harlan as play-by-play announcer, Boomer Esiason and Dan Fouts as color analysts, and James Lofton and Mark Malone as sideline reporters. Jim Gray will anchor the pre-game and halftime coverage." config.question = "What radio network carried the Super Bowl?" experiment = Experiment(Mode.PREDICT, config) experiment() @pytest.mark.order3 def test_qa_predict_squad_bert_short_1_example(): config = NestedNamespace() config.checkpoint_path = "./logs/test/bert_for_qa/checkpoint/model_1.pkl" config.cude_devices = None config.interactive = False set_gpu_env(config) config.context = "Westwood One will carry the game throughout North America, with Kevin Harlan as play-by-play announcer, Boomer Esiason and Dan Fouts as color analysts, and James Lofton and Mark Malone as sideline reporters. Jim Gray will anchor the pre-game and halftime coverage." config.question = "What radio network carried the Super Bowl?" experiment = Experiment(Mode.PREDICT, config) experiment() @pytest.mark.order3 def test_qa_predict_squad_bert_long_1_example(): config = NestedNamespace() config.checkpoint_path = "./logs/test/bert_for_qa/checkpoint/model_1.pkl" config.cude_devices = None config.interactive = False set_gpu_env(config) config.context = "hi ho hi ho 1 hi ho hi ho 2 hi ho hi ho 3 hi ho hi ho 4 hi ho hi ho 5 hi ho hi ho 6 hi ho hi ho 7 hi ho hi ho 8 hi ho hi ho hi 9 ho hi ho hi ho hi 10 ho hi ho hi ho hi ho 11 hi ho hi ho hi 12 ANSWER ho hi ho hi ho hi 13 ho hi ho hi ho hi 14 ho hi ho hi ho hi 15 ho hi ho hi ho hi 16 ho hi ho hi ho hi 17 ho hi ho hi ho hi 18 ho hi ho hi ho hi 19 ho hi ho hi ho hi 20 ho hi ho hi ho hi 21 ho hi ho hi ho hi 22 ho hi ho hi ho hi 23 ho hi ho hi ho hi 24 ho hi ho hi 25 ho hi ho hi ho 1 hi ho hi ho 2 hi ho hi ho 3 hi ho hi ho 4 hi ho hi ho 5 hi ho hi ho 6 hi ho hi ho 7 hi ho hi ho 8 hi ho hi ho hi 9 ho hi ho hi ho hi 10 ho hi ho hi ho hi ho 11 hi ho hi ho hi 12 ho hi ho hi ho hi 13 ho hi ho hi ho hi 14 ho hi ho hi ho hi 15 ho hi ho hi ho hi 16 ho hi ho hi ho hi 17 ho hi ho hi ho hi 18 ho hi ho hi ho hi 19 ho hi ho hi ho hi 20 ho hi ho hi ho hi 21 ho hi ho hi ho hi 22 ho hi ho hi ho hi 23 ho hi ho hi ho hi 24 ho hi ho hi 25 ho hi ho hi ho 1 hi ho hi ho 2 hi ho hi ho 3 hi ho hi ho 4 hi ho hi ho 5 hi ho hi ho 6 hi ho hi ho 7 hi ho hi ho 8 hi ho hi ho hi 9 ho hi ho hi ho hi 10 ho hi ho hi ho hi ho 11 hi ho hi ho hi 12 ho hi ho hi ho hi 13 ho hi ho hi ho hi 14 ho hi ho hi ho hi 15 ho hi ho hi ho hi 16 ho hi ho hi ho hi 17 ho hi ho hi ho hi 18 ho hi ho hi ho hi 19 ho hi ho hi ho hi 20 ho hi ho hi ho hi 21 ho hi ho hi ho hi 22 ho hi ho hi ho hi 23 ho hi ho hi ho hi 24 ho hi ho hi 25 ho hi ho hi ho 1 hi ho hi ho 2 hi ho hi ho 3 hi ho hi ho 4 hi ho hi ho 5 hi ho hi ho 6 hi ho hi ho 7 hi ho hi ho 8 hi ho hi ho hi 9 ho hi ho hi ho hi 10 ho hi ho hi ho hi ho 11 hi ho hi ho hi 12 ho hi ho hi ho hi 13 ho hi ho hi ho hi 14 ho hi ho hi ho hi 15 ho hi ho hi ho hi 16 ho hi ho hi ho hi 17 ho hi ho hi ho hi 18 ho hi ho hi ho hi 19 ho hi ho hi ho hi 20 ho hi ho hi ho hi 21 ho hi ho hi ho hi 22 ho hi ho hi ho hi 23 ho hi ho hi ho hi 24 ho hi ho hi 25 ho" config.question = "good hi ho hi ho hi good hi ho hi ho hi good hi ho hi ho hi good hi ho hi ho hi good hi ho hi ho hi" experiment = Experiment(Mode.PREDICT, config) experiment() @pytest.mark.order4 def test_remove_tested_directory(): test_path = "logs/test" shutil.rmtree(test_path) ================================================ FILE: tests/integration/test_semantic_parsing.py ================================================ import json import os import pytest import shutil from claf.config.args import optimize_config, set_gpu_env from claf.config.namespace import NestedNamespace from claf.learn.experiment import Experiment from claf.learn.mode import Mode @pytest.fixture def test_config(request): return load_and_setting(request.param) def load_and_setting(config_path): config = NestedNamespace() with open(config_path, "r") as f: defined_config = json.load(f) config.load_from_json(defined_config) config.data_reader.wikisql = NestedNamespace() config.data_reader.wikisql.is_test = True config = optimize_config(config, is_test=True) set_gpu_env(config) return config @pytest.mark.order1 @pytest.mark.parametrize("test_config", ["./base_config/test/sqlnet.json"], indirect=True) def test_train_wikisql_sqlnet_model(test_config): os.system("sh script/download_wikisql.sh") experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 def test_qa_predict_wikisql_sqlnet_1_example(): config = NestedNamespace() config.checkpoint_path = "./logs/test/sqlnet/checkpoint/model_1.pkl" config.cude_devices = None config.interactive = False set_gpu_env(config) config.column = ["Player", "No.", "Nationality", "Position", "Years in Toronto", "School/Club Team"] config.db_path = "data/wikisql/dev.db" config.table_id = "1-10015132-11" config.question = "What position does the player who played for butler cc (ks) play?" experiment = Experiment(Mode.PREDICT, config) experiment() @pytest.mark.order3 def test_remove_tested_directory(): test_path = "logs/test" shutil.rmtree(test_path) ================================================ FILE: tests/integration/test_sequence_classification.py ================================================ import json import os import pytest import shutil from claf.config.args import optimize_config, set_gpu_env from claf.config.namespace import NestedNamespace from claf.learn.experiment import Experiment from claf.learn.mode import Mode import utils SYNTHETIC_DATA_PATH= os.path.join("logs", "test", "seq_cls", "synthetic_data.json") @pytest.fixture def test_config(request): return load_and_setting(request.param) def load_and_setting(config_path): config = NestedNamespace() with open(config_path, "r") as f: defined_config = json.load(f) config.load_from_json(defined_config) config = optimize_config(config, is_test=True) set_gpu_env(config) config.data_reader.train_file_path = SYNTHETIC_DATA_PATH config.data_reader.valid_file_path = SYNTHETIC_DATA_PATH return config @pytest.mark.order1 def test_make_synthetic_data(): utils.make_seq_cls_synthetic_data(SYNTHETIC_DATA_PATH) @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/ssa.json"], indirect=True) def test_train_nlu_ssa_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/bert_for_seq_cls.json"], indirect=True) def test_train_nlu_bert_for_seq_cls_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order3 def test_eval_nlu_ssa(): config = NestedNamespace() config.data_file_path = SYNTHETIC_DATA_PATH config.checkpoint_path = "./logs/test/seq_cls/ssa/checkpoint/model_1.pkl" config.cude_devices = None set_gpu_env(config) experiment = Experiment(Mode.EVAL, config) experiment() @pytest.mark.order3 def test_eval_nlu_bert_for_seq_cls(): config = NestedNamespace() config.data_file_path = SYNTHETIC_DATA_PATH config.checkpoint_path = "./logs/test/seq_cls/bert/checkpoint/model_1.pkl" config.cude_devices = None set_gpu_env(config) experiment = Experiment(Mode.EVAL, config) experiment() @pytest.mark.order3 def test_predict_nlu_ssa_1_example(): config = NestedNamespace() config.checkpoint_path = "./logs/test/seq_cls/ssa/checkpoint/model_1.pkl" config.cude_devices = None config.interactive = False set_gpu_env(config) config.sequence = "hi, how are you?" experiment = Experiment(Mode.PREDICT, config) experiment() @pytest.mark.order3 def test_predict_nlu_bert_for_seq_cls_1_example(): config = NestedNamespace() config.checkpoint_path = "./logs/test/seq_cls/bert/checkpoint/model_1.pkl" config.cude_devices = None config.interactive = False set_gpu_env(config) config.sequence = "hi, how are you?" experiment = Experiment(Mode.PREDICT, config) experiment() @pytest.mark.order4 def test_remove_tested_directory(): test_path = "logs/test" shutil.rmtree(test_path) ================================================ FILE: tests/integration/test_token_classification.py ================================================ import json import os import pytest import shutil import random from claf.config.args import optimize_config, set_gpu_env from claf.config.namespace import NestedNamespace from claf.learn.experiment import Experiment from claf.learn.mode import Mode import utils SYNTHETIC_DATA_PATH= os.path.join("logs", "test", "tok_cls", "synthetic_data.json") @pytest.fixture def test_config(request): return load_and_setting(request.param) def load_and_setting(config_path): config = NestedNamespace() with open(config_path, "r") as f: defined_config = json.load(f) config.load_from_json(defined_config) config = optimize_config(config, is_test=True) set_gpu_env(config) config.data_reader.train_file_path = SYNTHETIC_DATA_PATH config.data_reader.valid_file_path = SYNTHETIC_DATA_PATH return config @pytest.mark.order1 def test_make_synthetic_data(): utils.make_tok_cls_synthetic_data(SYNTHETIC_DATA_PATH) @pytest.mark.order2 @pytest.mark.parametrize("test_config", ["./base_config/test/bert_for_tok_cls.json"], indirect=True) def test_train_bert_tok_cls_model(test_config): experiment = Experiment(Mode.TRAIN, test_config) experiment() @pytest.mark.order3 def test_eval_nlu_bert_for_tok_cls(): config = NestedNamespace() config.data_file_path = SYNTHETIC_DATA_PATH config.checkpoint_path = "./logs/test/tok_cls/bert/checkpoint/model_1.pkl" config.cude_devices = None set_gpu_env(config) experiment = Experiment(Mode.EVAL, config) experiment() @pytest.mark.order3 def test_predict_nlu_bert_for_tok_cls_1_example(): config = NestedNamespace() config.checkpoint_path = "./logs/test/tok_cls/bert/checkpoint/model_1.pkl" config.cude_devices = None config.interactive = False set_gpu_env(config) config.sequence = "hi, how are you?" experiment = Experiment(Mode.PREDICT, config) experiment() @pytest.mark.order4 def test_remove_tested_directory(): test_path = "logs/test" shutil.rmtree(test_path) ================================================ FILE: tests/integration/test_tokenizers.py ================================================ import pytest import spacy from claf.tokens.tokenizer import BPETokenizer, CharTokenizer, SubwordTokenizer, WordTokenizer, SentTokenizer from claf.tokens.tokenizer.utils import load_spacy_model_for_tokenizer @pytest.fixture def tokenizers(request): sent_name, sent_config, word_name, word_config, \ subword_name, subword_config, char_name, char_config, \ bpe_name, bpe_config = request.param sent_tokenizer = SentTokenizer(sent_name, config=sent_config) word_tokenizer = WordTokenizer(word_name, sent_tokenizer, config=word_config) subword_tokenizer = SubwordTokenizer(subword_name, word_tokenizer, config=subword_config) char_tokenizer = CharTokenizer(char_name, word_tokenizer, config=char_config) bpe_tokenizer = BPETokenizer(bpe_name, config=bpe_config) return { "sent": sent_tokenizer, "word": word_tokenizer, "subword": subword_tokenizer, "char": char_tokenizer, "bpe": bpe_tokenizer, } @pytest.mark.parametrize("tokenizers", [( "punkt", {}, "space_all", {}, "wordpiece", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" }, "character", {}, "bpe", {})], indirect=True) def test_en_character_tokenize(tokenizers): text = "Hello World" tokenizer = tokenizers["char"] results = tokenizer.tokenize(text) assert results == [["H", "e", "l", "l", "o"], ["W", "o", "r", "l", "d"]] @pytest.mark.parametrize("tokenizers", [( "punkt", {}, "space_all", {}, "wordpiece", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" }, "jamo_ko", {}, "bpe", {})], indirect=True) def test_jamo_ko_tokenize(tokenizers): text = "안녕 세상" tokenizer = tokenizers["char"] results = tokenizer.tokenize(text) assert results == [["ㅇ", "ㅏ", "ㄴ", "ㄴ", "ㅕ", "ㅇ"], ["ㅅ", "ㅔ", "ㅅ", "ㅏ", "ㅇ"]] @pytest.mark.parametrize("tokenizers", [( "punkt", {}, "bert_basic", { "do_lower_case": True }, "wordpiece", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" }, "jamo_ko", {}, "bpe", {})], indirect=True) def test_bert_uncased_en_tokenize(tokenizers): text = "expectancy of anyone" tokenizer = tokenizers["subword"] results = tokenizer.tokenize(text) assert results == ['expect', '##ancy', 'of', 'anyone'] @pytest.mark.parametrize("tokenizers", [( "punkt", {}, "space_all", {}, "wordpiece", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" }, "character", {}, "bpe", {})], indirect=True) def test_space_all_tokenize(tokenizers): text = "Hi Hello\tHi\rHello\nHi" tokenizer = tokenizers["word"] results = tokenizer.tokenize(text) assert results == ['Hi', 'Hello', 'Hi', 'Hello', 'Hi'] @pytest.mark.parametrize("tokenizers", [( "punkt", {}, "space_all", {}, "wordpiece", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" }, "character", {}, "bpe", {})], indirect=True) def test_punkt_tokenize(tokenizers): text = "Hello World. This is punkt tokenizer." tokenizer = tokenizers["sent"] results = tokenizer.tokenize(text) assert results == ['Hello World.', 'This is punkt tokenizer.'] @pytest.mark.parametrize("tokenizers", [( "punkt", {}, "space_all", {}, "wordpiece", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" }, "character", {}, "bpe", {})], indirect=True) def test_word_with_regex_example_tokenize(tokenizers): text = "New York City:57–60 And Ted Ginn Jr.[citation needed]" sent_tokenizer = tokenizers["sent"] word_tokenizer = WordTokenizer("treebank_en", sent_tokenizer, split_with_regex=True) results = word_tokenizer.tokenize(text) print(results) assert results == ['New', 'York', 'City', ':', '57', '–', '60', 'And', 'Ted', 'Ginn', 'Jr', '.', '[', 'citation', 'needed', ']'] @pytest.mark.parametrize("tokenizers", [( "punkt", {}, "space_all", {}, "wordpiece", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" }, "character", {}, "bpe", {})], indirect=True) def test_spacy_model_with_regex_example_tokenize(tokenizers): text = "In 1096, Crusaders passing by the siege of Amalfi were joined by Bohemond of Taranto and his nephew Tancred with an army of Italo-Normans. Bohemond was the de facto leader of the Crusade during its passage through Asia Minor. After the successful Siege of Antioch in 1097, Bohemond began carving out an independent principality around that city. Tancred was instrumental in the conquest of Jerusalem and he worked for the expansion of the Crusader kingdom in Transjordan and the region of Galilee.[citation needed]" sent_tokenizer = SentTokenizer("punkt") word_tokenizer = WordTokenizer("spacy_en", sent_tokenizer, split_with_regex=True) disables = ["vectors", "textcat", "parser"] spacy_model = spacy.load("en_core_web_sm", disable=disables) spacy_model.tokenizer = load_spacy_model_for_tokenizer( word_tokenizer.extra_split_chars_re ) sentences = sent_tokenizer.tokenize(text) spacy_model_results = [] for sentence in sentences: spacy_model_results += [token.text for token in spacy_model(sentence)] assert word_tokenizer.tokenize(text) == spacy_model_results text = "20th Century Fox, Lionsgate, Paramount Pictures, Universal Studios and Walt Disney Studios paid for movie trailers to be aired during the Super Bowl. Fox paid for Deadpool, X-Men: Apocalypse, Independence Day: Resurgence and Eddie the Eagle, Lionsgate paid for Gods of Egypt, Paramount paid for Teenage Mutant Ninja Turtles: Out of the Shadows and 10 Cloverfield Lane, Universal paid for The Secret Life of Pets and the debut trailer for Jason Bourne and Disney paid for Captain America: Civil War, The Jungle Book and Alice Through the Looking Glass.[citation needed]" sentences = sent_tokenizer.tokenize(text) spacy_model_results = [] for sentence in sentences: spacy_model_results += [token.text for token in spacy_model(sentence)] assert word_tokenizer.tokenize(text) == spacy_model_results @pytest.mark.parametrize("tokenizers", [( "punkt", {}, "space_all", {}, "wordpiece", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt" }, "character", {}, "roberta", { "vocab_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-vocab.json", "merges_path": "https://s3.amazonaws.com/models.huggingface.co/bert/roberta-base-merges.txt" })], indirect=True) def test_bpe_tokenize(tokenizers): text = "As you eat the most, you want the least." tokenizer = tokenizers["bpe"] results = tokenizer.tokenize(text) assert results == ['As', 'Ġyou', 'Ġeat', 'Ġthe', 'Ġmost', ',', 'Ġyou', 'Ġwant', 'Ġthe', 'Ġleast', '.'] ================================================ FILE: tests/integration/utils.py ================================================ import json import os import random import shutil import numpy as np RANDOM_TOKENS = ['kox', 'pev', 'hi', 'shemini', 'outvote', "foo", "bar", "baz", "qux"] def make_bert_seq_cls_synthetic_data(output_path, remove_exist=True): data = {"data": []} for i in range(10): data["data"].append({ "sequence_a": make_random_tokens(8), "sequence_b": make_random_tokens(8), "class": str(i % 2) }) make_directory(output_path, remove_exist=remove_exist) with open(output_path, 'w') as fp: json.dump(data, fp) def make_bert_reg_synthetic_data(output_path, remove_exist=True): data = {"data": []} for i in range(10): data["data"].append({ "sequence_a": make_random_tokens(8), "sequence_b": make_random_tokens(8), "score": i * 0.1 }) make_directory(output_path, remove_exist=remove_exist) with open(output_path, 'w') as fp: json.dump(data, fp) def make_squad_synthetic_data(output_path, remove_exist=True): ANSWER_TOKEN = "ANSWER" DATA_SIZE = 10 out_squad = {'data': [], 'version': "0.1"} article = { "paragraphs": [], "title": "Synthetic data for test" } for _ in range(DATA_SIZE): token_count = random.randint(10, 20) qas = [] query_count = 10 answers = [{"answer_start": 0, "answer_end": 0, "text": ANSWER_TOKEN}] qa = { "id": f"{token_count}_{query_count}", "answers": answers, "question": make_random_tokens(query_count) } qas.append(qa) paragraph = { "context": make_random_tokens(token_count, answer_token=ANSWER_TOKEN), "qas": qas } article["paragraphs"].append(paragraph) out_squad['data'].append(article) make_directory(output_path, remove_exist=False) with open(output_path, 'w') as fp: json.dump(out_squad, fp) def make_directory(output_path, remove_exist=True): dir_path = os.path.dirname(output_path) if remove_exist and os.path.exists(dir_path): shutil.rmtree(dir_path, ignore_errors=True) os.makedirs(os.path.dirname(output_path), exist_ok=True) def make_wiki_article_synthetic_data(output_dir): AA_articles = [ {"id": 0, "url": "url", "title": "title1", "text": make_random_tokens(10)}, {"id": 1, "url": "url", "title": "title2", "text": make_random_tokens(10)}, {"id": 2, "url": "url", "title": "title3", "text": make_random_tokens(10)}, ] AA_articles = [json.dumps(item) for item in AA_articles] AA_path = os.path.join(output_dir, "AA", "wiki_00") print(AA_path) os.makedirs(os.path.dirname(AA_path), exist_ok=True) with open(AA_path, "w", encoding="utf-8") as out_file: out_file.write("\n".join(AA_articles)) assert os.path.exists(AA_path) == True AB_articles = [ {"id": 3, "url": "url", "title": "title4", "text": make_random_tokens(10)}, {"id": 4, "url": "url", "title": "title5", "text": make_random_tokens(10)}, {"id": 5, "url": "url", "title": "title6", "text": make_random_tokens(10)}, ] AB_articles = [json.dumps(item) for item in AB_articles] AB_path = os.path.join(output_dir, "AB", "wiki_00") os.makedirs(os.path.dirname(AB_path), exist_ok=True) with open(AB_path, "w", encoding="utf-8") as out_file: out_file.write("\n".join(AB_articles)) assert os.path.exists(AB_path) == True def make_random_tokens(length, answer_token=""): tokens = RANDOM_TOKENS if answer_token: output = [answer_token] else: output = [] for _ in range(length-1): output.append(random.choice(tokens)) return " ".join(output) def make_seq_cls_synthetic_data(output_path): class_key = "label" classes = ["foo", "bar", "baz", "qux", "quux", "corge", "grault", "graply", "waldo"] data_size = 10 out_seq_cls = { "data": [], class_key: classes, } for _ in range(data_size): token_count = random.randint(10, 20) sequence = make_random_tokens(token_count) class_ = random.choice(classes) out_seq_cls["data"].append({ "sequence": sequence, class_key: class_, }) os.makedirs(os.path.dirname(output_path), exist_ok=True) with open(output_path, 'w') as fp: json.dump(out_seq_cls, fp) def make_tok_cls_synthetic_data(output_path): tag_key = "label" tags = ["O"] + RANDOM_TOKENS data_size = 10 out_tok_cls = { "data": [], tag_key: ["O"] + [f"{prefix}-{tag}" for prefix in ["B", "I"] for tag in tags] } for _ in range(data_size): token_count = random.randint(10, 20) sequence = make_random_tokens(token_count) tag_sequence = make_dummy_tags(sequence, tags) out_tok_cls["data"].append({ "sequence": sequence, tag_key: tag_sequence, }) os.makedirs(os.path.dirname(output_path), exist_ok=True) with open(output_path, 'w') as fp: json.dump(out_tok_cls, fp) def make_dummy_tags(sequence, dummy_tag_cands): words = sequence.split() tags = [] prev_tag = None for word in words: if random.random() < 0.3: tag = "O" else: tag = random.choice(dummy_tag_cands) if prev_tag is None or prev_tag[2:] != tag: tag = "B-" + tag else: tag = "I-" + tag tags.append(tag) if tag == "O": prev_tag = None else: prev_tag = tag return tags def write_embedding_txt(output_path, dim): random_nums = np.random.rand(len(RANDOM_TOKENS), 300) with open(output_path, "w") as out_file: for token, num in zip(RANDOM_TOKENS, random_nums): out_file.write(f"{token} {num}\n") ================================================ FILE: train.py ================================================ # -*- coding: utf-8 -*- from claf.config import args from claf.learn.experiment import Experiment from claf.learn.mode import Mode if __name__ == "__main__": experiment = Experiment(Mode.TRAIN, args.config(mode=Mode.TRAIN)) experiment()