Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
005fcce7cc | ||
|
|
5102527eee | ||
|
|
6861aa9cc4 | ||
|
|
0691e49741 | ||
|
|
ca2725ee79 | ||
|
|
ba66c4c817 | ||
|
|
da59db93ad | ||
|
|
37d8870048 | ||
|
|
11c0a0d905 | ||
|
|
7ee992e98c | ||
|
|
c236808b72 | ||
|
|
9418015c27 | ||
|
|
2f44197b38 | ||
|
|
45641355a3 | ||
|
|
538a67eb46 | ||
|
|
42d5d27247 | ||
|
|
e25958043d | ||
|
|
eb9910798b | ||
|
|
86aa165fcd | ||
|
|
58ff811920 | ||
|
|
78fc0f44c0 | ||
|
|
da1d0e06b7 | ||
|
|
3114c8cd17 | ||
|
|
8f80607e9a | ||
|
|
13c7cdac47 | ||
|
|
13cadf7a02 | ||
|
|
3383e79fc0 | ||
|
|
e6eeed9622 | ||
|
|
ac313f350f | ||
|
|
9bb00602a2 | ||
|
|
11429609fc |
No files matched your search
@@ -188,6 +188,7 @@ Min, Patrick Lewis, Ledell Wu, Sergey Edunov, Danqi Chen, and Wen-tau Yih.
|
|||||||
ultilingual BERT into [DistilmBERT](https://github.com/huggingface/transformers/tree/master/examples/distillation) and a German version of DistilBERT.
|
ultilingual BERT into [DistilmBERT](https://github.com/huggingface/transformers/tree/master/examples/distillation) and a German version of DistilBERT.
|
||||||
1. **[SqueezeBert](https://huggingface.co/transformers/model_doc/squeezebert.html)** released with the paper [SqueezeBERT: What can computer vision teach NLP about efficient neural networks?](https://arxiv.org/abs/2006.11316) by Forrest N. Iandola, Albert E. Shaw, Ravi Krishna, and Kurt W. Keutzer.
|
1. **[SqueezeBert](https://huggingface.co/transformers/model_doc/squeezebert.html)** released with the paper [SqueezeBERT: What can computer vision teach NLP about efficient neural networks?](https://arxiv.org/abs/2006.11316) by Forrest N. Iandola, Albert E. Shaw, Ravi Krishna, and Kurt W. Keutzer.
|
||||||
1. **[T5](https://huggingface.co/transformers/model_doc/t5.html)** (from Google AI) released with the paper [Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer](https://arxiv.org/abs/1910.10683) by Colin Raffel and Noam Shazeer and Adam Roberts and Katherine Lee and Sharan Narang and Michael Matena and Yanqi Zhou and Wei Li and Peter J. Liu.
|
1. **[T5](https://huggingface.co/transformers/model_doc/t5.html)** (from Google AI) released with the paper [Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer](https://arxiv.org/abs/1910.10683) by Colin Raffel and Noam Shazeer and Adam Roberts and Katherine Lee and Sharan Narang and Michael Matena and Yanqi Zhou and Wei Li and Peter J. Liu.
|
||||||
|
1. **[TAPAS](https://huggingface.co/transformers/master/model_doc/tapas.html)** released with the paper [TAPAS: Weakly Supervised Table Parsing via Pre-training](https://arxiv.org/abs/2004.02349) by Jonathan Herzig, Paweł Krzysztof Nowak, Thomas Müller, Francesco Piccinno and Julian Martin Eisenschlos.
|
||||||
1. **[Transformer-XL](https://huggingface.co/transformers/model_doc/transformerxl.html)** (from Google/CMU) released with the paper [Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context](https://arxiv.org/abs/1901.02860) by Zihang Dai*, Zhilin Yang*, Yiming Yang, Jaime Carbonell, Quoc V. Le, Ruslan Salakhutdinov.
|
1. **[Transformer-XL](https://huggingface.co/transformers/model_doc/transformerxl.html)** (from Google/CMU) released with the paper [Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context](https://arxiv.org/abs/1901.02860) by Zihang Dai*, Zhilin Yang*, Yiming Yang, Jaime Carbonell, Quoc V. Le, Ruslan Salakhutdinov.
|
||||||
1. **[XLM](https://huggingface.co/transformers/model_doc/xlm.html)** (from Facebook) released together with the paper [Cross-lingual Language Model Pretraining](https://arxiv.org/abs/1901.07291) by Guillaume Lample and Alexis Conneau.
|
1. **[XLM](https://huggingface.co/transformers/model_doc/xlm.html)** (from Facebook) released together with the paper [Cross-lingual Language Model Pretraining](https://arxiv.org/abs/1901.07291) by Guillaume Lample and Alexis Conneau.
|
||||||
1. **[XLM-ProphetNet](https://huggingface.co/transformers/model_doc/xlmprophetnet.html)** (from Microsoft Research) released with the paper [ProphetNet: Predicting Future N-gram for Sequence-to-Sequence Pre-training](https://arxiv.org/abs/2001.04063) by Yu Yan, Weizhen Qi, Yeyun Gong, Dayiheng Liu, Nan Duan, Jiusheng Chen, Ruofei Zhang and Ming Zhou.
|
1. **[XLM-ProphetNet](https://huggingface.co/transformers/model_doc/xlmprophetnet.html)** (from Microsoft Research) released with the paper [ProphetNet: Predicting Future N-gram for Sequence-to-Sequence Pre-training](https://arxiv.org/abs/2001.04063) by Yu Yan, Weizhen Qi, Yeyun Gong, Dayiheng Liu, Nan Duan, Jiusheng Chen, Ruofei Zhang and Ming Zhou.
|
||||||
@@ -222,4 +223,4 @@ We now have a [paper](https://arxiv.org/abs/1910.03771) you can cite for the
|
|||||||
year={2019},
|
year={2019},
|
||||||
volume={abs/1910.03771}
|
volume={abs/1910.03771}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
+10
-6
@@ -145,22 +145,25 @@ conversion utilities for the following models:
|
|||||||
27. :doc:`T5 <model_doc/t5>` (from Google AI) released with the paper `Exploring the Limits of Transfer Learning with a
|
27. :doc:`T5 <model_doc/t5>` (from Google AI) released with the paper `Exploring the Limits of Transfer Learning with a
|
||||||
Unified Text-to-Text Transformer <https://arxiv.org/abs/1910.10683>`__ by Colin Raffel and Noam Shazeer and Adam
|
Unified Text-to-Text Transformer <https://arxiv.org/abs/1910.10683>`__ by Colin Raffel and Noam Shazeer and Adam
|
||||||
Roberts and Katherine Lee and Sharan Narang and Michael Matena and Yanqi Zhou and Wei Li and Peter J. Liu.
|
Roberts and Katherine Lee and Sharan Narang and Michael Matena and Yanqi Zhou and Wei Li and Peter J. Liu.
|
||||||
28. :doc:`Transformer-XL <model_doc/transformerxl>` (from Google/CMU) released with the paper `Transformer-XL:
|
28. :doc:`TAPAS <model_doc/tapas>` (from Google AI) released with the paper `TAPAS: Weakly Supervised Table Parsing via
|
||||||
|
Pre-training <https://arxiv.org/abs/2004.02349>`__ by Jonathan Herzig, Paweł Krzysztof Nowak, Thomas Müller,
|
||||||
|
Francesco Piccinno and Julian Martin Eisenschlos.
|
||||||
|
29. :doc:`Transformer-XL <model_doc/transformerxl>` (from Google/CMU) released with the paper `Transformer-XL:
|
||||||
Attentive Language Models Beyond a Fixed-Length Context <https://arxiv.org/abs/1901.02860>`__ by Zihang Dai*,
|
Attentive Language Models Beyond a Fixed-Length Context <https://arxiv.org/abs/1901.02860>`__ by Zihang Dai*,
|
||||||
Zhilin Yang*, Yiming Yang, Jaime Carbonell, Quoc V. Le, Ruslan Salakhutdinov.
|
Zhilin Yang*, Yiming Yang, Jaime Carbonell, Quoc V. Le, Ruslan Salakhutdinov.
|
||||||
29. :doc:`XLM <model_doc/xlm>` (from Facebook) released together with the paper `Cross-lingual Language Model
|
30. :doc:`XLM <model_doc/xlm>` (from Facebook) released together with the paper `Cross-lingual Language Model
|
||||||
Pretraining <https://arxiv.org/abs/1901.07291>`__ by Guillaume Lample and Alexis Conneau.
|
Pretraining <https://arxiv.org/abs/1901.07291>`__ by Guillaume Lample and Alexis Conneau.
|
||||||
30. :doc:`XLM-ProphetNet <model_doc/xlmprophetnet>` (from Microsoft Research) released with the paper `ProphetNet:
|
31. :doc:`XLM-ProphetNet <model_doc/xlmprophetnet>` (from Microsoft Research) released with the paper `ProphetNet:
|
||||||
Predicting Future N-gram for Sequence-to-Sequence Pre-training <https://arxiv.org/abs/2001.04063>`__ by Yu Yan,
|
Predicting Future N-gram for Sequence-to-Sequence Pre-training <https://arxiv.org/abs/2001.04063>`__ by Yu Yan,
|
||||||
Weizhen Qi, Yeyun Gong, Dayiheng Liu, Nan Duan, Jiusheng Chen, Ruofei Zhang and Ming Zhou.
|
Weizhen Qi, Yeyun Gong, Dayiheng Liu, Nan Duan, Jiusheng Chen, Ruofei Zhang and Ming Zhou.
|
||||||
31. :doc:`XLM-RoBERTa <model_doc/xlmroberta>` (from Facebook AI), released together with the paper `Unsupervised
|
32. :doc:`XLM-RoBERTa <model_doc/xlmroberta>` (from Facebook AI), released together with the paper `Unsupervised
|
||||||
Cross-lingual Representation Learning at Scale <https://arxiv.org/abs/1911.02116>`__ by Alexis Conneau*, Kartikay
|
Cross-lingual Representation Learning at Scale <https://arxiv.org/abs/1911.02116>`__ by Alexis Conneau*, Kartikay
|
||||||
Khandelwal*, Naman Goyal, Vishrav Chaudhary, Guillaume Wenzek, Francisco Guzmán, Edouard Grave, Myle Ott, Luke
|
Khandelwal*, Naman Goyal, Vishrav Chaudhary, Guillaume Wenzek, Francisco Guzmán, Edouard Grave, Myle Ott, Luke
|
||||||
Zettlemoyer and Veselin Stoyanov.
|
Zettlemoyer and Veselin Stoyanov.
|
||||||
32. :doc:`XLNet <model_doc/xlnet>` (from Google/CMU) released with the paper `XLNet: Generalized Autoregressive
|
33. :doc:`XLNet <model_doc/xlnet>` (from Google/CMU) released with the paper `XLNet: Generalized Autoregressive
|
||||||
Pretraining for Language Understanding <https://arxiv.org/abs/1906.08237>`__ by Zhilin Yang*, Zihang Dai*, Yiming
|
Pretraining for Language Understanding <https://arxiv.org/abs/1906.08237>`__ by Zhilin Yang*, Zihang Dai*, Yiming
|
||||||
Yang, Jaime Carbonell, Ruslan Salakhutdinov, Quoc V. Le.
|
Yang, Jaime Carbonell, Ruslan Salakhutdinov, Quoc V. Le.
|
||||||
33. `Other community models <https://huggingface.co/models>`__, contributed by the `community
|
34. `Other community models <https://huggingface.co/models>`__, contributed by the `community
|
||||||
<https://huggingface.co/users>`__.
|
<https://huggingface.co/users>`__.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
@@ -258,6 +261,7 @@ conversion utilities for the following models:
|
|||||||
model_doc/roberta
|
model_doc/roberta
|
||||||
model_doc/squeezebert
|
model_doc/squeezebert
|
||||||
model_doc/t5
|
model_doc/t5
|
||||||
|
model_doc/tapas
|
||||||
model_doc/transformerxl
|
model_doc/transformerxl
|
||||||
model_doc/xlm
|
model_doc/xlm
|
||||||
model_doc/xlmprophetnet
|
model_doc/xlmprophetnet
|
||||||
|
|||||||
@@ -0,0 +1,162 @@
|
|||||||
|
TAPAS
|
||||||
|
-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Overview
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The TAPAS model was proposed in `TAPAS: Weakly Supervised Table Parsing via Pre-training
|
||||||
|
<https://arxiv.org/abs/2004.02349>`__ by Jonathan Herzig, Paweł Krzysztof Nowak, Thomas Müller, Francesco Piccinno and
|
||||||
|
Julian Martin Eisenschlos. It's a BERT-based model specifically designed (and pre-trained) for answering questions
|
||||||
|
about tabular data. Compared to BERT, TAPAS uses relative position embeddings and has 7 token types that encode tabular
|
||||||
|
structure. TAPAS is pre-trained on the masked language modeling (MLM) objective on a large dataset comprising millions
|
||||||
|
of tables from English Wikipedia and corresponding texts. For question answering, TAPAS has 2 heads on top: a cell
|
||||||
|
selection head and an aggregation head, for (optionally) performing aggregations (such as counting or summing) among
|
||||||
|
selected cells. TAPAS has been fine-tuned on several datasets: SQA (Sequential Question Answering by Microsoft), WTQ
|
||||||
|
(Wiki Table Questions by Stanford University) and WikiSQL (by Salesforce). It achieves state-of-the-art on both SQA and
|
||||||
|
WTQ, while having comparable performance to SOTA on WikiSQL, with a much simpler architecture.
|
||||||
|
|
||||||
|
The abstract from the paper is the following:
|
||||||
|
|
||||||
|
*Answering natural language questions over tables is usually seen as a semantic parsing task. To alleviate the
|
||||||
|
collection cost of full logical forms, one popular approach focuses on weak supervision consisting of denotations
|
||||||
|
instead of logical forms. However, training semantic parsers from weak supervision poses difficulties, and in addition,
|
||||||
|
the generated logical forms are only used as an intermediate step prior to retrieving the denotation. In this paper, we
|
||||||
|
present TAPAS, an approach to question answering over tables without generating logical forms. TAPAS trains from weak
|
||||||
|
supervision, and predicts the denotation by selecting table cells and optionally applying a corresponding aggregation
|
||||||
|
operator to such selection. TAPAS extends BERT's architecture to encode tables as input, initializes from an effective
|
||||||
|
joint pre-training of text segments and tables crawled from Wikipedia, and is trained end-to-end. We experiment with
|
||||||
|
three different semantic parsing datasets, and find that TAPAS outperforms or rivals semantic parsing models by
|
||||||
|
improving state-of-the-art accuracy on SQA from 55.1 to 67.2 and performing on par with the state-of-the-art on WIKISQL
|
||||||
|
and WIKITQ, but with a simpler model architecture. We additionally find that transfer learning, which is trivial in our
|
||||||
|
setting, from WIKISQL to WIKITQ, yields 48.7 accuracy, 4.2 points above the state-of-the-art.*
|
||||||
|
|
||||||
|
In addition, the authors have further pre-trained TAPAS to recognize table entailment, by creating a balanced dataset
|
||||||
|
of millions of automatically created training examples which are learned in an intermediate step prior to fine-tuning.
|
||||||
|
The authors of TAPAS call this further pre-training intermediate pre-training (since TAPAS is first pre-trained on MLM,
|
||||||
|
and then on another dataset). They found that intermediate pre-training further improves performance on SQA, achieving
|
||||||
|
a new state-of-the-art as well as state-of-the-art on TabFact, a large-scale dataset with 16k Wikipedia tables for
|
||||||
|
table entailment (a binary classification task). For more details, see their new paper: `Understanding tables with
|
||||||
|
intermediate pre-training <https://arxiv.org/abs/2010.00571>`__ by Julian Martin Eisenschlos, Syrine Krichene and
|
||||||
|
Thomas Müller.
|
||||||
|
|
||||||
|
The original code can be found `here <https://github.com/google-research/tapas>`__.
|
||||||
|
|
||||||
|
Tips:
|
||||||
|
|
||||||
|
- TAPAS is a model that uses relative position embeddings by default (restarting the position embeddings at every cell
|
||||||
|
of the table). According to the authors, this usually results in a slightly better performance, and allows you to
|
||||||
|
encode longer sequences without running out of embeddings. If you don't want this, you can set the
|
||||||
|
`reset_position_index_per_cell` parameter of :class:`~transformers.TapasConfig` to False.
|
||||||
|
- TAPAS has checkpoints fine-tuned on SQA, which are capable of answering questions related to a table in a
|
||||||
|
conversational set-up. This means that you can ask follow-up questions such as "what is his age?" related to the
|
||||||
|
previous question. Note that the forward pass of TAPAS is a bit different in case of a conversational set-up: in that
|
||||||
|
case, you have to feed every training example one by one to the model, such that the `prev_label_ids` token type ids
|
||||||
|
can be overwritten by the predicted `label_ids` of the model to the previous question.
|
||||||
|
- TAPAS is similar to BERT and therefore relies on the masked language modeling (MLM) objective. It is therefore
|
||||||
|
efficient at predicting masked tokens and at NLU in general, but is not optimal for text generation. Models trained
|
||||||
|
with a causal language modeling (CLM) objective are better in that regard.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If you just want to perform inference (i.e. making predictions) in a non-conversational setup, you can do the
|
||||||
|
following:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
>>> from transformers import TapasTokenizer, TapasForQuestionAnswering
|
||||||
|
>>> import pandas as pd
|
||||||
|
|
||||||
|
>>> model_name = 'tapas-base-finetuned-wtq'
|
||||||
|
>>> model = TapasForQuestionAnswering.from_pretrained(model_name)
|
||||||
|
>>> tokenizer = TapasTokenizer.from_pretrained(model_name)
|
||||||
|
|
||||||
|
>>> data = {'Actors': ["Brad Pitt", "Leonardo Di Caprio", "George Clooney"], 'Number of movies': ["87", "53", "69"]}
|
||||||
|
>>> queries = ["What is the name of the first actor?", "How many movies has George Clooney played in?", "What is the total number of movies?"]
|
||||||
|
>>> table = pd.Dataframe(data)
|
||||||
|
>>> inputs = tokenizer(table, queries, return_tensors='pt')
|
||||||
|
>>> logits, logits_agg = model(**inputs)
|
||||||
|
>>> answer_coordinates_batch, aggregation_predictions = tokenizer.convert_logits_to_predictions(inputs, logits, logits_agg)
|
||||||
|
|
||||||
|
>>> # let's print out the results:
|
||||||
|
>>> id2aggregation = {0: "NONE", 1: "SUM", 2: "AVERAGE", 3:"COUNT"}
|
||||||
|
>>> aggregation_predictions_string = [id2aggregation[x] for x in aggregation_predictions]
|
||||||
|
|
||||||
|
>>> answers = []
|
||||||
|
>>> for coordinates in answer_coordinates_batch:
|
||||||
|
... if len(coordinates) == 1:
|
||||||
|
... # only a single cell:
|
||||||
|
... answers.append(df.iat[coordinates[0]])
|
||||||
|
... else:
|
||||||
|
... # multiple cells
|
||||||
|
... cell_values = []
|
||||||
|
... for coordinate in coordinates:
|
||||||
|
... cell_values.append(df.iat[coordinate])
|
||||||
|
... answers.append(", ".join(cell_values))
|
||||||
|
|
||||||
|
>>> display(df)
|
||||||
|
>>> print("")
|
||||||
|
>>> for query, answer, predicted_agg in zip(queries, answers, aggregation_predictions_string):
|
||||||
|
... print(query)
|
||||||
|
... if predicted_agg == "NONE":
|
||||||
|
... print("Predicted answer: " + answer)
|
||||||
|
... else:
|
||||||
|
... print("Predicted answer: " + predicted_agg + " > " + answer)
|
||||||
|
When was Brad Pitt born?
|
||||||
|
Predicted answer: 18 december 1963
|
||||||
|
Which actor appeared in the least number of movies?
|
||||||
|
Predicted answer: Leonardo Di Caprio
|
||||||
|
What is the average number of movies?
|
||||||
|
Predicted answer: AVERAGE > 87, 53, 69
|
||||||
|
|
||||||
|
|
||||||
|
Tapas specific outputs
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: transformers.modeling_tapas.TableQuestionAnsweringOutput
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
TapasConfig
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: transformers.TapasConfig
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
TapasTokenizer
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: transformers.TapasTokenizer
|
||||||
|
:members: convert_logits_to_predictions, save_vocabulary
|
||||||
|
|
||||||
|
|
||||||
|
TapasModel
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: transformers.TapasModel
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
TapasForMaskedLM
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: transformers.TapasForMaskedLM
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
TapasForSequenceClassification
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: transformers.TapasForSequenceClassification
|
||||||
|
:members: forward
|
||||||
|
|
||||||
|
|
||||||
|
TapasForQuestionAnswering
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: transformers.TapasForQuestionAnswering
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ from .configuration_retribert import RETRIBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, Re
|
|||||||
from .configuration_roberta import ROBERTA_PRETRAINED_CONFIG_ARCHIVE_MAP, RobertaConfig
|
from .configuration_roberta import ROBERTA_PRETRAINED_CONFIG_ARCHIVE_MAP, RobertaConfig
|
||||||
from .configuration_squeezebert import SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, SqueezeBertConfig
|
from .configuration_squeezebert import SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, SqueezeBertConfig
|
||||||
from .configuration_t5 import T5_PRETRAINED_CONFIG_ARCHIVE_MAP, T5Config
|
from .configuration_t5 import T5_PRETRAINED_CONFIG_ARCHIVE_MAP, T5Config
|
||||||
|
from .configuration_tapas import TAPAS_PRETRAINED_CONFIG_ARCHIVE_MAP, TapasConfig
|
||||||
from .configuration_transfo_xl import TRANSFO_XL_PRETRAINED_CONFIG_ARCHIVE_MAP, TransfoXLConfig
|
from .configuration_transfo_xl import TRANSFO_XL_PRETRAINED_CONFIG_ARCHIVE_MAP, TransfoXLConfig
|
||||||
from .configuration_utils import PretrainedConfig
|
from .configuration_utils import PretrainedConfig
|
||||||
from .configuration_xlm import XLM_PRETRAINED_CONFIG_ARCHIVE_MAP, XLMConfig
|
from .configuration_xlm import XLM_PRETRAINED_CONFIG_ARCHIVE_MAP, XLMConfig
|
||||||
@@ -190,6 +191,7 @@ from .tokenization_rag import RagTokenizer
|
|||||||
from .tokenization_retribert import RetriBertTokenizer
|
from .tokenization_retribert import RetriBertTokenizer
|
||||||
from .tokenization_roberta import RobertaTokenizer
|
from .tokenization_roberta import RobertaTokenizer
|
||||||
from .tokenization_squeezebert import SqueezeBertTokenizer
|
from .tokenization_squeezebert import SqueezeBertTokenizer
|
||||||
|
from .tokenization_tapas import TapasTokenizer
|
||||||
from .tokenization_transfo_xl import TransfoXLCorpus, TransfoXLTokenizer
|
from .tokenization_transfo_xl import TransfoXLCorpus, TransfoXLTokenizer
|
||||||
from .tokenization_utils import PreTrainedTokenizer
|
from .tokenization_utils import PreTrainedTokenizer
|
||||||
from .tokenization_utils_base import (
|
from .tokenization_utils_base import (
|
||||||
@@ -558,6 +560,14 @@ if is_torch_available():
|
|||||||
T5PreTrainedModel,
|
T5PreTrainedModel,
|
||||||
load_tf_weights_in_t5,
|
load_tf_weights_in_t5,
|
||||||
)
|
)
|
||||||
|
from .modeling_tapas import (
|
||||||
|
TAPAS_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||||
|
TapasForMaskedLM,
|
||||||
|
TapasForQuestionAnswering,
|
||||||
|
TapasForSequenceClassification,
|
||||||
|
TapasModel,
|
||||||
|
load_tf_weights_in_tapas,
|
||||||
|
)
|
||||||
from .modeling_transfo_xl import (
|
from .modeling_transfo_xl import (
|
||||||
TRANSFO_XL_PRETRAINED_MODEL_ARCHIVE_LIST,
|
TRANSFO_XL_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||||
AdaptiveEmbedding,
|
AdaptiveEmbedding,
|
||||||
|
|||||||
@@ -130,6 +130,13 @@ class ConvertCommand(BaseTransformersCLICommand):
|
|||||||
raise ImportError(IMPORT_ERROR_MESSAGE)
|
raise ImportError(IMPORT_ERROR_MESSAGE)
|
||||||
|
|
||||||
convert_gpt2_checkpoint_to_pytorch(self._tf_checkpoint, self._config, self._pytorch_dump_output)
|
convert_gpt2_checkpoint_to_pytorch(self._tf_checkpoint, self._config, self._pytorch_dump_output)
|
||||||
|
elif self._model_type == "tapas":
|
||||||
|
try:
|
||||||
|
from transformers.convert_tapas_original_tf_checkpoint_to_pytorch import (
|
||||||
|
convert_tf_checkpoint_to_pytorch,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
raise ImportError(IMPORT_ERROR_MESSAGE)
|
||||||
elif self._model_type == "xlnet":
|
elif self._model_type == "xlnet":
|
||||||
try:
|
try:
|
||||||
from transformers.convert_xlnet_original_tf_checkpoint_to_pytorch import (
|
from transformers.convert_xlnet_original_tf_checkpoint_to_pytorch import (
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ from .configuration_retribert import RETRIBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, Re
|
|||||||
from .configuration_roberta import ROBERTA_PRETRAINED_CONFIG_ARCHIVE_MAP, RobertaConfig
|
from .configuration_roberta import ROBERTA_PRETRAINED_CONFIG_ARCHIVE_MAP, RobertaConfig
|
||||||
from .configuration_squeezebert import SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, SqueezeBertConfig
|
from .configuration_squeezebert import SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, SqueezeBertConfig
|
||||||
from .configuration_t5 import T5_PRETRAINED_CONFIG_ARCHIVE_MAP, T5Config
|
from .configuration_t5 import T5_PRETRAINED_CONFIG_ARCHIVE_MAP, T5Config
|
||||||
|
from .configuration_tapas import TAPAS_PRETRAINED_CONFIG_ARCHIVE_MAP, TapasConfig
|
||||||
from .configuration_transfo_xl import TRANSFO_XL_PRETRAINED_CONFIG_ARCHIVE_MAP, TransfoXLConfig
|
from .configuration_transfo_xl import TRANSFO_XL_PRETRAINED_CONFIG_ARCHIVE_MAP, TransfoXLConfig
|
||||||
from .configuration_utils import PretrainedConfig
|
from .configuration_utils import PretrainedConfig
|
||||||
from .configuration_xlm import XLM_PRETRAINED_CONFIG_ARCHIVE_MAP, XLMConfig
|
from .configuration_xlm import XLM_PRETRAINED_CONFIG_ARCHIVE_MAP, XLMConfig
|
||||||
@@ -88,6 +89,7 @@ ALL_PRETRAINED_CONFIG_ARCHIVE_MAP = dict(
|
|||||||
SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||||
XLM_PROPHETNET_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
XLM_PROPHETNET_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||||
PROPHETNET_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
PROPHETNET_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||||
|
TAPAS_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||||
]
|
]
|
||||||
for key, value, in pretrained_map.items()
|
for key, value, in pretrained_map.items()
|
||||||
)
|
)
|
||||||
@@ -131,6 +133,7 @@ CONFIG_MAPPING = OrderedDict(
|
|||||||
("dpr", DPRConfig),
|
("dpr", DPRConfig),
|
||||||
("layoutlm", LayoutLMConfig),
|
("layoutlm", LayoutLMConfig),
|
||||||
("rag", RagConfig),
|
("rag", RagConfig),
|
||||||
|
("tapas", TapasConfig),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -172,6 +175,7 @@ MODEL_NAMES_MAPPING = OrderedDict(
|
|||||||
("rag", "RAG"),
|
("rag", "RAG"),
|
||||||
("xlm-prophetnet", "XLMProphetNet"),
|
("xlm-prophetnet", "XLMProphetNet"),
|
||||||
("prophetnet", "ProphetNet"),
|
("prophetnet", "ProphetNet"),
|
||||||
|
("tapas", "TAPAS"),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
# Copyright 2020 Google Research and The HuggingFace Inc. team.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
""" TAPAS configuration. Adds additional hyperparameters to the configuration of BERT."""
|
||||||
|
|
||||||
|
|
||||||
|
from .configuration_utils import PretrainedConfig
|
||||||
|
|
||||||
|
|
||||||
|
TAPAS_PRETRAINED_CONFIG_ARCHIVE_MAP = {"tapas-base": "", "tapas-large": ""} # to be added # to be added
|
||||||
|
|
||||||
|
|
||||||
|
class TapasConfig(PretrainedConfig):
|
||||||
|
r"""
|
||||||
|
This is the configuration class to store the configuration of a :class:`~transformers.TapasModel`. It is used to
|
||||||
|
instantiate a TAPAS model according to the specified arguments, defining the model architecture. Instantiating a
|
||||||
|
configuration with the defaults will yield a similar configuration to that of the TAPAS `tapas-base-finetuned-sqa`
|
||||||
|
architecture. Configuration objects inherit from :class:`~transformers.PreTrainedConfig` and can be used to control
|
||||||
|
the model outputs. Read the documentation from :class:`~transformers.PretrainedConfig` for more information.
|
||||||
|
|
||||||
|
Hyperparameters additional to BERT are taken from run_task_main.py and hparam_utils.py of the original
|
||||||
|
implementation. Original implementation available at https://github.com/google-research/tapas/tree/master.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
vocab_size (:obj:`int`, `optional`, defaults to 30522):
|
||||||
|
Vocabulary size of the TAPAS model. Defines the number of different tokens that can be represented by the
|
||||||
|
:obj:`inputs_ids` passed when calling :class:`~transformers.TapasModel`.
|
||||||
|
hidden_size (:obj:`int`, `optional`, defaults to 768):
|
||||||
|
Dimensionality of the encoder layers and the pooler layer.
|
||||||
|
num_hidden_layers (:obj:`int`, `optional`, defaults to 12):
|
||||||
|
Number of hidden layers in the Transformer encoder.
|
||||||
|
num_attention_heads (:obj:`int`, `optional`, defaults to 12):
|
||||||
|
Number of attention heads for each attention layer in the Transformer encoder.
|
||||||
|
intermediate_size (:obj:`int`, `optional`, defaults to 3072):
|
||||||
|
Dimensionality of the "intermediate" (often named feed-forward) layer in the Transformer encoder.
|
||||||
|
hidden_act (:obj:`str` or :obj:`Callable`, `optional`, defaults to :obj:`"gelu"`):
|
||||||
|
The non-linear activation function (function or string) in the encoder and pooler. If string,
|
||||||
|
:obj:`"gelu"`, :obj:`"relu"`, :obj:`"swish"` and :obj:`"gelu_new"` are supported.
|
||||||
|
hidden_dropout_prob (:obj:`float`, `optional`, defaults to 0.1):
|
||||||
|
The dropout probability for all fully connected layers in the embeddings, encoder, and pooler.
|
||||||
|
attention_probs_dropout_prob (:obj:`float`, `optional`, defaults to 0.1):
|
||||||
|
The dropout ratio for the attention probabilities.
|
||||||
|
max_position_embeddings (:obj:`int`, `optional`, defaults to 1024):
|
||||||
|
The maximum sequence length that this model might ever be used with. Typically set this to something large
|
||||||
|
just in case (e.g., 512 or 1024 or 2048).
|
||||||
|
type_vocab_sizes (:obj:`List[int]`, `optional`, defaults to [3, 256, 256, 2, 256, 256, 10]):
|
||||||
|
The vocabulary sizes of the :obj:`token_type_ids` passed when calling :class:`~transformers.TapasModel`.
|
||||||
|
initializer_range (:obj:`float`, `optional`, defaults to 0.02):
|
||||||
|
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
||||||
|
layer_norm_eps (:obj:`float`, `optional`, defaults to 1e-12):
|
||||||
|
The epsilon used by the layer normalization layers.
|
||||||
|
gradient_checkpointing (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||||
|
If True, use gradient checkpointing to save memory at the expense of slower backward pass.
|
||||||
|
positive_label_weight (:obj:`float`, `optional`, defaults to 10.0):
|
||||||
|
Weight for positive labels.
|
||||||
|
num_aggregation_labels (:obj:`int`, `optional`, defaults to 0):
|
||||||
|
The number of aggregation operators to predict.
|
||||||
|
aggregation_loss_weight (:obj:`float`, `optional`, defaults to 1.0):
|
||||||
|
Importance weight for the aggregation loss.
|
||||||
|
use_answer_as_supervision (:obj:`bool`, `optional`, defaults to :obj:`None`):
|
||||||
|
Whether to use the answer as the only supervision for aggregation examples.
|
||||||
|
answer_loss_importance (:obj:`float`, `optional`, defaults to 1.0):
|
||||||
|
Importance weight for the regression loss.
|
||||||
|
use_normalized_answer_loss (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||||
|
Normalize loss by max of predicted and expected value.
|
||||||
|
huber_loss_delta: (:obj:`float`, `optional`, defaults to None):
|
||||||
|
Delta parameter used to calculate the regression loss.
|
||||||
|
temperature: (:obj:`float`, `optional`, defaults to 1.0):
|
||||||
|
Scales cell logits to control the skewness of probabilities.
|
||||||
|
aggregation_temperature: (:obj:`float`, `optional`, defaults to 1.0):
|
||||||
|
Scales aggregation logits to control the skewness of probabilities.
|
||||||
|
use_gumbel_for_cells: (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||||
|
Applies Gumbel-Softmax to cell selection.
|
||||||
|
use_gumbel_for_aggregation: (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||||
|
Applies Gumbel-Softmax to aggregation selection.
|
||||||
|
average_approximation_function: (:obj:`string`, `optional`, defaults to :obj:`"ratio"`):
|
||||||
|
Method to calculate expected average of cells in the relaxed case.
|
||||||
|
cell_selection_preference: (:obj:`float`, `optional`, defaults to None):
|
||||||
|
Preference for cell selection in ambiguous cases. Only applicable in case of weak supervision for
|
||||||
|
aggregation (WTQ, WikiSQL). If the total mass of the aggregation probabilities (excluding the "NONE"
|
||||||
|
operator) is higher than this hyperparameter, then aggregation is predicted for an example.
|
||||||
|
answer_loss_cutoff: (:obj:`float`, `optional`, defaults to None):
|
||||||
|
Ignore examples with answer loss larger than cutoff.
|
||||||
|
max_num_rows: (:obj:`int`, `optional`, defaults to 64):
|
||||||
|
Maximum number of rows.
|
||||||
|
max_num_columns: (:obj:`int`, `optional`, defaults to 32):
|
||||||
|
Maximum number of columns.
|
||||||
|
average_logits_per_cell: (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||||
|
Whether to average logits per cell.
|
||||||
|
select_one_column: (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||||
|
Whether to constrain the model to only select cells from a single column.
|
||||||
|
allow_empty_column_selection: (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||||
|
Allow not to select any column.
|
||||||
|
init_cell_selection_weights_to_zero: (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||||
|
Whether to initialize cell selection weights to 0 so that the initial probabilities are 50%.
|
||||||
|
reset_position_index_per_cell: (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||||
|
Restart position indexes at every cell.
|
||||||
|
disable_per_token_loss: (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||||
|
Disable any (strong or weak) supervision on cells.
|
||||||
|
span_prediction: (:obj:`string`, `optional`, defaults to :obj:`"none"`):
|
||||||
|
Span selection mode to use. Currently only "none" is supported.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
>>> from transformers import TapasModel, TapasConfig
|
||||||
|
>>> # Initializing a Tapas configuration
|
||||||
|
>>> configuration = TapasConfig()
|
||||||
|
>>> # Initializing a model from the configuration
|
||||||
|
>>> model = TapasModel(configuration)
|
||||||
|
>>> # Accessing the model configuration
|
||||||
|
>>> configuration = model.config
|
||||||
|
"""
|
||||||
|
|
||||||
|
model_type = "tapas"
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
vocab_size=30522,
|
||||||
|
hidden_size=768,
|
||||||
|
num_hidden_layers=12,
|
||||||
|
num_attention_heads=12,
|
||||||
|
intermediate_size=3072,
|
||||||
|
hidden_act="gelu",
|
||||||
|
hidden_dropout_prob=0.1,
|
||||||
|
attention_probs_dropout_prob=0.1,
|
||||||
|
max_position_embeddings=1024,
|
||||||
|
type_vocab_sizes=[3, 256, 256, 2, 256, 256, 10],
|
||||||
|
initializer_range=0.02,
|
||||||
|
layer_norm_eps=1e-12,
|
||||||
|
pad_token_id=0,
|
||||||
|
gradient_checkpointing=False,
|
||||||
|
positive_label_weight=10.0,
|
||||||
|
num_aggregation_labels=0,
|
||||||
|
aggregation_loss_weight=1.0,
|
||||||
|
use_answer_as_supervision=None,
|
||||||
|
answer_loss_importance=1.0,
|
||||||
|
use_normalized_answer_loss=False,
|
||||||
|
huber_loss_delta=None,
|
||||||
|
temperature=1.0,
|
||||||
|
aggregation_temperature=1.0,
|
||||||
|
use_gumbel_for_cells=False,
|
||||||
|
use_gumbel_for_aggregation=False,
|
||||||
|
average_approximation_function="ratio",
|
||||||
|
cell_selection_preference=None,
|
||||||
|
answer_loss_cutoff=None,
|
||||||
|
max_num_rows=64,
|
||||||
|
max_num_columns=32,
|
||||||
|
average_logits_per_cell=False,
|
||||||
|
select_one_column=True,
|
||||||
|
allow_empty_column_selection=False,
|
||||||
|
init_cell_selection_weights_to_zero=False,
|
||||||
|
reset_position_index_per_cell=True,
|
||||||
|
disable_per_token_loss=False,
|
||||||
|
span_prediction="none",
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
|
||||||
|
super().__init__(pad_token_id=pad_token_id, **kwargs)
|
||||||
|
|
||||||
|
# BERT hyperparameters (with updated max_position_embeddings and type_vocab_sizes)
|
||||||
|
self.vocab_size = vocab_size
|
||||||
|
self.hidden_size = hidden_size
|
||||||
|
self.num_hidden_layers = num_hidden_layers
|
||||||
|
self.num_attention_heads = num_attention_heads
|
||||||
|
self.hidden_act = hidden_act
|
||||||
|
self.intermediate_size = intermediate_size
|
||||||
|
self.hidden_dropout_prob = hidden_dropout_prob
|
||||||
|
self.attention_probs_dropout_prob = attention_probs_dropout_prob
|
||||||
|
self.max_position_embeddings = max_position_embeddings
|
||||||
|
self.type_vocab_sizes = type_vocab_sizes
|
||||||
|
self.initializer_range = initializer_range
|
||||||
|
self.layer_norm_eps = layer_norm_eps
|
||||||
|
self.gradient_checkpointing = gradient_checkpointing
|
||||||
|
|
||||||
|
# Fine-tuning task hyperparameters
|
||||||
|
self.positive_label_weight = positive_label_weight
|
||||||
|
self.num_aggregation_labels = num_aggregation_labels
|
||||||
|
self.aggregation_loss_weight = aggregation_loss_weight
|
||||||
|
self.use_answer_as_supervision = use_answer_as_supervision
|
||||||
|
self.answer_loss_importance = answer_loss_importance
|
||||||
|
self.use_normalized_answer_loss = use_normalized_answer_loss
|
||||||
|
self.huber_loss_delta = huber_loss_delta
|
||||||
|
self.temperature = temperature
|
||||||
|
self.aggregation_temperature = aggregation_temperature
|
||||||
|
self.use_gumbel_for_cells = use_gumbel_for_cells
|
||||||
|
self.use_gumbel_for_aggregation = use_gumbel_for_aggregation
|
||||||
|
self.average_approximation_function = average_approximation_function
|
||||||
|
self.cell_selection_preference = cell_selection_preference
|
||||||
|
self.answer_loss_cutoff = answer_loss_cutoff
|
||||||
|
self.max_num_rows = max_num_rows
|
||||||
|
self.max_num_columns = max_num_columns
|
||||||
|
self.average_logits_per_cell = average_logits_per_cell
|
||||||
|
self.select_one_column = select_one_column
|
||||||
|
self.allow_empty_column_selection = allow_empty_column_selection
|
||||||
|
self.init_cell_selection_weights_to_zero = init_cell_selection_weights_to_zero
|
||||||
|
self.reset_position_index_per_cell = reset_position_index_per_cell
|
||||||
|
self.disable_per_token_loss = disable_per_token_loss
|
||||||
|
self.span_prediction = span_prediction
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
# Copyright 2018 The HuggingFace Inc. team.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
"""Convert TAPAS checkpoint."""
|
||||||
|
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
import torch
|
||||||
|
|
||||||
|
from transformers import (
|
||||||
|
TapasConfig,
|
||||||
|
TapasForQuestionAnswering,
|
||||||
|
TapasForSequenceClassification,
|
||||||
|
load_tf_weights_in_tapas,
|
||||||
|
)
|
||||||
|
from transformers.utils import logging
|
||||||
|
|
||||||
|
|
||||||
|
logging.set_verbosity_info()
|
||||||
|
|
||||||
|
|
||||||
|
def convert_tf_checkpoint_to_pytorch(tf_checkpoint_path, tapas_config_file, pytorch_dump_path):
|
||||||
|
# Initialise PyTorch model
|
||||||
|
|
||||||
|
# WTQ config
|
||||||
|
# config = TapasConfig(# run_task_main.py hparams
|
||||||
|
# num_aggregation_labels = 4,
|
||||||
|
# use_answer_as_supervision = True,
|
||||||
|
# # hparam_utils.py hparams
|
||||||
|
# answer_loss_cutoff = 0.664694,
|
||||||
|
# cell_select_pref = 0.207951,
|
||||||
|
# huber_loss_delta = 0.121194,
|
||||||
|
# init_cell_selection_weights_to_zero = True,
|
||||||
|
# select_one_column = True,
|
||||||
|
# allow_empty_column_selection = False,
|
||||||
|
# temperature = 0.0352513)
|
||||||
|
|
||||||
|
# SQA config
|
||||||
|
config = TapasConfig()
|
||||||
|
|
||||||
|
print("Building PyTorch model from configuration: {}".format(str(config)))
|
||||||
|
# model = TapasForMaskedLM(config)
|
||||||
|
model = TapasForQuestionAnswering(config)
|
||||||
|
# model = TapasForSequenceClassification(config)
|
||||||
|
|
||||||
|
# Load weights from tf checkpoint
|
||||||
|
load_tf_weights_in_tapas(model, config, tf_checkpoint_path)
|
||||||
|
|
||||||
|
# Save pytorch-model
|
||||||
|
print("Save PyTorch model to {}".format(pytorch_dump_path))
|
||||||
|
torch.save(model.state_dict(), pytorch_dump_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
# Required parameters
|
||||||
|
parser.add_argument(
|
||||||
|
"--tf_checkpoint_path", default=None, type=str, required=True, help="Path to the TensorFlow checkpoint path."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--tapas_config_file",
|
||||||
|
default=None,
|
||||||
|
type=str,
|
||||||
|
required=True,
|
||||||
|
help="The config json file corresponding to the pre-trained TAPAS model. \n"
|
||||||
|
"This specifies the model architecture.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--pytorch_dump_path", default=None, type=str, required=True, help="Path to the output PyTorch model."
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
convert_tf_checkpoint_to_pytorch(args.tf_checkpoint_path, args.tapas_config_file, args.pytorch_dump_path)
|
||||||
@@ -193,6 +193,20 @@ except ImportError:
|
|||||||
_tokenizers_available = False
|
_tokenizers_available = False
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
import torch_scatter
|
||||||
|
|
||||||
|
# Check we're not importing a "torch_scatter" directory somewhere
|
||||||
|
_scatter_available = hasattr(torch_scatter, "__version__") and hasattr(torch_scatter, "scatter")
|
||||||
|
if _scatter_available:
|
||||||
|
logger.debug(f"Succesfully imported torch-scatter version {torch_scatter.__version__}")
|
||||||
|
else:
|
||||||
|
logger.debug("Imported a torch_scatter object but this doesn't seem to be the torch-scatter library.")
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
_scatter_available = False
|
||||||
|
|
||||||
|
|
||||||
default_cache_path = os.path.join(torch_cache_home, "transformers")
|
default_cache_path = os.path.join(torch_cache_home, "transformers")
|
||||||
|
|
||||||
|
|
||||||
@@ -289,6 +303,14 @@ def torch_only_method(fn):
|
|||||||
|
|
||||||
|
|
||||||
# docstyle-ignore
|
# docstyle-ignore
|
||||||
|
def is_sklearn_available():
|
||||||
|
return _has_sklearn
|
||||||
|
|
||||||
|
|
||||||
|
def is_scatter_available():
|
||||||
|
return _scatter_available
|
||||||
|
|
||||||
|
|
||||||
DATASETS_IMPORT_ERROR = """
|
DATASETS_IMPORT_ERROR = """
|
||||||
{0} requires the 🤗 Datasets library but it was not found in your environment. You can install it with:
|
{0} requires the 🤗 Datasets library but it was not found in your environment. You can install it with:
|
||||||
```
|
```
|
||||||
@@ -368,6 +390,12 @@ FLAX_IMPORT_ERROR = """
|
|||||||
installation page: https://github.com/google/flax and follow the ones that match your environment.
|
installation page: https://github.com/google/flax and follow the ones that match your environment.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
SCATTER_IMPORT_ERROR = """
|
||||||
|
{0} requires the torch-scatter library but it was not found in your environment. You can install it with pip as
|
||||||
|
explained here: https://github.com/rusty1s/pytorch_scatter.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def requires_datasets(obj):
|
def requires_datasets(obj):
|
||||||
name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__
|
name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__
|
||||||
@@ -417,6 +445,12 @@ def requires_sentencepiece(obj):
|
|||||||
raise ImportError(SENTENCEPIECE_IMPORT_ERROR.format(name))
|
raise ImportError(SENTENCEPIECE_IMPORT_ERROR.format(name))
|
||||||
|
|
||||||
|
|
||||||
|
def requires_scatter(obj):
|
||||||
|
name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__
|
||||||
|
if not is_scatter_available():
|
||||||
|
raise ImportError(SCATTER_IMPORT_ERROR.format(name))
|
||||||
|
|
||||||
|
|
||||||
def add_start_docstrings(*docstr):
|
def add_start_docstrings(*docstr):
|
||||||
def docstring_decorator(fn):
|
def docstring_decorator(fn):
|
||||||
fn.__doc__ = "".join(docstr) + (fn.__doc__ if fn.__doc__ is not None else "")
|
fn.__doc__ = "".join(docstr) + (fn.__doc__ if fn.__doc__ is not None else "")
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ from .configuration_auto import (
|
|||||||
RobertaConfig,
|
RobertaConfig,
|
||||||
SqueezeBertConfig,
|
SqueezeBertConfig,
|
||||||
T5Config,
|
T5Config,
|
||||||
|
TapasConfig,
|
||||||
TransfoXLConfig,
|
TransfoXLConfig,
|
||||||
XLMConfig,
|
XLMConfig,
|
||||||
XLMProphetNetConfig,
|
XLMProphetNetConfig,
|
||||||
@@ -188,6 +189,7 @@ from .modeling_squeezebert import (
|
|||||||
SqueezeBertModel,
|
SqueezeBertModel,
|
||||||
)
|
)
|
||||||
from .modeling_t5 import T5ForConditionalGeneration, T5Model
|
from .modeling_t5 import T5ForConditionalGeneration, T5Model
|
||||||
|
from .modeling_tapas import TapasForMaskedLM, TapasForQuestionAnswering, TapasForSequenceClassification, TapasModel
|
||||||
from .modeling_transfo_xl import TransfoXLLMHeadModel, TransfoXLModel
|
from .modeling_transfo_xl import TransfoXLLMHeadModel, TransfoXLModel
|
||||||
from .modeling_xlm import (
|
from .modeling_xlm import (
|
||||||
XLMForMultipleChoice,
|
XLMForMultipleChoice,
|
||||||
@@ -229,6 +231,7 @@ MODEL_MAPPING = OrderedDict(
|
|||||||
[
|
[
|
||||||
(RetriBertConfig, RetriBertModel),
|
(RetriBertConfig, RetriBertModel),
|
||||||
(T5Config, T5Model),
|
(T5Config, T5Model),
|
||||||
|
(TapasConfig, TapasModel),
|
||||||
(DistilBertConfig, DistilBertModel),
|
(DistilBertConfig, DistilBertModel),
|
||||||
(AlbertConfig, AlbertModel),
|
(AlbertConfig, AlbertModel),
|
||||||
(CamembertConfig, CamembertModel),
|
(CamembertConfig, CamembertModel),
|
||||||
@@ -265,6 +268,7 @@ MODEL_FOR_PRETRAINING_MAPPING = OrderedDict(
|
|||||||
(LayoutLMConfig, LayoutLMForMaskedLM),
|
(LayoutLMConfig, LayoutLMForMaskedLM),
|
||||||
(RetriBertConfig, RetriBertModel),
|
(RetriBertConfig, RetriBertModel),
|
||||||
(T5Config, T5ForConditionalGeneration),
|
(T5Config, T5ForConditionalGeneration),
|
||||||
|
(TapasConfig, TapasForMaskedLM),
|
||||||
(DistilBertConfig, DistilBertForMaskedLM),
|
(DistilBertConfig, DistilBertForMaskedLM),
|
||||||
(AlbertConfig, AlbertForPreTraining),
|
(AlbertConfig, AlbertForPreTraining),
|
||||||
(CamembertConfig, CamembertForMaskedLM),
|
(CamembertConfig, CamembertForMaskedLM),
|
||||||
@@ -292,6 +296,7 @@ MODEL_WITH_LM_HEAD_MAPPING = OrderedDict(
|
|||||||
[
|
[
|
||||||
(LayoutLMConfig, LayoutLMForMaskedLM),
|
(LayoutLMConfig, LayoutLMForMaskedLM),
|
||||||
(T5Config, T5ForConditionalGeneration),
|
(T5Config, T5ForConditionalGeneration),
|
||||||
|
(TapasConfig, TapasForMaskedLM),
|
||||||
(DistilBertConfig, DistilBertForMaskedLM),
|
(DistilBertConfig, DistilBertForMaskedLM),
|
||||||
(AlbertConfig, AlbertForMaskedLM),
|
(AlbertConfig, AlbertForMaskedLM),
|
||||||
(CamembertConfig, CamembertForMaskedLM),
|
(CamembertConfig, CamembertForMaskedLM),
|
||||||
@@ -351,6 +356,7 @@ MODEL_FOR_MASKED_LM_MAPPING = OrderedDict(
|
|||||||
(LongformerConfig, LongformerForMaskedLM),
|
(LongformerConfig, LongformerForMaskedLM),
|
||||||
(RobertaConfig, RobertaForMaskedLM),
|
(RobertaConfig, RobertaForMaskedLM),
|
||||||
(SqueezeBertConfig, SqueezeBertForMaskedLM),
|
(SqueezeBertConfig, SqueezeBertForMaskedLM),
|
||||||
|
(TapasConfig, TapasForMaskedLM),
|
||||||
(BertConfig, BertForMaskedLM),
|
(BertConfig, BertForMaskedLM),
|
||||||
(MobileBertConfig, MobileBertForMaskedLM),
|
(MobileBertConfig, MobileBertForMaskedLM),
|
||||||
(FlaubertConfig, FlaubertWithLMHeadModel),
|
(FlaubertConfig, FlaubertWithLMHeadModel),
|
||||||
@@ -396,6 +402,7 @@ MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING = OrderedDict(
|
|||||||
(DebertaConfig, DebertaForSequenceClassification),
|
(DebertaConfig, DebertaForSequenceClassification),
|
||||||
(GPT2Config, GPT2ForSequenceClassification),
|
(GPT2Config, GPT2ForSequenceClassification),
|
||||||
(OpenAIGPTConfig, OpenAIGPTForSequenceClassification),
|
(OpenAIGPTConfig, OpenAIGPTForSequenceClassification),
|
||||||
|
(TapasConfig, TapasForSequenceClassification),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -410,6 +417,7 @@ MODEL_FOR_QUESTION_ANSWERING_MAPPING = OrderedDict(
|
|||||||
(RobertaConfig, RobertaForQuestionAnswering),
|
(RobertaConfig, RobertaForQuestionAnswering),
|
||||||
(SqueezeBertConfig, SqueezeBertForQuestionAnswering),
|
(SqueezeBertConfig, SqueezeBertForQuestionAnswering),
|
||||||
(BertConfig, BertForQuestionAnswering),
|
(BertConfig, BertForQuestionAnswering),
|
||||||
|
(TapasConfig, TapasForQuestionAnswering),
|
||||||
(XLNetConfig, XLNetForQuestionAnsweringSimple),
|
(XLNetConfig, XLNetForQuestionAnsweringSimple),
|
||||||
(FlaubertConfig, FlaubertForQuestionAnsweringSimple),
|
(FlaubertConfig, FlaubertForQuestionAnsweringSimple),
|
||||||
(MobileBertConfig, MobileBertForQuestionAnswering),
|
(MobileBertConfig, MobileBertForQuestionAnswering),
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -50,6 +50,7 @@ from .configuration_auto import (
|
|||||||
RobertaConfig,
|
RobertaConfig,
|
||||||
SqueezeBertConfig,
|
SqueezeBertConfig,
|
||||||
T5Config,
|
T5Config,
|
||||||
|
TapasConfig,
|
||||||
TransfoXLConfig,
|
TransfoXLConfig,
|
||||||
XLMConfig,
|
XLMConfig,
|
||||||
XLMProphetNetConfig,
|
XLMProphetNetConfig,
|
||||||
@@ -85,6 +86,7 @@ from .tokenization_rag import RagTokenizer
|
|||||||
from .tokenization_retribert import RetriBertTokenizer
|
from .tokenization_retribert import RetriBertTokenizer
|
||||||
from .tokenization_roberta import RobertaTokenizer
|
from .tokenization_roberta import RobertaTokenizer
|
||||||
from .tokenization_squeezebert import SqueezeBertTokenizer
|
from .tokenization_squeezebert import SqueezeBertTokenizer
|
||||||
|
from .tokenization_tapas import TapasTokenizer
|
||||||
from .tokenization_transfo_xl import TransfoXLTokenizer
|
from .tokenization_transfo_xl import TransfoXLTokenizer
|
||||||
from .tokenization_xlm import XLMTokenizer
|
from .tokenization_xlm import XLMTokenizer
|
||||||
from .utils import logging
|
from .utils import logging
|
||||||
@@ -210,6 +212,7 @@ TOKENIZER_MAPPING = OrderedDict(
|
|||||||
(RagConfig, (RagTokenizer, None)),
|
(RagConfig, (RagTokenizer, None)),
|
||||||
(XLMProphetNetConfig, (XLMProphetNetTokenizer, None)),
|
(XLMProphetNetConfig, (XLMProphetNetTokenizer, None)),
|
||||||
(ProphetNetConfig, (ProphetNetTokenizer, None)),
|
(ProphetNetConfig, (ProphetNetTokenizer, None)),
|
||||||
|
(TapasConfig, (TapasTokenizer, None)),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,612 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
# Copyright 2020 Google Research and The HuggingFace Inc. team.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from transformers import is_torch_available
|
||||||
|
from transformers.testing_utils import require_torch, slow, torch_device
|
||||||
|
|
||||||
|
from .test_configuration_common import ConfigTester
|
||||||
|
from .test_modeling_common import ModelTesterMixin, floats_tensor, ids_tensor, random_attention_mask
|
||||||
|
|
||||||
|
|
||||||
|
if is_torch_available():
|
||||||
|
import torch
|
||||||
|
|
||||||
|
from transformers import (
|
||||||
|
TAPAS_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||||
|
TapasConfig,
|
||||||
|
TapasForMaskedLM,
|
||||||
|
TapasForQuestionAnswering,
|
||||||
|
TapasForSequenceClassification,
|
||||||
|
TapasModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TapasModelTester:
|
||||||
|
"""You can also import this e.g from .test_modeling_tapas import TapasModelTester """
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
parent,
|
||||||
|
batch_size=13,
|
||||||
|
seq_length=7,
|
||||||
|
is_training=True,
|
||||||
|
use_input_mask=True,
|
||||||
|
use_token_type_ids=True,
|
||||||
|
use_labels=True,
|
||||||
|
vocab_size=99,
|
||||||
|
hidden_size=32,
|
||||||
|
num_hidden_layers=5,
|
||||||
|
num_attention_heads=4,
|
||||||
|
intermediate_size=37,
|
||||||
|
hidden_act="gelu",
|
||||||
|
hidden_dropout_prob=0.1,
|
||||||
|
attention_probs_dropout_prob=0.1,
|
||||||
|
initializer_range=0.02,
|
||||||
|
max_position_embeddings=512,
|
||||||
|
type_vocab_sizes=[3, 256, 256, 2, 256, 256, 10],
|
||||||
|
type_sequence_label_size=2,
|
||||||
|
positive_weight=10.0,
|
||||||
|
num_aggregation_labels=4,
|
||||||
|
num_labels=2,
|
||||||
|
aggregation_loss_importance=0.8,
|
||||||
|
use_answer_as_supervision=True,
|
||||||
|
answer_loss_importance=0.001,
|
||||||
|
use_normalized_answer_loss=False,
|
||||||
|
huber_loss_delta=25.0,
|
||||||
|
temperature=1.0,
|
||||||
|
agg_temperature=1.0,
|
||||||
|
use_gumbel_for_cells=False,
|
||||||
|
use_gumbel_for_agg=False,
|
||||||
|
average_approximation_function="ratio",
|
||||||
|
cell_select_pref=0.5,
|
||||||
|
answer_loss_cutoff=100,
|
||||||
|
max_num_rows=64,
|
||||||
|
max_num_columns=32,
|
||||||
|
average_logits_per_cell=True,
|
||||||
|
select_one_column=True,
|
||||||
|
allow_empty_column_selection=False,
|
||||||
|
init_cell_selection_weights_to_zero=False,
|
||||||
|
reset_position_index_per_cell=False,
|
||||||
|
disable_per_token_loss=False,
|
||||||
|
span_prediction="none",
|
||||||
|
scope=None,
|
||||||
|
):
|
||||||
|
self.parent = parent
|
||||||
|
self.batch_size = batch_size
|
||||||
|
self.seq_length = seq_length
|
||||||
|
self.is_training = is_training
|
||||||
|
self.use_input_mask = use_input_mask
|
||||||
|
self.use_token_type_ids = use_token_type_ids
|
||||||
|
self.use_labels = use_labels
|
||||||
|
self.vocab_size = vocab_size
|
||||||
|
self.hidden_size = hidden_size
|
||||||
|
self.num_hidden_layers = num_hidden_layers
|
||||||
|
self.num_attention_heads = num_attention_heads
|
||||||
|
self.intermediate_size = intermediate_size
|
||||||
|
self.hidden_act = hidden_act
|
||||||
|
self.hidden_dropout_prob = hidden_dropout_prob
|
||||||
|
self.attention_probs_dropout_prob = attention_probs_dropout_prob
|
||||||
|
self.initializer_range = initializer_range
|
||||||
|
self.max_position_embeddings = max_position_embeddings
|
||||||
|
self.type_vocab_sizes = type_vocab_sizes
|
||||||
|
self.type_sequence_label_size = type_sequence_label_size
|
||||||
|
self.positive_weight = positive_weight
|
||||||
|
self.num_aggregation_labels = num_aggregation_labels
|
||||||
|
self.num_labels = num_labels
|
||||||
|
self.aggregation_loss_importance = aggregation_loss_importance
|
||||||
|
self.use_answer_as_supervision = use_answer_as_supervision
|
||||||
|
self.answer_loss_importance = answer_loss_importance
|
||||||
|
self.use_normalized_answer_loss = use_normalized_answer_loss
|
||||||
|
self.huber_loss_delta = huber_loss_delta
|
||||||
|
self.temperature = temperature
|
||||||
|
self.agg_temperature = agg_temperature
|
||||||
|
self.use_gumbel_for_cells = use_gumbel_for_cells
|
||||||
|
self.use_gumbel_for_agg = use_gumbel_for_agg
|
||||||
|
self.average_approximation_function = average_approximation_function
|
||||||
|
self.cell_select_pref = cell_select_pref
|
||||||
|
self.answer_loss_cutoff = answer_loss_cutoff
|
||||||
|
self.max_num_rows = max_num_rows
|
||||||
|
self.max_num_columns = max_num_columns
|
||||||
|
self.average_logits_per_cell = average_logits_per_cell
|
||||||
|
self.select_one_column = select_one_column
|
||||||
|
self.allow_empty_column_selection = allow_empty_column_selection
|
||||||
|
self.init_cell_selection_weights_to_zero = init_cell_selection_weights_to_zero
|
||||||
|
self.reset_position_index_per_cell = reset_position_index_per_cell
|
||||||
|
self.disable_per_token_loss = disable_per_token_loss
|
||||||
|
self.span_prediction = span_prediction
|
||||||
|
self.scope = scope
|
||||||
|
|
||||||
|
def prepare_config_and_inputs(self):
|
||||||
|
input_ids = ids_tensor([self.batch_size, self.seq_length], self.vocab_size)
|
||||||
|
|
||||||
|
input_mask = None
|
||||||
|
if self.use_input_mask:
|
||||||
|
input_mask = random_attention_mask([self.batch_size, self.seq_length])
|
||||||
|
|
||||||
|
token_type_ids = []
|
||||||
|
for type_vocab_size in self.type_vocab_sizes:
|
||||||
|
token_type_ids.append(ids_tensor(shape=[self.batch_size, self.seq_length], vocab_size=type_vocab_size))
|
||||||
|
token_type_ids = torch.stack(token_type_ids, dim=2)
|
||||||
|
|
||||||
|
sequence_labels = None
|
||||||
|
token_labels = None
|
||||||
|
label_ids = None
|
||||||
|
answer = None
|
||||||
|
numeric_values = None
|
||||||
|
numeric_values_scale = None
|
||||||
|
aggregation_labels = None
|
||||||
|
if self.use_labels:
|
||||||
|
sequence_labels = ids_tensor([self.batch_size], self.type_sequence_label_size)
|
||||||
|
token_labels = ids_tensor([self.batch_size, self.seq_length], self.num_labels)
|
||||||
|
label_ids = ids_tensor([self.batch_size, self.seq_length], vocab_size=2)
|
||||||
|
answer = floats_tensor([self.batch_size])
|
||||||
|
numeric_values = floats_tensor([self.batch_size, self.seq_length])
|
||||||
|
numeric_values_scale = floats_tensor([self.batch_size, self.seq_length])
|
||||||
|
aggregation_labels = ids_tensor([self.batch_size], self.num_aggregation_labels)
|
||||||
|
|
||||||
|
config = TapasConfig(
|
||||||
|
vocab_size=self.vocab_size,
|
||||||
|
hidden_size=self.hidden_size,
|
||||||
|
num_hidden_layers=self.num_hidden_layers,
|
||||||
|
num_attention_heads=self.num_attention_heads,
|
||||||
|
intermediate_size=self.intermediate_size,
|
||||||
|
hidden_act=self.hidden_act,
|
||||||
|
hidden_dropout_prob=self.hidden_dropout_prob,
|
||||||
|
attention_probs_dropout_prob=self.attention_probs_dropout_prob,
|
||||||
|
max_position_embeddings=self.max_position_embeddings,
|
||||||
|
type_vocab_sizes=self.type_vocab_sizes,
|
||||||
|
initializer_range=self.initializer_range,
|
||||||
|
positive_weight=self.positive_weight,
|
||||||
|
num_aggregation_labels=self.num_aggregation_labels,
|
||||||
|
num_labels=self.num_labels,
|
||||||
|
aggregation_loss_importance=self.aggregation_loss_importance,
|
||||||
|
use_answer_as_supervision=self.use_answer_as_supervision,
|
||||||
|
answer_loss_importance=self.answer_loss_importance,
|
||||||
|
use_normalized_answer_loss=self.use_normalized_answer_loss,
|
||||||
|
huber_loss_delta=self.huber_loss_delta,
|
||||||
|
temperature=self.temperature,
|
||||||
|
agg_temperature=self.agg_temperature,
|
||||||
|
use_gumbel_for_cells=self.use_gumbel_for_cells,
|
||||||
|
use_gumbel_for_agg=self.use_gumbel_for_agg,
|
||||||
|
average_approximation_function=self.average_approximation_function,
|
||||||
|
cell_select_pref=self.cell_select_pref,
|
||||||
|
answer_loss_cutoff=self.answer_loss_cutoff,
|
||||||
|
max_num_rows=self.max_num_rows,
|
||||||
|
max_num_columns=self.max_num_columns,
|
||||||
|
average_logits_per_cell=self.average_logits_per_cell,
|
||||||
|
select_one_column=self.select_one_column,
|
||||||
|
allow_empty_column_selection=self.allow_empty_column_selection,
|
||||||
|
init_cell_selection_weights_to_zero=self.init_cell_selection_weights_to_zero,
|
||||||
|
reset_position_index_per_cell=self.reset_position_index_per_cell,
|
||||||
|
disable_per_token_loss=self.disable_per_token_loss,
|
||||||
|
span_prediction=self.span_prediction,
|
||||||
|
return_dict=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
config,
|
||||||
|
input_ids,
|
||||||
|
input_mask,
|
||||||
|
token_type_ids,
|
||||||
|
sequence_labels,
|
||||||
|
token_labels,
|
||||||
|
label_ids,
|
||||||
|
answer,
|
||||||
|
numeric_values,
|
||||||
|
numeric_values_scale,
|
||||||
|
aggregation_labels,
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_and_check_model(
|
||||||
|
self,
|
||||||
|
config,
|
||||||
|
input_ids,
|
||||||
|
input_mask,
|
||||||
|
token_type_ids,
|
||||||
|
sequence_labels,
|
||||||
|
token_labels,
|
||||||
|
label_ids,
|
||||||
|
answer,
|
||||||
|
numeric_values,
|
||||||
|
numeric_values_scale,
|
||||||
|
aggregation_labels,
|
||||||
|
):
|
||||||
|
model = TapasModel(config=config)
|
||||||
|
model.to(torch_device)
|
||||||
|
model.eval()
|
||||||
|
result = model(input_ids, attention_mask=input_mask, token_type_ids=token_type_ids)
|
||||||
|
result = model(input_ids, token_type_ids=token_type_ids)
|
||||||
|
result = model(input_ids)
|
||||||
|
self.parent.assertEqual(result.last_hidden_state.shape, (self.batch_size, self.seq_length, self.hidden_size))
|
||||||
|
self.parent.assertEqual(result.pooler_output.shape, (self.batch_size, self.hidden_size))
|
||||||
|
|
||||||
|
def create_and_check_for_masked_lm(
|
||||||
|
self,
|
||||||
|
config,
|
||||||
|
input_ids,
|
||||||
|
input_mask,
|
||||||
|
token_type_ids,
|
||||||
|
sequence_labels,
|
||||||
|
token_labels,
|
||||||
|
label_ids,
|
||||||
|
answer,
|
||||||
|
numeric_values,
|
||||||
|
numeric_values_scale,
|
||||||
|
aggregation_labels,
|
||||||
|
):
|
||||||
|
model = TapasForMaskedLM(config=config)
|
||||||
|
model.to(torch_device)
|
||||||
|
model.eval()
|
||||||
|
result = model(input_ids, attention_mask=input_mask, token_type_ids=token_type_ids, labels=token_labels)
|
||||||
|
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.seq_length, self.vocab_size))
|
||||||
|
|
||||||
|
def create_and_check_for_question_answering(
|
||||||
|
self,
|
||||||
|
config,
|
||||||
|
input_ids,
|
||||||
|
input_mask,
|
||||||
|
token_type_ids,
|
||||||
|
sequence_labels,
|
||||||
|
token_labels,
|
||||||
|
label_ids,
|
||||||
|
answer,
|
||||||
|
numeric_values,
|
||||||
|
numeric_values_scale,
|
||||||
|
aggregation_labels,
|
||||||
|
):
|
||||||
|
model = TapasForQuestionAnswering(config=config)
|
||||||
|
model.to(torch_device)
|
||||||
|
model.eval()
|
||||||
|
result = model(
|
||||||
|
input_ids,
|
||||||
|
attention_mask=input_mask,
|
||||||
|
token_type_ids=token_type_ids,
|
||||||
|
label_ids=label_ids,
|
||||||
|
answer=answer,
|
||||||
|
numeric_values=numeric_values,
|
||||||
|
numeric_values_scale=numeric_values_scale,
|
||||||
|
aggregation_labels=aggregation_labels,
|
||||||
|
)
|
||||||
|
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.seq_length))
|
||||||
|
self.parent.assertEqual(result.logits_aggregation.shape, (self.batch_size, self.num_aggregation_labels))
|
||||||
|
|
||||||
|
def create_and_check_for_sequence_classification(
|
||||||
|
self,
|
||||||
|
config,
|
||||||
|
input_ids,
|
||||||
|
input_mask,
|
||||||
|
token_type_ids,
|
||||||
|
sequence_labels,
|
||||||
|
token_labels,
|
||||||
|
label_ids,
|
||||||
|
answer,
|
||||||
|
numeric_values,
|
||||||
|
numeric_values_scale,
|
||||||
|
aggregation_labels,
|
||||||
|
):
|
||||||
|
config.num_labels = self.num_labels
|
||||||
|
model = TapasForSequenceClassification(config)
|
||||||
|
model.to(torch_device)
|
||||||
|
model.eval()
|
||||||
|
result = model(input_ids, attention_mask=input_mask, labels=sequence_labels)
|
||||||
|
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.num_labels))
|
||||||
|
|
||||||
|
def prepare_config_and_inputs_for_common(self):
|
||||||
|
config_and_inputs = self.prepare_config_and_inputs()
|
||||||
|
(
|
||||||
|
config,
|
||||||
|
input_ids,
|
||||||
|
input_mask,
|
||||||
|
token_type_ids,
|
||||||
|
sequence_labels,
|
||||||
|
token_labels,
|
||||||
|
label_ids,
|
||||||
|
answer,
|
||||||
|
numeric_values,
|
||||||
|
numeric_values_scale,
|
||||||
|
aggregation_labels,
|
||||||
|
) = config_and_inputs
|
||||||
|
inputs_dict = {"input_ids": input_ids, "token_type_ids": token_type_ids, "attention_mask": input_mask}
|
||||||
|
return config, inputs_dict
|
||||||
|
|
||||||
|
|
||||||
|
@require_torch
|
||||||
|
class TapasModelTest(ModelTesterMixin, unittest.TestCase):
|
||||||
|
|
||||||
|
all_model_classes = (
|
||||||
|
(
|
||||||
|
TapasModel,
|
||||||
|
TapasForMaskedLM,
|
||||||
|
TapasForQuestionAnswering,
|
||||||
|
TapasForSequenceClassification,
|
||||||
|
)
|
||||||
|
if is_torch_available()
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
test_pruning = False
|
||||||
|
test_torchscript = True
|
||||||
|
test_resize_embeddings = True
|
||||||
|
test_head_masking = False
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.model_tester = TapasModelTester(self)
|
||||||
|
self.config_tester = ConfigTester(self, config_class=TapasConfig, dim=37)
|
||||||
|
|
||||||
|
def test_config(self):
|
||||||
|
self.config_tester.run_common_tests()
|
||||||
|
|
||||||
|
def test_model(self):
|
||||||
|
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||||
|
self.model_tester.create_and_check_model(*config_and_inputs)
|
||||||
|
|
||||||
|
def test_for_masked_lm(self):
|
||||||
|
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||||
|
self.model_tester.create_and_check_for_masked_lm(*config_and_inputs)
|
||||||
|
|
||||||
|
def test_for_question_answering(self):
|
||||||
|
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||||
|
self.model_tester.create_and_check_for_question_answering(*config_and_inputs)
|
||||||
|
|
||||||
|
def test_for_sequence_classification(self):
|
||||||
|
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||||
|
self.model_tester.create_and_check_for_sequence_classification(*config_and_inputs)
|
||||||
|
|
||||||
|
# @slow
|
||||||
|
# def test_lm_outputs_same_as_reference_model(self):
|
||||||
|
# """Write something that could help someone fixing this here."""
|
||||||
|
# checkpoint_path = "XXX/bart-large"
|
||||||
|
# model = self.big_model
|
||||||
|
# tokenizer = AutoTokenizer.from_pretrained(
|
||||||
|
# checkpoint_path
|
||||||
|
# ) # same with AutoTokenizer (see tokenization_auto.py). This is not mandatory
|
||||||
|
# # MODIFY THIS DEPENDING ON YOUR MODELS RELEVANT TASK.
|
||||||
|
# batch = tokenizer(["I went to the <mask> yesterday"]).to(torch_device)
|
||||||
|
# desired_mask_result = tokenizer.decode("store") # update this
|
||||||
|
# logits = model(**batch).logits
|
||||||
|
# masked_index = (batch.input_ids == self.tokenizer.mask_token_id).nonzero()
|
||||||
|
# assert model.num_parameters() == 175e9 # a joke
|
||||||
|
# mask_entry_logits = logits[0, masked_index.item(), :]
|
||||||
|
# probs = mask_entry_logits.softmax(dim=0)
|
||||||
|
# _, predictions = probs.topk(1)
|
||||||
|
# self.assertEqual(tokenizer.decode(predictions), desired_mask_result)
|
||||||
|
|
||||||
|
# @cached_property
|
||||||
|
# def big_model(self):
|
||||||
|
# """Cached property means this code will only be executed once."""
|
||||||
|
# checkpoint_path = "XXX/bart-large"
|
||||||
|
# model = AutoModelForMaskedLM.from_pretrained(checkpoint_path).to(
|
||||||
|
# torch_device
|
||||||
|
# ) # test whether AutoModel can determine your model_class from checkpoint name
|
||||||
|
# if torch_device == "cuda":
|
||||||
|
# model.half()
|
||||||
|
|
||||||
|
# optional: do more testing! This will save you time later!
|
||||||
|
# @slow
|
||||||
|
# def test_that_XXX_can_be_used_in_a_pipeline(self):
|
||||||
|
# """We can use self.big_model here without calling __init__ again."""
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# def test_XXX_loss_doesnt_change_if_you_add_padding(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# def test_XXX_bad_args(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# def test_XXX_backward_pass_reduces_loss(self):
|
||||||
|
# """Test loss/gradients same as reference implementation, for example."""
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# @require_torch_and_cuda
|
||||||
|
# def test_large_inputs_in_fp16_dont_cause_overflow(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
|
||||||
|
# Below: tests for Tapas utilities, based on segmented_tensor_test.py of the original implementation.
|
||||||
|
# These test the operations on segmented tensors.
|
||||||
|
class TapasUtilitiesTest(unittest.TestCase):
|
||||||
|
def _prepare_tables(self):
|
||||||
|
"""Prepares two tables, both with three distinct rows.
|
||||||
|
The first table has two columns:
|
||||||
|
1.0, 2.0 | 3.0
|
||||||
|
2.0, 0.0 | 1.0
|
||||||
|
1.0, 3.0 | 4.0
|
||||||
|
The second table has three columns:
|
||||||
|
1.0 | 2.0 | 3.0
|
||||||
|
2.0 | 0.0 | 1.0
|
||||||
|
1.0 | 3.0 | 4.0
|
||||||
|
Returns:
|
||||||
|
SegmentedTensors with the tables.
|
||||||
|
"""
|
||||||
|
values = torch.tensor(
|
||||||
|
[
|
||||||
|
[[1.0, 2.0, 3.0], [2.0, 0.0, 1.0], [1.0, 3.0, 4.0]],
|
||||||
|
[[1.0, 2.0, 3.0], [2.0, 0.0, 1.0], [1.0, 3.0, 4.0]],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
row_index = utils.IndexMap(
|
||||||
|
indices=torch.tensor(
|
||||||
|
[
|
||||||
|
[[0, 0, 0], [1, 1, 1], [2, 2, 2]],
|
||||||
|
[[0, 0, 0], [1, 1, 1], [2, 2, 2]],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
num_segments=3,
|
||||||
|
batch_dims=1,
|
||||||
|
)
|
||||||
|
col_index = utils.IndexMap(
|
||||||
|
indices=torch.tensor(
|
||||||
|
[
|
||||||
|
[[0, 0, 1], [0, 0, 1], [0, 0, 1]],
|
||||||
|
[[0, 1, 2], [0, 1, 2], [0, 1, 2]],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
num_segments=3,
|
||||||
|
batch_dims=1,
|
||||||
|
)
|
||||||
|
return values, row_index, col_index
|
||||||
|
|
||||||
|
def test_product_index(self):
|
||||||
|
_, row_index, col_index = self._prepare_tables()
|
||||||
|
cell_index = utils.ProductIndexMap(row_index, col_index)
|
||||||
|
row_index_proj = cell_index.project_outer(cell_index)
|
||||||
|
col_index_proj = cell_index.project_inner(cell_index)
|
||||||
|
|
||||||
|
ind = cell_index.indices
|
||||||
|
self.assertEqual(cell_index.num_segments, 9)
|
||||||
|
|
||||||
|
# Projections should give back the original indices.
|
||||||
|
# we use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_array_equal(row_index.indices.numpy(), row_index_proj.indices.numpy())
|
||||||
|
self.assertEqual(row_index.num_segments, row_index_proj.num_segments)
|
||||||
|
self.assertEqual(row_index.batch_dims, row_index_proj.batch_dims)
|
||||||
|
# We use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_array_equal(col_index.indices.numpy(), col_index_proj.indices.numpy())
|
||||||
|
self.assertEqual(col_index.batch_dims, col_index_proj.batch_dims)
|
||||||
|
|
||||||
|
# The first and second "column" are identified in the first table.
|
||||||
|
for i in range(3):
|
||||||
|
self.assertEqual(ind[0, i, 0], ind[0, i, 1])
|
||||||
|
self.assertNotEqual(ind[0, i, 0], ind[0, i, 2])
|
||||||
|
|
||||||
|
# All rows are distinct in the first table.
|
||||||
|
for i, i_2 in zip(range(3), range(3)):
|
||||||
|
for j, j_2 in zip(range(3), range(3)):
|
||||||
|
if i != i_2 and j != j_2:
|
||||||
|
self.assertNotEqual(ind[0, i, j], ind[0, i_2, j_2])
|
||||||
|
|
||||||
|
# All cells are distinct in the second table.
|
||||||
|
for i, i_2 in zip(range(3), range(3)):
|
||||||
|
for j, j_2 in zip(range(3), range(3)):
|
||||||
|
if i != i_2 or j != j_2:
|
||||||
|
self.assertNotEqual(ind[1, i, j], ind[1, i_2, j_2])
|
||||||
|
|
||||||
|
def test_flatten(self):
|
||||||
|
_, row_index, col_index = self._prepare_tables()
|
||||||
|
row_index_flat = utils.flatten(row_index)
|
||||||
|
col_index_flat = utils.flatten(col_index)
|
||||||
|
|
||||||
|
shape = [3, 4, 5]
|
||||||
|
batched_index = utils.IndexMap(indices=torch.zeros(shape).type(torch.LongTensor), num_segments=1, batch_dims=3)
|
||||||
|
batched_index_flat = utils.flatten(batched_index)
|
||||||
|
|
||||||
|
# We use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_array_equal(
|
||||||
|
row_index_flat.indices.numpy(), [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]
|
||||||
|
)
|
||||||
|
np.testing.assert_array_equal(
|
||||||
|
col_index_flat.indices.numpy(), [0, 0, 1, 0, 0, 1, 0, 0, 1, 3, 4, 5, 3, 4, 5, 3, 4, 5]
|
||||||
|
)
|
||||||
|
self.assertEqual(batched_index_flat.num_segments.numpy(), np.prod(shape))
|
||||||
|
np.testing.assert_array_equal(batched_index_flat.indices.numpy(), range(np.prod(shape)))
|
||||||
|
|
||||||
|
def test_range_index_map(self):
|
||||||
|
batch_shape = [3, 4]
|
||||||
|
num_segments = 5
|
||||||
|
index = utils.range_index_map(batch_shape, num_segments)
|
||||||
|
|
||||||
|
self.assertEqual(num_segments, index.num_segments)
|
||||||
|
self.assertEqual(2, index.batch_dims)
|
||||||
|
indices = index.indices
|
||||||
|
# We use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_array_equal(list(indices.size()), [3, 4, 5])
|
||||||
|
for i in range(batch_shape[0]):
|
||||||
|
for j in range(batch_shape[1]):
|
||||||
|
# We use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_array_equal(indices[i, j, :].numpy(), range(num_segments))
|
||||||
|
|
||||||
|
def test_reduce_sum(self):
|
||||||
|
values, row_index, col_index = self._prepare_tables()
|
||||||
|
cell_index = utils.ProductIndexMap(row_index, col_index)
|
||||||
|
row_sum, _ = utils.reduce_sum(values, row_index)
|
||||||
|
col_sum, _ = utils.reduce_sum(values, col_index)
|
||||||
|
cell_sum, _ = utils.reduce_sum(values, cell_index)
|
||||||
|
|
||||||
|
# We use np.testing.assert_allclose rather than Tensorflow's assertAllClose
|
||||||
|
np.testing.assert_allclose(row_sum.numpy(), [[6.0, 3.0, 8.0], [6.0, 3.0, 8.0]])
|
||||||
|
np.testing.assert_allclose(col_sum.numpy(), [[9.0, 8.0, 0.0], [4.0, 5.0, 8.0]])
|
||||||
|
np.testing.assert_allclose(
|
||||||
|
cell_sum.numpy(),
|
||||||
|
[[3.0, 3.0, 0.0, 2.0, 1.0, 0.0, 4.0, 4.0, 0.0], [1.0, 2.0, 3.0, 2.0, 0.0, 1.0, 1.0, 3.0, 4.0]],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_reduce_mean(self):
|
||||||
|
values, row_index, col_index = self._prepare_tables()
|
||||||
|
cell_index = utils.ProductIndexMap(row_index, col_index)
|
||||||
|
row_mean, _ = utils.reduce_mean(values, row_index)
|
||||||
|
col_mean, _ = utils.reduce_mean(values, col_index)
|
||||||
|
cell_mean, _ = utils.reduce_mean(values, cell_index)
|
||||||
|
|
||||||
|
# We use np.testing.assert_allclose rather than Tensorflow's assertAllClose
|
||||||
|
np.testing.assert_allclose(
|
||||||
|
row_mean.numpy(), [[6.0 / 3.0, 3.0 / 3.0, 8.0 / 3.0], [6.0 / 3.0, 3.0 / 3.0, 8.0 / 3.0]]
|
||||||
|
)
|
||||||
|
np.testing.assert_allclose(col_mean.numpy(), [[9.0 / 6.0, 8.0 / 3.0, 0.0], [4.0 / 3.0, 5.0 / 3.0, 8.0 / 3.0]])
|
||||||
|
np.testing.assert_allclose(
|
||||||
|
cell_mean.numpy(),
|
||||||
|
[
|
||||||
|
[3.0 / 2.0, 3.0, 0.0, 2.0 / 2.0, 1.0, 0.0, 4.0 / 2.0, 4.0, 0.0],
|
||||||
|
[1.0, 2.0, 3.0, 2.0, 0.0, 1.0, 1.0, 3.0, 4.0],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_reduce_max(self):
|
||||||
|
values = torch.as_tensor([2.0, 1.0, 0.0, 3.0])
|
||||||
|
index = utils.IndexMap(indices=torch.as_tensor([0, 1, 0, 1]), num_segments=2)
|
||||||
|
maximum, _ = utils.reduce_max(values, index)
|
||||||
|
|
||||||
|
# We use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_array_equal(maximum.numpy(), [2, 3])
|
||||||
|
|
||||||
|
def test_reduce_sum_vectorized(self):
|
||||||
|
values = torch.as_tensor([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0], [3.0, 4.0, 5.0]])
|
||||||
|
index = utils.IndexMap(indices=torch.as_tensor([0, 0, 1]), num_segments=2, batch_dims=0)
|
||||||
|
sums, new_index = utils.reduce_sum(values, index)
|
||||||
|
|
||||||
|
# We use np.testing.assert_allclose rather than Tensorflow's assertAllClose
|
||||||
|
np.testing.assert_allclose(sums.numpy(), [[3.0, 5.0, 7.0], [3.0, 4.0, 5.0]])
|
||||||
|
# We use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_array_equal(new_index.indices.numpy(), [0, 1])
|
||||||
|
np.testing.assert_array_equal(new_index.num_segments.numpy(), 2)
|
||||||
|
np.testing.assert_array_equal(new_index.batch_dims, 0)
|
||||||
|
|
||||||
|
def test_gather(self):
|
||||||
|
values, row_index, col_index = self._prepare_tables()
|
||||||
|
cell_index = utils.ProductIndexMap(row_index, col_index)
|
||||||
|
|
||||||
|
# Compute sums and then gather. The result should have the same shape as
|
||||||
|
# the original table and each element should contain the sum the values in
|
||||||
|
# its cell.
|
||||||
|
sums, _ = utils.reduce_sum(values, cell_index)
|
||||||
|
cell_sum = utils.gather(sums, cell_index)
|
||||||
|
assert cell_sum.size() == values.size()
|
||||||
|
|
||||||
|
# We use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_allclose(
|
||||||
|
cell_sum.numpy(),
|
||||||
|
[[[3.0, 3.0, 3.0], [2.0, 2.0, 1.0], [4.0, 4.0, 4.0]], [[1.0, 2.0, 3.0], [2.0, 0.0, 1.0], [1.0, 3.0, 4.0]]],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_gather_vectorized(self):
|
||||||
|
values = torch.as_tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
|
||||||
|
index = utils.IndexMap(indices=torch.as_tensor([[0, 1], [1, 0]]), num_segments=2, batch_dims=1)
|
||||||
|
result = utils.gather(values, index)
|
||||||
|
|
||||||
|
# We use np.testing.assert_array_equal rather than Tensorflow's assertAllEqual
|
||||||
|
np.testing.assert_array_equal(result.numpy(), [[[1, 2], [3, 4]], [[7, 8], [5, 6]]])
|
||||||
@@ -0,0 +1,573 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
# Copyright 2018 The Google AI Language Team Authors.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
import functools
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
import regex as re
|
||||||
|
from transformers import AddedToken, PreTrainedTokenizerBase
|
||||||
|
from transformers.testing_utils import require_tokenizers, slow
|
||||||
|
from transformers.tokenization_tapas import (
|
||||||
|
VOCAB_FILES_NAMES,
|
||||||
|
BasicTokenizer,
|
||||||
|
TapasTokenizer,
|
||||||
|
WordpieceTokenizer,
|
||||||
|
_is_control,
|
||||||
|
_is_punctuation,
|
||||||
|
_is_whitespace,
|
||||||
|
)
|
||||||
|
|
||||||
|
from .test_tokenization_common import TokenizerTesterMixin, filter_non_english
|
||||||
|
|
||||||
|
|
||||||
|
@require_tokenizers
|
||||||
|
class TapasTokenizationTest(TokenizerTesterMixin, unittest.TestCase):
|
||||||
|
|
||||||
|
tokenizer_class = TapasTokenizer
|
||||||
|
test_rust_tokenizer = False
|
||||||
|
space_between_special_tokens = True
|
||||||
|
from_pretrained_filter = filter_non_english
|
||||||
|
|
||||||
|
def get_clean_sequence(
|
||||||
|
self, tokenizer: TapasTokenizer, empty_table: bool = False, add_special_tokens: bool = True
|
||||||
|
) -> Tuple[pd.DataFrame, str, List[int]]:
|
||||||
|
if empty_table:
|
||||||
|
table = pd.DataFrame.from_dict({})
|
||||||
|
else:
|
||||||
|
data = {
|
||||||
|
"Actors": ["Brad Pitt", "Leonardo Di Caprio", "George Clooney"],
|
||||||
|
"Age": ["56", "45", "59"],
|
||||||
|
"Number of movies": ["87", "53", "69"],
|
||||||
|
"Date of birth": ["18 december 1963", "11 november 1974", "6 may 1961"],
|
||||||
|
}
|
||||||
|
table = pd.DataFrame.from_dict(data)
|
||||||
|
query = "Which actor appeared in the least number of movies?"
|
||||||
|
|
||||||
|
inputs = tokenizer.encode(table, query, add_special_tokens=add_special_tokens)
|
||||||
|
|
||||||
|
return table, query, inputs
|
||||||
|
|
||||||
|
# def get_clean_sequence(self, tokenizer, with_prefix_space=False, max_length=20, min_length=5) -> Tuple[str, list]:
|
||||||
|
# data = {
|
||||||
|
# 'Actors': ["Brad Pitt", "Leonardo Di Caprio", "George Clooney"],
|
||||||
|
# 'Age': ["56", "45", "59"],
|
||||||
|
# 'Number of movies': ["87", "53", "69"],
|
||||||
|
# 'Date of birth': ["18 december 1963", "11 november 1974", "6 may 1961"]
|
||||||
|
# }
|
||||||
|
# table = pd.DataFrame.from_dict(data)
|
||||||
|
# output_ids = tokenizer.encode(table, add_special_tokens=False, max_length=max_length)
|
||||||
|
# output_txt = tokenizer.decode(output_ids)
|
||||||
|
#
|
||||||
|
# return output_txt, output_ids
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
vocab_tokens = [
|
||||||
|
"[UNK]",
|
||||||
|
"[CLS]",
|
||||||
|
"[SEP]",
|
||||||
|
"[PAD]",
|
||||||
|
"[MASK]",
|
||||||
|
"want",
|
||||||
|
"##want",
|
||||||
|
"##ed",
|
||||||
|
"wa",
|
||||||
|
"un",
|
||||||
|
"runn",
|
||||||
|
"##ing",
|
||||||
|
",",
|
||||||
|
"low",
|
||||||
|
"lowest",
|
||||||
|
]
|
||||||
|
self.vocab_file = os.path.join(self.tmpdirname, VOCAB_FILES_NAMES["vocab_file"])
|
||||||
|
with open(self.vocab_file, "w", encoding="utf-8") as vocab_writer:
|
||||||
|
vocab_writer.write("".join([x + "\n" for x in vocab_tokens]))
|
||||||
|
|
||||||
|
def get_input_output_texts(self, tokenizer):
|
||||||
|
input_text = "UNwant\u00E9d,running"
|
||||||
|
output_text = "unwanted, running"
|
||||||
|
return input_text, output_text
|
||||||
|
|
||||||
|
def test_full_tokenizer(self):
|
||||||
|
tokenizer = self.tokenizer_class(self.vocab_file)
|
||||||
|
|
||||||
|
tokens = tokenizer.tokenize("UNwant\u00E9d,running")
|
||||||
|
self.assertListEqual(tokens, ["un", "##want", "##ed", ",", "runn", "##ing"])
|
||||||
|
self.assertListEqual(tokenizer.convert_tokens_to_ids(tokens), [9, 6, 7, 12, 10, 11])
|
||||||
|
|
||||||
|
def test_rust_and_python_full_tokenizers(self):
|
||||||
|
if not self.test_rust_tokenizer:
|
||||||
|
return
|
||||||
|
|
||||||
|
tokenizer = self.get_tokenizer()
|
||||||
|
rust_tokenizer = self.get_rust_tokenizer()
|
||||||
|
|
||||||
|
sequence = "UNwant\u00E9d,running"
|
||||||
|
|
||||||
|
tokens = tokenizer.tokenize(sequence)
|
||||||
|
rust_tokens = rust_tokenizer.tokenize(sequence)
|
||||||
|
self.assertListEqual(tokens, rust_tokens)
|
||||||
|
|
||||||
|
ids = tokenizer.encode(sequence, add_special_tokens=False)
|
||||||
|
rust_ids = rust_tokenizer.encode(sequence, add_special_tokens=False)
|
||||||
|
self.assertListEqual(ids, rust_ids)
|
||||||
|
|
||||||
|
rust_tokenizer = self.get_rust_tokenizer()
|
||||||
|
ids = tokenizer.encode(sequence)
|
||||||
|
rust_ids = rust_tokenizer.encode(sequence)
|
||||||
|
self.assertListEqual(ids, rust_ids)
|
||||||
|
|
||||||
|
# With lower casing
|
||||||
|
tokenizer = self.get_tokenizer(do_lower_case=True)
|
||||||
|
rust_tokenizer = self.get_rust_tokenizer(do_lower_case=True)
|
||||||
|
|
||||||
|
sequence = "UNwant\u00E9d,running"
|
||||||
|
|
||||||
|
tokens = tokenizer.tokenize(sequence)
|
||||||
|
rust_tokens = rust_tokenizer.tokenize(sequence)
|
||||||
|
self.assertListEqual(tokens, rust_tokens)
|
||||||
|
|
||||||
|
ids = tokenizer.encode(sequence, add_special_tokens=False)
|
||||||
|
rust_ids = rust_tokenizer.encode(sequence, add_special_tokens=False)
|
||||||
|
self.assertListEqual(ids, rust_ids)
|
||||||
|
|
||||||
|
rust_tokenizer = self.get_rust_tokenizer()
|
||||||
|
ids = tokenizer.encode(sequence)
|
||||||
|
rust_ids = rust_tokenizer.encode(sequence)
|
||||||
|
self.assertListEqual(ids, rust_ids)
|
||||||
|
|
||||||
|
def test_chinese(self):
|
||||||
|
tokenizer = BasicTokenizer()
|
||||||
|
|
||||||
|
self.assertListEqual(tokenizer.tokenize("ah\u535A\u63A8zz"), ["ah", "\u535A", "\u63A8", "zz"])
|
||||||
|
|
||||||
|
def test_basic_tokenizer_lower(self):
|
||||||
|
tokenizer = BasicTokenizer(do_lower_case=True)
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
tokenizer.tokenize(" \tHeLLo!how \n Are yoU? "), ["hello", "!", "how", "are", "you", "?"]
|
||||||
|
)
|
||||||
|
self.assertListEqual(tokenizer.tokenize("H\u00E9llo"), ["hello"])
|
||||||
|
|
||||||
|
def test_basic_tokenizer_lower_strip_accents_false(self):
|
||||||
|
tokenizer = BasicTokenizer(do_lower_case=True, strip_accents=False)
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
tokenizer.tokenize(" \tHäLLo!how \n Are yoU? "), ["hällo", "!", "how", "are", "you", "?"]
|
||||||
|
)
|
||||||
|
self.assertListEqual(tokenizer.tokenize("H\u00E9llo"), ["h\u00E9llo"])
|
||||||
|
|
||||||
|
def test_basic_tokenizer_lower_strip_accents_true(self):
|
||||||
|
tokenizer = BasicTokenizer(do_lower_case=True, strip_accents=True)
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
tokenizer.tokenize(" \tHäLLo!how \n Are yoU? "), ["hallo", "!", "how", "are", "you", "?"]
|
||||||
|
)
|
||||||
|
self.assertListEqual(tokenizer.tokenize("H\u00E9llo"), ["hello"])
|
||||||
|
|
||||||
|
def test_basic_tokenizer_lower_strip_accents_default(self):
|
||||||
|
tokenizer = BasicTokenizer(do_lower_case=True)
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
tokenizer.tokenize(" \tHäLLo!how \n Are yoU? "), ["hallo", "!", "how", "are", "you", "?"]
|
||||||
|
)
|
||||||
|
self.assertListEqual(tokenizer.tokenize("H\u00E9llo"), ["hello"])
|
||||||
|
|
||||||
|
def test_basic_tokenizer_no_lower(self):
|
||||||
|
tokenizer = BasicTokenizer(do_lower_case=False)
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
tokenizer.tokenize(" \tHeLLo!how \n Are yoU? "), ["HeLLo", "!", "how", "Are", "yoU", "?"]
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_basic_tokenizer_no_lower_strip_accents_false(self):
|
||||||
|
tokenizer = BasicTokenizer(do_lower_case=False, strip_accents=False)
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
tokenizer.tokenize(" \tHäLLo!how \n Are yoU? "), ["HäLLo", "!", "how", "Are", "yoU", "?"]
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_basic_tokenizer_no_lower_strip_accents_true(self):
|
||||||
|
tokenizer = BasicTokenizer(do_lower_case=False, strip_accents=True)
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
tokenizer.tokenize(" \tHäLLo!how \n Are yoU? "), ["HaLLo", "!", "how", "Are", "yoU", "?"]
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_basic_tokenizer_respects_never_split_tokens(self):
|
||||||
|
tokenizer = BasicTokenizer(do_lower_case=False, never_split=["[UNK]"])
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
tokenizer.tokenize(" \tHeLLo!how \n Are yoU? [UNK]"), ["HeLLo", "!", "how", "Are", "yoU", "?", "[UNK]"]
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_wordpiece_tokenizer(self):
|
||||||
|
vocab_tokens = ["[UNK]", "[CLS]", "[SEP]", "want", "##want", "##ed", "wa", "un", "runn", "##ing"]
|
||||||
|
|
||||||
|
vocab = {}
|
||||||
|
for (i, token) in enumerate(vocab_tokens):
|
||||||
|
vocab[token] = i
|
||||||
|
tokenizer = WordpieceTokenizer(vocab=vocab, unk_token="[UNK]")
|
||||||
|
|
||||||
|
self.assertListEqual(tokenizer.tokenize(""), [])
|
||||||
|
|
||||||
|
self.assertListEqual(tokenizer.tokenize("unwanted running"), ["un", "##want", "##ed", "runn", "##ing"])
|
||||||
|
|
||||||
|
self.assertListEqual(tokenizer.tokenize("unwantedX running"), ["[UNK]", "runn", "##ing"])
|
||||||
|
|
||||||
|
def test_is_whitespace(self):
|
||||||
|
self.assertTrue(_is_whitespace(" "))
|
||||||
|
self.assertTrue(_is_whitespace("\t"))
|
||||||
|
self.assertTrue(_is_whitespace("\r"))
|
||||||
|
self.assertTrue(_is_whitespace("\n"))
|
||||||
|
self.assertTrue(_is_whitespace("\u00A0"))
|
||||||
|
|
||||||
|
self.assertFalse(_is_whitespace("A"))
|
||||||
|
self.assertFalse(_is_whitespace("-"))
|
||||||
|
|
||||||
|
def test_is_control(self):
|
||||||
|
self.assertTrue(_is_control("\u0005"))
|
||||||
|
|
||||||
|
self.assertFalse(_is_control("A"))
|
||||||
|
self.assertFalse(_is_control(" "))
|
||||||
|
self.assertFalse(_is_control("\t"))
|
||||||
|
self.assertFalse(_is_control("\r"))
|
||||||
|
|
||||||
|
def test_is_punctuation(self):
|
||||||
|
self.assertTrue(_is_punctuation("-"))
|
||||||
|
self.assertTrue(_is_punctuation("$"))
|
||||||
|
self.assertTrue(_is_punctuation("`"))
|
||||||
|
self.assertTrue(_is_punctuation("."))
|
||||||
|
|
||||||
|
self.assertFalse(_is_punctuation("A"))
|
||||||
|
self.assertFalse(_is_punctuation(" "))
|
||||||
|
|
||||||
|
def test_clean_text(self):
|
||||||
|
tokenizer = self.get_tokenizer()
|
||||||
|
# rust_tokenizer = self.get_rust_tokenizer()
|
||||||
|
|
||||||
|
# Example taken from the issue https://github.com/huggingface/tokenizers/issues/340
|
||||||
|
self.assertListEqual([tokenizer.tokenize(t) for t in ["Test", "\xad", "test"]], [["[UNK]"], [], ["[UNK]"]])
|
||||||
|
|
||||||
|
# self.assertListEqual(
|
||||||
|
# [rust_tokenizer.tokenize(t) for t in ["Test", "\xad", "test"]], [["[UNK]"], [], ["[UNK]"]]
|
||||||
|
# )
|
||||||
|
|
||||||
|
@slow
|
||||||
|
def test_sequence_builders(self):
|
||||||
|
tokenizer = self.tokenizer_class.from_pretrained("tapas-base-uncased")
|
||||||
|
|
||||||
|
text = tokenizer.encode("sequence builders", add_special_tokens=False)
|
||||||
|
text_2 = tokenizer.encode("multi-sequence build", add_special_tokens=False)
|
||||||
|
|
||||||
|
encoded_sentence = tokenizer.build_inputs_with_special_tokens(text)
|
||||||
|
encoded_pair = tokenizer.build_inputs_with_special_tokens(text, text_2)
|
||||||
|
|
||||||
|
assert encoded_sentence == [101] + text + [102]
|
||||||
|
assert encoded_pair == [101] + text + [102] + text_2 + [102]
|
||||||
|
|
||||||
|
def test_offsets_with_special_characters(self):
|
||||||
|
for tokenizer, pretrained_name, kwargs in self.tokenizers_list:
|
||||||
|
with self.subTest("{} ({})".format(tokenizer.__class__.__name__, pretrained_name)):
|
||||||
|
tokenizer_r = self.rust_tokenizer_class.from_pretrained(pretrained_name, **kwargs)
|
||||||
|
|
||||||
|
sentence = f"A, naïve {tokenizer_r.mask_token} AllenNLP sentence."
|
||||||
|
tokens = tokenizer_r.encode_plus(
|
||||||
|
sentence,
|
||||||
|
return_attention_mask=False,
|
||||||
|
return_token_type_ids=False,
|
||||||
|
return_offsets_mapping=True,
|
||||||
|
add_special_tokens=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
do_lower_case = tokenizer_r.do_lower_case if hasattr(tokenizer_r, "do_lower_case") else False
|
||||||
|
expected_results = (
|
||||||
|
[
|
||||||
|
((0, 0), tokenizer_r.cls_token),
|
||||||
|
((0, 1), "A"),
|
||||||
|
((1, 2), ","),
|
||||||
|
((3, 5), "na"),
|
||||||
|
((5, 6), "##ï"),
|
||||||
|
((6, 8), "##ve"),
|
||||||
|
((9, 15), tokenizer_r.mask_token),
|
||||||
|
((16, 21), "Allen"),
|
||||||
|
((21, 23), "##NL"),
|
||||||
|
((23, 24), "##P"),
|
||||||
|
((25, 33), "sentence"),
|
||||||
|
((33, 34), "."),
|
||||||
|
((0, 0), tokenizer_r.sep_token),
|
||||||
|
]
|
||||||
|
if not do_lower_case
|
||||||
|
else [
|
||||||
|
((0, 0), tokenizer_r.cls_token),
|
||||||
|
((0, 1), "a"),
|
||||||
|
((1, 2), ","),
|
||||||
|
((3, 8), "naive"),
|
||||||
|
((9, 15), tokenizer_r.mask_token),
|
||||||
|
((16, 21), "allen"),
|
||||||
|
((21, 23), "##nl"),
|
||||||
|
((23, 24), "##p"),
|
||||||
|
((25, 33), "sentence"),
|
||||||
|
((33, 34), "."),
|
||||||
|
((0, 0), tokenizer_r.sep_token),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[e[1] for e in expected_results], tokenizer_r.convert_ids_to_tokens(tokens["input_ids"])
|
||||||
|
)
|
||||||
|
self.assertEqual([e[0] for e in expected_results], tokens["offset_mapping"])
|
||||||
|
|
||||||
|
def test_add_special_tokens(self):
|
||||||
|
tokenizers: List[TapasTokenizer] = self.get_tokenizers(do_lower_case=False)
|
||||||
|
for tokenizer in tokenizers:
|
||||||
|
with self.subTest(f"{tokenizer.__class__.__name__}"):
|
||||||
|
input_table, input_query, ids = self.get_clean_sequence(
|
||||||
|
tokenizer, empty_table=True, add_special_tokens=False
|
||||||
|
)
|
||||||
|
|
||||||
|
special_token = "[SPECIAL_TOKEN]"
|
||||||
|
|
||||||
|
tokenizer.add_special_tokens({"cls_token": special_token})
|
||||||
|
encoded_special_token = tokenizer.encode(input_table, special_token, add_special_tokens=False)
|
||||||
|
self.assertEqual(len(encoded_special_token), 1)
|
||||||
|
|
||||||
|
text = tokenizer.decode(ids + encoded_special_token, clean_up_tokenization_spaces=False)
|
||||||
|
encoded = tokenizer.encode(input_table, text, add_special_tokens=False)
|
||||||
|
|
||||||
|
input_encoded = tokenizer.encode(input_table, input_query, add_special_tokens=False)
|
||||||
|
special_token_id = tokenizer.encode(input_table, special_token, add_special_tokens=False)
|
||||||
|
self.assertEqual(encoded, input_encoded + special_token_id)
|
||||||
|
|
||||||
|
decoded = tokenizer.decode(encoded, skip_special_tokens=True)
|
||||||
|
self.assertTrue(special_token not in decoded)
|
||||||
|
|
||||||
|
def test_add_tokens_tokenizer(self):
|
||||||
|
tokenizers: List[TapasTokenizer] = self.get_tokenizers(do_lower_case=False)
|
||||||
|
for tokenizer in tokenizers:
|
||||||
|
with self.subTest(f"{tokenizer.__class__.__name__}"):
|
||||||
|
input_table, input_query, ids = self.get_clean_sequence(tokenizer, empty_table=True)
|
||||||
|
vocab_size = tokenizer.vocab_size
|
||||||
|
all_size = len(tokenizer)
|
||||||
|
|
||||||
|
self.assertNotEqual(vocab_size, 0)
|
||||||
|
|
||||||
|
# We usually have added tokens from the start in tests because our vocab fixtures are
|
||||||
|
# smaller than the original vocabs - let's not assert this
|
||||||
|
# self.assertEqual(vocab_size, all_size)
|
||||||
|
|
||||||
|
new_toks = ["aaaaa bbbbbb", "cccccccccdddddddd"]
|
||||||
|
added_toks = tokenizer.add_tokens(new_toks)
|
||||||
|
vocab_size_2 = tokenizer.vocab_size
|
||||||
|
all_size_2 = len(tokenizer)
|
||||||
|
|
||||||
|
self.assertNotEqual(vocab_size_2, 0)
|
||||||
|
self.assertEqual(vocab_size, vocab_size_2)
|
||||||
|
self.assertEqual(added_toks, len(new_toks))
|
||||||
|
self.assertEqual(all_size_2, all_size + len(new_toks))
|
||||||
|
|
||||||
|
tokens = tokenizer.encode(
|
||||||
|
input_table, "aaaaa bbbbbb low cccccccccdddddddd l", add_special_tokens=False
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertGreaterEqual(len(tokens), 4)
|
||||||
|
self.assertGreater(tokens[0], tokenizer.vocab_size - 1)
|
||||||
|
self.assertGreater(tokens[-2], tokenizer.vocab_size - 1)
|
||||||
|
|
||||||
|
new_toks_2 = {"eos_token": ">>>>|||<||<<|<<", "pad_token": "<<<<<|||>|>>>>|>"}
|
||||||
|
added_toks_2 = tokenizer.add_special_tokens(new_toks_2)
|
||||||
|
vocab_size_3 = tokenizer.vocab_size
|
||||||
|
all_size_3 = len(tokenizer)
|
||||||
|
|
||||||
|
self.assertNotEqual(vocab_size_3, 0)
|
||||||
|
self.assertEqual(vocab_size, vocab_size_3)
|
||||||
|
self.assertEqual(added_toks_2, len(new_toks_2))
|
||||||
|
self.assertEqual(all_size_3, all_size_2 + len(new_toks_2))
|
||||||
|
|
||||||
|
tokens = tokenizer.encode(
|
||||||
|
input_table,
|
||||||
|
">>>>|||<||<<|<< aaaaabbbbbb low cccccccccdddddddd <<<<<|||>|>>>>|> l",
|
||||||
|
add_special_tokens=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertGreaterEqual(len(tokens), 6)
|
||||||
|
self.assertGreater(tokens[0], tokenizer.vocab_size - 1)
|
||||||
|
self.assertGreater(tokens[0], tokens[1])
|
||||||
|
self.assertGreater(tokens[-2], tokenizer.vocab_size - 1)
|
||||||
|
self.assertGreater(tokens[-2], tokens[-3])
|
||||||
|
self.assertEqual(tokens[0], tokenizer.eos_token_id)
|
||||||
|
self.assertEqual(tokens[-2], tokenizer.pad_token_id)
|
||||||
|
|
||||||
|
@require_tokenizers
|
||||||
|
def test_encode_decode_with_spaces(self):
|
||||||
|
tokenizers = self.get_tokenizers(do_lower_case=False)
|
||||||
|
for tokenizer in tokenizers:
|
||||||
|
with self.subTest(f"{tokenizer.__class__.__name__}"):
|
||||||
|
input_table, input_query, ids = self.get_clean_sequence(tokenizer, empty_table=True)
|
||||||
|
|
||||||
|
# new_toks = ["[ABC]", "[DEF]"] # TODO(thom) add this one back when Rust toks are ready: , "GHI IHG"]
|
||||||
|
new_toks = [AddedToken("[ABC]", normalized=False), AddedToken("[DEF]", normalized=False)]
|
||||||
|
tokenizer.add_tokens(new_toks)
|
||||||
|
input = "[ABC][DEF][ABC][DEF]" # TODO(thom) add back cf above: "[ABC] [DEF] [ABC] GHI IHG [DEF]"
|
||||||
|
if self.space_between_special_tokens:
|
||||||
|
output = "[ABC] [DEF] [ABC] [DEF]"
|
||||||
|
else:
|
||||||
|
output = input
|
||||||
|
encoded = tokenizer.encode(input_table, input, add_special_tokens=False)
|
||||||
|
decoded = tokenizer.decode(encoded, spaces_between_special_tokens=self.space_between_special_tokens)
|
||||||
|
self.assertIn(decoded, [output, output.lower()])
|
||||||
|
|
||||||
|
def test_encode_plus_with_padding(self):
|
||||||
|
tokenizers = self.get_tokenizers(do_lower_case=False)
|
||||||
|
for tokenizer in tokenizers:
|
||||||
|
with self.subTest(f"{tokenizer.__class__.__name__}"):
|
||||||
|
input_table, input_query, ids = self.get_clean_sequence(tokenizer, empty_table=True)
|
||||||
|
sequence = "Sequence"
|
||||||
|
|
||||||
|
# check correct behaviour if no pad_token_id exists and add it eventually
|
||||||
|
self._check_no_pad_token_padding(tokenizer, sequence)
|
||||||
|
|
||||||
|
padding_size = 10
|
||||||
|
padding_idx = tokenizer.pad_token_id
|
||||||
|
token_type_padding_idx = tokenizer.pad_token_type_id
|
||||||
|
|
||||||
|
encoded_sequence = tokenizer.encode_plus(input_table, sequence, return_special_tokens_mask=True)
|
||||||
|
input_ids = encoded_sequence["input_ids"]
|
||||||
|
special_tokens_mask = encoded_sequence["special_tokens_mask"]
|
||||||
|
sequence_length = len(input_ids)
|
||||||
|
|
||||||
|
# Test 'longest' and 'no_padding' don't do anything
|
||||||
|
tokenizer.padding_side = "right"
|
||||||
|
|
||||||
|
not_padded_sequence = tokenizer.encode_plus(
|
||||||
|
input_table,
|
||||||
|
sequence,
|
||||||
|
padding=True,
|
||||||
|
return_special_tokens_mask=True,
|
||||||
|
)
|
||||||
|
not_padded_input_ids = not_padded_sequence["input_ids"]
|
||||||
|
|
||||||
|
not_padded_special_tokens_mask = not_padded_sequence["special_tokens_mask"]
|
||||||
|
not_padded_sequence_length = len(not_padded_input_ids)
|
||||||
|
|
||||||
|
assert sequence_length == not_padded_sequence_length
|
||||||
|
assert input_ids == not_padded_input_ids
|
||||||
|
assert special_tokens_mask == not_padded_special_tokens_mask
|
||||||
|
|
||||||
|
not_padded_sequence = tokenizer.encode_plus(
|
||||||
|
input_table,
|
||||||
|
sequence,
|
||||||
|
padding=False,
|
||||||
|
return_special_tokens_mask=True,
|
||||||
|
)
|
||||||
|
not_padded_input_ids = not_padded_sequence["input_ids"]
|
||||||
|
|
||||||
|
not_padded_special_tokens_mask = not_padded_sequence["special_tokens_mask"]
|
||||||
|
not_padded_sequence_length = len(not_padded_input_ids)
|
||||||
|
|
||||||
|
assert sequence_length == not_padded_sequence_length
|
||||||
|
assert input_ids == not_padded_input_ids
|
||||||
|
assert special_tokens_mask == not_padded_special_tokens_mask
|
||||||
|
|
||||||
|
# Test right padding
|
||||||
|
tokenizer.padding_side = "right"
|
||||||
|
|
||||||
|
right_padded_sequence = tokenizer.encode_plus(
|
||||||
|
input_table,
|
||||||
|
sequence,
|
||||||
|
max_length=sequence_length + padding_size,
|
||||||
|
padding="max_length",
|
||||||
|
return_special_tokens_mask=True,
|
||||||
|
)
|
||||||
|
right_padded_input_ids = right_padded_sequence["input_ids"]
|
||||||
|
|
||||||
|
right_padded_special_tokens_mask = right_padded_sequence["special_tokens_mask"]
|
||||||
|
right_padded_sequence_length = len(right_padded_input_ids)
|
||||||
|
|
||||||
|
assert sequence_length + padding_size == right_padded_sequence_length
|
||||||
|
assert input_ids + [padding_idx] * padding_size == right_padded_input_ids
|
||||||
|
assert special_tokens_mask + [1] * padding_size == right_padded_special_tokens_mask
|
||||||
|
|
||||||
|
# Test left padding
|
||||||
|
tokenizer.padding_side = "left"
|
||||||
|
left_padded_sequence = tokenizer.encode_plus(
|
||||||
|
input_table,
|
||||||
|
sequence,
|
||||||
|
max_length=sequence_length + padding_size,
|
||||||
|
padding="max_length",
|
||||||
|
return_special_tokens_mask=True,
|
||||||
|
)
|
||||||
|
left_padded_input_ids = left_padded_sequence["input_ids"]
|
||||||
|
left_padded_special_tokens_mask = left_padded_sequence["special_tokens_mask"]
|
||||||
|
left_padded_sequence_length = len(left_padded_input_ids)
|
||||||
|
|
||||||
|
assert sequence_length + padding_size == left_padded_sequence_length
|
||||||
|
assert [padding_idx] * padding_size + input_ids == left_padded_input_ids
|
||||||
|
assert [1] * padding_size + special_tokens_mask == left_padded_special_tokens_mask
|
||||||
|
|
||||||
|
if "token_type_ids" in tokenizer.model_input_names:
|
||||||
|
token_type_ids = encoded_sequence["token_type_ids"]
|
||||||
|
left_padded_token_type_ids = left_padded_sequence["token_type_ids"]
|
||||||
|
right_padded_token_type_ids = right_padded_sequence["token_type_ids"]
|
||||||
|
|
||||||
|
assert (
|
||||||
|
token_type_ids + [[token_type_padding_idx] * 7] * padding_size == right_padded_token_type_ids
|
||||||
|
)
|
||||||
|
assert [[token_type_padding_idx] * 7] * padding_size + token_type_ids == left_padded_token_type_ids
|
||||||
|
|
||||||
|
if "attention_mask" in tokenizer.model_input_names:
|
||||||
|
attention_mask = encoded_sequence["attention_mask"]
|
||||||
|
right_padded_attention_mask = right_padded_sequence["attention_mask"]
|
||||||
|
left_padded_attention_mask = left_padded_sequence["attention_mask"]
|
||||||
|
|
||||||
|
assert attention_mask + [0] * padding_size == right_padded_attention_mask
|
||||||
|
assert [0] * padding_size + attention_mask == left_padded_attention_mask
|
||||||
|
|
||||||
|
def test_internal_consistency(self):
|
||||||
|
tokenizers = self.get_tokenizers()
|
||||||
|
for tokenizer in tokenizers:
|
||||||
|
with self.subTest(f"{tokenizer.__class__.__name__}"):
|
||||||
|
input_table, input_query, ids = self.get_clean_sequence(tokenizer, empty_table=True)
|
||||||
|
input_text, output_text = self.get_input_output_texts(tokenizer)
|
||||||
|
|
||||||
|
tokens = tokenizer.tokenize(input_text)
|
||||||
|
ids = tokenizer.convert_tokens_to_ids(tokens)
|
||||||
|
ids_2 = tokenizer.encode(input_table, input_text, add_special_tokens=False)
|
||||||
|
self.assertListEqual(ids, ids_2)
|
||||||
|
|
||||||
|
tokens_2 = tokenizer.convert_ids_to_tokens(ids)
|
||||||
|
self.assertNotEqual(len(tokens_2), 0)
|
||||||
|
text_2 = tokenizer.decode(ids)
|
||||||
|
self.assertIsInstance(text_2, str)
|
||||||
|
|
||||||
|
self.assertEqual(text_2, output_text)
|
||||||
|
|
||||||
|
def test_mask_output(self):
|
||||||
|
tokenizers = self.get_tokenizers(fast=False, do_lower_case=False)
|
||||||
|
for tokenizer in tokenizers:
|
||||||
|
with self.subTest(f"{tokenizer.__class__.__name__}"):
|
||||||
|
input_table, input_query, ids = self.get_clean_sequence(tokenizer)
|
||||||
|
|
||||||
|
if (
|
||||||
|
tokenizer.build_inputs_with_special_tokens.__qualname__.split(".")[0] != "PreTrainedTokenizer"
|
||||||
|
and "token_type_ids" in tokenizer.model_input_names
|
||||||
|
):
|
||||||
|
information = tokenizer.encode_plus(input_table, input_query, add_special_tokens=True)
|
||||||
|
sequences, mask = information["input_ids"], information["token_type_ids"]
|
||||||
|
self.assertEqual(len(sequences), len(mask))
|
||||||
Reference in new issue
Block a user