Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b85ebc3581 | ||
|
|
a439cce9de | ||
|
|
e5f055ddd9 | ||
|
|
fb474cc696 | ||
|
|
2ade06704e | ||
|
|
9312e5fbc1 | ||
|
|
5ed6135511 | ||
|
|
3acfb4b3ba | ||
|
|
0b848a812b | ||
|
|
083721acf8 | ||
|
|
9294c5f621 | ||
|
|
65143092a3 | ||
|
|
5288d6a728 | ||
|
|
6202c574ab | ||
|
|
81c4ac4e52 | ||
|
|
fe338453f8 | ||
|
|
23d75be3d7 |
No files matched your search
@@ -213,7 +213,6 @@ Min, Patrick Lewis, Ledell Wu, Sergey Edunov, Danqi Chen, and Wen-tau Yih.
|
||||
1. **[LXMERT](https://huggingface.co/transformers/model_doc/lxmert.html)** (from UNC Chapel Hill) released with the paper [LXMERT: Learning Cross-Modality Encoder Representations from Transformers for Open-Domain Question Answering](https://arxiv.org/abs/1908.07490) by Hao Tan and Mohit Bansal.
|
||||
1. **[MarianMT](https://huggingface.co/transformers/model_doc/marian.html)** Machine translation models trained using [OPUS](http://opus.nlpl.eu/) data by Jörg Tiedemann. The [Marian Framework](https://marian-nmt.github.io/) is being developed by the Microsoft Translator Team.
|
||||
1. **[MBart](https://huggingface.co/transformers/model_doc/mbart.html)** (from Facebook) released with the paper [Multilingual Denoising Pre-training for Neural Machine Translation](https://arxiv.org/abs/2001.08210) by Yinhan Liu, Jiatao Gu, Naman Goyal, Xian Li, Sergey Edunov, Marjan Ghazvininejad, Mike Lewis, Luke Zettlemoyer.
|
||||
1. **[MPNet](https://huggingface.co/transformers/model_doc/mpnet.html)** (from Microsoft Research) released with the paper [MPNet: Masked and Permuted Pre-training for Language Understanding](https://arxiv.org/abs/2004.09297) by Kaitao Song, Xu Tan, Tao Qin, Jianfeng Lu, Tie-Yan Liu.
|
||||
1. **[MT5](https://huggingface.co/transformers/model_doc/mt5.html)** (from Google AI) released with the paper [mT5: A massively multilingual pre-trained text-to-text transformer](https://arxiv.org/abs/2010.11934) by Linting Xue, Noah Constant, Adam Roberts, Mihir Kale, Rami Al-Rfou, Aditya Siddhant, Aditya Barua, Colin Raffel.
|
||||
1. **[Pegasus](https://huggingface.co/transformers/model_doc/pegasus.html)** (from Google) released with the paper [PEGASUS: Pre-training with Extracted Gap-sentences for Abstractive Summarization](https://arxiv.org/abs/1912.08777)> by Jingqing Zhang, Yao Zhao, Mohammad Saleh and Peter J. Liu.
|
||||
1. **[ProphetNet](https://huggingface.co/transformers/model_doc/prophetnet.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,6 +221,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.
|
||||
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. **[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. **[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.
|
||||
|
||||
+12
-13
@@ -151,31 +151,31 @@ and conversion utilities for the following models:
|
||||
22. :doc:`MBart <model_doc/mbart>` (from Facebook) released with the paper `Multilingual Denoising Pre-training for
|
||||
Neural Machine Translation <https://arxiv.org/abs/2001.08210>`__ by Yinhan Liu, Jiatao Gu, Naman Goyal, Xian Li,
|
||||
Sergey Edunov, Marjan Ghazvininejad, Mike Lewis, Luke Zettlemoyer.
|
||||
23. :doc:`MPNet <model_doc/mpnet>` (from Microsoft Research) released with the paper `MPNet: Masked and Permuted
|
||||
Pre-training for Language Understanding <https://arxiv.org/abs/2004.09297>`__ by Kaitao Song, Xu Tan, Tao Qin,
|
||||
Jianfeng Lu, Tie-Yan Liu.
|
||||
24. :doc:`MT5 <model_doc/mt5>` (from Google AI) released with the paper `mT5: A massively multilingual pre-trained
|
||||
23. :doc:`MT5 <model_doc/mt5>` (from Google AI) released with the paper `mT5: A massively multilingual pre-trained
|
||||
text-to-text transformer <https://arxiv.org/abs/2010.11934>`__ by Linting Xue, Noah Constant, Adam Roberts, Mihir
|
||||
Kale, Rami Al-Rfou, Aditya Siddhant, Aditya Barua, Colin Raffel.
|
||||
25. :doc:`Pegasus <model_doc/pegasus>` (from Google) released with the paper `PEGASUS: Pre-training with Extracted
|
||||
24. :doc:`Pegasus <model_doc/pegasus>` (from Google) released with the paper `PEGASUS: Pre-training with Extracted
|
||||
Gap-sentences for Abstractive Summarization <https://arxiv.org/abs/1912.08777>`__> by Jingqing Zhang, Yao Zhao,
|
||||
Mohammad Saleh and Peter J. Liu.
|
||||
26. :doc:`ProphetNet <model_doc/prophetnet>` (from Microsoft Research) released with the paper `ProphetNet: Predicting
|
||||
25. :doc:`ProphetNet <model_doc/prophetnet>` (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.
|
||||
27. :doc:`Reformer <model_doc/reformer>` (from Google Research) released with the paper `Reformer: The Efficient
|
||||
26. :doc:`Reformer <model_doc/reformer>` (from Google Research) released with the paper `Reformer: The Efficient
|
||||
Transformer <https://arxiv.org/abs/2001.04451>`__ by Nikita Kitaev, Łukasz Kaiser, Anselm Levskaya.
|
||||
28. :doc:`RoBERTa <model_doc/roberta>` (from Facebook), released together with the paper a `Robustly Optimized BERT
|
||||
27. :doc:`RoBERTa <model_doc/roberta>` (from Facebook), released together with the paper a `Robustly Optimized BERT
|
||||
Pretraining Approach <https://arxiv.org/abs/1907.11692>`__ by Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar
|
||||
Joshi, Danqi Chen, Omer Levy, Mike Lewis, Luke Zettlemoyer, Veselin Stoyanov. ultilingual BERT into `DistilmBERT
|
||||
<https://github.com/huggingface/transformers/tree/master/examples/distillation>`__ and a German version of
|
||||
DistilBERT.
|
||||
29. :doc:`SqueezeBert <model_doc/squeezebert>` released with the paper `SqueezeBERT: What can computer vision teach NLP
|
||||
28. :doc:`SqueezeBert <model_doc/squeezebert>` 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.
|
||||
30. :doc:`T5 <model_doc/t5>` (from Google AI) released with the paper `Exploring the Limits of Transfer Learning with a
|
||||
29. :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
|
||||
Roberts and Katherine Lee and Sharan Narang and Michael Matena and Yanqi Zhou and Wei Li and Peter J. Liu.
|
||||
30. :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.
|
||||
31. :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*,
|
||||
Zhilin Yang*, Yiming Yang, Jaime Carbonell, Quoc V. Le, Ruslan Salakhutdinov.
|
||||
@@ -243,8 +243,6 @@ TensorFlow and/or Flax.
|
||||
+-----------------------------+----------------+----------------+-----------------+--------------------+--------------+
|
||||
| Longformer | ✅ | ✅ | ✅ | ✅ | ❌ |
|
||||
+-----------------------------+----------------+----------------+-----------------+--------------------+--------------+
|
||||
| MPNet | ✅ | ✅ | ✅ | ✅ | ❌ |
|
||||
+-----------------------------+----------------+----------------+-----------------+--------------------+--------------+
|
||||
| Marian | ✅ | ❌ | ✅ | ✅ | ❌ |
|
||||
+-----------------------------+----------------+----------------+-----------------+--------------------+--------------+
|
||||
| MobileBERT | ✅ | ✅ | ✅ | ✅ | ❌ |
|
||||
@@ -284,6 +282,7 @@ TensorFlow and/or Flax.
|
||||
| mT5 | ✅ | ✅ | ✅ | ✅ | ❌ |
|
||||
+-----------------------------+----------------+----------------+-----------------+--------------------+--------------+
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Get started
|
||||
@@ -370,7 +369,6 @@ TensorFlow and/or Flax.
|
||||
model_doc/marian
|
||||
model_doc/mbart
|
||||
model_doc/mobilebert
|
||||
model_doc/mpnet
|
||||
model_doc/mt5
|
||||
model_doc/gpt
|
||||
model_doc/gpt2
|
||||
@@ -382,6 +380,7 @@ TensorFlow and/or Flax.
|
||||
model_doc/roberta
|
||||
model_doc/squeezebert
|
||||
model_doc/t5
|
||||
model_doc/tapas
|
||||
model_doc/transformerxl
|
||||
model_doc/xlm
|
||||
model_doc/xlmprophetnet
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
MPNet
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The MPNet model was proposed in `MPNet: Masked and Permuted Pre-training for Language Understanding
|
||||
<https://arxiv.org/abs/2004.09297>`__ by Kaitao Song, Xu Tan, Tao Qin, Jianfeng Lu, Tie-Yan Liu.
|
||||
|
||||
MPNet adopts a novel pre-training method, named masked and permuted language modeling, to inherit the advantages of
|
||||
masked language modeling and permuted language modeling for natural language understanding.
|
||||
|
||||
The abstract from the paper is the following:
|
||||
|
||||
*BERT adopts masked language modeling (MLM) for pre-training and is one of the most successful pre-training models.
|
||||
Since BERT neglects dependency among predicted tokens, XLNet introduces permuted language modeling (PLM) for
|
||||
pre-training to address this problem. However, XLNet does not leverage the full position information of a sentence and
|
||||
thus suffers from position discrepancy between pre-training and fine-tuning. In this paper, we propose MPNet, a novel
|
||||
pre-training method that inherits the advantages of BERT and XLNet and avoids their limitations. MPNet leverages the
|
||||
dependency among predicted tokens through permuted language modeling (vs. MLM in BERT), and takes auxiliary position
|
||||
information as input to make the model see a full sentence and thus reducing the position discrepancy (vs. PLM in
|
||||
XLNet). We pre-train MPNet on a large-scale dataset (over 160GB text corpora) and fine-tune on a variety of
|
||||
down-streaming tasks (GLUE, SQuAD, etc). Experimental results show that MPNet outperforms MLM and PLM by a large
|
||||
margin, and achieves better results on these tasks compared with previous state-of-the-art pre-trained methods (e.g.,
|
||||
BERT, XLNet, RoBERTa) under the same model setting.*
|
||||
|
||||
Tips:
|
||||
|
||||
- MPNet doesn't have :obj:`token_type_ids`, you don't need to indicate which token belongs to which segment. just
|
||||
separate your segments with the separation token :obj:`tokenizer.sep_token` (or :obj:`[sep]`).
|
||||
|
||||
The original code can be found `here <https://github.com/microsoft/MPNet>`__.
|
||||
|
||||
MPNetConfig
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetConfig
|
||||
:members:
|
||||
|
||||
|
||||
MPNetTokenizer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetTokenizer
|
||||
:members: build_inputs_with_special_tokens, get_special_tokens_mask,
|
||||
create_token_type_ids_from_sequences, save_vocabulary
|
||||
|
||||
|
||||
MPNetTokenizerFast
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetTokenizerFast
|
||||
:members:
|
||||
|
||||
|
||||
MPNetModel
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetModel
|
||||
:members: forward
|
||||
|
||||
|
||||
MPNetForMaskedLM
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetForMaskedLM
|
||||
:members: forward
|
||||
|
||||
|
||||
MPNetForSequenceClassification
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetForSequenceClassification
|
||||
:members: forward
|
||||
|
||||
|
||||
MPNetForMultipleChoice
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetForMultipleChoice
|
||||
:members: forward
|
||||
|
||||
|
||||
MPNetForTokenClassification
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetForTokenClassification
|
||||
:members: forward
|
||||
|
||||
|
||||
MPNetForQuestionAnswering
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.MPNetForQuestionAnswering
|
||||
:members: forward
|
||||
|
||||
|
||||
TFMPNetModel
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.TFMPNetModel
|
||||
:members: call
|
||||
|
||||
|
||||
TFMPNetForMaskedLM
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.TFMPNetForMaskedLM
|
||||
:members: call
|
||||
|
||||
|
||||
TFMPNetForSequenceClassification
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.TFMPNetForSequenceClassification
|
||||
:members: call
|
||||
|
||||
|
||||
TFMPNetForMultipleChoice
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.TFMPNetForMultipleChoice
|
||||
:members: call
|
||||
|
||||
|
||||
TFMPNetForTokenClassification
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.TFMPNetForTokenClassification
|
||||
:members: call
|
||||
|
||||
|
||||
TFMPNetForQuestionAnswering
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.TFMPNetForQuestionAnswering
|
||||
:members: call
|
||||
@@ -0,0 +1,382 @@
|
||||
TAPAS
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Overview
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The TAPAS model was proposed in `TAPAS: Weakly Supervised Table Parsing via Pre-training
|
||||
<https://www.aclweb.org/anthology/2020.acl-main.398>`__ 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 follow-up 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>`__. This page also includes links to the
|
||||
datasets (SQA, WTQ, WikiSQL and TabFact).
|
||||
|
||||
Tips:
|
||||
|
||||
- TAPAS is a model that uses relative position embeddings by default (restarting the position embeddings at every cell
|
||||
of the table). Note that this is something that was added after the publication of the original TAPAS paper. According
|
||||
to the authors, this usually results in a slightly better performance, and allows you to encode longer sequences without
|
||||
running out of embeddings. This is reflected in the ``reset_position_index_per_cell`` parameter of :class:`~transformers.TapasConfig`,
|
||||
which is set to ``True`` by default.
|
||||
The latest versions of the models available in the `model hub <https://huggingface.co/models?search=tapas>`_ all use relative
|
||||
position embeddings. You can still use the ones with absolute position embeddings by passing in a certain version when calling the
|
||||
`.from_pretrained` method as explained in the model cards.
|
||||
Note that it's usually advised to pad the inputs on the right rather than the left.
|
||||
- TAPAS is based on BERT, so ``TAPAS-base`` for example corresponds to a ``BERT-base`` architecture. Of course, TAPAS-large
|
||||
will result in the best performance (the results reported in the paper are from TAPAS-large). Metrics of the various
|
||||
sized models are shown on the `original Github repository <https://github.com/google-research/tapas>`_.
|
||||
- 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_labels` token type ids
|
||||
can be overwritten by the predicted `label_ids` of the model to the previous question. See "Usage" section for more info.
|
||||
- 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: fine-tuning
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Here we explain how you can fine-tune :class:`~transformers.TapasForQuestionAnswering` on your own dataset.
|
||||
|
||||
===========================================================================
|
||||
STEP 1: Choose one of the 3 ways in which you can use TAPAS - or experiment
|
||||
===========================================================================
|
||||
|
||||
Basically, there are 3 different ways in which one can fine-tune :class:`~transformers.TapasForQuestionAnswering`, corresponding to
|
||||
the different datasets on which Tapas was fine-tuned:
|
||||
|
||||
1. SQA: if you're interested in asking follow-up questions related to a table, in a conversational set-up. For example if you
|
||||
first ask "what's the name of the first actor?" then you can ask a follow-up question such as "how old is he?". Here, questions
|
||||
do not involve any aggregation (all questions are cell selection questions).
|
||||
2. WTQ: if you're not interested in asking questions in a conversational set-up, but rather just asking questions related
|
||||
to a table, which might involve aggregation, such as counting a number of rows, summing up cell values or averaging cell values.
|
||||
You can then for example ask "what's the total number of goals Cristiano Ronaldo made in his career?". This case is also called **weak
|
||||
supervision**, since the model itself must learn the appropriate aggregation operator (SUM/COUNT/AVERAGE/NONE) given only the answer
|
||||
to the question as supervision.
|
||||
3. WikiSQL-supervised: this dataset is based on WikiSQL with the model being given the ground truth aggregation operator during training.
|
||||
This is also called **strong supervision**. Here, learning the appropriate aggregation operator is much easier.
|
||||
|
||||
To summarize:
|
||||
|
||||
+------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------+
|
||||
| **Task** | **Example datasets** | **Description** |
|
||||
+------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------+
|
||||
| Conversational | SQA | Conversational, only cell selection questions |
|
||||
+------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------+
|
||||
| Weak supervision for aggregation | WTQ | Questions might involve aggregation, and the model must learn this given only the answer as supervision |
|
||||
+------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------+
|
||||
| Strong supervision for aggregation | WikiSQL-supervised | Questions might involve aggregation, and the model must learn this given the gold aggregation operator |
|
||||
+------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
Initializing a model with a pre-trained base and randomly initialized classification heads from the model hub is as easy as:
|
||||
|
||||
.. code-block::
|
||||
|
||||
>>> from transformers import TapasForQuestionAnswering
|
||||
|
||||
>>> # for example, the base sized model
|
||||
>>> model = TapasForQuestionAnswering.from_pretrained('google/tapas-base-uncased')
|
||||
|
||||
|
||||
Of course, you don't necessarily have to follow one of these three ways in which TAPAS was fine-tuned. You can also experiment by defining any hyperparameters
|
||||
you want when initializing :class:`~transformers.TapasConfig`, and then create a :class:`~transformers.TapasForQuestionAnswering` based on that
|
||||
configuration. For example, if you have a dataset that has both conversational questions and questions that might involve aggregation, then you can do it
|
||||
this way. Here's an example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
>>> from transformers import TapasConfig, TapasForQuestionAnswering
|
||||
|
||||
>>> # you can initialize the classification heads any way you want (see docs of TapasConfig)
|
||||
>>> config = TapasConfig(num_aggregation_labels=3, average_logits_per_cell=True, select_one_column=False)
|
||||
>>> # initializing the pre-trained base sized model with our custom classification heads
|
||||
>>> model = TapasForQuestionAnswering.from_pretrained('google/tapas-base-uncased', config=config)
|
||||
|
||||
What you can also do is start from an already fine-tuned checkpoint. A note here is that the already fine-tuned checkpoint on WTQ has some issues
|
||||
due to the L2-loss which is somewhat brittle. See `here <https://github.com/google-research/tapas/issues/91#issuecomment-735719340>`__ for more info.
|
||||
|
||||
For a list of all pre-trained and fine-tuned TAPAS checkpoints available in the HuggingFace model hub, see `here <https://huggingface.co/models?search=tapas>`__.
|
||||
|
||||
===========================================
|
||||
STEP 2: Prepare your data in the SQA format
|
||||
===========================================
|
||||
|
||||
Second, no matter what you picked above, you should prepare your dataset in the `SQA format <https://www.microsoft.com/en-us/download/details.aspx?id=54253>`__.
|
||||
This format is a TSV/CSV file with the following columns:
|
||||
|
||||
- ``id``: optional, id of the table-question pair, for bookkeeping purposes.
|
||||
- ``annotator``: optional, id of the person who annotated the table-question pair, for bookkeeping purposes.
|
||||
- ``position``: integer indicating if the question is the first, second, third,... related to the table. Only required in case of conversational setup (SQA).
|
||||
You don't need this column in case you're going for WTQ/WikiSQL-supervised.
|
||||
- ``question``: string
|
||||
- ``table_file``: string, name of a csv file containing the tabular data
|
||||
- ``answer_coordinates``: list of one or more tuples (each tuple being a cell coordinate, i.e. row, column pair that is part of the answer)
|
||||
- ``answer_text``: list of one or more strings (each string being a cell value that is part of the answer)
|
||||
- ``aggregation_label``: index of the aggregation operator. Only required in case of strong supervision for aggregation (the WikiSQL-supervised case)
|
||||
- ``float_answer``: the float answer to the question, if there is one (np.nan if there isn't). Only required in case of weak supervision for aggregation (such as WTQ and WikiSQL)
|
||||
|
||||
The tables themselves should be present in a folder, each table being a separate csv file. Note that the authors of the TAPAS algorithm used conversion
|
||||
scripts with some automated logic to convert the other datasets (WTQ, WikiSQL) into the SQA format. The author explains this `here <https://github.com/google-research/tapas/issues/50#issuecomment-705465960>`__.
|
||||
Interestingly, these conversion scripts are not perfect (the ``answer_coordinates`` and ``float_answer`` fields are populated based on the ``answer_text``),
|
||||
meaning that WTQ and WikiSQL results could actually be improved.
|
||||
|
||||
|
||||
==========================================================================================
|
||||
STEP 3: Convert your data into PyTorch tensors using :class:`~transformers.TapasTokenizer`
|
||||
==========================================================================================
|
||||
|
||||
Third, given that you've prepared your data in this TSV/CSV format (and corresponding CSV files containing the tabular data), you can then
|
||||
use :class:`~transformers.TapasTokenizer` to convert table-question pairs into :obj:`input_ids`, :obj:`attention_mask`, :obj:`token_type_ids`
|
||||
and so on. Again, based on which of the three cases you picked above, :class:`~transformers.TapasForQuestionAnswering` requires different inputs
|
||||
to be fine-tuned:
|
||||
|
||||
+------------------------------------+----------------------------------------------------------------------------------------------+
|
||||
| **Task** | **Required inputs** |
|
||||
+------------------------------------+----------------------------------------------------------------------------------------------+
|
||||
| Conversational | ``input_ids``, ``attention_mask``, ``token_type_ids``, ``label_ids`` |
|
||||
+------------------------------------+----------------------------------------------------------------------------------------------+
|
||||
| Weak supervision for aggregation | ``input_ids``, ``attention_mask``, ``token_type_ids``, ``label_ids``, ``numeric_values``, |
|
||||
| | ``numeric_values_scale``, ``float_answer`` |
|
||||
+------------------------------------+----------------------------------------------------------------------------------------------+
|
||||
| Strong supervision for aggregation | ``input ids``, ``attention mask``, ``token type ids``, ``label ids``, ``aggregation_labels`` |
|
||||
+------------------------------------+----------------------------------------------------------------------------------------------+
|
||||
|
||||
:class:`~transformers.TapasTokenizer` creates the ``label_ids``, ``numeric_values`` and ``numeric_values_scale`` based on the
|
||||
``answer_coordinates`` and ``answer_text`` columns of the TSV file. The ``float_answer`` and ``aggregation_labels`` are already in the TSV file of step 2.
|
||||
Here's an example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
>>> from transformers import TapasTokenizer
|
||||
>>> import pandas as pd
|
||||
|
||||
>>> model_name = 'google/tapas-base-uncased'
|
||||
>>> 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?"]
|
||||
>>> answer_coordinates = [[(0, 0)], [(1, 0)], [(0, 2), (1, 2), (2, 2)]]
|
||||
>>> answer_text = [["Brad Pitt"], ["69"], ["209"]]
|
||||
>>> table = pd.Dataframe(data)
|
||||
>>> inputs = tokenizer(table=table, queries=queries, answer_coordinates=answer_coordinates, answer_text=answer_text, padding='max_length', return_tensors='pt')
|
||||
>>> inputs
|
||||
{'input_ids': tensor([[ ... ]]), 'attention_mask': tensor([[...]]), 'token_type_ids': tensor([[[...]]]),
|
||||
'numeric_values': tensor([[ ... ]]), 'numeric_values_scale: tensor([[ ... ]]), label_ids: tensor([[ ... ]])}
|
||||
|
||||
Note that :class:`~transformers.TapasTokenizer` expects the data of the table to be text-only. You can use ``.astype(str)`` on a dataframe to turn it into
|
||||
text-only data. Of course, this only shows how to encode a single training example. It is advised to create a PyTorch dataset and a corresponding dataloader:
|
||||
|
||||
.. code-block::
|
||||
|
||||
>>> import torch
|
||||
>>> import pandas as pd
|
||||
|
||||
>>> tsv_path = "your_path_to_the_tsv_file"
|
||||
>>> table_csv_path = "your_path_to_a_directory_containing_all_csv_files"
|
||||
|
||||
>>> class TableDataset(torch.utils.data.Dataset):
|
||||
... def __init__(self, data, tokenizer):
|
||||
... self.data = data
|
||||
... self.tokenizer = tokenizer
|
||||
...
|
||||
... def __getitem__(self, idx):
|
||||
... item = data.iloc[idx]
|
||||
... table = pd.read_csv(table_csv_path + item.table_file).astype(str)
|
||||
... encoding = self.tokenizer(table=table,
|
||||
... queries=item.question,
|
||||
... answer_coordinates=item.answer_coordinates,
|
||||
... answer_text=item.answer_text,
|
||||
... padding="max_length",
|
||||
... return_tensors="pt"
|
||||
... )
|
||||
... # we add the float_answer which is also required (weak supervision for aggregation)
|
||||
... encoding["float_answer"] = torch.tensor(item.float_answer)
|
||||
... return encoding
|
||||
...
|
||||
... def __len__(self):
|
||||
... return len(self.data)
|
||||
|
||||
>>> data = pd.read_csv(tsv_path, sep='\t')
|
||||
>>> train_dataset = TableDataset(data, tokenizer)
|
||||
>>> train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=32)
|
||||
|
||||
Note that here, we encode each table-question pair independently. This is fine as long as your dataset is **not conversational**. In case your
|
||||
dataset involves conversational questions (such as in SQA), then you should first group together the ``queries``, ``answer_coordinates`` and
|
||||
``answer_text`` per table (in the order of their ``position`` index) and batch encode each table with its questions. This will make sure that
|
||||
the ``prev_labels`` token types (see docs of :class:`~transformers.TapasTokenizer`) are set correctly.
|
||||
|
||||
===================================================
|
||||
STEP 4: Train (fine-tune) TapasForQuestionAnswering
|
||||
===================================================
|
||||
|
||||
You can then fine-tune :class:`~transformers.TapasForQuestionAnswering` using native PyTorch as follows:
|
||||
|
||||
.. code-block::
|
||||
|
||||
>>> from transformers import TapasForQuestionAnswering
|
||||
|
||||
>>> model = TapasForQuestionAnswering.from_pretrained("google/tapas-base-uncased")
|
||||
|
||||
>>> for epoch in range(2): # loop over the dataset multiple times
|
||||
... for idx, batch in enumerate(train_dataloader):
|
||||
... # get the inputs;
|
||||
... input_ids, attention_mask, token_type_ids, label_ids, numeric_values, numeric_values_scale, float_answer = batch
|
||||
|
||||
... # zero the parameter gradients
|
||||
... optimizer.zero_grad()
|
||||
|
||||
... # forward + backward + optimize
|
||||
... outputs = model(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids,
|
||||
... label_ids=label_ids, numeric_values=numeric_values, numeric_values_scale=numeric_values_scale,
|
||||
... float_answer=float_answer)
|
||||
... loss = outputs.loss
|
||||
... loss.backward()
|
||||
... optimizer.step()
|
||||
|
||||
Usage: inference
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Here we explain how you can use :class:`~transformers.TapasForQuestionAnswering` for inference (i.e. making predictions on new data).
|
||||
For inference, only ``input_ids``, ``attention_mask`` and ``token_type_ids`` (which you can obtain using
|
||||
:class:`~transformers.TapasTokenizer`) have to be provided to the model to obtain the logits. Next, you can use the handy
|
||||
``convert_logits_to_predictions`` method of :class:`~transformers.TapasTokenizer` to convert these into predicted coordinates
|
||||
and optional aggregation indices.
|
||||
|
||||
However, note that inference is **different** depending on whether or not the setup is conversational. In a non-conversational set-up, inference
|
||||
can be done in parallel on all table-question pairs of a batch. Here's an example of that:
|
||||
|
||||
.. code-block::
|
||||
|
||||
>>> from transformers import TapasTokenizer, TapasForQuestionAnswering
|
||||
>>> import pandas as pd
|
||||
|
||||
>>> model_name = 'google/tapas-base-uncased-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=table, queries=queries, padding='max_length', return_tensors="pt")
|
||||
>>> outputs = model(**inputs)
|
||||
>>> predicted_answer_coordinates, predicted_aggregation_indices = tokenizer.convert_logits_to_predictions(
|
||||
... inputs,
|
||||
... output.logits,
|
||||
... outputs.logits_aggregation
|
||||
...)
|
||||
|
||||
>>> # let's print out the results:
|
||||
>>> id2aggregation = {0: "NONE", 1: "SUM", 2: "AVERAGE", 3:"COUNT"}
|
||||
>>> aggregation_predictions_string = [id2aggregation[x] for x in predicted_aggregation_indices]
|
||||
|
||||
>>> answers = []
|
||||
>>> for coordinates in predicted_answer_coordinates:
|
||||
... 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
|
||||
|
||||
In case of a conversational set-up, then each table-question pair must be provided **sequentially** to the model, such that
|
||||
the ``prev_labels`` token types can be overwritten by the predicted ``label_ids`` of the previous table-question pair.
|
||||
|
||||
|
||||
Tapas specific outputs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.models.tapas.modeling_tapas.TableQuestionAnsweringOutput
|
||||
:members:
|
||||
|
||||
|
||||
TapasConfig
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.TapasConfig
|
||||
:members:
|
||||
|
||||
|
||||
TapasTokenizer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.TapasTokenizer
|
||||
:members: __call__, 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:
|
||||
@@ -0,0 +1,123 @@
|
||||
---
|
||||
language: en
|
||||
tags:
|
||||
- tapas
|
||||
- masked-lm
|
||||
license: apache-2.0
|
||||
---
|
||||
|
||||
# TAPAS base model
|
||||
|
||||
This model corresponds to the `tapas_inter_masklm_base_reset` checkpoint of the [original Github repository](https://github.com/google-research/tapas).
|
||||
|
||||
Disclaimer: The team releasing TAPAS did not write a model card for this model so this model card has been written by
|
||||
the Hugging Face team and contributors.
|
||||
|
||||
## Model description
|
||||
|
||||
TAPAS is a BERT-like transformers model pretrained on a large corpus of English data from Wikipedia in a self-supervised fashion.
|
||||
This means it was pretrained on the raw tables and associated texts only, with no humans labelling them in any way (which is why it
|
||||
can use lots of publicly available data) with an automatic process to generate inputs and labels from those texts. More precisely, it
|
||||
was pretrained with two objectives:
|
||||
|
||||
- Masked language modeling (MLM): taking a (flattened) table and associated context, the model randomly masks 15% of the words in
|
||||
the input, then runs the entire (partially masked) sequence through the model. The model then has to predict the masked words.
|
||||
This is different from traditional recurrent neural networks (RNNs) that usually see the words one after the other,
|
||||
or from autoregressive models like GPT which internally mask the future tokens. It allows the model to learn a bidirectional
|
||||
representation of a table and associated text.
|
||||
- Intermediate pre-training: to encourage numerical reasoning on tables, the authors additionally pre-trained the model by creating
|
||||
a balanced dataset of millions of syntactically created training examples. Here, the model must predict (classify) whether a sentence
|
||||
is supported or refuted by the contents of a table. The training examples are created based on synthetic as well as counterfactual statements.
|
||||
|
||||
This way, the model learns an inner representation of the English language used in tables and associated texts, which can then be used
|
||||
to extract features useful for downstream tasks such as answering questions about a table, or determining whether a sentence is entailed
|
||||
or refuted by the contents of a table. Fine-tuning is done by adding classification heads on top of the pre-trained model, and then jointly
|
||||
train the randomly initialized classification heads with the base model on a labelled dataset.
|
||||
|
||||
## Intended uses & limitations
|
||||
|
||||
You can use the raw model for masked language modeling, but it's mostly intended to be fine-tuned on a downstream task.
|
||||
See the [model hub](https://huggingface.co/models?filter=tapas) to look for fine-tuned versions on a task that interests you.
|
||||
|
||||
|
||||
Here is how to use this model to get the features of a given table-text pair in PyTorch:
|
||||
|
||||
```python
|
||||
from transformers import TapasTokenizer, TapasModel
|
||||
import pandas as pd
|
||||
tokenizer = TapasTokenizer.from_pretrained('tapase-base')
|
||||
model = TapasModel.from_pretrained("tapas-base")
|
||||
data = {'Actors': ["Brad Pitt", "Leonardo Di Caprio", "George Clooney"],
|
||||
'Age': ["56", "45", "59"],
|
||||
'Number of movies': ["87", "53", "69"]
|
||||
}
|
||||
table = pd.DataFrame.from_dict(data)
|
||||
queries = ["How many movies has George Clooney played in?"]
|
||||
text = "Replace me by any text you'd like."
|
||||
encoded_input = tokenizer(table=table, queries=queries, return_tensors='pt')
|
||||
output = model(**encoded_input)
|
||||
```
|
||||
|
||||
## Training data
|
||||
|
||||
For masked language modeling (MLM), a collection of 6.2 million tables was extracted from English Wikipedia: 3.3M of class [Infobox](https://en.wikipedia.org/wiki/Help:Infobox)
|
||||
and 2.9M of class WikiTable. The author only considered tables with at most 500 cells. As a proxy for questions that appear in the
|
||||
downstream tasks, the authros extracted the table caption, article title, article description, segment title and text of the segment
|
||||
the table occurs in as relevant text snippets. In this way, 21.3M snippets were created. For more info, see the original [TAPAS paper](https://www.aclweb.org/anthology/2020.acl-main.398.pdf).
|
||||
|
||||
For intermediate pre-training, 2 tasks are introduced: one based on synthetic and the other from counterfactual statements. The first one
|
||||
generates a sentence by sampling from a set of logical expressions that filter, combine and compare the information on the table, which is
|
||||
required in table entailment (e.g., knowing that Gerald Ford is taller than the average president requires summing
|
||||
all presidents and dividing by the number of presidents). The second one corrupts sentences about tables appearing on Wikipedia by swapping
|
||||
entities for plausible alternatives. Examples of the two tasks can be seen in Figure 1. The procedure is described in detail in section 3 of
|
||||
the [TAPAS follow-up paper](https://www.aclweb.org/anthology/2020.findings-emnlp.27.pdf).
|
||||
|
||||
## Training procedure
|
||||
|
||||
### Preprocessing
|
||||
|
||||
The texts are lowercased and tokenized using WordPiece and a vocabulary size of 30,000. The inputs of the model are
|
||||
then of the form:
|
||||
|
||||
```
|
||||
[CLS] Context [SEP] Flattened table [SEP]
|
||||
```
|
||||
|
||||
The details of the masking procedure for each sequence are the following:
|
||||
- 15% of the tokens are masked.
|
||||
- In 80% of the cases, the masked tokens are replaced by `[MASK]`.
|
||||
- In 10% of the cases, the masked tokens are replaced by a random token (different) from the one they replace.
|
||||
- In the 10% remaining cases, the masked tokens are left as is.
|
||||
|
||||
The details of the creation of the synthetic and counterfactual examples can be found in the [follow-up paper](https://arxiv.org/abs/2010.00571).
|
||||
|
||||
### Pretraining
|
||||
|
||||
The model was trained on 32 Cloud TPU v3 cores for one million steps with maximum sequence length 512 and batch size of 512.
|
||||
In this setup, pre-training takes around 3 days. The optimizer used is Adam with a learning rate of 5e-5, and a warmup ratio
|
||||
of 0.10.
|
||||
|
||||
|
||||
### BibTeX entry and citation info
|
||||
|
||||
```bibtex
|
||||
@misc{herzig2020tapas,
|
||||
title={TAPAS: Weakly Supervised Table Parsing via Pre-training},
|
||||
author={Jonathan Herzig and Paweł Krzysztof Nowak and Thomas Müller and Francesco Piccinno and Julian Martin Eisenschlos},
|
||||
year={2020},
|
||||
eprint={2004.02349},
|
||||
archivePrefix={arXiv},
|
||||
primaryClass={cs.IR}
|
||||
}
|
||||
```
|
||||
|
||||
```bibtex
|
||||
@misc{eisenschlos2020understanding,
|
||||
title={Understanding tables with intermediate pre-training},
|
||||
author={Julian Martin Eisenschlos and Syrine Krichene and Thomas Müller},
|
||||
year={2020},
|
||||
eprint={2010.00571},
|
||||
archivePrefix={arXiv},
|
||||
primaryClass={cs.CL}
|
||||
}
|
||||
```
|
||||
@@ -152,7 +152,6 @@ from .models.marian import MarianConfig
|
||||
from .models.mbart import MBartConfig
|
||||
from .models.mmbt import MMBTConfig
|
||||
from .models.mobilebert import MOBILEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, MobileBertConfig, MobileBertTokenizer
|
||||
from .models.mpnet import MPNET_PRETRAINED_CONFIG_ARCHIVE_MAP, MPNetConfig, MPNetTokenizer
|
||||
from .models.mt5 import MT5Config
|
||||
from .models.openai import OPENAI_GPT_PRETRAINED_CONFIG_ARCHIVE_MAP, OpenAIGPTConfig, OpenAIGPTTokenizer
|
||||
from .models.pegasus import PegasusConfig
|
||||
@@ -164,6 +163,7 @@ from .models.retribert import RETRIBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, RetriBert
|
||||
from .models.roberta import ROBERTA_PRETRAINED_CONFIG_ARCHIVE_MAP, RobertaConfig, RobertaTokenizer
|
||||
from .models.squeezebert import SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, SqueezeBertConfig, SqueezeBertTokenizer
|
||||
from .models.t5 import T5_PRETRAINED_CONFIG_ARCHIVE_MAP, T5Config
|
||||
from .models.tapas import TAPAS_PRETRAINED_CONFIG_ARCHIVE_MAP, TapasConfig, TapasTokenizer
|
||||
from .models.transfo_xl import (
|
||||
TRANSFO_XL_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||
TransfoXLConfig,
|
||||
@@ -256,7 +256,6 @@ if is_tokenizers_available():
|
||||
from .models.lxmert import LxmertTokenizerFast
|
||||
from .models.mbart import MBartTokenizerFast
|
||||
from .models.mobilebert import MobileBertTokenizerFast
|
||||
from .models.mpnet import MPNetTokenizerFast
|
||||
from .models.mt5 import MT5TokenizerFast
|
||||
from .models.openai import OpenAIGPTTokenizerFast
|
||||
from .models.pegasus import PegasusTokenizerFast
|
||||
@@ -530,17 +529,6 @@ if is_torch_available():
|
||||
MobileBertPreTrainedModel,
|
||||
load_tf_weights_in_mobilebert,
|
||||
)
|
||||
from .models.mpnet import (
|
||||
MPNET_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
MPNetForMaskedLM,
|
||||
MPNetForMultipleChoice,
|
||||
MPNetForQuestionAnswering,
|
||||
MPNetForSequenceClassification,
|
||||
MPNetForTokenClassification,
|
||||
MPNetLayer,
|
||||
MPNetModel,
|
||||
MPNetPreTrainedModel,
|
||||
)
|
||||
from .models.mt5 import MT5EncoderModel, MT5ForConditionalGeneration, MT5Model
|
||||
from .models.openai import (
|
||||
OPENAI_GPT_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
@@ -602,6 +590,13 @@ if is_torch_available():
|
||||
T5PreTrainedModel,
|
||||
load_tf_weights_in_t5,
|
||||
)
|
||||
from .models.tapas import(
|
||||
TAPAS_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
TapasModel,
|
||||
TapasForMaskedLM,
|
||||
TapasForQuestionAnswering,
|
||||
TapasForSequenceClassification,
|
||||
)
|
||||
from .models.transfo_xl import (
|
||||
TRANSFO_XL_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
AdaptiveEmbedding,
|
||||
@@ -841,17 +836,6 @@ if is_tf_available():
|
||||
TFMobileBertModel,
|
||||
TFMobileBertPreTrainedModel,
|
||||
)
|
||||
from .models.mpnet import (
|
||||
TF_MPNET_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
TFMPNetForMaskedLM,
|
||||
TFMPNetForMultipleChoice,
|
||||
TFMPNetForQuestionAnswering,
|
||||
TFMPNetForSequenceClassification,
|
||||
TFMPNetForTokenClassification,
|
||||
TFMPNetMainLayer,
|
||||
TFMPNetModel,
|
||||
TFMPNetPreTrainedModel,
|
||||
)
|
||||
from .models.mt5 import TFMT5EncoderModel, TFMT5ForConditionalGeneration, TFMT5Model
|
||||
from .models.openai import (
|
||||
TF_OPENAI_GPT_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
|
||||
@@ -28,7 +28,7 @@ from .utils import DataProcessor
|
||||
|
||||
|
||||
# Store the tokenizers which insert 2 separators tokens
|
||||
MULTI_SEP_TOKENS_TOKENIZERS_SET = {"roberta", "camembert", "bart", "mpnet"}
|
||||
MULTI_SEP_TOKENS_TOKENIZERS_SET = {"roberta", "camembert", "bart"}
|
||||
|
||||
|
||||
if is_torch_available():
|
||||
|
||||
@@ -216,6 +216,20 @@ except ImportError:
|
||||
_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
|
||||
|
||||
|
||||
old_default_cache_path = os.path.join(torch_cache_home, "transformers")
|
||||
# New default cache, shared with the Datasets library
|
||||
hf_cache_home = os.path.expanduser(
|
||||
@@ -325,6 +339,10 @@ def is_in_notebook():
|
||||
return _in_notebook
|
||||
|
||||
|
||||
def is_scatter_available():
|
||||
return _scatter_available
|
||||
|
||||
|
||||
def torch_only_method(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
if not _torch_available:
|
||||
@@ -427,6 +445,13 @@ installation page: https://github.com/google/flax and follow the ones that match
|
||||
"""
|
||||
|
||||
|
||||
# docstyle-ignore
|
||||
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):
|
||||
name = obj.__name__ if hasattr(obj, "__name__") else obj.__class__.__name__
|
||||
if not is_datasets_available():
|
||||
@@ -481,6 +506,12 @@ def requires_protobuf(obj):
|
||||
raise ImportError(PROTOBUF_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 docstring_decorator(fn):
|
||||
fn.__doc__ = "".join(docstr) + (fn.__doc__ if fn.__doc__ is not None else "")
|
||||
|
||||
@@ -40,7 +40,6 @@ from ..lxmert.configuration_lxmert import LXMERT_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||
from ..marian.configuration_marian import MarianConfig
|
||||
from ..mbart.configuration_mbart import MBART_PRETRAINED_CONFIG_ARCHIVE_MAP, MBartConfig
|
||||
from ..mobilebert.configuration_mobilebert import MobileBertConfig
|
||||
from ..mpnet.configuration_mpnet import MPNET_PRETRAINED_CONFIG_ARCHIVE_MAP, MPNetConfig
|
||||
from ..mt5.configuration_mt5 import MT5Config
|
||||
from ..openai.configuration_openai import OPENAI_GPT_PRETRAINED_CONFIG_ARCHIVE_MAP, OpenAIGPTConfig
|
||||
from ..pegasus.configuration_pegasus import PegasusConfig
|
||||
@@ -51,6 +50,7 @@ from ..retribert.configuration_retribert import RETRIBERT_PRETRAINED_CONFIG_ARCH
|
||||
from ..roberta.configuration_roberta import ROBERTA_PRETRAINED_CONFIG_ARCHIVE_MAP, RobertaConfig
|
||||
from ..squeezebert.configuration_squeezebert import SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, SqueezeBertConfig
|
||||
from ..t5.configuration_t5 import T5_PRETRAINED_CONFIG_ARCHIVE_MAP, T5Config
|
||||
from ..tapas.configuration_tapas import TAPAS_PRETRAINED_CONFIG_ARCHIVE_MAP, TapasConfig
|
||||
from ..transfo_xl.configuration_transfo_xl import TRANSFO_XL_PRETRAINED_CONFIG_ARCHIVE_MAP, TransfoXLConfig
|
||||
from ..xlm.configuration_xlm import XLM_PRETRAINED_CONFIG_ARCHIVE_MAP, XLMConfig
|
||||
from ..xlm_prophetnet.configuration_xlm_prophetnet import (
|
||||
@@ -94,7 +94,7 @@ ALL_PRETRAINED_CONFIG_ARCHIVE_MAP = dict(
|
||||
SQUEEZEBERT_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||
XLM_PROPHETNET_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||
PROPHETNET_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||
MPNET_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||
TAPAS_PRETRAINED_CONFIG_ARCHIVE_MAP,
|
||||
]
|
||||
for key, value, in pretrained_map.items()
|
||||
)
|
||||
@@ -115,7 +115,6 @@ CONFIG_MAPPING = OrderedDict(
|
||||
("pegasus", PegasusConfig),
|
||||
("marian", MarianConfig),
|
||||
("mbart", MBartConfig),
|
||||
("mpnet", MPNetConfig),
|
||||
("bart", BartConfig),
|
||||
("blenderbot", BlenderbotConfig),
|
||||
("reformer", ReformerConfig),
|
||||
@@ -141,6 +140,7 @@ CONFIG_MAPPING = OrderedDict(
|
||||
("dpr", DPRConfig),
|
||||
("layoutlm", LayoutLMConfig),
|
||||
("rag", RagConfig),
|
||||
("tapas", TapasConfig),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -184,7 +184,7 @@ MODEL_NAMES_MAPPING = OrderedDict(
|
||||
("xlm-prophetnet", "XLMProphetNet"),
|
||||
("prophetnet", "ProphetNet"),
|
||||
("mt5", "mT5"),
|
||||
("mpnet", "MPNet"),
|
||||
("tapas", "TAPAS"),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -122,14 +122,6 @@ from ..mobilebert.modeling_mobilebert import (
|
||||
MobileBertForTokenClassification,
|
||||
MobileBertModel,
|
||||
)
|
||||
from ..mpnet.modeling_mpnet import (
|
||||
MPNetForMaskedLM,
|
||||
MPNetForMultipleChoice,
|
||||
MPNetForQuestionAnswering,
|
||||
MPNetForSequenceClassification,
|
||||
MPNetForTokenClassification,
|
||||
MPNetModel,
|
||||
)
|
||||
from ..mt5.modeling_mt5 import MT5ForConditionalGeneration, MT5Model
|
||||
from ..openai.modeling_openai import OpenAIGPTForSequenceClassification, OpenAIGPTLMHeadModel, OpenAIGPTModel
|
||||
from ..pegasus.modeling_pegasus import PegasusForConditionalGeneration
|
||||
@@ -165,6 +157,12 @@ from ..squeezebert.modeling_squeezebert import (
|
||||
SqueezeBertModel,
|
||||
)
|
||||
from ..t5.modeling_t5 import T5ForConditionalGeneration, T5Model
|
||||
from ..tapas.modeling_tapas import (
|
||||
TapasModel,
|
||||
TapasForMaskedLM,
|
||||
TapasForQuestionAnswering,
|
||||
TapasForSequenceClassification,
|
||||
)
|
||||
from ..transfo_xl.modeling_transfo_xl import TransfoXLForSequenceClassification, TransfoXLLMHeadModel, TransfoXLModel
|
||||
from ..xlm.modeling_xlm import (
|
||||
XLMForMultipleChoice,
|
||||
@@ -220,7 +218,6 @@ from .configuration_auto import (
|
||||
MarianConfig,
|
||||
MBartConfig,
|
||||
MobileBertConfig,
|
||||
MPNetConfig,
|
||||
MT5Config,
|
||||
OpenAIGPTConfig,
|
||||
PegasusConfig,
|
||||
@@ -230,6 +227,7 @@ from .configuration_auto import (
|
||||
RobertaConfig,
|
||||
SqueezeBertConfig,
|
||||
T5Config,
|
||||
TapasConfig,
|
||||
TransfoXLConfig,
|
||||
XLMConfig,
|
||||
XLMProphetNetConfig,
|
||||
@@ -276,7 +274,7 @@ MODEL_MAPPING = OrderedDict(
|
||||
(DPRConfig, DPRQuestionEncoder),
|
||||
(XLMProphetNetConfig, XLMProphetNetModel),
|
||||
(ProphetNetConfig, ProphetNetModel),
|
||||
(MPNetConfig, MPNetModel),
|
||||
(TapasConfig, TapasModel),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -307,7 +305,7 @@ MODEL_FOR_PRETRAINING_MAPPING = OrderedDict(
|
||||
(ElectraConfig, ElectraForPreTraining),
|
||||
(LxmertConfig, LxmertForPreTraining),
|
||||
(FunnelConfig, FunnelForPreTraining),
|
||||
(MPNetConfig, MPNetForMaskedLM),
|
||||
(TapasConfig, TapasForMaskedLM),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -339,7 +337,7 @@ MODEL_WITH_LM_HEAD_MAPPING = OrderedDict(
|
||||
(EncoderDecoderConfig, EncoderDecoderModel),
|
||||
(ReformerConfig, ReformerModelWithLMHead),
|
||||
(FunnelConfig, FunnelForMaskedLM),
|
||||
(MPNetConfig, MPNetForMaskedLM),
|
||||
(TapasConfig, TapasForMaskedLM),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -385,7 +383,7 @@ MODEL_FOR_MASKED_LM_MAPPING = OrderedDict(
|
||||
(ElectraConfig, ElectraForMaskedLM),
|
||||
(ReformerConfig, ReformerForMaskedLM),
|
||||
(FunnelConfig, FunnelForMaskedLM),
|
||||
(MPNetConfig, MPNetForMaskedLM),
|
||||
(TapasConfig, TapasForMaskedLM),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -430,7 +428,7 @@ MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING = OrderedDict(
|
||||
(ReformerConfig, ReformerForSequenceClassification),
|
||||
(CTRLConfig, CTRLForSequenceClassification),
|
||||
(TransfoXLConfig, TransfoXLForSequenceClassification),
|
||||
(MPNetConfig, MPNetForSequenceClassification),
|
||||
(TapasConfig, TapasForSequenceClassification),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -454,7 +452,7 @@ MODEL_FOR_QUESTION_ANSWERING_MAPPING = OrderedDict(
|
||||
(ReformerConfig, ReformerForQuestionAnswering),
|
||||
(FunnelConfig, FunnelForQuestionAnswering),
|
||||
(LxmertConfig, LxmertForQuestionAnswering),
|
||||
(MPNetConfig, MPNetForQuestionAnswering),
|
||||
(TapasConfig, TapasForQuestionAnswering),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -477,7 +475,6 @@ MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING = OrderedDict(
|
||||
(ElectraConfig, ElectraForTokenClassification),
|
||||
(FlaubertConfig, FlaubertForTokenClassification),
|
||||
(FunnelConfig, FunnelForTokenClassification),
|
||||
(MPNetConfig, MPNetForTokenClassification),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -498,7 +495,6 @@ MODEL_FOR_MULTIPLE_CHOICE_MAPPING = OrderedDict(
|
||||
(XLMConfig, XLMForMultipleChoice),
|
||||
(FlaubertConfig, FlaubertForMultipleChoice),
|
||||
(FunnelConfig, FunnelForMultipleChoice),
|
||||
(MPNetConfig, MPNetForMultipleChoice),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -111,14 +111,6 @@ from ..mobilebert.modeling_tf_mobilebert import (
|
||||
TFMobileBertForTokenClassification,
|
||||
TFMobileBertModel,
|
||||
)
|
||||
from ..mpnet.modeling_tf_mpnet import (
|
||||
TFMPNetForMaskedLM,
|
||||
TFMPNetForMultipleChoice,
|
||||
TFMPNetForQuestionAnswering,
|
||||
TFMPNetForSequenceClassification,
|
||||
TFMPNetForTokenClassification,
|
||||
TFMPNetModel,
|
||||
)
|
||||
from ..mt5.modeling_tf_mt5 import TFMT5ForConditionalGeneration, TFMT5Model
|
||||
from ..openai.modeling_tf_openai import TFOpenAIGPTLMHeadModel, TFOpenAIGPTModel
|
||||
from ..pegasus.modeling_tf_pegasus import TFPegasusForConditionalGeneration
|
||||
@@ -175,7 +167,6 @@ from .configuration_auto import (
|
||||
MarianConfig,
|
||||
MBartConfig,
|
||||
MobileBertConfig,
|
||||
MPNetConfig,
|
||||
MT5Config,
|
||||
OpenAIGPTConfig,
|
||||
PegasusConfig,
|
||||
@@ -217,7 +208,6 @@ TF_MODEL_MAPPING = OrderedDict(
|
||||
(ElectraConfig, TFElectraModel),
|
||||
(FunnelConfig, TFFunnelModel),
|
||||
(DPRConfig, TFDPRQuestionEncoder),
|
||||
(MPNetConfig, TFMPNetModel),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -243,7 +233,6 @@ TF_MODEL_FOR_PRETRAINING_MAPPING = OrderedDict(
|
||||
(CTRLConfig, TFCTRLLMHeadModel),
|
||||
(ElectraConfig, TFElectraForPreTraining),
|
||||
(FunnelConfig, TFFunnelForPreTraining),
|
||||
(MPNetConfig, TFMPNetForMaskedLM),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -270,7 +259,6 @@ TF_MODEL_WITH_LM_HEAD_MAPPING = OrderedDict(
|
||||
(CTRLConfig, TFCTRLLMHeadModel),
|
||||
(ElectraConfig, TFElectraForMaskedLM),
|
||||
(FunnelConfig, TFFunnelForMaskedLM),
|
||||
(MPNetConfig, TFMPNetForMaskedLM),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -305,7 +293,6 @@ TF_MODEL_FOR_MASKED_LM_MAPPING = OrderedDict(
|
||||
(XLMConfig, TFXLMWithLMHeadModel),
|
||||
(ElectraConfig, TFElectraForMaskedLM),
|
||||
(FunnelConfig, TFFunnelForMaskedLM),
|
||||
(MPNetConfig, TFMPNetForMaskedLM),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -340,7 +327,6 @@ TF_MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING = OrderedDict(
|
||||
(ElectraConfig, TFElectraForSequenceClassification),
|
||||
(FunnelConfig, TFFunnelForSequenceClassification),
|
||||
(GPT2Config, TFGPT2ForSequenceClassification),
|
||||
(MPNetConfig, TFMPNetForSequenceClassification),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -360,7 +346,6 @@ TF_MODEL_FOR_QUESTION_ANSWERING_MAPPING = OrderedDict(
|
||||
(XLMConfig, TFXLMForQuestionAnsweringSimple),
|
||||
(ElectraConfig, TFElectraForQuestionAnswering),
|
||||
(FunnelConfig, TFFunnelForQuestionAnswering),
|
||||
(MPNetConfig, TFMPNetForQuestionAnswering),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -380,7 +365,6 @@ TF_MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING = OrderedDict(
|
||||
(XLNetConfig, TFXLNetForTokenClassification),
|
||||
(ElectraConfig, TFElectraForTokenClassification),
|
||||
(FunnelConfig, TFFunnelForTokenClassification),
|
||||
(MPNetConfig, TFMPNetForTokenClassification),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -400,7 +384,6 @@ TF_MODEL_FOR_MULTIPLE_CHOICE_MAPPING = OrderedDict(
|
||||
(AlbertConfig, TFAlbertForMultipleChoice),
|
||||
(ElectraConfig, TFElectraForMultipleChoice),
|
||||
(FunnelConfig, TFFunnelForMultipleChoice),
|
||||
(MPNetConfig, TFMPNetForMultipleChoice),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ from ..layoutlm.tokenization_layoutlm import LayoutLMTokenizer
|
||||
from ..longformer.tokenization_longformer import LongformerTokenizer
|
||||
from ..lxmert.tokenization_lxmert import LxmertTokenizer
|
||||
from ..mobilebert.tokenization_mobilebert import MobileBertTokenizer
|
||||
from ..mpnet.tokenization_mpnet import MPNetTokenizer
|
||||
from ..openai.tokenization_openai import OpenAIGPTTokenizer
|
||||
from ..phobert.tokenization_phobert import PhobertTokenizer
|
||||
from ..prophetnet.tokenization_prophetnet import ProphetNetTokenizer
|
||||
@@ -47,6 +46,7 @@ from ..rag.tokenization_rag import RagTokenizer
|
||||
from ..retribert.tokenization_retribert import RetriBertTokenizer
|
||||
from ..roberta.tokenization_roberta import RobertaTokenizer
|
||||
from ..squeezebert.tokenization_squeezebert import SqueezeBertTokenizer
|
||||
from ..tapas.tokenization_tapas import TapasTokenizer
|
||||
from ..transfo_xl.tokenization_transfo_xl import TransfoXLTokenizer
|
||||
from ..xlm.tokenization_xlm import XLMTokenizer
|
||||
from .configuration_auto import (
|
||||
@@ -73,7 +73,6 @@ from .configuration_auto import (
|
||||
MarianConfig,
|
||||
MBartConfig,
|
||||
MobileBertConfig,
|
||||
MPNetConfig,
|
||||
MT5Config,
|
||||
OpenAIGPTConfig,
|
||||
PegasusConfig,
|
||||
@@ -84,6 +83,7 @@ from .configuration_auto import (
|
||||
RobertaConfig,
|
||||
SqueezeBertConfig,
|
||||
T5Config,
|
||||
TapasConfig,
|
||||
TransfoXLConfig,
|
||||
XLMConfig,
|
||||
XLMProphetNetConfig,
|
||||
@@ -139,7 +139,6 @@ if is_tokenizers_available():
|
||||
from ..lxmert.tokenization_lxmert_fast import LxmertTokenizerFast
|
||||
from ..mbart.tokenization_mbart_fast import MBartTokenizerFast
|
||||
from ..mobilebert.tokenization_mobilebert_fast import MobileBertTokenizerFast
|
||||
from ..mpnet.tokenization_mpnet_fast import MPNetTokenizerFast
|
||||
from ..mt5 import MT5TokenizerFast
|
||||
from ..openai.tokenization_openai_fast import OpenAIGPTTokenizerFast
|
||||
from ..pegasus.tokenization_pegasus_fast import PegasusTokenizerFast
|
||||
@@ -167,7 +166,6 @@ else:
|
||||
LxmertTokenizerFast = None
|
||||
MBartTokenizerFast = None
|
||||
MobileBertTokenizerFast = None
|
||||
MPNetTokenizerFast = None
|
||||
MT5TokenizerFast = None
|
||||
OpenAIGPTTokenizerFast = None
|
||||
PegasusTokenizerFast = None
|
||||
@@ -222,7 +220,7 @@ TOKENIZER_MAPPING = OrderedDict(
|
||||
(RagConfig, (RagTokenizer, None)),
|
||||
(XLMProphetNetConfig, (XLMProphetNetTokenizer, None)),
|
||||
(ProphetNetConfig, (ProphetNetTokenizer, None)),
|
||||
(MPNetConfig, (MPNetTokenizer, MPNetTokenizerFast)),
|
||||
(TapasConfig, (TapasTokenizer, None)),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# flake8: noqa
|
||||
# There's no way to ignore "F401 '...' imported but unused" warnings in this
|
||||
# module, but to preserve other warnings. So, don't check this module at all.
|
||||
|
||||
from ...file_utils import is_flax_available, is_tf_available, is_tokenizers_available, is_torch_available
|
||||
from .configuration_mpnet import MPNET_PRETRAINED_CONFIG_ARCHIVE_MAP, MPNetConfig
|
||||
from .tokenization_mpnet import MPNetTokenizer
|
||||
|
||||
|
||||
if is_tokenizers_available():
|
||||
from .tokenization_mpnet_fast import MPNetTokenizerFast
|
||||
|
||||
if is_torch_available():
|
||||
from .modeling_mpnet import (
|
||||
MPNET_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
MPNetForMaskedLM,
|
||||
MPNetForMultipleChoice,
|
||||
MPNetForQuestionAnswering,
|
||||
MPNetForSequenceClassification,
|
||||
MPNetForTokenClassification,
|
||||
MPNetLayer,
|
||||
MPNetModel,
|
||||
MPNetPreTrainedModel,
|
||||
)
|
||||
|
||||
if is_tf_available():
|
||||
from .modeling_tf_mpnet import (
|
||||
TF_MPNET_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
TFMPNetEmbeddings,
|
||||
TFMPNetForMaskedLM,
|
||||
TFMPNetForMultipleChoice,
|
||||
TFMPNetForQuestionAnswering,
|
||||
TFMPNetForSequenceClassification,
|
||||
TFMPNetForTokenClassification,
|
||||
TFMPNetMainLayer,
|
||||
TFMPNetModel,
|
||||
TFMPNetPreTrainedModel,
|
||||
)
|
||||
@@ -1,116 +0,0 @@
|
||||
# coding=utf-8
|
||||
# Copyright 2018 The HuggingFace Inc. team, Microsoft Corporation.
|
||||
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
""" MPNet model configuration """
|
||||
|
||||
from ...configuration_utils import PretrainedConfig
|
||||
from ...utils import logging
|
||||
|
||||
|
||||
logger = logging.get_logger(__name__)
|
||||
|
||||
MPNET_PRETRAINED_CONFIG_ARCHIVE_MAP = {
|
||||
"microsoft/mpnet-base": "https://huggingface.co/microsoft/mpnet-base/resolve/main/config.json",
|
||||
}
|
||||
|
||||
|
||||
class MPNetConfig(PretrainedConfig):
|
||||
r"""
|
||||
This is the configuration class to store the configuration of a :class:`~transformers.MPNetModel` or a
|
||||
:class:`~transformers.TFMPNetModel`. It is used to instantiate a MPNet 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 MPNet `mpnet-base <https://huggingface.co/mpnet-base>`__ 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.
|
||||
|
||||
Args:
|
||||
vocab_size (:obj:`int`, `optional`, defaults to 30527):
|
||||
Vocabulary size of the MPNet model. Defines the number of different tokens that can be represented by the
|
||||
:obj:`inputs_ids` passed when calling :class:`~transformers.MPNetModel` or
|
||||
:class:`~transformers.TFMPNetModel`.
|
||||
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:`"silu"` 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 512):
|
||||
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).
|
||||
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.
|
||||
relative_attention_num_buckets (:obj:`int`, `optional`, defaults to 32):
|
||||
The number of buckets to use for each attention layer.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> from transformers import MPNetModel, MPNetConfig
|
||||
|
||||
>>> # Initializing a MPNet mpnet-base style configuration
|
||||
>>> configuration = MPNetConfig()
|
||||
|
||||
>>> # Initializing a model from the mpnet-base style configuration
|
||||
>>> model = MPNetModel(configuration)
|
||||
|
||||
>>> # Accessing the model configuration
|
||||
>>> configuration = model.config
|
||||
"""
|
||||
model_type = "mpnet"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
vocab_size=30527,
|
||||
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=512,
|
||||
initializer_range=0.02,
|
||||
layer_norm_eps=1e-12,
|
||||
relative_attention_num_buckets=32,
|
||||
pad_token_id=1,
|
||||
bos_token_id=0,
|
||||
eos_token_id=2,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(pad_token_id=pad_token_id, bos_token_id=bos_token_id, eos_token_id=eos_token_id, **kwargs)
|
||||
|
||||
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.initializer_range = initializer_range
|
||||
self.layer_norm_eps = layer_norm_eps
|
||||
self.relative_attention_num_buckets = relative_attention_num_buckets
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,528 +0,0 @@
|
||||
# coding=utf-8
|
||||
# Copyright 2018 The HuggingFace Inc. team, Microsoft Corporation.
|
||||
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
"""Tokenization classes for MPNet."""
|
||||
|
||||
import collections
|
||||
import os
|
||||
import unicodedata
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from ...tokenization_utils import AddedToken, PreTrainedTokenizer, _is_control, _is_punctuation, _is_whitespace
|
||||
from ...utils import logging
|
||||
|
||||
|
||||
logger = logging.get_logger(__name__)
|
||||
|
||||
VOCAB_FILES_NAMES = {"vocab_file": "vocab.txt"}
|
||||
|
||||
PRETRAINED_VOCAB_FILES_MAP = {
|
||||
"vocab_file": {
|
||||
"microsoft/mpnet-base": "https://huggingface.co/microsoft/mpnet-base/resolve/main/vocab.txt",
|
||||
}
|
||||
}
|
||||
|
||||
PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES = {
|
||||
"microsoft/mpnet-base": 512,
|
||||
}
|
||||
|
||||
PRETRAINED_INIT_CONFIGURATION = {
|
||||
"microsoft/mpnet-base": {"do_lower_case": True},
|
||||
}
|
||||
|
||||
|
||||
def load_vocab(vocab_file):
|
||||
"""Loads a vocabulary file into a dictionary."""
|
||||
vocab = collections.OrderedDict()
|
||||
with open(vocab_file, "r", encoding="utf-8") as reader:
|
||||
tokens = reader.readlines()
|
||||
for index, token in enumerate(tokens):
|
||||
token = token.rstrip("\n")
|
||||
vocab[token] = index
|
||||
return vocab
|
||||
|
||||
|
||||
def whitespace_tokenize(text):
|
||||
"""Runs basic whitespace cleaning and splitting on a piece of text."""
|
||||
text = text.strip()
|
||||
if not text:
|
||||
return []
|
||||
tokens = text.split()
|
||||
return tokens
|
||||
|
||||
|
||||
class MPNetTokenizer(PreTrainedTokenizer):
|
||||
"""
|
||||
|
||||
This tokenizer inherits from :class:`~transformers.BertTokenizer` which contains most of the methods. Users should
|
||||
refer to the superclass for more information regarding methods.
|
||||
|
||||
Args:
|
||||
vocab_file (:obj:`str`):
|
||||
Path to the vocabulary file.
|
||||
do_lower_case (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
Whether or not to lowercase the input when tokenizing.
|
||||
do_basic_tokenize (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
Whether or not to do basic tokenization before WordPiece.
|
||||
never_split (:obj:`Iterable`, `optional`):
|
||||
Collection of tokens which will never be split during tokenization. Only has an effect when
|
||||
:obj:`do_basic_tokenize=True`
|
||||
bos_token (:obj:`str`, `optional`, defaults to :obj:`"<s>"`):
|
||||
The beginning of sequence token that was used during pre-training. Can be used a sequence classifier token.
|
||||
|
||||
.. note::
|
||||
|
||||
When building a sequence using special tokens, this is not the token that is used for the beginning of
|
||||
sequence. The token used is the :obj:`cls_token`.
|
||||
eos_token (:obj:`str`, `optional`, defaults to :obj:`"</s>"`):
|
||||
The end of sequence token.
|
||||
|
||||
.. note::
|
||||
|
||||
When building a sequence using special tokens, this is not the token that is used for the end of
|
||||
sequence. The token used is the :obj:`sep_token`.
|
||||
sep_token (:obj:`str`, `optional`, defaults to :obj:`"</s>"`):
|
||||
The separator token, which is used when building a sequence from multiple sequences, e.g. two sequences for
|
||||
sequence classification or for a text and a question for question answering. It is also used as the last
|
||||
token of a sequence built with special tokens.
|
||||
cls_token (:obj:`str`, `optional`, defaults to :obj:`"<s>"`):
|
||||
The classifier token which is used when doing sequence classification (classification of the whole sequence
|
||||
instead of per-token classification). It is the first token of the sequence when built with special tokens.
|
||||
unk_token (:obj:`str`, `optional`, defaults to :obj:`"[UNK]"`):
|
||||
The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
|
||||
token instead.
|
||||
pad_token (:obj:`str`, `optional`, defaults to :obj:`"<pad>"`):
|
||||
The token used for padding, for example when batching sequences of different lengths.
|
||||
mask_token (:obj:`str`, `optional`, defaults to :obj:`"<mask>"`):
|
||||
The token used for masking values. This is the token used when training this model with masked language
|
||||
modeling. This is the token which the model will try to predict.
|
||||
tokenize_chinese_chars (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
Whether or not to tokenize Chinese characters.
|
||||
|
||||
This should likely be deactivated for Japanese (see this `issue
|
||||
<https://github.com/huggingface/transformers/issues/328>`__).
|
||||
strip_accents: (:obj:`bool`, `optional`):
|
||||
Whether or not to strip all accents. If this option is not specified, then it will be determined by the
|
||||
value for :obj:`lowercase` (as in the original BERT).
|
||||
"""
|
||||
|
||||
vocab_files_names = VOCAB_FILES_NAMES
|
||||
pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP
|
||||
pretrained_init_configuration = PRETRAINED_INIT_CONFIGURATION
|
||||
max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
vocab_file,
|
||||
do_lower_case=True,
|
||||
do_basic_tokenize=True,
|
||||
never_split=None,
|
||||
bos_token="<s>",
|
||||
eos_token="</s>",
|
||||
sep_token="</s>",
|
||||
cls_token="<s>",
|
||||
unk_token="[UNK]",
|
||||
pad_token="<pad>",
|
||||
mask_token="<mask>",
|
||||
tokenize_chinese_chars=True,
|
||||
strip_accents=None,
|
||||
**kwargs
|
||||
):
|
||||
bos_token = AddedToken(bos_token, lstrip=False, rstrip=False) if isinstance(bos_token, str) else bos_token
|
||||
eos_token = AddedToken(eos_token, lstrip=False, rstrip=False) if isinstance(eos_token, str) else eos_token
|
||||
sep_token = AddedToken(sep_token, lstrip=False, rstrip=False) if isinstance(sep_token, str) else sep_token
|
||||
cls_token = AddedToken(cls_token, lstrip=False, rstrip=False) if isinstance(cls_token, str) else cls_token
|
||||
unk_token = AddedToken(unk_token, lstrip=False, rstrip=False) if isinstance(unk_token, str) else unk_token
|
||||
pad_token = AddedToken(pad_token, lstrip=False, rstrip=False) if isinstance(pad_token, str) else pad_token
|
||||
|
||||
# Mask token behave like a normal word, i.e. include the space before it
|
||||
mask_token = AddedToken(mask_token, lstrip=True, rstrip=False) if isinstance(mask_token, str) else mask_token
|
||||
|
||||
super().__init__(
|
||||
do_lower_case=do_lower_case,
|
||||
do_basic_tokenize=do_basic_tokenize,
|
||||
never_split=never_split,
|
||||
bos_token=bos_token,
|
||||
eos_token=eos_token,
|
||||
unk_token=unk_token,
|
||||
sep_token=sep_token,
|
||||
cls_token=cls_token,
|
||||
pad_token=pad_token,
|
||||
mask_token=mask_token,
|
||||
tokenize_chinese_chars=tokenize_chinese_chars,
|
||||
strip_accents=strip_accents,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
if not os.path.isfile(vocab_file):
|
||||
raise ValueError(
|
||||
"Can't find a vocabulary file at path '{}'. To load the vocabulary from a Google pretrained "
|
||||
"model use `tokenizer = BertTokenizer.from_pretrained(PRETRAINED_MODEL_NAME)`".format(vocab_file)
|
||||
)
|
||||
self.vocab = load_vocab(vocab_file)
|
||||
self.ids_to_tokens = collections.OrderedDict([(ids, tok) for tok, ids in self.vocab.items()])
|
||||
self.do_basic_tokenize = do_basic_tokenize
|
||||
if do_basic_tokenize:
|
||||
self.basic_tokenizer = BasicTokenizer(
|
||||
do_lower_case=do_lower_case,
|
||||
never_split=never_split,
|
||||
tokenize_chinese_chars=tokenize_chinese_chars,
|
||||
strip_accents=strip_accents,
|
||||
)
|
||||
self.wordpiece_tokenizer = WordpieceTokenizer(vocab=self.vocab, unk_token=self.unk_token)
|
||||
|
||||
@property
|
||||
def do_lower_case(self):
|
||||
return self.basic_tokenizer.do_lower_case
|
||||
|
||||
@property
|
||||
def vocab_size(self):
|
||||
return len(self.vocab)
|
||||
|
||||
def get_vocab(self):
|
||||
return dict(self.vocab, **self.added_tokens_encoder)
|
||||
|
||||
def _tokenize(self, text):
|
||||
split_tokens = []
|
||||
if self.do_basic_tokenize:
|
||||
for token in self.basic_tokenizer.tokenize(text, never_split=self.all_special_tokens):
|
||||
|
||||
# If the token is part of the never_split set
|
||||
if token in self.basic_tokenizer.never_split:
|
||||
split_tokens.append(token)
|
||||
else:
|
||||
split_tokens += self.wordpiece_tokenizer.tokenize(token)
|
||||
else:
|
||||
split_tokens = self.wordpiece_tokenizer.tokenize(text)
|
||||
return split_tokens
|
||||
|
||||
def _convert_token_to_id(self, token):
|
||||
""" Converts a token (str) in an id using the vocab. """
|
||||
return self.vocab.get(token, self.vocab.get(self.unk_token))
|
||||
|
||||
def _convert_id_to_token(self, index):
|
||||
"""Converts an index (integer) in a token (str) using the vocab."""
|
||||
return self.ids_to_tokens.get(index, self.unk_token)
|
||||
|
||||
def convert_tokens_to_string(self, tokens):
|
||||
""" Converts a sequence of tokens (string) in a single string. """
|
||||
out_string = " ".join(tokens).replace(" ##", "").strip()
|
||||
return out_string
|
||||
|
||||
def build_inputs_with_special_tokens(
|
||||
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
||||
) -> List[int]:
|
||||
"""
|
||||
Build model inputs from a sequence or a pair of sequence for sequence classification tasks by concatenating and
|
||||
adding special tokens. A MPNet sequence has the following format:
|
||||
|
||||
- single sequence: ``<s> X </s>``
|
||||
- pair of sequences: ``<s> A </s></s> B </s>``
|
||||
|
||||
Args:
|
||||
token_ids_0 (:obj:`List[int]`):
|
||||
List of IDs to which the special tokens will be added
|
||||
token_ids_1 (:obj:`List[int]`, `optional`, defaults to :obj:`None`):
|
||||
Optional second list of IDs for sequence pairs.
|
||||
|
||||
Returns:
|
||||
:obj:`List[int]`: list of `input IDs <../glossary.html#input-ids>`__ with the appropriate special tokens.
|
||||
"""
|
||||
if token_ids_1 is None:
|
||||
return [self.cls_token_id] + token_ids_0 + [self.sep_token_id]
|
||||
cls = [self.cls_token_id]
|
||||
sep = [self.sep_token_id]
|
||||
return cls + token_ids_0 + sep + sep + token_ids_1 + sep
|
||||
|
||||
def get_special_tokens_mask(
|
||||
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None, already_has_special_tokens: bool = False
|
||||
) -> List[int]:
|
||||
"""
|
||||
Retrieves sequence ids from a token list that has no special tokens added. This method is called when adding
|
||||
special tokens using the tokenizer ``prepare_for_model`` methods.
|
||||
|
||||
Args:
|
||||
token_ids_0 (:obj:`List[int]`):
|
||||
List of ids.
|
||||
token_ids_1 (:obj:`List[int]`, `optional`):
|
||||
Optional second list of IDs for sequence pairs.
|
||||
already_has_special_tokens (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Set to True if the token list is already formatted with special tokens for the model
|
||||
|
||||
Returns:
|
||||
:obj:`List[int]`: A list of integers in the range [0, 1]: 1 for a special token, 0 for a sequence token.
|
||||
"""
|
||||
if already_has_special_tokens:
|
||||
if token_ids_1 is not None:
|
||||
raise ValueError(
|
||||
"You should not supply a second sequence if the provided sequence of "
|
||||
"ids is already formated with special tokens for the model."
|
||||
)
|
||||
return list(map(lambda x: 1 if x in [self.sep_token_id, self.cls_token_id] else 0, token_ids_0))
|
||||
|
||||
if token_ids_1 is None:
|
||||
return [1] + ([0] * len(token_ids_0)) + [1]
|
||||
return [1] + ([0] * len(token_ids_0)) + [1, 1] + ([0] * len(token_ids_1)) + [1]
|
||||
|
||||
def create_token_type_ids_from_sequences(
|
||||
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
||||
) -> List[int]:
|
||||
"""
|
||||
Creates a mask from the two sequences passed to be used in a sequence-pair classification task. MPNet does not
|
||||
make use of token type ids, therefore a list of zeros is returned.
|
||||
|
||||
Args:
|
||||
token_ids_0 (:obj:`List[int]`):
|
||||
List of ids.
|
||||
token_ids_1 (:obj:`List[int]`, `optional`):
|
||||
Optional second list of IDs for sequence pairs.
|
||||
|
||||
Returns:
|
||||
:obj:`List[int]`: List of zeros.
|
||||
"""
|
||||
sep = [self.sep_token_id]
|
||||
cls = [self.cls_token_id]
|
||||
|
||||
if token_ids_1 is None:
|
||||
return len(cls + token_ids_0 + sep) * [0]
|
||||
return len(cls + token_ids_0 + sep + sep + token_ids_1 + sep) * [0]
|
||||
|
||||
def save_vocabulary(self, save_directory: str, filename_prefix: Optional[str] = None) -> Tuple[str]:
|
||||
index = 0
|
||||
if os.path.isdir(save_directory):
|
||||
vocab_file = os.path.join(
|
||||
save_directory, (filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["vocab_file"]
|
||||
)
|
||||
else:
|
||||
vocab_file = (filename_prefix + "-" if filename_prefix else "") + save_directory
|
||||
with open(vocab_file, "w", encoding="utf-8") as writer:
|
||||
for token, token_index in sorted(self.vocab.items(), key=lambda kv: kv[1]):
|
||||
if index != token_index:
|
||||
logger.warning(
|
||||
"Saving vocabulary to {}: vocabulary indices are not consecutive."
|
||||
" Please check that the vocabulary is not corrupted!".format(vocab_file)
|
||||
)
|
||||
index = token_index
|
||||
writer.write(token + "\n")
|
||||
index += 1
|
||||
return (vocab_file,)
|
||||
|
||||
|
||||
# Copied from transformers.models.bert.tokenization_bert.BasicTokenizer
|
||||
class BasicTokenizer(object):
|
||||
"""
|
||||
Constructs a BasicTokenizer that will run basic tokenization (punctuation splitting, lower casing, etc.).
|
||||
|
||||
Args:
|
||||
do_lower_case (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
Whether or not to lowercase the input when tokenizing.
|
||||
never_split (:obj:`Iterable`, `optional`):
|
||||
Collection of tokens which will never be split during tokenization. Only has an effect when
|
||||
:obj:`do_basic_tokenize=True`
|
||||
tokenize_chinese_chars (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
Whether or not to tokenize Chinese characters.
|
||||
|
||||
This should likely be deactivated for Japanese (see this `issue
|
||||
<https://github.com/huggingface/transformers/issues/328>`__).
|
||||
strip_accents: (:obj:`bool`, `optional`):
|
||||
Whether or not to strip all accents. If this option is not specified, then it will be determined by the
|
||||
value for :obj:`lowercase` (as in the original BERT).
|
||||
"""
|
||||
|
||||
def __init__(self, do_lower_case=True, never_split=None, tokenize_chinese_chars=True, strip_accents=None):
|
||||
if never_split is None:
|
||||
never_split = []
|
||||
self.do_lower_case = do_lower_case
|
||||
self.never_split = set(never_split)
|
||||
self.tokenize_chinese_chars = tokenize_chinese_chars
|
||||
self.strip_accents = strip_accents
|
||||
|
||||
def tokenize(self, text, never_split=None):
|
||||
"""
|
||||
Basic Tokenization of a piece of text. Split on "white spaces" only, for sub-word tokenization, see
|
||||
WordPieceTokenizer.
|
||||
|
||||
Args:
|
||||
**never_split**: (`optional`) list of str
|
||||
Kept for backward compatibility purposes. Now implemented directly at the base class level (see
|
||||
:func:`PreTrainedTokenizer.tokenize`) List of token not to split.
|
||||
"""
|
||||
# union() returns a new set by concatenating the two sets.
|
||||
never_split = self.never_split.union(set(never_split)) if never_split else self.never_split
|
||||
text = self._clean_text(text)
|
||||
|
||||
# This was added on November 1st, 2018 for the multilingual and Chinese
|
||||
# models. This is also applied to the English models now, but it doesn't
|
||||
# matter since the English models were not trained on any Chinese data
|
||||
# and generally don't have any Chinese data in them (there are Chinese
|
||||
# characters in the vocabulary because Wikipedia does have some Chinese
|
||||
# words in the English Wikipedia.).
|
||||
if self.tokenize_chinese_chars:
|
||||
text = self._tokenize_chinese_chars(text)
|
||||
orig_tokens = whitespace_tokenize(text)
|
||||
split_tokens = []
|
||||
for token in orig_tokens:
|
||||
if token not in never_split:
|
||||
if self.do_lower_case:
|
||||
token = token.lower()
|
||||
if self.strip_accents is not False:
|
||||
token = self._run_strip_accents(token)
|
||||
elif self.strip_accents:
|
||||
token = self._run_strip_accents(token)
|
||||
split_tokens.extend(self._run_split_on_punc(token, never_split))
|
||||
|
||||
output_tokens = whitespace_tokenize(" ".join(split_tokens))
|
||||
return output_tokens
|
||||
|
||||
def _run_strip_accents(self, text):
|
||||
"""Strips accents from a piece of text."""
|
||||
text = unicodedata.normalize("NFD", text)
|
||||
output = []
|
||||
for char in text:
|
||||
cat = unicodedata.category(char)
|
||||
if cat == "Mn":
|
||||
continue
|
||||
output.append(char)
|
||||
return "".join(output)
|
||||
|
||||
def _run_split_on_punc(self, text, never_split=None):
|
||||
"""Splits punctuation on a piece of text."""
|
||||
if never_split is not None and text in never_split:
|
||||
return [text]
|
||||
chars = list(text)
|
||||
i = 0
|
||||
start_new_word = True
|
||||
output = []
|
||||
while i < len(chars):
|
||||
char = chars[i]
|
||||
if _is_punctuation(char):
|
||||
output.append([char])
|
||||
start_new_word = True
|
||||
else:
|
||||
if start_new_word:
|
||||
output.append([])
|
||||
start_new_word = False
|
||||
output[-1].append(char)
|
||||
i += 1
|
||||
|
||||
return ["".join(x) for x in output]
|
||||
|
||||
def _tokenize_chinese_chars(self, text):
|
||||
"""Adds whitespace around any CJK character."""
|
||||
output = []
|
||||
for char in text:
|
||||
cp = ord(char)
|
||||
if self._is_chinese_char(cp):
|
||||
output.append(" ")
|
||||
output.append(char)
|
||||
output.append(" ")
|
||||
else:
|
||||
output.append(char)
|
||||
return "".join(output)
|
||||
|
||||
def _is_chinese_char(self, cp):
|
||||
"""Checks whether CP is the codepoint of a CJK character."""
|
||||
# This defines a "chinese character" as anything in the CJK Unicode block:
|
||||
# https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block)
|
||||
#
|
||||
# Note that the CJK Unicode block is NOT all Japanese and Korean characters,
|
||||
# despite its name. The modern Korean Hangul alphabet is a different block,
|
||||
# as is Japanese Hiragana and Katakana. Those alphabets are used to write
|
||||
# space-separated words, so they are not treated specially and handled
|
||||
# like the all of the other languages.
|
||||
if (
|
||||
(cp >= 0x4E00 and cp <= 0x9FFF)
|
||||
or (cp >= 0x3400 and cp <= 0x4DBF) #
|
||||
or (cp >= 0x20000 and cp <= 0x2A6DF) #
|
||||
or (cp >= 0x2A700 and cp <= 0x2B73F) #
|
||||
or (cp >= 0x2B740 and cp <= 0x2B81F) #
|
||||
or (cp >= 0x2B820 and cp <= 0x2CEAF) #
|
||||
or (cp >= 0xF900 and cp <= 0xFAFF)
|
||||
or (cp >= 0x2F800 and cp <= 0x2FA1F) #
|
||||
): #
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _clean_text(self, text):
|
||||
"""Performs invalid character removal and whitespace cleanup on text."""
|
||||
output = []
|
||||
for char in text:
|
||||
cp = ord(char)
|
||||
if cp == 0 or cp == 0xFFFD or _is_control(char):
|
||||
continue
|
||||
if _is_whitespace(char):
|
||||
output.append(" ")
|
||||
else:
|
||||
output.append(char)
|
||||
return "".join(output)
|
||||
|
||||
|
||||
# Copied from transformers.models.bert.tokenization_bert.WordpieceTokenizer
|
||||
class WordpieceTokenizer(object):
|
||||
"""Runs WordPiece tokenization."""
|
||||
|
||||
def __init__(self, vocab, unk_token, max_input_chars_per_word=100):
|
||||
self.vocab = vocab
|
||||
self.unk_token = unk_token
|
||||
self.max_input_chars_per_word = max_input_chars_per_word
|
||||
|
||||
def tokenize(self, text):
|
||||
"""
|
||||
Tokenizes a piece of text into its word pieces. This uses a greedy longest-match-first algorithm to perform
|
||||
tokenization using the given vocabulary.
|
||||
|
||||
For example, :obj:`input = "unaffable"` wil return as output :obj:`["un", "##aff", "##able"]`.
|
||||
|
||||
Args:
|
||||
text: A single token or whitespace separated tokens. This should have
|
||||
already been passed through `BasicTokenizer`.
|
||||
|
||||
Returns:
|
||||
A list of wordpiece tokens.
|
||||
"""
|
||||
|
||||
output_tokens = []
|
||||
for token in whitespace_tokenize(text):
|
||||
chars = list(token)
|
||||
if len(chars) > self.max_input_chars_per_word:
|
||||
output_tokens.append(self.unk_token)
|
||||
continue
|
||||
|
||||
is_bad = False
|
||||
start = 0
|
||||
sub_tokens = []
|
||||
while start < len(chars):
|
||||
end = len(chars)
|
||||
cur_substr = None
|
||||
while start < end:
|
||||
substr = "".join(chars[start:end])
|
||||
if start > 0:
|
||||
substr = "##" + substr
|
||||
if substr in self.vocab:
|
||||
cur_substr = substr
|
||||
break
|
||||
end -= 1
|
||||
if cur_substr is None:
|
||||
is_bad = True
|
||||
break
|
||||
sub_tokens.append(cur_substr)
|
||||
start = end
|
||||
|
||||
if is_bad:
|
||||
output_tokens.append(self.unk_token)
|
||||
else:
|
||||
output_tokens.extend(sub_tokens)
|
||||
return output_tokens
|
||||
@@ -1,208 +0,0 @@
|
||||
# coding=utf-8
|
||||
# Copyright 2018 The HuggingFace Inc. team, Microsoft Corporation.
|
||||
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
"""Fast Tokenization classes for MPNet."""
|
||||
|
||||
import json
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from tokenizers import normalizers
|
||||
|
||||
from ...tokenization_utils import AddedToken
|
||||
from ...tokenization_utils_fast import PreTrainedTokenizerFast
|
||||
from ...utils import logging
|
||||
from .tokenization_mpnet import MPNetTokenizer
|
||||
|
||||
|
||||
logger = logging.get_logger(__name__)
|
||||
|
||||
VOCAB_FILES_NAMES = {"vocab_file": "vocab.txt", "tokenizer_file": "tokenizer.json"}
|
||||
|
||||
PRETRAINED_VOCAB_FILES_MAP = {
|
||||
"vocab_file": {
|
||||
"microsoft/mpnet-base": "https://huggingface.co/microsoft/mpnet-base/resolve/main/vocab.txt",
|
||||
},
|
||||
"tokenizer_file": {
|
||||
"microsoft/mpnet-base": "https://huggingface.co/microsoft/mpnet-base/resolve/main/tokenizer.json",
|
||||
},
|
||||
}
|
||||
|
||||
PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES = {
|
||||
"microsoft/mpnet-base": 512,
|
||||
}
|
||||
|
||||
PRETRAINED_INIT_CONFIGURATION = {
|
||||
"microsoft/mpnet-base": {"do_lower_case": True},
|
||||
}
|
||||
|
||||
|
||||
class MPNetTokenizerFast(PreTrainedTokenizerFast):
|
||||
r"""
|
||||
Construct a "fast" MPNet tokenizer (backed by HuggingFace's `tokenizers` library). Based on WordPiece.
|
||||
|
||||
This tokenizer inherits from :class:`~transformers.PreTrainedTokenizerFast` which contains most of the main
|
||||
methods. Users should refer to this superclass for more information regarding those methods.
|
||||
|
||||
Args:
|
||||
vocab_file (:obj:`str`):
|
||||
File containing the vocabulary.
|
||||
do_lower_case (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
Whether or not to lowercase the input when tokenizing.
|
||||
bos_token (:obj:`str`, `optional`, defaults to :obj:`"<s>"`):
|
||||
The beginning of sequence token that was used during pretraining. Can be used a sequence classifier token.
|
||||
|
||||
.. note::
|
||||
|
||||
When building a sequence using special tokens, this is not the token that is used for the beginning of
|
||||
sequence. The token used is the :obj:`cls_token`.
|
||||
eos_token (:obj:`str`, `optional`, defaults to :obj:`"</s>"`):
|
||||
The end of sequence token.
|
||||
|
||||
.. note::
|
||||
|
||||
When building a sequence using special tokens, this is not the token that is used for the end of
|
||||
sequence. The token used is the :obj:`sep_token`.
|
||||
sep_token (:obj:`str`, `optional`, defaults to :obj:`"</s>"`):
|
||||
The separator token, which is used when building a sequence from multiple sequences, e.g. two sequences for
|
||||
sequence classification or for a text and a question for question answering. It is also used as the last
|
||||
token of a sequence built with special tokens.
|
||||
cls_token (:obj:`str`, `optional`, defaults to :obj:`"<s>"`):
|
||||
The classifier token which is used when doing sequence classification (classification of the whole sequence
|
||||
instead of per-token classification). It is the first token of the sequence when built with special tokens.
|
||||
unk_token (:obj:`str`, `optional`, defaults to :obj:`"[UNK]"`):
|
||||
The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this
|
||||
token instead.
|
||||
pad_token (:obj:`str`, `optional`, defaults to :obj:`"<pad>"`):
|
||||
The token used for padding, for example when batching sequences of different lengths.
|
||||
mask_token (:obj:`str`, `optional`, defaults to :obj:`"<mask>"`):
|
||||
The token used for masking values. This is the token used when training this model with masked language
|
||||
modeling. This is the token which the model will try to predict.
|
||||
tokenize_chinese_chars (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
Whether or not to tokenize Chinese characters. This should likely be deactivated for Japanese (see `this
|
||||
issue <https://github.com/huggingface/transformers/issues/328>`__).
|
||||
strip_accents: (:obj:`bool`, `optional`):
|
||||
Whether or not to strip all accents. If this option is not specified, then it will be determined by the
|
||||
value for :obj:`lowercase` (as in the original BERT).
|
||||
"""
|
||||
|
||||
vocab_files_names = VOCAB_FILES_NAMES
|
||||
pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP
|
||||
pretrained_init_configuration = PRETRAINED_INIT_CONFIGURATION
|
||||
max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
|
||||
slow_tokenizer_class = MPNetTokenizer
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
vocab_file,
|
||||
tokenizer_file=None,
|
||||
do_lower_case=True,
|
||||
bos_token="<s>",
|
||||
eos_token="</s>",
|
||||
sep_token="</s>",
|
||||
cls_token="<s>",
|
||||
unk_token="[UNK]",
|
||||
pad_token="<pad>",
|
||||
mask_token="<mask>",
|
||||
tokenize_chinese_chars=True,
|
||||
strip_accents=None,
|
||||
**kwargs
|
||||
):
|
||||
super().__init__(
|
||||
vocab_file,
|
||||
tokenizer_file=tokenizer_file,
|
||||
do_lower_case=do_lower_case,
|
||||
bos_token=bos_token,
|
||||
eos_token=eos_token,
|
||||
sep_token=sep_token,
|
||||
cls_token=cls_token,
|
||||
unk_token=unk_token,
|
||||
pad_token=pad_token,
|
||||
mask_token=mask_token,
|
||||
tokenize_chinese_chars=tokenize_chinese_chars,
|
||||
strip_accents=strip_accents,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
pre_tok_state = json.loads(self.backend_tokenizer.normalizer.__getstate__())
|
||||
if (
|
||||
pre_tok_state.get("do_lower_case", do_lower_case) != do_lower_case
|
||||
or pre_tok_state.get("strip_accents", strip_accents) != strip_accents
|
||||
):
|
||||
pre_tok_class = getattr(normalizers, pre_tok_state.pop("type"))
|
||||
pre_tok_state["do_lower_case"] = do_lower_case
|
||||
pre_tok_state["strip_accents"] = strip_accents
|
||||
self.backend_tokenizer.normalizer = pre_tok_class(**pre_tok_state)
|
||||
|
||||
self.do_lower_case = do_lower_case
|
||||
|
||||
@property
|
||||
def mask_token(self) -> str:
|
||||
"""
|
||||
:obj:`str`: Mask token, to use when training a model with masked-language modeling. Log an error if used while
|
||||
not having been set.
|
||||
|
||||
MPNet tokenizer has a special mask token to be usble in the fill-mask pipeline. The mask token will greedily
|
||||
comprise the space before the `<mask>`.
|
||||
"""
|
||||
if self._mask_token is None and self.verbose:
|
||||
logger.error("Using mask_token, but it is not set yet.")
|
||||
return None
|
||||
return str(self._mask_token)
|
||||
|
||||
@mask_token.setter
|
||||
def mask_token(self, value):
|
||||
"""
|
||||
Overriding the default behavior of the mask token to have it eat the space before it.
|
||||
|
||||
This is needed to preserve backward compatibility with all the previously used models based on MPNet.
|
||||
"""
|
||||
# Mask token behave like a normal word, i.e. include the space before it
|
||||
# So we set lstrip to True
|
||||
value = AddedToken(value, lstrip=True, rstrip=False) if isinstance(value, str) else value
|
||||
self._mask_token = value
|
||||
|
||||
def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None):
|
||||
output = [self.bos_token_id] + token_ids_0 + [self.eos_token_id]
|
||||
if token_ids_1 is None:
|
||||
return output
|
||||
|
||||
return output + [self.eos_token_id] + token_ids_1 + [self.eos_token_id]
|
||||
|
||||
def create_token_type_ids_from_sequences(
|
||||
self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None
|
||||
) -> List[int]:
|
||||
"""
|
||||
Creates a mask from the two sequences passed to be used in a sequence-pair classification task. MPNet does not
|
||||
make use of token type ids, therefore a list of zeros is returned
|
||||
|
||||
Args:
|
||||
token_ids_0 (:obj:`List[int]`):
|
||||
List of ids.
|
||||
token_ids_1 (:obj:`List[int]`, `optional`):
|
||||
Optional second list of IDs for sequence pairs
|
||||
|
||||
Returns:
|
||||
:obj:`List[int]`: List of zeros.
|
||||
"""
|
||||
sep = [self.sep_token_id]
|
||||
cls = [self.cls_token_id]
|
||||
|
||||
if token_ids_1 is None:
|
||||
return len(cls + token_ids_0 + sep) * [0]
|
||||
return len(cls + token_ids_0 + sep + sep + token_ids_1 + sep) * [0]
|
||||
|
||||
def save_vocabulary(self, save_directory: str, filename_prefix: Optional[str] = None) -> Tuple[str]:
|
||||
files = self._tokenizer.model.save(save_directory, name=filename_prefix)
|
||||
return tuple(files)
|
||||
@@ -0,0 +1,16 @@
|
||||
# flake8: noqa
|
||||
# There's no way to ignore "F401 '...' imported but unused" warnings in this
|
||||
# module, but to preserve other warnings. So, don't check this module at all.
|
||||
|
||||
from ...file_utils import is_torch_available
|
||||
from .configuration_tapas import TAPAS_PRETRAINED_CONFIG_ARCHIVE_MAP, TapasConfig
|
||||
from .tokenization_tapas import TapasTokenizer
|
||||
|
||||
if is_torch_available():
|
||||
from .modeling_tapas import (
|
||||
TAPAS_PRETRAINED_MODEL_ARCHIVE_LIST,
|
||||
TapasModel,
|
||||
TapasForMaskedLM,
|
||||
TapasForQuestionAnswering,
|
||||
TapasForSequenceClassification,
|
||||
)
|
||||
@@ -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 = {"nielsr/tapas-base-finetuned-sqa": "https://huggingface.co/nielsr/tapas-base-finetuned-sqa/resolve/main/config.json",
|
||||
"nielsr/tapas-base-finetuned-wtq": "https://huggingface.co/nielsr/tapas-base-finetuned-wtq/resolve/main/config.json",
|
||||
"nielsr/tapas-base-finetuned-wikisql-supervised": "https://huggingface.co/nielsr/tapas-base-finetuned-wikisql-supervised/resolve/main/config.json",
|
||||
"nielsr/tapas-base-finetuned-tabfact": "https://huggingface.co/nielsr/tapas-base-finetuned-tabfact/resolve/main/config.json"}
|
||||
|
||||
|
||||
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`):
|
||||
Whether to use gradient checkpointing to save memory at the expense of a 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`):
|
||||
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`):
|
||||
Whether to normalize the answer loss by the maximum of the predicted and expected value.
|
||||
huber_loss_delta: (:obj:`float`, `optional`):
|
||||
Delta parameter used to calculate the regression loss.
|
||||
temperature: (:obj:`float`, `optional`, defaults to 1.0):
|
||||
Value used to control (OR change) the skewness of cell logits 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`):
|
||||
Whether to apply Gumbel-Softmax to cell selection.
|
||||
use_gumbel_for_aggregation: (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Whether to apply Gumbel-Softmax to aggregation selection.
|
||||
average_approximation_function: (:obj:`string`, `optional`, defaults to :obj:`"ratio"`):
|
||||
Method to calculate the expected average of cells in the weak supervision case. One of :obj:`"ratio"`,
|
||||
:obj:`"first_order"` or :obj:`"second_order"`.
|
||||
cell_selection_preference: (:obj:`float`, `optional`):
|
||||
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`):
|
||||
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`):
|
||||
Whether to 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`):
|
||||
Whether to restart position indexes at every cell (i.e. use relative position embeddings).
|
||||
disable_per_token_loss: (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Whether to disable any (strong or weak) supervision on cells.
|
||||
|
||||
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,
|
||||
**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
|
||||
@@ -0,0 +1,120 @@
|
||||
# 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,
|
||||
TapasModel,
|
||||
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. Defaults to TapasForQuestionAnswering with default SQA config.
|
||||
# Uncomment another config and/or model to change this. If you want to convert a checkpoint
|
||||
# that has absolute position embeddings, make sure to set reset_position_index_per_cell of
|
||||
# TapasConfig to False.
|
||||
|
||||
# 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_selection_preference = 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,
|
||||
# )
|
||||
|
||||
# WikiSQL 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.185567,
|
||||
# cell_selection_preference = 0.611754,
|
||||
# huber_loss_delta = 1265.74,
|
||||
# init_cell_selection_weights_to_zero = False,
|
||||
# select_one_column = False,
|
||||
# allow_empty_column_selection = False,
|
||||
# temperature = 0.107515,
|
||||
# )
|
||||
|
||||
# WikiSQL-supervised config
|
||||
# config = TapasConfig(
|
||||
# # run_task_main.py hparams
|
||||
# num_aggregation_labels = 4,
|
||||
# use_answer_as_supervision = False,
|
||||
# # hparam_utils.py hparams
|
||||
# answer_loss_cutoff = 36.4519,
|
||||
# cell_selection_preference = 0.903421,
|
||||
# huber_loss_delta = 222.088,
|
||||
# init_cell_selection_weights_to_zero = True,
|
||||
# select_one_column = True,
|
||||
# allow_empty_column_selection = True,
|
||||
# temperature = 0.763141,
|
||||
# )
|
||||
|
||||
# SQA config
|
||||
config = TapasConfig()
|
||||
|
||||
print("Building PyTorch model from configuration: {}".format(str(config)))
|
||||
model = TapasModel(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)
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -29,6 +29,7 @@ from .file_utils import (
|
||||
_faiss_available,
|
||||
_flax_available,
|
||||
_sentencepiece_available,
|
||||
_scatter_available,
|
||||
_tf_available,
|
||||
_tokenizers_available,
|
||||
_torch_available,
|
||||
@@ -221,6 +222,17 @@ def require_tokenizers(test_case):
|
||||
return test_case
|
||||
|
||||
|
||||
def require_scatter(test_case):
|
||||
"""
|
||||
Decorator marking a test that requires PyTorch Scatter.
|
||||
These tests are skipped when PyTorch Scatter isn't installed.
|
||||
"""
|
||||
if not _scatter_available:
|
||||
return unittest.skip("test requires PyTorch Scatter")(test_case)
|
||||
else:
|
||||
return test_case
|
||||
|
||||
|
||||
def require_torch_multi_gpu(test_case):
|
||||
"""
|
||||
Decorator marking a test that requires a multi-GPU setup (in PyTorch).
|
||||
|
||||
@@ -1370,77 +1370,6 @@ def load_tf_weights_in_mobilebert(*args, **kwargs):
|
||||
requires_pytorch(load_tf_weights_in_mobilebert)
|
||||
|
||||
|
||||
MPNET_PRETRAINED_MODEL_ARCHIVE_LIST = None
|
||||
|
||||
|
||||
class MPNetForMaskedLM:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
|
||||
class MPNetForMultipleChoice:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
|
||||
class MPNetForQuestionAnswering:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
|
||||
class MPNetForSequenceClassification:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
|
||||
class MPNetForTokenClassification:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
|
||||
class MPNetLayer:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
|
||||
class MPNetModel:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
|
||||
class MPNetPreTrainedModel:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
|
||||
class MT5EncoderModel:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_pytorch(self)
|
||||
|
||||
@@ -1006,77 +1006,6 @@ class TFMobileBertPreTrainedModel:
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
TF_MPNET_PRETRAINED_MODEL_ARCHIVE_LIST = None
|
||||
|
||||
|
||||
class TFMPNetForMaskedLM:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
class TFMPNetForMultipleChoice:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
class TFMPNetForQuestionAnswering:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
class TFMPNetForSequenceClassification:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
class TFMPNetForTokenClassification:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
class TFMPNetMainLayer:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
class TFMPNetModel:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
class TFMPNetPreTrainedModel:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
|
||||
class TFMT5EncoderModel:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tf(self)
|
||||
|
||||
@@ -164,15 +164,6 @@ class MobileBertTokenizerFast:
|
||||
requires_tokenizers(self)
|
||||
|
||||
|
||||
class MPNetTokenizerFast:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tokenizers(self)
|
||||
|
||||
@classmethod
|
||||
def from_pretrained(self, *args, **kwargs):
|
||||
requires_tokenizers(self)
|
||||
|
||||
|
||||
class MT5TokenizerFast:
|
||||
def __init__(self, *args, **kwargs):
|
||||
requires_tokenizers(self)
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
# coding=utf-8
|
||||
# Copyright 2020 The HuggingFace Inc. team, Microsoft Corporation.
|
||||
#
|
||||
# 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
|
||||
|
||||
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, ids_tensor, random_attention_mask
|
||||
|
||||
|
||||
if is_torch_available():
|
||||
import torch
|
||||
|
||||
from transformers import (
|
||||
MPNetConfig,
|
||||
MPNetForMaskedLM,
|
||||
MPNetForMultipleChoice,
|
||||
MPNetForQuestionAnswering,
|
||||
MPNetForSequenceClassification,
|
||||
MPNetForTokenClassification,
|
||||
MPNetModel,
|
||||
)
|
||||
|
||||
|
||||
class MPNetModelTester:
|
||||
def __init__(
|
||||
self,
|
||||
parent,
|
||||
batch_size=13,
|
||||
seq_length=7,
|
||||
is_training=True,
|
||||
use_input_mask=True,
|
||||
use_token_type_ids=False,
|
||||
use_labels=True,
|
||||
vocab_size=99,
|
||||
hidden_size=64,
|
||||
num_hidden_layers=5,
|
||||
num_attention_heads=4,
|
||||
intermediate_size=64,
|
||||
hidden_act="gelu",
|
||||
hidden_dropout_prob=0.1,
|
||||
attention_probs_dropout_prob=0.1,
|
||||
max_position_embeddings=512,
|
||||
type_vocab_size=16,
|
||||
type_sequence_label_size=2,
|
||||
initializer_range=0.02,
|
||||
num_labels=3,
|
||||
num_choices=4,
|
||||
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.max_position_embeddings = max_position_embeddings
|
||||
self.type_vocab_size = type_vocab_size
|
||||
self.type_sequence_label_size = type_sequence_label_size
|
||||
self.initializer_range = initializer_range
|
||||
self.num_labels = num_labels
|
||||
self.num_choices = num_choices
|
||||
self.scope = scope
|
||||
|
||||
def get_large_model_config(self):
|
||||
return MPNetConfig.from_pretrained("microsoft/mpnet-base")
|
||||
|
||||
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])
|
||||
|
||||
sequence_labels = None
|
||||
token_labels = None
|
||||
choice_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)
|
||||
choice_labels = ids_tensor([self.batch_size], self.num_choices)
|
||||
|
||||
config = MPNetConfig(
|
||||
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,
|
||||
initializer_range=self.initializer_range,
|
||||
)
|
||||
return config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
|
||||
def create_and_check_mpnet_model(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
model = MPNetModel(config=config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
result = model(input_ids, input_mask)
|
||||
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_mpnet_for_question_answering(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
model = MPNetForQuestionAnswering(config=config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
result = model(
|
||||
input_ids,
|
||||
attention_mask=input_mask,
|
||||
start_positions=sequence_labels,
|
||||
end_positions=sequence_labels,
|
||||
)
|
||||
self.parent.assertEqual(result.start_logits.shape, (self.batch_size, self.seq_length))
|
||||
self.parent.assertEqual(result.end_logits.shape, (self.batch_size, self.seq_length))
|
||||
|
||||
def create_and_check_mpnet_for_sequence_classification(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
config.num_labels = self.num_labels
|
||||
model = MPNetForSequenceClassification(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 create_and_check_mpnet_for_multiple_choice(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
config.num_choices = self.num_choices
|
||||
model = MPNetForMultipleChoice(config=config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
multiple_choice_inputs_ids = input_ids.unsqueeze(1).expand(-1, self.num_choices, -1).contiguous()
|
||||
multiple_choice_input_mask = input_mask.unsqueeze(1).expand(-1, self.num_choices, -1).contiguous()
|
||||
result = model(
|
||||
multiple_choice_inputs_ids,
|
||||
attention_mask=multiple_choice_input_mask,
|
||||
labels=choice_labels,
|
||||
)
|
||||
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.num_choices))
|
||||
|
||||
def create_and_check_mpnet_for_token_classification(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
config.num_labels = self.num_labels
|
||||
model = MPNetForTokenClassification(config=config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
result = model(input_ids, attention_mask=input_mask, labels=token_labels)
|
||||
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.seq_length, self.num_labels))
|
||||
|
||||
def prepare_config_and_inputs_for_common(self):
|
||||
config_and_inputs = self.prepare_config_and_inputs()
|
||||
(config, input_ids, input_mask, sequence_labels, token_labels, choice_labels) = config_and_inputs
|
||||
inputs_dict = {"input_ids": input_ids, "attention_mask": input_mask}
|
||||
return config, inputs_dict
|
||||
|
||||
|
||||
@require_torch
|
||||
class MPNetModelTest(ModelTesterMixin, unittest.TestCase):
|
||||
|
||||
all_model_classes = (
|
||||
(
|
||||
MPNetForMaskedLM,
|
||||
MPNetForMultipleChoice,
|
||||
MPNetForQuestionAnswering,
|
||||
MPNetForSequenceClassification,
|
||||
MPNetForTokenClassification,
|
||||
MPNetModel,
|
||||
)
|
||||
if is_torch_available()
|
||||
else ()
|
||||
)
|
||||
test_pruning = False
|
||||
test_torchscript = True
|
||||
test_resize_embeddings = True
|
||||
|
||||
def setUp(self):
|
||||
self.model_tester = MPNetModelTester(self)
|
||||
self.config_tester = ConfigTester(self, config_class=MPNetConfig, hidden_size=37)
|
||||
|
||||
def test_config(self):
|
||||
self.config_tester.run_common_tests()
|
||||
|
||||
def test_mpnet_model(self):
|
||||
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||
self.model_tester.create_and_check_mpnet_model(*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_mpnet_for_sequence_classification(*config_and_inputs)
|
||||
|
||||
def test_for_multiple_choice(self):
|
||||
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||
self.model_tester.create_and_check_mpnet_for_multiple_choice(*config_and_inputs)
|
||||
|
||||
def test_for_token_classification(self):
|
||||
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||
self.model_tester.create_and_check_mpnet_for_token_classification(*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_mpnet_for_question_answering(*config_and_inputs)
|
||||
|
||||
|
||||
@require_torch
|
||||
class MPNetModelIntegrationTest(unittest.TestCase):
|
||||
@slow
|
||||
def test_inference_no_head(self):
|
||||
model = MPNetModel.from_pretrained("microsoft/mpnet-base")
|
||||
input_ids = torch.tensor([[0, 345, 232, 328, 740, 140, 1695, 69, 6078, 1588, 2]])
|
||||
output = model(input_ids)[0]
|
||||
expected_shape = torch.Size((1, 11, 768))
|
||||
self.assertEqual(output.shape, expected_shape)
|
||||
expected_slice = torch.tensor(
|
||||
[[[-0.0550, 0.1943, -0.0740], [-0.0562, 0.2211, -0.0579], [-0.0437, 0.3337, -0.0641]]]
|
||||
)
|
||||
# compare the actual values for a slice.
|
||||
self.assertTrue(torch.allclose(output[:, :3, :3], expected_slice, atol=1e-4))
|
||||
@@ -0,0 +1,947 @@
|
||||
# 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 copy
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from transformers import is_torch_available, MODEL_FOR_MULTIPLE_CHOICE_MAPPING, MODEL_FOR_QUESTION_ANSWERING_MAPPING, \
|
||||
MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING, MODEL_FOR_NEXT_SENTENCE_PREDICTION_MAPPING, \
|
||||
MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING, MODEL_FOR_CAUSAL_LM_MAPPING, MODEL_FOR_MASKED_LM_MAPPING, \
|
||||
MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING
|
||||
from transformers.file_utils import cached_property
|
||||
from transformers.testing_utils import require_torch, require_scatter, 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,
|
||||
TapasTokenizer,
|
||||
TapasConfig,
|
||||
TapasForMaskedLM,
|
||||
TapasForQuestionAnswering,
|
||||
TapasForSequenceClassification,
|
||||
TapasModel,
|
||||
)
|
||||
|
||||
from transformers.models.tapas.modeling_tapas import (
|
||||
IndexMap,
|
||||
ProductIndexMap,
|
||||
gather,
|
||||
flatten,
|
||||
range_index_map,
|
||||
reduce_sum,
|
||||
reduce_mean,
|
||||
reduce_max,
|
||||
reduce_min,
|
||||
)
|
||||
|
||||
|
||||
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_selection_preference=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=True,
|
||||
disable_per_token_loss=False,
|
||||
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_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.scope = scope
|
||||
|
||||
def prepare_config_and_inputs(self):
|
||||
input_ids = ids_tensor([self.batch_size, self.seq_length], self.vocab_size).to(torch_device)
|
||||
|
||||
input_mask = None
|
||||
if self.use_input_mask:
|
||||
input_mask = random_attention_mask([self.batch_size, self.seq_length]).to(torch_device)
|
||||
|
||||
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).to(torch_device)
|
||||
|
||||
sequence_labels = None
|
||||
token_labels = None
|
||||
labels = None
|
||||
answer = None
|
||||
numeric_values = None
|
||||
numeric_values_scale = None
|
||||
float_answer = None
|
||||
aggregation_labels = None
|
||||
if self.use_labels:
|
||||
sequence_labels = ids_tensor([self.batch_size], self.type_sequence_label_size).to(torch_device)
|
||||
token_labels = ids_tensor([self.batch_size, self.seq_length], self.num_labels).to(torch_device)
|
||||
labels = ids_tensor([self.batch_size, self.seq_length], vocab_size=2).to(torch_device)
|
||||
numeric_values = floats_tensor([self.batch_size, self.seq_length]).to(torch_device)
|
||||
numeric_values_scale = floats_tensor([self.batch_size, self.seq_length]).to(torch_device)
|
||||
float_answer = floats_tensor([self.batch_size]).to(torch_device)
|
||||
aggregation_labels = ids_tensor([self.batch_size], self.num_aggregation_labels).to(torch_device)
|
||||
|
||||
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_selection_preference=self.cell_selection_preference,
|
||||
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,
|
||||
)
|
||||
|
||||
return (
|
||||
config,
|
||||
input_ids,
|
||||
input_mask,
|
||||
token_type_ids,
|
||||
sequence_labels,
|
||||
token_labels,
|
||||
labels,
|
||||
numeric_values,
|
||||
numeric_values_scale,
|
||||
float_answer,
|
||||
aggregation_labels,
|
||||
)
|
||||
|
||||
def create_and_check_model(
|
||||
self,
|
||||
config,
|
||||
input_ids,
|
||||
input_mask,
|
||||
token_type_ids,
|
||||
sequence_labels,
|
||||
token_labels,
|
||||
labels,
|
||||
numeric_values,
|
||||
numeric_values_scale,
|
||||
float_answer,
|
||||
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,
|
||||
labels,
|
||||
numeric_values,
|
||||
numeric_values_scale,
|
||||
float_answer,
|
||||
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,
|
||||
labels,
|
||||
numeric_values,
|
||||
numeric_values_scale,
|
||||
float_answer,
|
||||
aggregation_labels,
|
||||
):
|
||||
# inference: without aggregation head (SQA). Model only returns logits
|
||||
sqa_config = copy.copy(config)
|
||||
sqa_config.num_aggregation_labels = 0
|
||||
sqa_config.use_answer_as_supervision = False
|
||||
model = TapasForQuestionAnswering(config=sqa_config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
result = model(
|
||||
input_ids=input_ids,
|
||||
attention_mask=input_mask,
|
||||
token_type_ids=token_type_ids,
|
||||
)
|
||||
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.seq_length))
|
||||
|
||||
# inference: with aggregation head (WTQ, WikiSQL-supervised). Model returns logits and aggregation logits
|
||||
model = TapasForQuestionAnswering(config=config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
result = model(
|
||||
input_ids=input_ids,
|
||||
attention_mask=input_mask,
|
||||
token_type_ids=token_type_ids,
|
||||
)
|
||||
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))
|
||||
|
||||
# training: can happen in 3 main ways
|
||||
# case 1: conversational (SQA)
|
||||
model = TapasForQuestionAnswering(config=sqa_config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
result = model(
|
||||
input_ids,
|
||||
attention_mask=input_mask,
|
||||
token_type_ids=token_type_ids,
|
||||
labels=labels,
|
||||
)
|
||||
self.parent.assertEqual(result.loss.shape, ())
|
||||
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.seq_length))
|
||||
|
||||
# case 2: weak supervision for aggregation (WTQ)
|
||||
model = TapasForQuestionAnswering(config=config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
result = model(
|
||||
input_ids=input_ids,
|
||||
attention_mask=input_mask,
|
||||
token_type_ids=token_type_ids,
|
||||
labels=labels,
|
||||
numeric_values=numeric_values,
|
||||
numeric_values_scale=numeric_values_scale,
|
||||
float_answer=float_answer,
|
||||
)
|
||||
self.parent.assertEqual(result.loss.shape, ())
|
||||
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))
|
||||
|
||||
# case 3: strong supervision for aggregation (WikiSQL-supervised)
|
||||
wikisql_config = copy.copy(config)
|
||||
wikisql_config.use_answer_as_supervision = False
|
||||
model = TapasForQuestionAnswering(config=wikisql_config)
|
||||
model.to(torch_device)
|
||||
model.eval()
|
||||
result = model(
|
||||
input_ids,
|
||||
attention_mask=input_mask,
|
||||
token_type_ids=token_type_ids,
|
||||
labels=labels,
|
||||
aggregation_labels=aggregation_labels,
|
||||
)
|
||||
self.parent.assertEqual(result.loss.shape, ())
|
||||
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,
|
||||
labels,
|
||||
numeric_values,
|
||||
numeric_values_scale,
|
||||
float_answer,
|
||||
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,
|
||||
labels,
|
||||
numeric_values,
|
||||
numeric_values_scale,
|
||||
float_answer,
|
||||
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
|
||||
@require_scatter
|
||||
class TapasModelTest(ModelTesterMixin, unittest.TestCase):
|
||||
|
||||
all_model_classes = (
|
||||
(
|
||||
TapasModel,
|
||||
#TapasForMaskedLM,
|
||||
TapasForQuestionAnswering,
|
||||
TapasForSequenceClassification,
|
||||
)
|
||||
if is_torch_available()
|
||||
else None
|
||||
)
|
||||
test_pruning = False
|
||||
test_torchscript = False
|
||||
test_resize_embeddings = True
|
||||
test_head_masking = False
|
||||
|
||||
def _prepare_for_class(self, inputs_dict, model_class, return_labels=False):
|
||||
inputs_dict = copy.deepcopy(inputs_dict)
|
||||
if model_class in MODEL_FOR_MULTIPLE_CHOICE_MAPPING.values():
|
||||
inputs_dict = {
|
||||
k: v.unsqueeze(1).expand(-1, self.model_tester.num_choices, -1).contiguous()
|
||||
if isinstance(v, torch.Tensor) and v.ndim > 1
|
||||
else v
|
||||
for k, v in inputs_dict.items()
|
||||
}
|
||||
|
||||
if return_labels:
|
||||
if model_class in MODEL_FOR_MULTIPLE_CHOICE_MAPPING.values():
|
||||
inputs_dict["labels"] = torch.ones(self.model_tester.batch_size, dtype=torch.long, device=torch_device)
|
||||
elif model_class in MODEL_FOR_QUESTION_ANSWERING_MAPPING.values():
|
||||
inputs_dict["labels"] = torch.zeros(
|
||||
(self.model_tester.batch_size, self.model_tester.seq_length), dtype=torch.long, device=torch_device
|
||||
)
|
||||
inputs_dict["aggregation_labels"] = torch.zeros(
|
||||
self.model_tester.batch_size, dtype=torch.long, device=torch_device
|
||||
)
|
||||
inputs_dict["numeric_values"] = torch.zeros(
|
||||
(self.model_tester.batch_size, self.model_tester.seq_length), dtype=torch.float, device=torch_device
|
||||
)
|
||||
inputs_dict["numeric_values_scale"] = torch.zeros(
|
||||
(self.model_tester.batch_size, self.model_tester.seq_length), dtype=torch.float, device=torch_device
|
||||
)
|
||||
inputs_dict["float_answer"] = torch.zeros(
|
||||
self.model_tester.batch_size, dtype=torch.float, device=torch_device
|
||||
)
|
||||
elif model_class in [
|
||||
*MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING.values(),
|
||||
*MODEL_FOR_NEXT_SENTENCE_PREDICTION_MAPPING.values(),
|
||||
]:
|
||||
inputs_dict["labels"] = torch.zeros(
|
||||
self.model_tester.batch_size, dtype=torch.long, device=torch_device
|
||||
)
|
||||
elif model_class in [
|
||||
*MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING.values(),
|
||||
*MODEL_FOR_CAUSAL_LM_MAPPING.values(),
|
||||
*MODEL_FOR_MASKED_LM_MAPPING.values(),
|
||||
*MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING.values(),
|
||||
]:
|
||||
inputs_dict["labels"] = torch.zeros(
|
||||
(self.model_tester.batch_size, self.model_tester.seq_length), dtype=torch.long, device=torch_device
|
||||
)
|
||||
return inputs_dict
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def prepare_tapas_single_inputs_for_inference():
|
||||
# Here we prepare a single table-question pair to test TAPAS inference on:
|
||||
data = {'Footballer': ["Lionel Messi", "Cristiano Ronaldo"],
|
||||
'Age': ["33", "35"],
|
||||
}
|
||||
queries = "Which footballer is 33 years old?"
|
||||
table = pd.DataFrame.from_dict(data)
|
||||
|
||||
return table, queries
|
||||
|
||||
|
||||
def prepare_tapas_batch_inputs_for_inference():
|
||||
# Here we prepare a batch of 2 table-question pairs to test TAPAS inference on:
|
||||
data = {'Footballer': ["Lionel Messi", "Cristiano Ronaldo"],
|
||||
'Age': ["33", "35"],
|
||||
'Number of goals': ["712", "750"]
|
||||
}
|
||||
queries = ["Which footballer is 33 years old?", "How many goals does Ronaldo have?"]
|
||||
table = pd.DataFrame.from_dict(data)
|
||||
|
||||
return table, queries
|
||||
|
||||
|
||||
def prepare_tapas_batch_inputs_for_training():
|
||||
# Here we prepare a DIFFERENT batch of 2 table-question pairs to test TAPAS training on:
|
||||
data = {'Footballer': ["Lionel Messi", "Cristiano Ronaldo"],
|
||||
'Age': ["33", "35"],
|
||||
'Number of goals': ["712", "750"]
|
||||
}
|
||||
queries = ["Which footballer is 33 years old?", "What's the total number of goals?"]
|
||||
table = pd.DataFrame.from_dict(data)
|
||||
|
||||
answer_coordinates = [[(0, 0)], [(0, 2), (1, 2)]]
|
||||
answer_text = [["Lionel Messi"], ["1462"]]
|
||||
float_answer = [float("NaN"), float("1462")]
|
||||
|
||||
return table, queries, answer_coordinates, answer_text, float_answer
|
||||
|
||||
|
||||
TOLERANCE = 1
|
||||
|
||||
|
||||
@require_torch
|
||||
@require_scatter
|
||||
class TapasModelIntegrationTest(unittest.TestCase):
|
||||
@cached_property
|
||||
def default_tokenizer(self):
|
||||
return TapasTokenizer.from_pretrained("nielsr/tapas-base-finetuned-wtq")
|
||||
|
||||
@slow
|
||||
def test_inference_no_head(self):
|
||||
# ideally we want to test this with the weights of tapas_inter_masklm_base_reset,
|
||||
# but since it's not straightforward to do this with the TF 1 implementation, we test it with
|
||||
# the weights of the WTQ base model (i.e. tapas_wtq_wikisql_sqa_inter_masklm_base_reset)
|
||||
model = TapasModel.from_pretrained("nielsr/tapas-base-finetuned-wtq").to(torch_device)
|
||||
|
||||
tokenizer = self.default_tokenizer
|
||||
table, queries = prepare_tapas_single_inputs_for_inference()
|
||||
inputs = tokenizer(table=table, queries=queries, return_tensors="pt")
|
||||
inputs = {k: v.to(torch_device) for k, v in inputs.items()}
|
||||
outputs = model(**inputs)
|
||||
# test the sequence output
|
||||
expected_slice = torch.tensor(
|
||||
[[[-0.141581565, -0.599805772, 0.747186482],
|
||||
[-0.143664181, -0.602008104, 0.749218345],
|
||||
[-0.15169853, -0.603363097, 0.741370678]]], device=torch_device)
|
||||
|
||||
self.assertTrue(torch.allclose(outputs.last_hidden_state[:, :3, :3], expected_slice, atol=TOLERANCE))
|
||||
|
||||
# test the pooled output
|
||||
expected_slice = torch.tensor(
|
||||
[[0.987518311, -0.970520139, -0.994303405]], device=torch_device)
|
||||
|
||||
self.assertTrue(torch.allclose(outputs.pooler_output[:, :3], expected_slice, atol=TOLERANCE))
|
||||
|
||||
|
||||
@unittest.skip(reason="Model not available yet")
|
||||
def test_inference_masked_lm(self):
|
||||
pass
|
||||
|
||||
# TapasForQuestionAnswering has 3 possible ways of being fine-tuned:
|
||||
# - conversational set-up (SQA)
|
||||
# - weak supervision for aggregation (WTQ, WikiSQL)
|
||||
# - strong supervision for aggregation (WikiSQL-supervised)
|
||||
# We test all of them:
|
||||
@slow
|
||||
def test_inference_question_answering_head_conversational(self):
|
||||
# note that nielsr/tapas-base-finetuned-sqa should correspond to tapas_sqa_inter_masklm_base_reset
|
||||
model = TapasForQuestionAnswering.from_pretrained("nielsr/tapas-base-finetuned-sqa").to(torch_device)
|
||||
|
||||
tokenizer = self.default_tokenizer
|
||||
table, queries = prepare_tapas_single_inputs_for_inference()
|
||||
inputs = tokenizer(table=table, queries=queries, return_tensors="pt")
|
||||
inputs = {k: v.to(torch_device) for k, v in inputs.items()}
|
||||
outputs = model(**inputs)
|
||||
# test the logits
|
||||
logits = outputs.logits
|
||||
expected_shape = torch.Size((1, 21))
|
||||
self.assertEqual(logits.shape, expected_shape)
|
||||
|
||||
expected_tensor = torch.tensor([[-9997.22461, -9997.22461, -9997.22461, -9997.22461, -9997.22461,
|
||||
-9997.22461, -9997.22461, -9997.22461, -9997.22461, -16.2628059,
|
||||
-10004.082, 15.4330549, 15.4330549, 15.4330549, -9990.42,
|
||||
-16.3270779, -16.3270779, -16.3270779, -16.3270779, -16.3270779, -10004.8506]],
|
||||
device=torch_device) # ok
|
||||
|
||||
self.assertTrue(torch.allclose(logits, expected_tensor, atol=TOLERANCE))
|
||||
|
||||
@slow
|
||||
def test_inference_question_answering_head_weak_supervision(self):
|
||||
# note that nielsr/tapas-base-finetuned-wtq should correspond to tapas_wtq_wikisql_sqa_inter_masklm_base_reset
|
||||
model = TapasForQuestionAnswering.from_pretrained("nielsr/tapas-base-finetuned-wtq").to(torch_device)
|
||||
|
||||
tokenizer = self.default_tokenizer
|
||||
# let's test on a batch
|
||||
table, queries = prepare_tapas_batch_inputs_for_inference()
|
||||
inputs = tokenizer(table=table, queries=queries, padding="longest", return_tensors="pt")
|
||||
inputs = {k: v.to(torch_device) for k, v in inputs.items()}
|
||||
|
||||
outputs = model(**inputs)
|
||||
# test the logits
|
||||
logits = outputs.logits
|
||||
expected_shape = torch.Size((2, 28))
|
||||
self.assertEqual(logits.shape, expected_shape)
|
||||
|
||||
expected_slice = torch.tensor([[-160.375504, -160.375504, -160.375504, -10072.3965, -10070.9414, -10094.9736],
|
||||
[-9861.6123, -9861.6123, -9861.6123, -9861.6123, -9891.01172, 146.600677]],
|
||||
device=torch_device) # ok (batch size = 2)
|
||||
|
||||
self.assertTrue(torch.allclose(logits[:,-6:], expected_slice, atol=TOLERANCE))
|
||||
|
||||
# test the aggregation logits
|
||||
logits_aggregation = outputs.logits_aggregation
|
||||
expected_shape = torch.Size((2, 4))
|
||||
self.assertEqual(logits_aggregation.shape, expected_shape)
|
||||
expected_tensor = torch.tensor([[18.8545208, -9.76614857, -6.3128891, -2.93525243],
|
||||
[-4.05782509, 40.0351, -5.35329962, 23.3978653]],
|
||||
device=torch_device) # ok (batch size = 2)
|
||||
|
||||
self.assertTrue(torch.allclose(logits_aggregation, expected_tensor, atol=TOLERANCE))
|
||||
|
||||
# test the predicted answer coordinates and aggregation indices
|
||||
EXPECTED_PREDICTED_ANSWER_COORDINATES = [[(0, 0)], [(1, 2)]]
|
||||
EXPECTED_PREDICTED_AGGREGATION_INDICES = [0, 1]
|
||||
|
||||
predicted_answer_coordinates, predicted_aggregation_indices = tokenizer.convert_logits_to_predictions(inputs,
|
||||
outputs.logits,
|
||||
outputs.logits_aggregation)
|
||||
|
||||
self.assertEqual(EXPECTED_PREDICTED_ANSWER_COORDINATES, predicted_answer_coordinates)
|
||||
self.assertEqual(EXPECTED_PREDICTED_AGGREGATION_INDICES, predicted_aggregation_indices)
|
||||
|
||||
|
||||
@slow
|
||||
def test_training_question_answering_head_weak_supervision(self):
|
||||
# note that nielsr/tapas-base-finetuned-wtq should correspond to tapas_wtq_wikisql_sqa_inter_masklm_base_reset
|
||||
model = TapasForQuestionAnswering.from_pretrained("nielsr/tapas-base-finetuned-wtq").to(torch_device)
|
||||
model.to(torch_device)
|
||||
# normally we should put the model in training mode but it's a pain to do this with the TF 1 implementation
|
||||
|
||||
tokenizer = self.default_tokenizer
|
||||
# let's test on a batch
|
||||
table, queries, answer_coordinates, answer_text, float_answer = prepare_tapas_batch_inputs_for_training()
|
||||
inputs = tokenizer(table=table, queries=queries, answer_coordinates=answer_coordinates,
|
||||
answer_text=answer_text, padding="longest", return_tensors="pt")
|
||||
|
||||
# prepare data (created by the tokenizer) and move to torch_device
|
||||
input_ids = inputs["input_ids"].to(torch_device)
|
||||
attention_mask = inputs["attention_mask"].to(torch_device)
|
||||
token_type_ids = inputs["token_type_ids"].to(torch_device)
|
||||
labels = inputs["labels"].to(torch_device)
|
||||
numeric_values = inputs["numeric_values"].to(torch_device)
|
||||
numeric_values_scale = inputs["numeric_values_scale"].to(torch_device)
|
||||
|
||||
# the answer should be prepared by the user
|
||||
float_answer = torch.FloatTensor(float_answer).to(torch_device)
|
||||
|
||||
# forward pass to get loss + logits:
|
||||
outputs = model(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids, labels=labels,
|
||||
numeric_values=numeric_values, numeric_values_scale=numeric_values_scale,
|
||||
float_answer=float_answer)
|
||||
|
||||
# test the loss
|
||||
loss = outputs.loss
|
||||
expected_loss = torch.tensor(3.3527612686157227e-08, device=torch_device) # ok
|
||||
self.assertTrue(torch.allclose(loss, expected_loss, atol=TOLERANCE))
|
||||
|
||||
# test the logits on the first example
|
||||
logits = outputs.logits
|
||||
expected_shape = torch.Size((2, 29))
|
||||
self.assertEqual(logits.shape, expected_shape)
|
||||
expected_slice = torch.tensor([-160.0156, -160.0156, -160.0156, -160.0156, -160.0156,
|
||||
-10072.2266, -10070.8896, -10092.6006, -10092.6006],
|
||||
device=torch_device) # ok
|
||||
|
||||
self.assertTrue(torch.allclose(logits[0,-9:], expected_slice, atol=TOLERANCE))
|
||||
|
||||
|
||||
# test the aggregation logits on the second example
|
||||
logits_aggregation = outputs.logits_aggregation
|
||||
expected_shape = torch.Size((2, 4))
|
||||
self.assertEqual(logits_aggregation.shape, expected_shape)
|
||||
expected_slice = torch.tensor([-4.0538, 40.0304, -5.3554, 23.3965], device=torch_device) # ok
|
||||
|
||||
self.assertTrue(torch.allclose(logits_aggregation[1,-4:], expected_slice, atol=TOLERANCE))
|
||||
|
||||
@slow
|
||||
def test_inference_question_answering_head_strong_supervision(self):
|
||||
# note that nielsr/tapas-base-finetuned-wikisql-supervised should correspond to tapas_wikisql_sqa_inter_masklm_base_reset
|
||||
model = TapasForQuestionAnswering.from_pretrained("nielsr/tapas-base-finetuned-wikisql-supervised").to(torch_device)
|
||||
|
||||
tokenizer = self.default_tokenizer
|
||||
table, queries = prepare_tapas_single_inputs_for_inference()
|
||||
inputs = tokenizer(table=table, queries=queries, return_tensors="pt")
|
||||
inputs = {k: v.to(torch_device) for k, v in inputs.items()}
|
||||
outputs = model(**inputs)
|
||||
# test the logits
|
||||
logits = outputs.logits
|
||||
expected_shape = torch.Size((1, 21))
|
||||
self.assertEqual(logits.shape, expected_shape)
|
||||
expected_tensor = torch.tensor([[-10011.1084, -10011.1084, -10011.1084, -10011.1084, -10011.1084,
|
||||
-10011.1084, -10011.1084, -10011.1084, -10011.1084, -18.6185989,
|
||||
-10008.7969, 17.6355762, 17.6355762, 17.6355762, -10002.4404,
|
||||
-18.7111301, -18.7111301, -18.7111301, -18.7111301, -18.7111301, -10007.0977]],
|
||||
device=torch_device) # ok
|
||||
|
||||
self.assertTrue(torch.allclose(logits, expected_tensor, atol=TOLERANCE))
|
||||
|
||||
# test the aggregation logits
|
||||
logits_aggregation = outputs.logits_aggregation
|
||||
expected_shape = torch.Size((1, 4))
|
||||
self.assertEqual(logits_aggregation.shape, expected_shape)
|
||||
expected_tensor = torch.tensor([[16.5659733, -3.06624889, -2.34152961, -0.970244825]],
|
||||
device=torch_device) # ok, PyTorch model outputs [[16.5679, -3.0668, -2.3442, -0.9674]]
|
||||
|
||||
self.assertTrue(torch.allclose(logits_aggregation, expected_tensor, atol=TOLERANCE))
|
||||
|
||||
@slow
|
||||
def test_inference_classification_head(self):
|
||||
# note that nielsr/tapas-base-finetuned-tabfact should correspond to tapas_tabfact_inter_masklm_base_reset
|
||||
model = TapasForSequenceClassification.from_pretrained("nielsr/tapas-base-finetuned-tabfact").to(torch_device)
|
||||
|
||||
tokenizer = self.default_tokenizer
|
||||
table, queries = prepare_tapas_single_inputs_for_inference()
|
||||
inputs = tokenizer(table=table, queries=queries, padding="longest", return_tensors="pt")
|
||||
inputs = {k: v.to(torch_device) for k, v in inputs.items()}
|
||||
outputs = model(**inputs)
|
||||
|
||||
# test the classification logits
|
||||
logits = outputs.logits
|
||||
expected_shape = torch.Size((1, 2))
|
||||
self.assertEqual(logits.shape, expected_shape)
|
||||
expected_tensor = torch.tensor([[0.795137286, 9.5572]],
|
||||
device=torch_device) # ok. Note that the PyTorch model outputs [[0.8057, 9.5281]]
|
||||
|
||||
self.assertTrue(torch.allclose(outputs.logits, expected_tensor, atol=TOLERANCE))
|
||||
|
||||
|
||||
# Below: tests for Tapas utilities which are defined in modeling_tapas.py.
|
||||
# These are based on segmented_tensor_test.py of the original implementation.
|
||||
# URL: https://github.com/google-research/tapas/blob/master/tapas/models/segmented_tensor_test.py
|
||||
@require_scatter
|
||||
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 = 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 = 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 = 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 = flatten(row_index)
|
||||
col_index_flat = flatten(col_index)
|
||||
|
||||
shape = [3, 4, 5]
|
||||
batched_index = IndexMap(indices=torch.zeros(shape).type(torch.LongTensor), num_segments=1, batch_dims=3)
|
||||
batched_index_flat = 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 = 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 = ProductIndexMap(row_index, col_index)
|
||||
row_sum, _ = reduce_sum(values, row_index)
|
||||
col_sum, _ = reduce_sum(values, col_index)
|
||||
cell_sum, _ = 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 = ProductIndexMap(row_index, col_index)
|
||||
row_mean, _ = reduce_mean(values, row_index)
|
||||
col_mean, _ = reduce_mean(values, col_index)
|
||||
cell_mean, _ = 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 = IndexMap(indices=torch.as_tensor([0, 1, 0, 1]), num_segments=2)
|
||||
maximum, _ = 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 = IndexMap(indices=torch.as_tensor([0, 0, 1]), num_segments=2, batch_dims=0)
|
||||
sums, new_index = 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 = 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, _ = reduce_sum(values, cell_index)
|
||||
cell_sum = 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 = IndexMap(indices=torch.as_tensor([[0, 1], [1, 0]]), num_segments=2, batch_dims=1)
|
||||
result = 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]]])
|
||||
@@ -1,237 +0,0 @@
|
||||
# coding=utf-8
|
||||
# Copyright 2020 The HuggingFace Inc. team, Microsoft Corporation.
|
||||
#
|
||||
# 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
|
||||
|
||||
from transformers import MPNetConfig, is_tf_available
|
||||
from transformers.testing_utils import require_tf, slow
|
||||
|
||||
from .test_configuration_common import ConfigTester
|
||||
from .test_modeling_tf_common import TFModelTesterMixin, ids_tensor
|
||||
|
||||
|
||||
if is_tf_available():
|
||||
import tensorflow as tf
|
||||
|
||||
from transformers.models.mpnet.modeling_tf_mpnet import (
|
||||
TFMPNetForMaskedLM,
|
||||
TFMPNetForMultipleChoice,
|
||||
TFMPNetForQuestionAnswering,
|
||||
TFMPNetForSequenceClassification,
|
||||
TFMPNetForTokenClassification,
|
||||
TFMPNetModel,
|
||||
)
|
||||
|
||||
|
||||
class TFMPNetModelTester:
|
||||
def __init__(
|
||||
self,
|
||||
parent,
|
||||
batch_size=13,
|
||||
seq_length=7,
|
||||
is_training=True,
|
||||
use_input_mask=True,
|
||||
use_token_type_ids=False,
|
||||
use_labels=True,
|
||||
vocab_size=99,
|
||||
hidden_size=64,
|
||||
num_hidden_layers=5,
|
||||
num_attention_heads=4,
|
||||
intermediate_size=64,
|
||||
hidden_act="gelu",
|
||||
hidden_dropout_prob=0.1,
|
||||
attention_probs_dropout_prob=0.1,
|
||||
max_position_embeddings=512,
|
||||
type_vocab_size=16,
|
||||
type_sequence_label_size=2,
|
||||
initializer_range=0.02,
|
||||
num_labels=3,
|
||||
num_choices=4,
|
||||
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.max_position_embeddings = max_position_embeddings
|
||||
self.type_vocab_size = type_vocab_size
|
||||
self.type_sequence_label_size = type_sequence_label_size
|
||||
self.initializer_range = initializer_range
|
||||
self.num_labels = num_labels
|
||||
self.num_choices = num_choices
|
||||
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 = ids_tensor([self.batch_size, self.seq_length], vocab_size=2)
|
||||
|
||||
sequence_labels = None
|
||||
token_labels = None
|
||||
choice_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)
|
||||
choice_labels = ids_tensor([self.batch_size], self.num_choices)
|
||||
|
||||
config = MPNetConfig(
|
||||
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,
|
||||
initializer_range=self.initializer_range,
|
||||
)
|
||||
return config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
|
||||
def create_and_check_mpnet_model(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
model = TFMPNetModel(config=config)
|
||||
inputs = {"input_ids": input_ids, "attention_mask": input_mask}
|
||||
result = model(inputs)
|
||||
inputs = [input_ids, input_mask]
|
||||
result = model(inputs)
|
||||
self.parent.assertEqual(result.last_hidden_state.shape, (self.batch_size, self.seq_length, self.hidden_size))
|
||||
|
||||
def create_and_check_mpnet_for_masked_lm(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
model = TFMPNetForMaskedLM(config=config)
|
||||
inputs = {"input_ids": input_ids, "attention_mask": input_mask}
|
||||
result = model(inputs)
|
||||
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.seq_length, self.vocab_size))
|
||||
|
||||
def create_and_check_mpnet_for_question_answering(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
model = TFMPNetForQuestionAnswering(config=config)
|
||||
inputs = {
|
||||
"input_ids": input_ids,
|
||||
"attention_mask": input_mask,
|
||||
}
|
||||
result = model(inputs)
|
||||
self.parent.assertEqual(result.start_logits.shape, (self.batch_size, self.seq_length))
|
||||
self.parent.assertEqual(result.end_logits.shape, (self.batch_size, self.seq_length))
|
||||
|
||||
def create_and_check_mpnet_for_sequence_classification(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
config.num_labels = self.num_labels
|
||||
model = TFMPNetForSequenceClassification(config)
|
||||
inputs = {"input_ids": input_ids, "attention_mask": input_mask}
|
||||
result = model(inputs)
|
||||
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.num_labels))
|
||||
|
||||
def create_and_check_mpnet_for_multiple_choice(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
config.num_choices = self.num_choices
|
||||
model = TFMPNetForMultipleChoice(config)
|
||||
multiple_choice_inputs_ids = tf.tile(tf.expand_dims(input_ids, 1), (1, self.num_choices, 1))
|
||||
multiple_choice_input_mask = tf.tile(tf.expand_dims(input_mask, 1), (1, self.num_choices, 1))
|
||||
inputs = {
|
||||
"input_ids": multiple_choice_inputs_ids,
|
||||
"attention_mask": multiple_choice_input_mask,
|
||||
}
|
||||
result = model(inputs)
|
||||
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.num_choices))
|
||||
|
||||
def create_and_check_mpnet_for_token_classification(
|
||||
self, config, input_ids, input_mask, sequence_labels, token_labels, choice_labels
|
||||
):
|
||||
config.num_labels = self.num_labels
|
||||
model = TFMPNetForTokenClassification(config)
|
||||
inputs = {"input_ids": input_ids, "attention_mask": input_mask}
|
||||
result = model(inputs)
|
||||
self.parent.assertEqual(result.logits.shape, (self.batch_size, self.seq_length, self.num_labels))
|
||||
|
||||
def prepare_config_and_inputs_for_common(self):
|
||||
config_and_inputs = self.prepare_config_and_inputs()
|
||||
(config, input_ids, input_mask, sequence_labels, token_labels, choice_labels) = config_and_inputs
|
||||
inputs_dict = {"input_ids": input_ids, "attention_mask": input_mask}
|
||||
return config, inputs_dict
|
||||
|
||||
|
||||
@require_tf
|
||||
class TFMPNetModelTest(TFModelTesterMixin, unittest.TestCase):
|
||||
|
||||
all_model_classes = (
|
||||
(
|
||||
TFMPNetForMaskedLM,
|
||||
TFMPNetForMultipleChoice,
|
||||
TFMPNetForQuestionAnswering,
|
||||
TFMPNetForSequenceClassification,
|
||||
TFMPNetForTokenClassification,
|
||||
TFMPNetModel,
|
||||
)
|
||||
if is_tf_available()
|
||||
else ()
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
self.model_tester = TFMPNetModelTester(self)
|
||||
self.config_tester = ConfigTester(self, config_class=MPNetConfig, hidden_size=37)
|
||||
|
||||
def test_config(self):
|
||||
self.config_tester.run_common_tests()
|
||||
|
||||
def test_mpnet_model(self):
|
||||
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||
self.model_tester.create_and_check_mpnet_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_mpnet_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_mpnet_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_mpnet_for_sequence_classification(*config_and_inputs)
|
||||
|
||||
def test_for_multiple_choice(self):
|
||||
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||
self.model_tester.create_and_check_mpnet_for_multiple_choice(*config_and_inputs)
|
||||
|
||||
def test_for_token_classification(self):
|
||||
config_and_inputs = self.model_tester.prepare_config_and_inputs()
|
||||
self.model_tester.create_and_check_mpnet_for_token_classification(*config_and_inputs)
|
||||
|
||||
@slow
|
||||
def test_model_from_pretrained(self):
|
||||
for model_name in ["microsoft/mpnet-base"]:
|
||||
model = TFMPNetModel.from_pretrained(model_name)
|
||||
self.assertIsNotNone(model)
|
||||
@@ -584,7 +584,7 @@ class TokenizerTesterMixin:
|
||||
|
||||
# We want to have sequence 0 and sequence 1 are tagged
|
||||
# respectively with 0 and 1 token_ids
|
||||
# (regardeless of weither the model use token type ids)
|
||||
# (regardless of whether the model use token type ids)
|
||||
# We use this assumption in the QA pipeline among other place
|
||||
output = tokenizer(seq_0, return_token_type_ids=True)
|
||||
self.assertIn(0, output["token_type_ids"])
|
||||
@@ -600,7 +600,7 @@ class TokenizerTesterMixin:
|
||||
|
||||
# We want to have sequence 0 and sequence 1 are tagged
|
||||
# respectively with 0 and 1 token_ids
|
||||
# (regardeless of weither the model use token type ids)
|
||||
# (regardless of whether the model use token type ids)
|
||||
# We use this assumption in the QA pipeline among other place
|
||||
output = tokenizer(seq_0)
|
||||
self.assertIn(0, output.sequence_ids())
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
# coding=utf-8
|
||||
# Copyright 2020 The HuggingFace Inc. team, Microsoft Corporation.
|
||||
#
|
||||
# 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 os
|
||||
import unittest
|
||||
|
||||
from transformers.models.mpnet.tokenization_mpnet import VOCAB_FILES_NAMES, MPNetTokenizer
|
||||
from transformers.testing_utils import require_tokenizers, slow
|
||||
|
||||
from .test_tokenization_common import TokenizerTesterMixin
|
||||
|
||||
|
||||
@require_tokenizers
|
||||
class MPNetTokenizerTest(TokenizerTesterMixin, unittest.TestCase):
|
||||
|
||||
tokenizer_class = MPNetTokenizer
|
||||
test_rust_tokenizer = False
|
||||
|
||||
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])
|
||||
|
||||
@slow
|
||||
def test_sequence_builders(self):
|
||||
tokenizer = self.tokenizer_class.from_pretrained("microsoft/mpnet-base")
|
||||
|
||||
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 == [0] + text + [2]
|
||||
assert encoded_pair == [0] + text + [2] + [2] + text_2 + [2]
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user