Compare commits
39
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6626e9cf74 | ||
|
|
81d4fb79dd | ||
|
|
3aca02efb3 | ||
|
|
5164ea91a7 | ||
|
|
49debe62fd | ||
|
|
847d370301 | ||
|
|
eb3e6cb04f | ||
|
|
3e624c64ca | ||
|
|
b29fed790b | ||
|
|
e03129ad44 | ||
|
|
08a70fb392 | ||
|
|
0ae91c80aa | ||
|
|
d6df9a8ffe | ||
|
|
c52716d46c | ||
|
|
73a0c25376 | ||
|
|
ed37f9fa4f | ||
|
|
0416d437fb | ||
|
|
db9279dedb | ||
|
|
e58b3ec5df | ||
|
|
6ffe03a0a1 | ||
|
|
3e5da38dae | ||
|
|
9499a3778e | ||
|
|
9362eb4a07 | ||
|
|
31acb8dc52 | ||
|
|
06a6cb6f36 | ||
|
|
4c91a3af94 | ||
|
|
4be01e5cbf | ||
|
|
a355f4f0fc | ||
|
|
d262a5d48e | ||
|
|
3f067f4409 | ||
|
|
f564f93c84 | ||
|
|
4f338ed407 | ||
|
|
6fe1cc0874 | ||
|
|
18f4b9274f | ||
|
|
96c4990165 | ||
|
|
470753bcf5 | ||
|
|
0c716ede8c | ||
|
|
b8da16f390 | ||
|
|
ba28170717 |
No files matched your search
@@ -48,4 +48,4 @@ jobs:
|
||||
run: |
|
||||
source .env/bin/activate
|
||||
python -m pytest -n 1 --dist=loadfile -s -v ./tests/
|
||||
|
||||
|
||||
+1
-1
@@ -379,7 +379,7 @@ export SQUAD_DIR=/path/to/SQUAD
|
||||
|
||||
python run_squad.py \
|
||||
--model_type bert \
|
||||
--model_name_or_path bert-base-cased \
|
||||
--model_name_or_path bert-base-uncased \
|
||||
--do_train \
|
||||
--do_eval \
|
||||
--do_lower_case \
|
||||
|
||||
@@ -18,7 +18,7 @@ def chunks(lst, n):
|
||||
|
||||
def generate_summaries(lns, out_file, batch_size=8, device=DEFAULT_DEVICE):
|
||||
fout = Path(out_file).open("w")
|
||||
model = BartForConditionalGeneration.from_pretrained("bart-large-cnn", output_past=True,)
|
||||
model = BartForConditionalGeneration.from_pretrained("bart-large-cnn", output_past=True,).to(device)
|
||||
tokenizer = BartTokenizer.from_pretrained("bart-large")
|
||||
for batch in tqdm(list(chunks(lns, batch_size))):
|
||||
dct = tokenizer.batch_encode_plus(batch, max_length=1024, return_tensors="pt", pad_to_max_length=True)
|
||||
|
||||
@@ -8,11 +8,7 @@ language:
|
||||
|
||||
# bert-base-bg-cs-pl-ru-cased
|
||||
|
||||
SlavicBERT\[1\] \(Slavic \(bg, cs, pl, ru\), cased, 12-layer, 768-hidden, 12-heads, 180M parameters\) was trained
|
||||
on Russian News and four Wikipedias: Bulgarian, Czech, Polish, and Russian.
|
||||
Subtoken vocabulary was built using this data. Multilingual BERT was used as an initialization for SlavicBERT.
|
||||
SlavicBERT\[1\] \(Slavic \(bg, cs, pl, ru\), cased, 12‑layer, 768‑hidden, 12‑heads, 180M parameters\) was trained on Russian News and four Wikipedias: Bulgarian, Czech, Polish, and Russian. Subtoken vocabulary was built using this data. Multilingual BERT was used as an initialization for SlavicBERT.
|
||||
|
||||
|
||||
\[1\]: Arkhipov M., Trofimova M., Kuratov Y., Sorokin A. \(2019\).
|
||||
[Tuning Multilingual Transformers for Language-Specific Named Entity Recognition](https://www.aclweb.org/anthology/W19-3712/).
|
||||
ACL anthology W19-3712.
|
||||
\[1\]: Arkhipov M., Trofimova M., Kuratov Y., Sorokin A. \(2019\). [Tuning Multilingual Transformers for Language-Specific Named Entity Recognition](https://www.aclweb.org/anthology/W19-3712/). ACL anthology W19-3712.
|
||||
@@ -5,19 +5,13 @@ language:
|
||||
|
||||
# bert-base-cased-conversational
|
||||
|
||||
Conversational BERT \(English, cased, 12-layer, 768-hidden, 12-heads, 110M parameters\) was trained
|
||||
on the English part of Twitter, Reddit, DailyDialogues\[1\], OpenSubtitles\[2\], Debates\[3\], Blogs\[4\],
|
||||
Facebook News Comments. We used this training data to build the vocabulary of English subtokens and took
|
||||
English cased version of BERT-base as an initialization for English Conversational BERT.
|
||||
Conversational BERT \(English, cased, 12‑layer, 768‑hidden, 12‑heads, 110M parameters\) was trained on the English part of Twitter, Reddit, DailyDialogues\[1\], OpenSubtitles\[2\], Debates\[3\], Blogs\[4\], Facebook News Comments. We used this training data to build the vocabulary of English subtokens and took English cased version of BERT‑base as an initialization for English Conversational BERT.
|
||||
|
||||
|
||||
\[1\]: Yanran Li, Hui Su, Xiaoyu Shen, Wenjie Li, Ziqiang Cao, and Shuzi Niu. DailyDialog: A Manually Labelled
|
||||
Multi-turn Dialogue Dataset. IJCNLP 2017.
|
||||
\[1\]: Yanran Li, Hui Su, Xiaoyu Shen, Wenjie Li, Ziqiang Cao, and Shuzi Niu. DailyDialog: A Manually Labelled Multi-turn Dialogue Dataset. IJCNLP 2017.
|
||||
|
||||
\[2\]: P. Lison and J. Tiedemann, 2016, OpenSubtitles2016: Extracting Large Parallel Corpora from Movie and TV Subtitles.
|
||||
In Proceedings of the 10th International Conference on Language Resources and Evaluation \(LREC 2016\)
|
||||
\[2\]: P. Lison and J. Tiedemann, 2016, OpenSubtitles2016: Extracting Large Parallel Corpora from Movie and TV Subtitles. In Proceedings of the 10th International Conference on Language Resources and Evaluation \(LREC 2016\)
|
||||
|
||||
\[3\]: Justine Zhang, Ravi Kumar, Sujith Ravi, Cristian Danescu-Niculescu-Mizil. Proceedings of NAACL, 2016.
|
||||
|
||||
\[4\]: J. Schler, M. Koppel, S. Argamon and J. Pennebaker \(2006\). Effects of Age and Gender on Blogging
|
||||
in Proceedings of 2006 AAAI Spring Symposium on Computational Approaches for Analyzing Weblogs.
|
||||
\[4\]: J. Schler, M. Koppel, S. Argamon and J. Pennebaker \(2006\). Effects of Age and Gender on Blogging in Proceedings of 2006 AAAI Spring Symposium on Computational Approaches for Analyzing Weblogs.
|
||||
@@ -5,18 +5,11 @@ language:
|
||||
|
||||
# bert-base-multilingual-cased-sentence
|
||||
|
||||
Sentence Multilingual BERT \(101 languages, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\)
|
||||
is a representation-based sentence encoder for 101 languages of Multilingual BERT.
|
||||
It is initialized with Multilingual BERT and then fine-tuned on english MultiNLI\[1\] and on dev set
|
||||
of multilingual XNLI\[2\].
|
||||
Sentence representations are mean pooled token embeddings in the same manner as in Sentence-BERT\[3\].
|
||||
Sentence Multilingual BERT \(101 languages, cased, 12‑layer, 768‑hidden, 12‑heads, 180M parameters\) is a representation‑based sentence encoder for 101 languages of Multilingual BERT. It is initialized with Multilingual BERT and then fine‑tuned on english MultiNLI\[1\] and on dev set of multilingual XNLI\[2\]. Sentence representations are mean pooled token embeddings in the same manner as in Sentence‑BERT\[3\].
|
||||
|
||||
|
||||
\[1\]: Williams A., Nangia N. & Bowman S. \(2017\) A Broad-Coverage Challenge Corpus for Sentence Understanding
|
||||
through Inference. arXiv preprint [arXiv:1704.05426](https://arxiv.org/abs/1704.05426)
|
||||
\[1\]: Williams A., Nangia N. & Bowman S. \(2017\) A Broad-Coverage Challenge Corpus for Sentence Understanding through Inference. arXiv preprint [arXiv:1704.05426](https://arxiv.org/abs/1704.05426)
|
||||
|
||||
\[2\]: Williams A., Bowman S. \(2018\) XNLI: Evaluating Cross-lingual Sentence Representations.
|
||||
arXiv preprint [arXiv:1809.05053](https://arxiv.org/abs/1809.05053)
|
||||
\[2\]: Williams A., Bowman S. \(2018\) XNLI: Evaluating Cross-lingual Sentence Representations. arXiv preprint [arXiv:1809.05053](https://arxiv.org/abs/1809.05053)
|
||||
|
||||
\[3\]: N. Reimers, I. Gurevych \(2019\) Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks.
|
||||
arXiv preprint [arXiv:1908.10084](https://arxiv.org/abs/1908.10084)
|
||||
\[3\]: N. Reimers, I. Gurevych \(2019\) Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. arXiv preprint [arXiv:1908.10084](https://arxiv.org/abs/1908.10084)
|
||||
@@ -5,14 +5,9 @@ language:
|
||||
|
||||
# rubert-base-cased-conversational
|
||||
|
||||
Conversational RuBERT \(Russian, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\) was trained
|
||||
on OpenSubtitles\[1\], [Dirty](https://d3.ru/), [Pikabu](https://pikabu.ru/),
|
||||
and a Social Media segment of Taiga corpus\[2\]. We assembled a new vocabulary for Conversational RuBERT model
|
||||
on this data and initialized the model with [RuBERT](../rubert-base-cased).
|
||||
Conversational RuBERT \(Russian, cased, 12‑layer, 768‑hidden, 12‑heads, 180M parameters\) was trained on OpenSubtitles\[1\], [Dirty](https://d3.ru/), [Pikabu](https://pikabu.ru/), and a Social Media segment of Taiga corpus\[2\]. We assembled a new vocabulary for Conversational RuBERT model on this data and initialized the model with [RuBERT](../rubert-base-cased).
|
||||
|
||||
|
||||
\[1\]: P. Lison and J. Tiedemann, 2016, OpenSubtitles2016: Extracting Large Parallel Corpora from Movie and TV Subtitles.
|
||||
In Proceedings of the 10th International Conference on Language Resources and Evaluation \(LREC 2016\)
|
||||
\[1\]: P. Lison and J. Tiedemann, 2016, OpenSubtitles2016: Extracting Large Parallel Corpora from Movie and TV Subtitles. In Proceedings of the 10th International Conference on Language Resources and Evaluation \(LREC 2016\)
|
||||
|
||||
\[2\]: Shavrina T., Shapovalova O. \(2017\) TO THE METHODOLOGY OF CORPUS CONSTRUCTION FOR MACHINE LEARNING:
|
||||
«TAIGA» SYNTAX TREE CORPUS AND PARSER. in proc. of “CORPORA2017”, international conference , Saint-Petersbourg, 2017.
|
||||
\[2\]: Shavrina T., Shapovalova O. \(2017\) TO THE METHODOLOGY OF CORPUS CONSTRUCTION FOR MACHINE LEARNING: «TAIGA» SYNTAX TREE CORPUS AND PARSER. in proc. of “CORPORA2017”, international conference , Saint-Petersbourg, 2017.
|
||||
@@ -5,17 +5,11 @@ language:
|
||||
|
||||
# rubert-base-cased-sentence
|
||||
|
||||
Sentence RuBERT \(Russian, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\)
|
||||
is a representation-based sentence encoder for Russian. It is initialized with RuBERT and fine-tuned on SNLI\[1\]
|
||||
google-translated to russian and on russian part of XNLI dev set\[2\]. Sentence representations are mean pooled
|
||||
token embeddings in the same manner as in Sentence-BERT\[3\].
|
||||
Sentence RuBERT \(Russian, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\) is a representation‑based sentence encoder for Russian. It is initialized with RuBERT and fine‑tuned on SNLI\[1\] google-translated to russian and on russian part of XNLI dev set\[2\]. Sentence representations are mean pooled token embeddings in the same manner as in Sentence‑BERT\[3\].
|
||||
|
||||
|
||||
\[1\]: S. R. Bowman, G. Angeli, C. Potts, and C. D. Manning. \(2015\) A large annotated corpus for learning
|
||||
natural language inference. arXiv preprint [arXiv:1508.05326](https://arxiv.org/abs/1508.05326)
|
||||
\[1\]: S. R. Bowman, G. Angeli, C. Potts, and C. D. Manning. \(2015\) A large annotated corpus for learning natural language inference. arXiv preprint [arXiv:1508.05326](https://arxiv.org/abs/1508.05326)
|
||||
|
||||
\[2\]: Williams A., Bowman S. \(2018\) XNLI: Evaluating Cross-lingual Sentence Representations.
|
||||
arXiv preprint [arXiv:1809.05053](https://arxiv.org/abs/1809.05053)
|
||||
\[2\]: Williams A., Bowman S. \(2018\) XNLI: Evaluating Cross-lingual Sentence Representations. arXiv preprint [arXiv:1809.05053](https://arxiv.org/abs/1809.05053)
|
||||
|
||||
\[3\]: N. Reimers, I. Gurevych \(2019\) Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks.
|
||||
arXiv preprint [arXiv:1908.10084](https://arxiv.org/abs/1908.10084)
|
||||
\[3\]: N. Reimers, I. Gurevych \(2019\) Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. arXiv preprint [arXiv:1908.10084](https://arxiv.org/abs/1908.10084)
|
||||
@@ -5,10 +5,7 @@ language:
|
||||
|
||||
# rubert-base-cased
|
||||
|
||||
RuBERT \(Russian, cased, 12-layer, 768-hidden, 12-heads, 180M parameters\) was trained on the Russian part of Wikipedia
|
||||
and news data. We used this training data to build a vocabulary of Russian subtokens and took a multilingual version
|
||||
of BERT-base as an initialization for RuBERT\[1\].
|
||||
RuBERT \(Russian, cased, 12‑layer, 768‑hidden, 12‑heads, 180M parameters\) was trained on the Russian part of Wikipedia and news data. We used this training data to build a vocabulary of Russian subtokens and took a multilingual version of BERT‑base as an initialization for RuBERT\[1\].
|
||||
|
||||
|
||||
\[1\]: Kuratov, Y., Arkhipov, M. \(2019\). Adaptation of Deep Bidirectional Multilingual Transformers for Russian Language.
|
||||
arXiv preprint [arXiv:1905.07213](https://arxiv.org/abs/1905.07213).
|
||||
\[1\]: Kuratov, Y., Arkhipov, M. \(2019\). Adaptation of Deep Bidirectional Multilingual Transformers for Russian Language. arXiv preprint [arXiv:1905.07213](https://arxiv.org/abs/1905.07213).
|
||||
@@ -50,7 +50,8 @@ for the other languages.
|
||||
Citation:
|
||||
|
||||
<details>
|
||||
```
|
||||
|
||||
```bibtex
|
||||
@article{Artetxe:etal:2019,
|
||||
author = {Mikel Artetxe and Sebastian Ruder and Dani Yogatama},
|
||||
title = {On the cross-lingual transferability of monolingual representations},
|
||||
@@ -61,6 +62,7 @@ Citation:
|
||||
eprint = {1910.11856}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
I used `Data augmentation techniques` and splited the dataset in order to have a train and test set. The test set was created in a way that contains the same number of samples for each language. Finally, I got:
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
---
|
||||
language: multilingual
|
||||
thumbnail:
|
||||
---
|
||||
|
||||
# BERT (base-multilingual-uncased) fine-tuned on XQuAD
|
||||
|
||||
This model was created by [Google](https://github.com/google-research/bert/blob/master/multilingual.md) and fine-tuned on [XQuAD](https://github.com/deepmind/xquad) for multilingual (`11 different languages`) **Q&A** downstream task.
|
||||
|
||||
## Details of the language model('bert-base-multilingual-uncased')
|
||||
|
||||
[Language model](https://github.com/google-research/bert/blob/master/multilingual.md)
|
||||
|
||||
| Languages | Heads | Layers | Hidden | Params |
|
||||
| --------- | ----- | ------ | ------ | ------ |
|
||||
| 102 | 12 | 12 | 768 | 100 M |
|
||||
|
||||
## Details of the downstream task (multilingual Q&A) - Dataset
|
||||
|
||||
Deepmind [XQuAD](https://github.com/deepmind/xquad)
|
||||
|
||||
Languages covered:
|
||||
|
||||
- Arabic: `ar`
|
||||
- German: `de`
|
||||
- Greek: `el`
|
||||
- English: `en`
|
||||
- Spanish: `es`
|
||||
- Hindi: `hi`
|
||||
- Russian: `ru`
|
||||
- Thai: `th`
|
||||
- Turkish: `tr`
|
||||
- Vietnamese: `vi`
|
||||
- Chinese: `zh`
|
||||
|
||||
As the dataset is based on SQuAD v1.1, there are no unanswerable questions in the data. We chose this
|
||||
setting so that models can focus on cross-lingual transfer.
|
||||
|
||||
We show the average number of tokens per paragraph, question, and answer for each language in the
|
||||
table below. The statistics were obtained using [Jieba](https://github.com/fxsjy/jieba) for Chinese
|
||||
and the [Moses tokenizer](https://github.com/moses-smt/mosesdecoder/blob/master/scripts/tokenizer/tokenizer.perl)
|
||||
for the other languages.
|
||||
|
||||
| | en | es | de | el | ru | tr | ar | vi | th | zh | hi |
|
||||
| --------- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
|
||||
| Paragraph | 142.4 | 160.7 | 139.5 | 149.6 | 133.9 | 126.5 | 128.2 | 191.2 | 158.7 | 147.6 | 232.4 |
|
||||
| Question | 11.5 | 13.4 | 11.0 | 11.7 | 10.0 | 9.8 | 10.7 | 14.8 | 11.5 | 10.5 | 18.7 |
|
||||
| Answer | 3.1 | 3.6 | 3.0 | 3.3 | 3.1 | 3.1 | 3.1 | 4.5 | 4.1 | 3.5 | 5.6 |
|
||||
|
||||
Citation:
|
||||
|
||||
<details>
|
||||
|
||||
```bibtex
|
||||
@article{Artetxe:etal:2019,
|
||||
author = {Mikel Artetxe and Sebastian Ruder and Dani Yogatama},
|
||||
title = {On the cross-lingual transferability of monolingual representations},
|
||||
journal = {CoRR},
|
||||
volume = {abs/1910.11856},
|
||||
year = {2019},
|
||||
archivePrefix = {arXiv},
|
||||
eprint = {1910.11856}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
I used `Data augmentation techniques` to obtain more samples and splited the dataset in order to have a train and test set. The test set was created in a way that contains the same number of samples for each language. Finally, I got:
|
||||
|
||||
| Dataset | # samples |
|
||||
| ----------- | --------- |
|
||||
| XQUAD train | 50 K |
|
||||
| XQUAD test | 8 K |
|
||||
|
||||
## Model training
|
||||
|
||||
The model was trained on a Tesla P100 GPU and 25GB of RAM.
|
||||
The script for fine tuning can be found [here](https://github.com/huggingface/transformers/blob/master/examples/distillation/run_squad_w_distillation.py)
|
||||
|
||||
## Results:
|
||||
|
||||
| Metric | # Value |
|
||||
| --------- | ----------- |
|
||||
| **Exact** | **93.03** |
|
||||
| **F1** | **94.62** |
|
||||
|
||||
## Comparison:
|
||||
|
||||
| Model | Exact | F1 score |
|
||||
| --------- | ----------- | ------- |
|
||||
| [bert-multi-cased-finetuned-xquadv1](https://huggingface.co/mrm8488/bert-multi-cased-finetuned-xquadv1) | 91.43 | 94.14 |
|
||||
|bert-multi-uncased-finetuned-xquadv1 | **93.03** | **94.62**
|
||||
|
||||
## Model in action
|
||||
|
||||
Fast usage with **pipelines**:
|
||||
|
||||
```python
|
||||
from transformers import pipeline
|
||||
|
||||
qa_pipeline = pipeline(
|
||||
"question-answering",
|
||||
model="mrm8488/bert-multi-uncased-finetuned-xquadv1",
|
||||
tokenizer="bert-multi-uncased-finetuned-xquadv1"
|
||||
)
|
||||
|
||||
|
||||
# context: Coronavirus is seeding panic in the West because it expands so fast.
|
||||
|
||||
# question: Where is seeding panic Coronavirus?
|
||||
qa_pipeline({
|
||||
'context': "कोरोनावायरस पश्चिम में आतंक बो रहा है क्योंकि यह इतनी तेजी से फैलता है।",
|
||||
'question': "कोरोनावायरस घबराहट कहां है?"
|
||||
|
||||
})
|
||||
# output: {'answer': 'पश्चिम', 'end': 18, 'score': 0.7037217439689059, 'start': 12}
|
||||
|
||||
qa_pipeline({
|
||||
'context': "Manuel Romero has been working hardly in the repository hugginface/transformers lately",
|
||||
'question': "Who has been working hard for hugginface/transformers lately?"
|
||||
|
||||
})
|
||||
# output: {'answer': 'Manuel Romero', 'end': 13, 'score': 0.7254485993702389, 'start': 0}
|
||||
|
||||
qa_pipeline({
|
||||
'context': "Manuel Romero a travaillé à peine dans le référentiel hugginface / transformers ces derniers temps",
|
||||
'question': "Pour quel référentiel a travaillé Manuel Romero récemment?"
|
||||
|
||||
})
|
||||
#output: {'answer': 'hugginface / transformers', 'end': 79, 'score': 0.6482061613915384, 'start': 54}
|
||||
```
|
||||

|
||||
|
||||
Try it on a Colab:
|
||||
|
||||
<a href="https://colab.research.google.com/github/mrm8488/shared_colab_notebooks/blob/master/Try_mrm8488_xquad_finetuned_uncased_model.ipynb" target="_parent"><img src="https://camo.githubusercontent.com/52feade06f2fecbf006889a904d221e6a730c194/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667" alt="Open In Colab" data-canonical-src="https://colab.research.google.com/assets/colab-badge.svg"></a>
|
||||
|
||||
|
||||
|
||||
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488)
|
||||
|
||||
> Made with <span style="color: #e25555;">♥</span> in Spain
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
language:
|
||||
- chinese
|
||||
---
|
||||
|
||||
# albert_chinese_base
|
||||
|
||||
This a albert_chinese_base model from [Google's github](https://github.com/google-research/ALBERT)
|
||||
converted by huggingface's [script](https://github.com/huggingface/transformers/blob/master/src/transformers/convert_albert_original_tf_checkpoint_to_pytorch.py)
|
||||
|
||||
## Attention (注意)
|
||||
|
||||
Since sentencepiece is not used in albert_chinese_base model
|
||||
you have to call BertTokenizer instead of AlbertTokenizer !!!
|
||||
we can eval it using an example on MaskedLM
|
||||
|
||||
由於 albert_chinese_base 模型沒有用 sentencepiece
|
||||
用AlbertTokenizer會載不進詞表,因此需要改用BertTokenizer !!!
|
||||
我們可以跑MaskedLM預測來驗證這個做法是否正確
|
||||
|
||||
## Justify (驗證有效性)
|
||||
[colab trial](https://colab.research.google.com/drive/1Wjz48Uws6-VuSHv_-DcWLilv77-AaYgj)
|
||||
```python
|
||||
from transformers import *
|
||||
import torch
|
||||
from torch.nn.functional import softmax
|
||||
|
||||
pretrained = 'voidful/albert_chinese_base'
|
||||
tokenizer = BertTokenizer.from_pretrained(pretrained)
|
||||
model = AlbertForMaskedLM.from_pretrained(pretrained)
|
||||
|
||||
inputtext = "今天[MASK]情很好"
|
||||
|
||||
maskpos = tokenizer.encode(inputtext, add_special_tokens=True).index(103)
|
||||
|
||||
input_ids = torch.tensor(tokenizer.encode(inputtext, add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, masked_lm_labels=input_ids)
|
||||
loss, prediction_scores = outputs[:2]
|
||||
logit_prob = softmax(prediction_scores[0, maskpos]).data.tolist()
|
||||
predicted_index = torch.argmax(prediction_scores[0, maskpos]).item()
|
||||
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
|
||||
print(predicted_token,logit_prob[predicted_index])
|
||||
```
|
||||
Result: `感 0.36333346366882324`
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
language:
|
||||
- chinese
|
||||
---
|
||||
|
||||
# albert_chinese_large
|
||||
|
||||
This a albert_chinese_large model from [Google's github](https://github.com/google-research/ALBERT)
|
||||
converted by huggingface's [script](https://github.com/huggingface/transformers/blob/master/src/transformers/convert_albert_original_tf_checkpoint_to_pytorch.py)
|
||||
|
||||
## Attention (注意)
|
||||
|
||||
Since sentencepiece is not used in albert_chinese_large model
|
||||
you have to call BertTokenizer instead of AlbertTokenizer !!!
|
||||
we can eval it using an example on MaskedLM
|
||||
|
||||
由於 albert_chinese_large 模型沒有用 sentencepiece
|
||||
用AlbertTokenizer會載不進詞表,因此需要改用BertTokenizer !!!
|
||||
我們可以跑MaskedLM預測來驗證這個做法是否正確
|
||||
|
||||
## Justify (驗證有效性)
|
||||
[colab trial](https://colab.research.google.com/drive/1Wjz48Uws6-VuSHv_-DcWLilv77-AaYgj)
|
||||
```python
|
||||
from transformers import *
|
||||
import torch
|
||||
from torch.nn.functional import softmax
|
||||
|
||||
pretrained = 'voidful/albert_chinese_large'
|
||||
tokenizer = BertTokenizer.from_pretrained(pretrained)
|
||||
model = AlbertForMaskedLM.from_pretrained(pretrained)
|
||||
|
||||
inputtext = "今天[MASK]情很好"
|
||||
|
||||
maskpos = tokenizer.encode(inputtext, add_special_tokens=True).index(103)
|
||||
|
||||
input_ids = torch.tensor(tokenizer.encode(inputtext, add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, masked_lm_labels=input_ids)
|
||||
loss, prediction_scores = outputs[:2]
|
||||
logit_prob = softmax(prediction_scores[0, maskpos]).data.tolist()
|
||||
predicted_index = torch.argmax(prediction_scores[0, maskpos]).item()
|
||||
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
|
||||
print(predicted_token,logit_prob[predicted_index])
|
||||
```
|
||||
Result: `心 0.9422469735145569`
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
language:
|
||||
- chinese
|
||||
---
|
||||
|
||||
# albert_chinese_small
|
||||
|
||||
This a albert_chinese_small model from [brightmart/albert_zh project](https://github.com/brightmart/albert_zh), albert_small_google_zh model
|
||||
converted by huggingface's [script](https://github.com/huggingface/transformers/blob/master/src/transformers/convert_albert_original_tf_checkpoint_to_pytorch.py)
|
||||
|
||||
## Attention (注意)
|
||||
|
||||
Since sentencepiece is not used in albert_chinese_small model
|
||||
you have to call BertTokenizer instead of AlbertTokenizer !!!
|
||||
we can eval it using an example on MaskedLM
|
||||
|
||||
由於 albert_chinese_small 模型沒有用 sentencepiece
|
||||
用AlbertTokenizer會載不進詞表,因此需要改用BertTokenizer !!!
|
||||
我們可以跑MaskedLM預測來驗證這個做法是否正確
|
||||
|
||||
## Justify (驗證有效性)
|
||||
[colab trial](https://colab.research.google.com/drive/1Wjz48Uws6-VuSHv_-DcWLilv77-AaYgj)
|
||||
```python
|
||||
from transformers import *
|
||||
import torch
|
||||
from torch.nn.functional import softmax
|
||||
|
||||
pretrained = 'voidful/albert_chinese_small'
|
||||
tokenizer = BertTokenizer.from_pretrained(pretrained)
|
||||
model = AlbertForMaskedLM.from_pretrained(pretrained)
|
||||
|
||||
inputtext = "今天[MASK]情很好"
|
||||
|
||||
maskpos = tokenizer.encode(inputtext, add_special_tokens=True).index(103)
|
||||
|
||||
input_ids = torch.tensor(tokenizer.encode(inputtext, add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, masked_lm_labels=input_ids)
|
||||
loss, prediction_scores = outputs[:2]
|
||||
logit_prob = softmax(prediction_scores[0, maskpos]).data.tolist()
|
||||
predicted_index = torch.argmax(prediction_scores[0, maskpos]).item()
|
||||
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
|
||||
print(predicted_token,logit_prob[predicted_index])
|
||||
```
|
||||
Result: `感 0.6390823125839233`
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
language:
|
||||
- chinese
|
||||
---
|
||||
|
||||
# albert_chinese_tiny
|
||||
|
||||
This a albert_chinese_tiny model from [brightmart/albert_zh project](https://github.com/brightmart/albert_zh), albert_tiny_google_zh model
|
||||
converted by huggingface's [script](https://github.com/huggingface/transformers/blob/master/src/transformers/convert_albert_original_tf_checkpoint_to_pytorch.py)
|
||||
|
||||
## Attention (注意)
|
||||
|
||||
Since sentencepiece is not used in albert_chinese_tiny model
|
||||
you have to call BertTokenizer instead of AlbertTokenizer !!!
|
||||
we can eval it using an example on MaskedLM
|
||||
|
||||
由於 albert_chinese_tiny 模型沒有用 sentencepiece
|
||||
用AlbertTokenizer會載不進詞表,因此需要改用BertTokenizer !!!
|
||||
我們可以跑MaskedLM預測來驗證這個做法是否正確
|
||||
|
||||
## Justify (驗證有效性)
|
||||
[colab trial](https://colab.research.google.com/drive/1Wjz48Uws6-VuSHv_-DcWLilv77-AaYgj)
|
||||
```python
|
||||
from transformers import *
|
||||
import torch
|
||||
from torch.nn.functional import softmax
|
||||
|
||||
pretrained = 'voidful/albert_chinese_tiny'
|
||||
tokenizer = BertTokenizer.from_pretrained(pretrained)
|
||||
model = AlbertForMaskedLM.from_pretrained(pretrained)
|
||||
|
||||
inputtext = "今天[MASK]情很好"
|
||||
|
||||
maskpos = tokenizer.encode(inputtext, add_special_tokens=True).index(103)
|
||||
|
||||
input_ids = torch.tensor(tokenizer.encode(inputtext, add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, masked_lm_labels=input_ids)
|
||||
loss, prediction_scores = outputs[:2]
|
||||
logit_prob = softmax(prediction_scores[0, maskpos]).data.tolist()
|
||||
predicted_index = torch.argmax(prediction_scores[0, maskpos]).item()
|
||||
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
|
||||
print(predicted_token,logit_prob[predicted_index])
|
||||
```
|
||||
Result: `感 0.40312355756759644`
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
language:
|
||||
- chinese
|
||||
---
|
||||
|
||||
# albert_chinese_xlarge
|
||||
|
||||
This a albert_chinese_xlarge model from [Google's github](https://github.com/google-research/ALBERT)
|
||||
converted by huggingface's [script](https://github.com/huggingface/transformers/blob/master/src/transformers/convert_albert_original_tf_checkpoint_to_pytorch.py)
|
||||
|
||||
## Attention (注意)
|
||||
|
||||
Since sentencepiece is not used in albert_chinese_xlarge model
|
||||
you have to call BertTokenizer instead of AlbertTokenizer !!!
|
||||
we can eval it using an example on MaskedLM
|
||||
|
||||
由於 albert_chinese_xlarge 模型沒有用 sentencepiece
|
||||
用AlbertTokenizer會載不進詞表,因此需要改用BertTokenizer !!!
|
||||
我們可以跑MaskedLM預測來驗證這個做法是否正確
|
||||
|
||||
## Justify (驗證有效性)
|
||||
[colab trial](https://colab.research.google.com/drive/1Wjz48Uws6-VuSHv_-DcWLilv77-AaYgj)
|
||||
```python
|
||||
from transformers import *
|
||||
import torch
|
||||
from torch.nn.functional import softmax
|
||||
|
||||
pretrained = 'voidful/albert_chinese_xlarge'
|
||||
tokenizer = BertTokenizer.from_pretrained(pretrained)
|
||||
model = AlbertForMaskedLM.from_pretrained(pretrained)
|
||||
|
||||
inputtext = "今天[MASK]情很好"
|
||||
|
||||
maskpos = tokenizer.encode(inputtext, add_special_tokens=True).index(103)
|
||||
|
||||
input_ids = torch.tensor(tokenizer.encode(inputtext, add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, masked_lm_labels=input_ids)
|
||||
loss, prediction_scores = outputs[:2]
|
||||
logit_prob = softmax(prediction_scores[0, maskpos]).data.tolist()
|
||||
predicted_index = torch.argmax(prediction_scores[0, maskpos]).item()
|
||||
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
|
||||
print(predicted_token,logit_prob[predicted_index])
|
||||
```
|
||||
Result: `心 0.9942440390586853`
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
language:
|
||||
- chinese
|
||||
---
|
||||
|
||||
# albert_chinese_xxlarge
|
||||
|
||||
This a albert_chinese_xxlarge model from [Google's github](https://github.com/google-research/ALBERT)
|
||||
converted by huggingface's [script](https://github.com/huggingface/transformers/blob/master/src/transformers/convert_albert_original_tf_checkpoint_to_pytorch.py)
|
||||
|
||||
## Attention (注意)
|
||||
|
||||
Since sentencepiece is not used in albert_chinese_xxlarge model
|
||||
you have to call BertTokenizer instead of AlbertTokenizer !!!
|
||||
we can eval it using an example on MaskedLM
|
||||
|
||||
由於 albert_chinese_xxlarge 模型沒有用 sentencepiece
|
||||
用AlbertTokenizer會載不進詞表,因此需要改用BertTokenizer !!!
|
||||
我們可以跑MaskedLM預測來驗證這個做法是否正確
|
||||
|
||||
## Justify (驗證有效性)
|
||||
[colab trial](https://colab.research.google.com/drive/1Wjz48Uws6-VuSHv_-DcWLilv77-AaYgj)
|
||||
```python
|
||||
from transformers import *
|
||||
import torch
|
||||
from torch.nn.functional import softmax
|
||||
|
||||
pretrained = 'voidful/albert_chinese_xxlarge'
|
||||
tokenizer = BertTokenizer.from_pretrained(pretrained)
|
||||
model = AlbertForMaskedLM.from_pretrained(pretrained)
|
||||
|
||||
inputtext = "今天[MASK]情很好"
|
||||
|
||||
maskpos = tokenizer.encode(inputtext, add_special_tokens=True).index(103)
|
||||
|
||||
input_ids = torch.tensor(tokenizer.encode(inputtext, add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, masked_lm_labels=input_ids)
|
||||
loss, prediction_scores = outputs[:2]
|
||||
logit_prob = softmax(prediction_scores[0, maskpos]).data.tolist()
|
||||
predicted_index = torch.argmax(prediction_scores[0, maskpos]).item()
|
||||
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
|
||||
print(predicted_token,logit_prob[predicted_index])
|
||||
```
|
||||
Result: `心 0.995713472366333`
|
||||
@@ -238,7 +238,7 @@
|
||||
"Tokens: ['This', 'is', 'an', 'input', 'example']\n",
|
||||
"Tokens id: [1188, 1110, 1126, 7758, 1859]\n",
|
||||
"Tokens PyTorch: tensor([[ 101, 1188, 1110, 1126, 7758, 1859, 102]])\n",
|
||||
"Tokenw ise output: torch.Size([1, 7, 768]), Pooled output: torch.Size([1, 768])\n"
|
||||
"Token wise output: torch.Size([1, 7, 768]), Pooled output: torch.Size([1, 768])\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -261,7 +261,7 @@
|
||||
"\n",
|
||||
"# Now we're ready to go through BERT with out input\n",
|
||||
"outputs, pooled = model(tokens_pt)\n",
|
||||
"print(\"Tokenw ise output: {}, Pooled output: {}\".format(outputs.shape, pooled.shape))"
|
||||
"print(\"Token wise output: {}, Pooled output: {}\".format(outputs.shape, pooled.shape))"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -70,6 +70,7 @@ class PretrainedConfig(object):
|
||||
# Parameters for sequence generation
|
||||
self.max_length = kwargs.pop("max_length", 20)
|
||||
self.do_sample = kwargs.pop("do_sample", False)
|
||||
self.early_stopping = kwargs.pop("early_stopping", False)
|
||||
self.num_beams = kwargs.pop("num_beams", 1)
|
||||
self.temperature = kwargs.pop("temperature", 1.0)
|
||||
self.top_k = kwargs.pop("top_k", 50)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import io
|
||||
import os
|
||||
from os.path import expanduser
|
||||
from typing import List
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
@@ -27,6 +27,10 @@ ENDPOINT = "https://huggingface.co"
|
||||
|
||||
|
||||
class S3Obj:
|
||||
"""
|
||||
Data structure that represents a file belonging to the current user.
|
||||
"""
|
||||
|
||||
def __init__(self, filename: str, LastModified: str, ETag: str, Size: int, **kwargs):
|
||||
self.filename = filename
|
||||
self.LastModified = LastModified
|
||||
@@ -41,6 +45,50 @@ class PresignedUrl:
|
||||
self.type = type # mime-type to send to S3.
|
||||
|
||||
|
||||
class S3Object:
|
||||
"""
|
||||
Data structure that represents a public file accessible on our S3.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
key: str, # S3 object key
|
||||
etag: str,
|
||||
lastModified: str,
|
||||
size: int,
|
||||
rfilename: str, # filename relative to config.json
|
||||
**kwargs
|
||||
):
|
||||
self.key = key
|
||||
self.etag = etag
|
||||
self.lastModified = lastModified
|
||||
self.size = size
|
||||
self.rfilename = rfilename
|
||||
|
||||
|
||||
class ModelInfo:
|
||||
"""
|
||||
Info about a public model accessible from our S3.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
modelId: str, # id of model
|
||||
key: str, # S3 object key of config.json
|
||||
author: Optional[str] = None,
|
||||
downloads: Optional[int] = None,
|
||||
tags: List[str] = [],
|
||||
siblings: List[Dict] = [], # list of files that constitute the model
|
||||
**kwargs
|
||||
):
|
||||
self.modelId = modelId
|
||||
self.key = key
|
||||
self.author = author
|
||||
self.downloads = downloads
|
||||
self.tags = tags
|
||||
self.siblings = [S3Object(**x) for x in siblings]
|
||||
|
||||
|
||||
class HfApi:
|
||||
def __init__(self, endpoint=None):
|
||||
self.endpoint = endpoint if endpoint is not None else ENDPOINT
|
||||
@@ -129,6 +177,16 @@ class HfApi:
|
||||
r = requests.delete(path, headers={"authorization": "Bearer {}".format(token)}, json={"filename": filename})
|
||||
r.raise_for_status()
|
||||
|
||||
def model_list(self) -> List[ModelInfo]:
|
||||
"""
|
||||
Get the public list of all the models on huggingface, including the community models
|
||||
"""
|
||||
path = "{}/api/models".format(self.endpoint)
|
||||
r = requests.get(path)
|
||||
r.raise_for_status()
|
||||
d = r.json()
|
||||
return [ModelInfo(**x) for x in d]
|
||||
|
||||
|
||||
class TqdmProgressFileReader:
|
||||
"""
|
||||
|
||||
@@ -78,7 +78,7 @@ from .modeling_distilbert import (
|
||||
)
|
||||
from .modeling_flaubert import (
|
||||
FLAUBERT_PRETRAINED_MODEL_ARCHIVE_MAP,
|
||||
FlaubertForQuestionAnswering,
|
||||
FlaubertForQuestionAnsweringSimple,
|
||||
FlaubertForSequenceClassification,
|
||||
FlaubertModel,
|
||||
FlaubertWithLMHeadModel,
|
||||
@@ -97,7 +97,7 @@ from .modeling_t5 import T5_PRETRAINED_MODEL_ARCHIVE_MAP, T5Model, T5WithLMHeadM
|
||||
from .modeling_transfo_xl import TRANSFO_XL_PRETRAINED_MODEL_ARCHIVE_MAP, TransfoXLLMHeadModel, TransfoXLModel
|
||||
from .modeling_xlm import (
|
||||
XLM_PRETRAINED_MODEL_ARCHIVE_MAP,
|
||||
XLMForQuestionAnswering,
|
||||
XLMForQuestionAnsweringSimple,
|
||||
XLMForSequenceClassification,
|
||||
XLMModel,
|
||||
XLMWithLMHeadModel,
|
||||
@@ -111,7 +111,7 @@ from .modeling_xlm_roberta import (
|
||||
)
|
||||
from .modeling_xlnet import (
|
||||
XLNET_PRETRAINED_MODEL_ARCHIVE_MAP,
|
||||
XLNetForQuestionAnswering,
|
||||
XLNetForQuestionAnsweringSimple,
|
||||
XLNetForSequenceClassification,
|
||||
XLNetForTokenClassification,
|
||||
XLNetLMHeadModel,
|
||||
@@ -225,9 +225,9 @@ MODEL_FOR_QUESTION_ANSWERING_MAPPING = OrderedDict(
|
||||
(AlbertConfig, AlbertForQuestionAnswering),
|
||||
(RobertaConfig, RobertaForQuestionAnswering),
|
||||
(BertConfig, BertForQuestionAnswering),
|
||||
(XLNetConfig, XLNetForQuestionAnswering),
|
||||
(FlaubertConfig, FlaubertForQuestionAnswering),
|
||||
(XLMConfig, XLMForQuestionAnswering),
|
||||
(XLNetConfig, XLNetForQuestionAnsweringSimple),
|
||||
(FlaubertConfig, FlaubertForQuestionAnsweringSimple),
|
||||
(XLMConfig, XLMForQuestionAnsweringSimple),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ BART_INPUTS_DOCSTRING = r"""
|
||||
If you want to change padding behavior, you should read :func:`~transformers.modeling_bart._prepare_decoder_inputs` and modify.
|
||||
See diagram 1 in the paper for more info on the default strategy
|
||||
"""
|
||||
LARGE_NEGATIVE = -1e4
|
||||
LARGE_NEGATIVE = -1e8
|
||||
|
||||
|
||||
def _prepare_bart_decoder_inputs(
|
||||
@@ -144,18 +144,18 @@ def _check_shapes(shape_1, shape2):
|
||||
raise AssertionError("shape mismatch: {} != {}".format(shape_1, shape2))
|
||||
|
||||
|
||||
def _combine_masks(key_padding_mask, attn_mask, targ_size):
|
||||
def _combine_masks(key_padding_mask, causal_lm_mask, targ_size):
|
||||
# targ_size = (bsz, tgt_len, src_len)
|
||||
a = torch.zeros(targ_size)
|
||||
b = torch.zeros(targ_size)
|
||||
if key_padding_mask is not None: # (bsz, tgt_len) -> targ_size
|
||||
_check_shapes(key_padding_mask.shape, targ_size[:2])
|
||||
reshaped = key_padding_mask.unsqueeze(2).expand(*targ_size)
|
||||
a[reshaped] = 1e-8
|
||||
a[reshaped] = LARGE_NEGATIVE
|
||||
|
||||
if attn_mask is not None: # (tgt_len, src_len) -> targ_size
|
||||
_check_shapes(attn_mask.shape, targ_size[-2:])
|
||||
b = attn_mask.unsqueeze(0).expand(*targ_size)
|
||||
if causal_lm_mask is not None: # (tgt_len, src_len) -> targ_size
|
||||
_check_shapes(causal_lm_mask.shape, targ_size[-2:])
|
||||
b = causal_lm_mask.unsqueeze(0).expand(*targ_size)
|
||||
return (a + b).unsqueeze(1).clamp(LARGE_NEGATIVE,)
|
||||
|
||||
|
||||
@@ -271,6 +271,12 @@ class BartEncoder(nn.Module):
|
||||
- **all_attentions** (List[Tensor]): Attention weights for each layer.
|
||||
During training might not be of length n_layers because of layer dropout.
|
||||
"""
|
||||
# check attention mask and invert
|
||||
if attention_mask is not None:
|
||||
assert attention_mask.dim() == 2
|
||||
|
||||
attention_mask = (1.0 - attention_mask.long()) * -10000.0
|
||||
assert attention_mask.max() <= 0
|
||||
inputs_embeds = self.embed_tokens(input_ids)
|
||||
embed_pos = self.embed_positions(input_ids)
|
||||
x = inputs_embeds + embed_pos
|
||||
@@ -448,6 +454,13 @@ class BartDecoder(nn.Module):
|
||||
- hidden states
|
||||
- attentions
|
||||
"""
|
||||
# check attention mask and invert
|
||||
if encoder_padding_mask is not None:
|
||||
assert encoder_padding_mask.dim() == 2
|
||||
|
||||
encoder_padding_mask = (1.0 - encoder_padding_mask.long()) * -10000.0
|
||||
assert encoder_padding_mask.max() <= 0
|
||||
|
||||
# embed positions
|
||||
positions = self.embed_positions(input_ids, generation_mode=self.generation_mode)
|
||||
|
||||
@@ -808,11 +821,6 @@ class BartModel(PretrainedBartModel):
|
||||
decoder_attention_mask=None,
|
||||
decoder_cached_states=None,
|
||||
):
|
||||
if attention_mask is not None:
|
||||
assert attention_mask.dim() == 2
|
||||
|
||||
attention_mask = (1.0 - attention_mask.long()) * -10000.0
|
||||
assert attention_mask.max() <= 0
|
||||
|
||||
# make masks if user doesn't supply
|
||||
if not self.decoder.generation_mode:
|
||||
@@ -905,7 +913,7 @@ class BartForConditionalGeneration(PretrainedBartModel):
|
||||
|
||||
# Mask filling only works for bart-large
|
||||
from transformers import BartTokenizer, BartForConditionalGeneration
|
||||
tokenizer = AutoTokenizer.from_pretrained('bart-large')
|
||||
tokenizer = BartTokenizer.from_pretrained('bart-large')
|
||||
TXT = "My friends are <mask> but they eat too many carbs."
|
||||
model = BartForConditionalGeneration.from_pretrained('bart-large')
|
||||
input_ids = tokenizer.batch_encode_plus([TXT], return_tensors='pt')['input_ids']
|
||||
@@ -1023,8 +1031,7 @@ class BartForConditionalGeneration(PretrainedBartModel):
|
||||
Examples::
|
||||
from transformers import BartTokenizer, BartForConditionalGeneration, BartConfig
|
||||
# see ``examples/summarization/bart/evaluate_cnn.py`` for a longer example
|
||||
config = BartConfig(vocab_size=50264, output_past=True) # no mask_token_id
|
||||
model = BartForConditionalGeneration.from_pretrained('bart-large-cnn', config=config)
|
||||
model = BartForConditionalGeneration.from_pretrained('bart-large-cnn')
|
||||
tokenizer = BartTokenizer.from_pretrained('bart-large-cnn')
|
||||
ARTICLE_TO_SUMMARIZE = "My friends are cool but they eat too many carbs."
|
||||
inputs = tokenizer.batch_encode_plus([ARTICLE_TO_SUMMARIZE], max_length=1024, return_tensors='pt')
|
||||
|
||||
@@ -23,7 +23,7 @@ import tensorflow as tf
|
||||
from .configuration_albert import AlbertConfig
|
||||
from .file_utils import add_start_docstrings, add_start_docstrings_to_callable
|
||||
from .modeling_tf_bert import ACT2FN, TFBertSelfAttention
|
||||
from .modeling_tf_utils import TFPreTrainedModel, get_initializer, shape_list
|
||||
from .modeling_tf_utils import TFPreTrainedModel, get_initializer, keras_serializable, shape_list
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -478,7 +478,10 @@ class TFAlbertMLMHead(tf.keras.layers.Layer):
|
||||
return hidden_states
|
||||
|
||||
|
||||
@keras_serializable
|
||||
class TFAlbertMainLayer(tf.keras.layers.Layer):
|
||||
config_class = AlbertConfig
|
||||
|
||||
def __init__(self, config, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.num_hidden_layers = config.num_hidden_layers
|
||||
|
||||
@@ -23,7 +23,7 @@ import tensorflow as tf
|
||||
|
||||
from .configuration_bert import BertConfig
|
||||
from .file_utils import MULTIPLE_CHOICE_DUMMY_INPUTS, add_start_docstrings, add_start_docstrings_to_callable
|
||||
from .modeling_tf_utils import TFPreTrainedModel, get_initializer, shape_list
|
||||
from .modeling_tf_utils import TFPreTrainedModel, get_initializer, keras_serializable, shape_list
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -471,7 +471,10 @@ class TFBertNSPHead(tf.keras.layers.Layer):
|
||||
return seq_relationship_score
|
||||
|
||||
|
||||
@keras_serializable
|
||||
class TFBertMainLayer(tf.keras.layers.Layer):
|
||||
config_class = BertConfig
|
||||
|
||||
def __init__(self, config, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.num_hidden_layers = config.num_hidden_layers
|
||||
|
||||
@@ -23,7 +23,7 @@ import tensorflow as tf
|
||||
|
||||
from .configuration_ctrl import CTRLConfig
|
||||
from .file_utils import add_start_docstrings, add_start_docstrings_to_callable
|
||||
from .modeling_tf_utils import TFPreTrainedModel, TFSharedEmbeddings, shape_list
|
||||
from .modeling_tf_utils import TFPreTrainedModel, TFSharedEmbeddings, keras_serializable, shape_list
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -164,7 +164,10 @@ class TFEncoderLayer(tf.keras.layers.Layer):
|
||||
return outputs
|
||||
|
||||
|
||||
@keras_serializable
|
||||
class TFCTRLMainLayer(tf.keras.layers.Layer):
|
||||
config_class = CTRLConfig
|
||||
|
||||
def __init__(self, config, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.output_hidden_states = config.output_hidden_states
|
||||
|
||||
@@ -29,6 +29,7 @@ from .modeling_tf_utils import (
|
||||
TFSequenceSummary,
|
||||
TFSharedEmbeddings,
|
||||
get_initializer,
|
||||
keras_serializable,
|
||||
shape_list,
|
||||
)
|
||||
|
||||
@@ -196,7 +197,10 @@ class TFBlock(tf.keras.layers.Layer):
|
||||
return outputs # x, present, (attentions)
|
||||
|
||||
|
||||
@keras_serializable
|
||||
class TFGPT2MainLayer(tf.keras.layers.Layer):
|
||||
config_class = GPT2Config
|
||||
|
||||
def __init__(self, config, *inputs, **kwargs):
|
||||
super().__init__(*inputs, **kwargs)
|
||||
self.output_hidden_states = config.output_hidden_states
|
||||
|
||||
@@ -24,7 +24,7 @@ import tensorflow as tf
|
||||
from .configuration_transfo_xl import TransfoXLConfig
|
||||
from .file_utils import add_start_docstrings, add_start_docstrings_to_callable
|
||||
from .modeling_tf_transfo_xl_utilities import TFAdaptiveSoftmaxMask
|
||||
from .modeling_tf_utils import TFPreTrainedModel, get_initializer, shape_list
|
||||
from .modeling_tf_utils import TFPreTrainedModel, get_initializer, keras_serializable, shape_list
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -378,7 +378,10 @@ class TFAdaptiveEmbedding(tf.keras.layers.Layer):
|
||||
return embed
|
||||
|
||||
|
||||
@keras_serializable
|
||||
class TFTransfoXLMainLayer(tf.keras.layers.Layer):
|
||||
config_class = TransfoXLConfig
|
||||
|
||||
def __init__(self, config, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.output_attentions = config.output_attentions
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""TF general model utils."""
|
||||
|
||||
|
||||
import functools
|
||||
import logging
|
||||
import os
|
||||
|
||||
@@ -47,6 +46,64 @@ class TFModelUtilsMixin:
|
||||
return self.count_params()
|
||||
|
||||
|
||||
def keras_serializable(cls):
|
||||
"""
|
||||
Decorate a Keras Layer class to support Keras serialization.
|
||||
|
||||
This is done by:
|
||||
1. adding a `transformers_config` dict to the Keras config dictionary in `get_config` (called by Keras at
|
||||
serialization time
|
||||
2. wrapping `__init__` to accept that `transformers_config` dict (passed by Keras at deserialization time) and
|
||||
convert it to a config object for the actual layer initializer
|
||||
3. registering the class as a custom object in Keras (if the Tensorflow version supports this), so that it does
|
||||
not need to be supplied in `custom_objects` in the call to `tf.keras.models.load_model`
|
||||
|
||||
:param cls: a tf.keras.layers.Layers subclass that accepts a `config` argument to its initializer (typically a
|
||||
`TF*MainLayer` class in this project)
|
||||
:return: the same class object, with modifications for Keras deserialization.
|
||||
"""
|
||||
initializer = cls.__init__
|
||||
|
||||
config_class = getattr(cls, "config_class", None)
|
||||
if config_class is None:
|
||||
raise AttributeError("Must set `config_class` to use @keras_serializable")
|
||||
|
||||
@functools.wraps(initializer)
|
||||
def wrapped_init(self, *args, **kwargs):
|
||||
transformers_config = kwargs.pop("transformers_config", None)
|
||||
config = args[0] if args and isinstance(args[0], PretrainedConfig) else kwargs.get("config", None)
|
||||
if config is not None and transformers_config is not None:
|
||||
raise ValueError("Must pass either `config` or `transformers_config`, not both")
|
||||
elif config is not None:
|
||||
# normal layer construction, call with unchanged args (config is already in there)
|
||||
initializer(self, *args, **kwargs)
|
||||
elif transformers_config is not None:
|
||||
# Keras deserialization, convert dict to config
|
||||
config = config_class.from_dict(transformers_config)
|
||||
initializer(self, config, *args, **kwargs)
|
||||
else:
|
||||
raise ValueError("Must pass either `config` (PretrainedConfig) or `transformers_config` (dict)")
|
||||
self._transformers_config = config
|
||||
|
||||
cls.__init__ = wrapped_init
|
||||
|
||||
if not hasattr(cls, "get_config"):
|
||||
raise TypeError("Only use @keras_serializable on tf.keras.layers.Layer subclasses")
|
||||
if hasattr(cls.get_config, "_is_default"):
|
||||
|
||||
def get_config(self):
|
||||
cfg = super(cls, self).get_config()
|
||||
cfg["transformers_config"] = self._transformers_config.to_dict()
|
||||
return cfg
|
||||
|
||||
cls.get_config = get_config
|
||||
|
||||
cls._keras_serializable = True
|
||||
if hasattr(tf.keras.utils, "register_keras_serializable"):
|
||||
cls = tf.keras.utils.register_keras_serializable()(cls)
|
||||
return cls
|
||||
|
||||
|
||||
class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
r""" Base class for all TF models.
|
||||
|
||||
@@ -403,6 +460,7 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
input_ids=None,
|
||||
max_length=None,
|
||||
do_sample=True,
|
||||
early_stopping=False,
|
||||
num_beams=None,
|
||||
temperature=None,
|
||||
top_k=None,
|
||||
@@ -502,11 +560,12 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
if self.get_output_embeddings() is None:
|
||||
raise AttributeError(
|
||||
"You tried to generate sequences with a model that does not have a LM Head."
|
||||
"Please use another model class (e.g. `OpenAIGPTLMHeadModel`, `XLNetLMHeadModel`, `GPT2LMHeadModel`, `CTRLLMHeadModel`, `T5WithLMHeadModel`, `TransfoXLLMHeadModel`)"
|
||||
"Please use another model class (e.g. `TFOpenAIGPTLMHeadModel`, `TFXLNetLMHeadModel`, `TFGPT2LMHeadModel`, `TFCTRLLMHeadModel`, `TFT5WithLMHeadModel`, `TFTransfoXLLMHeadModel`)"
|
||||
)
|
||||
|
||||
max_length = max_length if max_length is not None else self.config.max_length
|
||||
do_sample = do_sample if do_sample is not None else self.config.do_sample
|
||||
early_stopping = early_stopping if early_stopping is not None else self.config.early_stopping
|
||||
num_beams = num_beams if num_beams is not None else self.config.num_beams
|
||||
temperature = temperature if temperature is not None else self.config.temperature
|
||||
top_k = top_k if top_k is not None else self.config.top_k
|
||||
@@ -529,6 +588,7 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
|
||||
assert isinstance(max_length, int) and max_length > 0, "`max_length` should be a strictely positive integer."
|
||||
assert isinstance(do_sample, bool), "`do_sample` should be a boolean."
|
||||
assert isinstance(early_stopping, bool), "`early_stopping` should be a boolean."
|
||||
assert isinstance(num_beams, int) and num_beams > 0, "`num_beams` should be a strictely positive integer."
|
||||
assert temperature > 0, "`temperature` should be strictely positive."
|
||||
assert isinstance(top_k, int) and top_k >= 0, "`top_k` should be a positive integer."
|
||||
@@ -557,6 +617,7 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
else:
|
||||
assert len(shape_list(input_ids)) == 2, "Input prompt should be of shape (batch_size, sequence length)."
|
||||
|
||||
# not allow to duplicate outputs when greedy decoding
|
||||
if do_sample is False:
|
||||
if num_beams == 1:
|
||||
# no_beam_search greedy generation conditions
|
||||
@@ -580,13 +641,23 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
cur_len = shape_list(input_ids)[1]
|
||||
vocab_size = self.config.vocab_size
|
||||
|
||||
if num_return_sequences != 1 and do_sample:
|
||||
# Expand input to num return sequences
|
||||
input_ids = tf.broadcast_to(tf.expand_dims(input_ids, 1), (batch_size, num_return_sequences, cur_len))
|
||||
# set effective batch size and effective batch multiplier according to do_sample
|
||||
if do_sample:
|
||||
effective_batch_size = batch_size * num_return_sequences
|
||||
input_ids = tf.reshape(input_ids, (effective_batch_size, cur_len))
|
||||
effective_batch_mult = num_return_sequences
|
||||
else:
|
||||
effective_batch_size = batch_size
|
||||
effective_batch_mult = 1
|
||||
|
||||
# Expand input ids if num_beams > 1 or num_return_sequences > 1
|
||||
if num_return_sequences > 1 or num_beams > 1:
|
||||
input_ids_len = shape_list(input_ids)[-1]
|
||||
input_ids = tf.broadcast_to(
|
||||
tf.expand_dims(input_ids, 1), (batch_size, effective_batch_mult * num_beams, input_ids_len)
|
||||
)
|
||||
input_ids = tf.reshape(
|
||||
input_ids, (effective_batch_size * num_beams, input_ids_len)
|
||||
) # shape: (batch_size * num_return_sequences * num_beams, cur_len)
|
||||
|
||||
if num_beams > 1:
|
||||
output = self._generate_beam_search(
|
||||
@@ -594,6 +665,7 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
cur_len,
|
||||
max_length,
|
||||
do_sample,
|
||||
early_stopping,
|
||||
temperature,
|
||||
top_k,
|
||||
top_p,
|
||||
@@ -701,12 +773,12 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
# unfinished_sents is set to zero if eos in sentence
|
||||
unfinished_sents -= is_sents_unfinished_and_token_to_add_is_eos
|
||||
|
||||
cur_len = cur_len + 1
|
||||
|
||||
# stop when there is a </s> in each sentence, or if we exceed the maximul length
|
||||
if tf.math.reduce_max(unfinished_sents) == 0:
|
||||
break
|
||||
|
||||
cur_len = cur_len + 1
|
||||
|
||||
# if there are different sentences lengths in the batch, some batches have to be padded
|
||||
min_sent_length = tf.math.reduce_min(sent_lengths)
|
||||
max_sent_length = tf.math.reduce_max(sent_lengths)
|
||||
@@ -735,6 +807,7 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
cur_len,
|
||||
max_length,
|
||||
do_sample,
|
||||
early_stopping,
|
||||
temperature,
|
||||
top_k,
|
||||
top_p,
|
||||
@@ -750,13 +823,10 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
""" Generate sequences for each example with beam search.
|
||||
"""
|
||||
|
||||
# Expand input to num beams
|
||||
input_ids = tf.broadcast_to(tf.expand_dims(input_ids, 1), (batch_size, num_beams, cur_len))
|
||||
input_ids = tf.reshape(input_ids, (batch_size * num_beams, cur_len)) # (batch_size * num_beams, cur_len)
|
||||
|
||||
# generated hypotheses
|
||||
generated_hyps = [
|
||||
BeamHypotheses(num_beams, max_length, length_penalty, early_stopping=False) for _ in range(batch_size)
|
||||
BeamHypotheses(num_beams, max_length, length_penalty, early_stopping=early_stopping)
|
||||
for _ in range(batch_size)
|
||||
]
|
||||
|
||||
# scores for each sentence in the beam
|
||||
@@ -768,7 +838,6 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
beam_scores = tf.zeros((batch_size, num_beams), dtype=tf.float32)
|
||||
|
||||
beam_scores = tf.reshape(beam_scores, (batch_size * num_beams,))
|
||||
|
||||
# cache compute states
|
||||
past = None
|
||||
|
||||
@@ -813,6 +882,11 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
) # (batch_size, 2 * num_beams)
|
||||
# Compute next scores
|
||||
next_scores = tf.gather(_scores, next_tokens, batch_dims=1) # (batch_size, 2 * num_beams)
|
||||
|
||||
# sort the sampled vector to make sure that the first num_beams samples are the best
|
||||
next_scores_indices = tf.argsort(next_scores, direction="DESCENDING", axis=1)
|
||||
next_scores = tf.gather(next_scores, next_scores_indices, batch_dims=1) # (batch_size, num_beams * 2)
|
||||
next_tokens = tf.gather(next_tokens, next_scores_indices, batch_dims=1) # (batch_size, num_beams * 2)
|
||||
else:
|
||||
# do greedy beam search
|
||||
scores = tf.nn.log_softmax(next_token_logits, axis=-1) # (batch_size * num_beams, vocab_size)
|
||||
@@ -826,6 +900,7 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
next_scores = tf.reshape(
|
||||
next_scores, (batch_size, num_beams * vocab_size)
|
||||
) # (batch_size, num_beams * vocab_size)
|
||||
|
||||
next_scores, next_tokens = tf.math.top_k(next_scores, 2 * num_beams, sorted=True)
|
||||
|
||||
assert shape_list(next_scores) == shape_list(next_tokens) == [batch_size, 2 * num_beams]
|
||||
@@ -861,14 +936,13 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
beam_id = idx // vocab_size
|
||||
token_id = idx % vocab_size
|
||||
|
||||
effective_beam_id = batch_idx * num_beams + beam_id
|
||||
# add to generated hypotheses if end of sentence or last iteration
|
||||
if eos_token_ids is not None and token_id.numpy() in eos_token_ids:
|
||||
generated_hyps[batch_idx].add(
|
||||
tf.identity(input_ids[batch_idx * num_beams + beam_id, :cur_len]), score.numpy()
|
||||
)
|
||||
generated_hyps[batch_idx].add(tf.identity(input_ids[effective_beam_id]), score.numpy())
|
||||
else:
|
||||
# add next predicted token if it is not eos_token
|
||||
next_sent_beam.append((score, token_id, batch_idx * num_beams + beam_id))
|
||||
next_sent_beam.append((score, token_id, effective_beam_id))
|
||||
|
||||
# the beam for next step is full
|
||||
if len(next_sent_beam) == num_beams:
|
||||
@@ -893,24 +967,34 @@ class TFPreTrainedModel(tf.keras.Model, TFModelUtilsMixin):
|
||||
if past:
|
||||
past = self._reorder_cache(past, beam_idx)
|
||||
|
||||
# update current length
|
||||
cur_len = cur_len + 1
|
||||
|
||||
# stop when we are done with each sentence
|
||||
if all(done):
|
||||
break
|
||||
|
||||
# update current length
|
||||
cur_len = cur_len + 1
|
||||
|
||||
# finalize all open beam hypotheses and end to generated hypotheses
|
||||
for batch_idx in range(batch_size):
|
||||
# Add all open beam hypothesis to generated_hyps
|
||||
if not done[batch_idx]:
|
||||
for idx, score in zip(next_tokens[batch_idx], next_scores[batch_idx]):
|
||||
if done[batch_idx]:
|
||||
continue
|
||||
# test that beam scores match previously calculated scores if not eos and batch_idx not done
|
||||
if eos_token_ids is not None and all(
|
||||
(token_id % vocab_size).numpy().item() not in eos_token_ids for token_id in next_tokens[batch_idx]
|
||||
):
|
||||
assert tf.reduce_all(
|
||||
next_scores[batch_idx, :num_beams] == tf.reshape(beam_scores, (batch_size, num_beams))[batch_idx]
|
||||
), "If batch_idx is not done, final next scores: {} have to equal to accumulated beam_scores: {}".format(
|
||||
next_scores[:, :num_beams][batch_idx], tf.reshape(beam_scores, (batch_size, num_beams))[batch_idx]
|
||||
)
|
||||
|
||||
# get beam and token IDs
|
||||
beam_id = idx // vocab_size
|
||||
token_id = idx % vocab_size
|
||||
generated_hyps[batch_idx].add(
|
||||
tf.identity(input_ids[batch_idx * num_beams + beam_id, :cur_len]), score.numpy()
|
||||
)
|
||||
# need to add best num_beams hypotheses to generated hyps
|
||||
for beam_id in range(num_beams):
|
||||
effective_beam_id = batch_idx * num_beams + beam_id
|
||||
final_score = beam_scores[effective_beam_id].numpy().item()
|
||||
final_tokens = input_ids[effective_beam_id]
|
||||
generated_hyps[batch_idx].add(final_tokens, final_score)
|
||||
|
||||
# depending on whether greedy generation is wanted or not define different output_batch_size and output_num_return_sequences_per_batch
|
||||
output_batch_size = batch_size if do_sample else batch_size * num_return_sequences
|
||||
@@ -980,10 +1064,11 @@ def _create_next_token_logits_penalties(input_ids, logits, repetition_penalty):
|
||||
prev_input_ids = [np.unique(input_id) for input_id in input_ids.numpy()]
|
||||
for i, prev_input_id in enumerate(prev_input_ids):
|
||||
logit_penalized = logits[i].numpy()[prev_input_id]
|
||||
logit_penalties = np.zeros(logit_penalized.shape)
|
||||
# if previous logit score is < 0 then multiply repetition penalty else divide
|
||||
logit_penalized[logit_penalized < 0] = repetition_penalty
|
||||
logit_penalized[logit_penalized > 0] = 1 / repetition_penalty
|
||||
np.put(token_penalties[i], prev_input_id, logit_penalized)
|
||||
logit_penalties[logit_penalized < 0] = repetition_penalty
|
||||
logit_penalties[logit_penalized > 0] = 1 / repetition_penalty
|
||||
np.put(token_penalties[i], prev_input_id, logit_penalties)
|
||||
return tf.convert_to_tensor(token_penalties, dtype=tf.float32)
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,14 @@ import tensorflow as tf
|
||||
|
||||
from .configuration_xlnet import XLNetConfig
|
||||
from .file_utils import add_start_docstrings, add_start_docstrings_to_callable
|
||||
from .modeling_tf_utils import TFPreTrainedModel, TFSequenceSummary, TFSharedEmbeddings, get_initializer, shape_list
|
||||
from .modeling_tf_utils import (
|
||||
TFPreTrainedModel,
|
||||
TFSequenceSummary,
|
||||
TFSharedEmbeddings,
|
||||
get_initializer,
|
||||
keras_serializable,
|
||||
shape_list,
|
||||
)
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -342,7 +349,10 @@ class TFXLNetLMHead(tf.keras.layers.Layer):
|
||||
return hidden_states
|
||||
|
||||
|
||||
@keras_serializable
|
||||
class TFXLNetMainLayer(tf.keras.layers.Layer):
|
||||
config_class = XLNetConfig
|
||||
|
||||
def __init__(self, config, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.output_attentions = config.output_attentions
|
||||
|
||||
+34
-105
@@ -296,19 +296,13 @@ class Pipeline(_ScikitCompat):
|
||||
pickle format.
|
||||
|
||||
Arguments:
|
||||
model (:obj:`str` or :obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`, `optional`, defaults to :obj:`None`):
|
||||
The model that will be used by the pipeline to make predictions. This can be :obj:`None`, a string
|
||||
checkpoint identifier or an actual pre-trained model inheriting from
|
||||
model (:obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`):
|
||||
The model that will be used by the pipeline to make predictions. This needs to be a model inheriting from
|
||||
:class:`~transformers.PreTrainedModel` for PyTorch and :class:`~transformers.TFPreTrainedModel` for
|
||||
TensorFlow.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
tokenizer (:obj:`str` or :obj:`~transformers.PreTrainedTokenizer`, `optional`, defaults to :obj:`None`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This can be :obj:`None`,
|
||||
a string checkpoint identifier or an actual pre-trained tokenizer inheriting from
|
||||
tokenizer (:obj:`~transformers.PreTrainedTokenizer`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This object inherits from
|
||||
:class:`~transformers.PreTrainedTokenizer`.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
modelcard (:obj:`str` or :class:`~transformers.ModelCard`, `optional`, defaults to :obj:`None`):
|
||||
Model card attributed to the model for this pipeline.
|
||||
framework (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
@@ -334,12 +328,11 @@ class Pipeline(_ScikitCompat):
|
||||
"""
|
||||
|
||||
default_input_names = None
|
||||
task = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: Optional = None,
|
||||
tokenizer: PreTrainedTokenizer = None,
|
||||
model: Union["PreTrainedModel", "TFPreTrainedModel"],
|
||||
tokenizer: PreTrainedTokenizer,
|
||||
modelcard: Optional[ModelCard] = None,
|
||||
framework: Optional[str] = None,
|
||||
args_parser: ArgumentHandler = None,
|
||||
@@ -350,8 +343,6 @@ class Pipeline(_ScikitCompat):
|
||||
if framework is None:
|
||||
framework = get_framework()
|
||||
|
||||
model, tokenizer = self.get_defaults(model, tokenizer, framework)
|
||||
|
||||
self.model = model
|
||||
self.tokenizer = tokenizer
|
||||
self.modelcard = modelcard
|
||||
@@ -483,26 +474,6 @@ class Pipeline(_ScikitCompat):
|
||||
else:
|
||||
return predictions.numpy()
|
||||
|
||||
def get_defaults(self, model, tokenizer, framework):
|
||||
task_defaults = SUPPORTED_TASKS[self.task]
|
||||
if model is None:
|
||||
if framework == "tf":
|
||||
model = task_defaults["tf"].from_pretrained(task_defaults["default"]["model"]["tf"])
|
||||
elif framework == "pt":
|
||||
model = task_defaults["pt"].from_pretrained(task_defaults["default"]["model"]["pt"])
|
||||
else:
|
||||
raise ValueError("Provided framework should be either 'tf' for TensorFlow or 'pt' for PyTorch.")
|
||||
|
||||
if tokenizer is None:
|
||||
default_tokenizer = task_defaults["default"]["tokenizer"]
|
||||
if isinstance(default_tokenizer, tuple):
|
||||
# For tuple we have (tokenizer name, {kwargs})
|
||||
tokenizer = AutoTokenizer.from_pretrained(default_tokenizer[0], **default_tokenizer[1])
|
||||
else:
|
||||
tokenizer = AutoTokenizer.from_pretrained(default_tokenizer)
|
||||
|
||||
return model, tokenizer
|
||||
|
||||
|
||||
class FeatureExtractionPipeline(Pipeline):
|
||||
"""
|
||||
@@ -518,19 +489,13 @@ class FeatureExtractionPipeline(Pipeline):
|
||||
`huggingface.co/models <https://huggingface.co/models>`__.
|
||||
|
||||
Arguments:
|
||||
model (:obj:`str` or :obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`, `optional`, defaults to :obj:`None`):
|
||||
The model that will be used by the pipeline to make predictions. This can be :obj:`None`, a string
|
||||
checkpoint identifier or an actual pre-trained model inheriting from
|
||||
model (:obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`):
|
||||
The model that will be used by the pipeline to make predictions. This needs to be a model inheriting from
|
||||
:class:`~transformers.PreTrainedModel` for PyTorch and :class:`~transformers.TFPreTrainedModel` for
|
||||
TensorFlow.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
tokenizer (:obj:`str` or :obj:`~transformers.PreTrainedTokenizer`, `optional`, defaults to :obj:`None`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This can be :obj:`None`,
|
||||
a string checkpoint identifier or an actual pre-trained tokenizer inheriting from
|
||||
tokenizer (:obj:`~transformers.PreTrainedTokenizer`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This object inherits from
|
||||
:class:`~transformers.PreTrainedTokenizer`.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
modelcard (:obj:`str` or :class:`~transformers.ModelCard`, `optional`, defaults to :obj:`None`):
|
||||
Model card attributed to the model for this pipeline.
|
||||
framework (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
@@ -546,12 +511,10 @@ class FeatureExtractionPipeline(Pipeline):
|
||||
on the associated CUDA device id.
|
||||
"""
|
||||
|
||||
task = "feature-extraction"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: Optional = None,
|
||||
tokenizer: PreTrainedTokenizer = None,
|
||||
model: Union["PreTrainedModel", "TFPreTrainedModel"],
|
||||
tokenizer: PreTrainedTokenizer,
|
||||
modelcard: Optional[ModelCard] = None,
|
||||
framework: Optional[str] = None,
|
||||
args_parser: ArgumentHandler = None,
|
||||
@@ -586,19 +549,13 @@ class TextClassificationPipeline(Pipeline):
|
||||
`huggingface.co/models <https://huggingface.co/models?search=&filter=text-classification>`__.
|
||||
|
||||
Arguments:
|
||||
model (:obj:`str` or :obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`, `optional`, defaults to :obj:`None`):
|
||||
The model that will be used by the pipeline to make predictions. This can be :obj:`None`, a string
|
||||
checkpoint identifier or an actual pre-trained model inheriting from
|
||||
model (:obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`):
|
||||
The model that will be used by the pipeline to make predictions. This needs to be a model inheriting from
|
||||
:class:`~transformers.PreTrainedModel` for PyTorch and :class:`~transformers.TFPreTrainedModel` for
|
||||
TensorFlow.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
tokenizer (:obj:`str` or :obj:`~transformers.PreTrainedTokenizer`, `optional`, defaults to :obj:`None`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This can be :obj:`None`,
|
||||
a string checkpoint identifier or an actual pre-trained tokenizer inheriting from
|
||||
tokenizer (:obj:`~transformers.PreTrainedTokenizer`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This object inherits from
|
||||
:class:`~transformers.PreTrainedTokenizer`.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
modelcard (:obj:`str` or :class:`~transformers.ModelCard`, `optional`, defaults to :obj:`None`):
|
||||
Model card attributed to the model for this pipeline.
|
||||
framework (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
@@ -614,8 +571,6 @@ class TextClassificationPipeline(Pipeline):
|
||||
on the associated CUDA device id.
|
||||
"""
|
||||
|
||||
task = "sentiment-analysis"
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
outputs = super().__call__(*args, **kwargs)
|
||||
scores = np.exp(outputs) / np.exp(outputs).sum(-1)
|
||||
@@ -638,19 +593,13 @@ class FillMaskPipeline(Pipeline):
|
||||
`huggingface.co/models <https://huggingface.co/models?search=&filter=lm-head>`__.
|
||||
|
||||
Arguments:
|
||||
model (:obj:`str` or :obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`, `optional`, defaults to :obj:`None`):
|
||||
The model that will be used by the pipeline to make predictions. This can be :obj:`None`, a string
|
||||
checkpoint identifier or an actual pre-trained model inheriting from
|
||||
model (:obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`):
|
||||
The model that will be used by the pipeline to make predictions. This needs to be a model inheriting from
|
||||
:class:`~transformers.PreTrainedModel` for PyTorch and :class:`~transformers.TFPreTrainedModel` for
|
||||
TensorFlow.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
tokenizer (:obj:`str` or :obj:`~transformers.PreTrainedTokenizer`, `optional`, defaults to :obj:`None`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This can be :obj:`None`,
|
||||
a string checkpoint identifier or an actual pre-trained tokenizer inheriting from
|
||||
tokenizer (:obj:`~transformers.PreTrainedTokenizer`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This object inherits from
|
||||
:class:`~transformers.PreTrainedTokenizer`.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
modelcard (:obj:`str` or :class:`~transformers.ModelCard`, `optional`, defaults to :obj:`None`):
|
||||
Model card attributed to the model for this pipeline.
|
||||
framework (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
@@ -666,12 +615,10 @@ class FillMaskPipeline(Pipeline):
|
||||
on the associated CUDA device id.
|
||||
"""
|
||||
|
||||
task = "fill-mask"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: Optional = None,
|
||||
tokenizer: PreTrainedTokenizer = None,
|
||||
model: Union["PreTrainedModel", "TFPreTrainedModel"],
|
||||
tokenizer: PreTrainedTokenizer,
|
||||
modelcard: Optional[ModelCard] = None,
|
||||
framework: Optional[str] = None,
|
||||
args_parser: ArgumentHandler = None,
|
||||
@@ -743,19 +690,13 @@ class NerPipeline(Pipeline):
|
||||
`huggingface.co/models <https://huggingface.co/models?search=&filter=token-classification>`__.
|
||||
|
||||
Arguments:
|
||||
model (:obj:`str` or :obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`, `optional`, defaults to :obj:`None`):
|
||||
The model that will be used by the pipeline to make predictions. This can be :obj:`None`, a string
|
||||
checkpoint identifier or an actual pre-trained model inheriting from
|
||||
model (:obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`):
|
||||
The model that will be used by the pipeline to make predictions. This needs to be a model inheriting from
|
||||
:class:`~transformers.PreTrainedModel` for PyTorch and :class:`~transformers.TFPreTrainedModel` for
|
||||
TensorFlow.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
tokenizer (:obj:`str` or :obj:`~transformers.PreTrainedTokenizer`, `optional`, defaults to :obj:`None`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This can be :obj:`None`,
|
||||
a string checkpoint identifier or an actual pre-trained tokenizer inheriting from
|
||||
tokenizer (:obj:`~transformers.PreTrainedTokenizer`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This object inherits from
|
||||
:class:`~transformers.PreTrainedTokenizer`.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
modelcard (:obj:`str` or :class:`~transformers.ModelCard`, `optional`, defaults to :obj:`None`):
|
||||
Model card attributed to the model for this pipeline.
|
||||
framework (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
@@ -769,19 +710,14 @@ class NerPipeline(Pipeline):
|
||||
device (:obj:`int`, `optional`, defaults to :obj:`-1`):
|
||||
Device ordinal for CPU/GPU supports. Setting this to -1 will leverage CPU, >=0 will run the model
|
||||
on the associated CUDA device id.
|
||||
|
||||
Example::
|
||||
|
||||
from transformers import pi
|
||||
"""
|
||||
|
||||
default_input_names = "sequences"
|
||||
task = "ner"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: Optional = None,
|
||||
tokenizer: PreTrainedTokenizer = None,
|
||||
model: Union["PreTrainedModel", "TFPreTrainedModel"],
|
||||
tokenizer: PreTrainedTokenizer,
|
||||
modelcard: Optional[ModelCard] = None,
|
||||
framework: Optional[str] = None,
|
||||
args_parser: ArgumentHandler = None,
|
||||
@@ -928,19 +864,13 @@ class QuestionAnsweringPipeline(Pipeline):
|
||||
`huggingface.co/models <https://huggingface.co/models?search=&filter=question-answering>`__.
|
||||
|
||||
Arguments:
|
||||
model (:obj:`str` or :obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`, `optional`, defaults to :obj:`None`):
|
||||
The model that will be used by the pipeline to make predictions. This can be :obj:`None`, a string
|
||||
checkpoint identifier or an actual pre-trained model inheriting from
|
||||
model (:obj:`~transformers.PreTrainedModel` or :obj:`~transformers.TFPreTrainedModel`):
|
||||
The model that will be used by the pipeline to make predictions. This needs to be a model inheriting from
|
||||
:class:`~transformers.PreTrainedModel` for PyTorch and :class:`~transformers.TFPreTrainedModel` for
|
||||
TensorFlow.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
tokenizer (:obj:`str` or :obj:`~transformers.PreTrainedTokenizer`, `optional`, defaults to :obj:`None`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This can be :obj:`None`,
|
||||
a string checkpoint identifier or an actual pre-trained tokenizer inheriting from
|
||||
tokenizer (:obj:`~transformers.PreTrainedTokenizer`):
|
||||
The tokenizer that will be used by the pipeline to encode data for the model. This object inherits from
|
||||
:class:`~transformers.PreTrainedTokenizer`.
|
||||
|
||||
If :obj:`None`, the default of the pipeline will be loaded.
|
||||
modelcard (:obj:`str` or :class:`~transformers.ModelCard`, `optional`, defaults to :obj:`None`):
|
||||
Model card attributed to the model for this pipeline.
|
||||
framework (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
@@ -957,12 +887,11 @@ class QuestionAnsweringPipeline(Pipeline):
|
||||
"""
|
||||
|
||||
default_input_names = "question,context"
|
||||
task = "question-answering"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: Optional = None,
|
||||
tokenizer: Optional[PreTrainedTokenizer] = None,
|
||||
model: Union["PreTrainedModel", "TFPreTrainedModel"],
|
||||
tokenizer: PreTrainedTokenizer,
|
||||
modelcard: Optional[ModelCard] = None,
|
||||
framework: Optional[str] = None,
|
||||
device: int = -1,
|
||||
|
||||
@@ -69,6 +69,7 @@ class DistilBertTokenizer(BertTokenizer):
|
||||
pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP
|
||||
max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
|
||||
pretrained_init_configuration = PRETRAINED_INIT_CONFIGURATION
|
||||
model_input_names = ["attention_mask"]
|
||||
|
||||
|
||||
class DistilBertTokenizerFast(BertTokenizerFast):
|
||||
@@ -76,3 +77,4 @@ class DistilBertTokenizerFast(BertTokenizerFast):
|
||||
pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP
|
||||
max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
|
||||
pretrained_init_configuration = PRETRAINED_INIT_CONFIGURATION
|
||||
model_input_names = ["attention_mask"]
|
||||
@@ -119,6 +119,7 @@ class RobertaTokenizer(GPT2Tokenizer):
|
||||
vocab_files_names = VOCAB_FILES_NAMES
|
||||
pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP
|
||||
max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
|
||||
model_input_names = ["attention_mask"]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -244,6 +245,7 @@ class RobertaTokenizerFast(GPT2TokenizerFast):
|
||||
vocab_files_names = VOCAB_FILES_NAMES
|
||||
pretrained_vocab_files_map = PRETRAINED_VOCAB_FILES_MAP
|
||||
max_model_input_sizes = PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
|
||||
model_input_names = ["attention_mask"]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
@@ -22,6 +22,7 @@ import os
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from contextlib import contextmanager
|
||||
from typing import List, Optional, Tuple, Union
|
||||
|
||||
from tokenizers.implementations import BaseTokenizer
|
||||
|
||||
@@ -138,6 +139,7 @@ class PreTrainedTokenizer(object):
|
||||
pretrained_vocab_files_map = {}
|
||||
pretrained_init_configuration = {}
|
||||
max_model_input_sizes = {}
|
||||
model_input_names = ["token_type_ids", "attention_mask"]
|
||||
|
||||
SPECIAL_TOKENS_ATTRIBUTES = [
|
||||
"bos_token",
|
||||
@@ -316,6 +318,7 @@ class PreTrainedTokenizer(object):
|
||||
|
||||
# Padding side is right by default and over-riden in subclasses. If specified in the kwargs, it is changed.
|
||||
self.padding_side = kwargs.pop("padding_side", self.padding_side)
|
||||
self.model_input_names = kwargs.pop("model_input_names", self.model_input_names)
|
||||
|
||||
# Added tokens
|
||||
self.added_tokens_encoder = {}
|
||||
@@ -849,14 +852,14 @@ class PreTrainedTokenizer(object):
|
||||
|
||||
def encode(
|
||||
self,
|
||||
text,
|
||||
text_pair=None,
|
||||
add_special_tokens=True,
|
||||
max_length=None,
|
||||
stride=0,
|
||||
truncation_strategy="longest_first",
|
||||
pad_to_max_length=False,
|
||||
return_tensors=None,
|
||||
text: str,
|
||||
text_pair: Optional[str] = None,
|
||||
add_special_tokens: bool = True,
|
||||
max_length: Optional[int] = None,
|
||||
stride: int = 0,
|
||||
truncation_strategy: str = "longest_first",
|
||||
pad_to_max_length: bool = False,
|
||||
return_tensors: Optional[str] = None,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
@@ -865,34 +868,43 @@ class PreTrainedTokenizer(object):
|
||||
Same as doing ``self.convert_tokens_to_ids(self.tokenize(text))``.
|
||||
|
||||
Args:
|
||||
text: The first sequence to be encoded. This can be a string, a list of strings (tokenized string using
|
||||
text (:obj:`str` or :obj:`List[str]`):
|
||||
The first sequence to be encoded. This can be a string, a list of strings (tokenized string using
|
||||
the `tokenize` method) or a list of integers (tokenized string ids using the `convert_tokens_to_ids`
|
||||
method)
|
||||
text_pair: Optional second sequence to be encoded. This can be a string, a list of strings (tokenized
|
||||
text_pair (:obj:`str` or :obj:`List[str]`, `optional`, defaults to :obj:`None`):
|
||||
Optional second sequence to be encoded. This can be a string, a list of strings (tokenized
|
||||
string using the `tokenize` method) or a list of integers (tokenized string ids using the
|
||||
`convert_tokens_to_ids` method)
|
||||
add_special_tokens: if set to ``True``, the sequences will be encoded with the special tokens relative
|
||||
add_special_tokens (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
If set to ``True``, the sequences will be encoded with the special tokens relative
|
||||
to their model.
|
||||
max_length: if set to a number, will limit the total sequence returned so that it has a maximum length.
|
||||
max_length (:obj:`int`, `optional`, defaults to :obj:`None`):
|
||||
If set to a number, will limit the total sequence returned so that it has a maximum length.
|
||||
If there are overflowing tokens, those will be added to the returned dictionary
|
||||
stride: if set to a number along with max_length, the overflowing tokens returned will contain some tokens
|
||||
stride (:obj:`int`, `optional`, defaults to ``0``):
|
||||
If set to a number along with max_length, the overflowing tokens returned will contain some tokens
|
||||
from the main sequence returned. The value of this argument defines the number of additional tokens.
|
||||
truncation_strategy: string selected in the following options:
|
||||
truncation_strategy (:obj:`str`, `optional`, defaults to `longest_first`):
|
||||
String selected in the following options:
|
||||
|
||||
- 'longest_first' (default) Iteratively reduce the inputs sequence until the input is under max_length
|
||||
starting from the longest one at each token (when there is a pair of input sequences)
|
||||
starting from the longest one at each token (when there is a pair of input sequences)
|
||||
- 'only_first': Only truncate the first sequence
|
||||
- 'only_second': Only truncate the second sequence
|
||||
- 'do_not_truncate': Does not truncate (raise an error if the input sequence is longer than max_length)
|
||||
pad_to_max_length: if set to True, the returned sequences will be padded according to the model's padding side and
|
||||
padding index, up to their max length. If no max length is specified, the padding is done up to the model's max length.
|
||||
The tokenizer padding sides are handled by the class attribute `padding_side` which can be set to the following strings:
|
||||
pad_to_max_length (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
If set to True, the returned sequences will be padded according to the model's padding side and
|
||||
padding index, up to their max length. If no max length is specified, the padding is done up to the
|
||||
model's max length. The tokenizer padding sides are handled by the class attribute `padding_side`
|
||||
which can be set to the following strings:
|
||||
|
||||
- 'left': pads on the left of the sequences
|
||||
- 'right': pads on the right of the sequences
|
||||
Defaults to False: no padding.
|
||||
return_tensors: (optional) can be set to 'tf' or 'pt' to return respectively TensorFlow tf.constant
|
||||
or PyTorch torch.Tensor instead of a list of python integers.
|
||||
add_prefix_space: Only applies to GPT-2 and RoBERTa tokenizers. When `True`, this ensures that the sequence
|
||||
begins with an empty space. False by default except for when using RoBERTa with `add_special_tokens=True`.
|
||||
return_tensors (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
Can be set to 'tf' or 'pt' to return respectively TensorFlow :obj:`tf.constant`
|
||||
or PyTorch :obj:`torch.Tensor` instead of a list of python integers.
|
||||
**kwargs: passed to the `self.tokenize()` method
|
||||
"""
|
||||
encoded_inputs = self.encode_plus(
|
||||
@@ -911,59 +923,79 @@ class PreTrainedTokenizer(object):
|
||||
|
||||
def encode_plus(
|
||||
self,
|
||||
text,
|
||||
text_pair=None,
|
||||
add_special_tokens=True,
|
||||
max_length=None,
|
||||
stride=0,
|
||||
truncation_strategy="longest_first",
|
||||
pad_to_max_length=False,
|
||||
return_tensors=None,
|
||||
return_token_type_ids=True,
|
||||
return_attention_mask=True,
|
||||
return_overflowing_tokens=False,
|
||||
return_special_tokens_mask=False,
|
||||
return_offsets_mapping=False,
|
||||
text: str,
|
||||
text_pair: Optional[str] = None,
|
||||
add_special_tokens: bool = True,
|
||||
max_length: Optional[int] = None,
|
||||
stride: int = 0,
|
||||
truncation_strategy: str = "longest_first",
|
||||
pad_to_max_length: bool = False,
|
||||
return_tensors: Optional[str] = None,
|
||||
return_token_type_ids: Optional[bool] = None,
|
||||
return_attention_mask: Optional[bool] = None,
|
||||
return_overflowing_tokens: bool = False,
|
||||
return_special_tokens_mask: bool = False,
|
||||
return_offsets_mapping: bool = False,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
Returns a dictionary containing the encoded sequence or sequence pair and additional informations:
|
||||
Returns a dictionary containing the encoded sequence or sequence pair and additional information:
|
||||
the mask for sequence classification and the overflowing elements if a ``max_length`` is specified.
|
||||
|
||||
Args:
|
||||
text: The first sequence to be encoded. This can be a string, a list of strings (tokenized string using
|
||||
text (:obj:`str` or :obj:`List[str]`):
|
||||
The first sequence to be encoded. This can be a string, a list of strings (tokenized string using
|
||||
the `tokenize` method) or a list of integers (tokenized string ids using the `convert_tokens_to_ids`
|
||||
method)
|
||||
text_pair: Optional second sequence to be encoded. This can be a string, a list of strings (tokenized
|
||||
text_pair (:obj:`str` or :obj:`List[str]`, `optional`, defaults to :obj:`None`):
|
||||
Optional second sequence to be encoded. This can be a string, a list of strings (tokenized
|
||||
string using the `tokenize` method) or a list of integers (tokenized string ids using the
|
||||
`convert_tokens_to_ids` method)
|
||||
add_special_tokens: if set to ``True``, the sequences will be encoded with the special tokens relative
|
||||
add_special_tokens (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
If set to ``True``, the sequences will be encoded with the special tokens relative
|
||||
to their model.
|
||||
max_length: if set to a number, will limit the total sequence returned so that it has a maximum length.
|
||||
max_length (:obj:`int`, `optional`, defaults to :obj:`None`):
|
||||
If set to a number, will limit the total sequence returned so that it has a maximum length.
|
||||
If there are overflowing tokens, those will be added to the returned dictionary
|
||||
stride: if set to a number along with max_length, the overflowing tokens returned will contain some tokens
|
||||
stride (:obj:`int`, `optional`, defaults to ``0``):
|
||||
If set to a number along with max_length, the overflowing tokens returned will contain some tokens
|
||||
from the main sequence returned. The value of this argument defines the number of additional tokens.
|
||||
truncation_strategy: string selected in the following options:
|
||||
truncation_strategy (:obj:`str`, `optional`, defaults to `longest_first`):
|
||||
String selected in the following options:
|
||||
|
||||
- 'longest_first' (default) Iteratively reduce the inputs sequence until the input is under max_length
|
||||
starting from the longest one at each token (when there is a pair of input sequences)
|
||||
starting from the longest one at each token (when there is a pair of input sequences)
|
||||
- 'only_first': Only truncate the first sequence
|
||||
- 'only_second': Only truncate the second sequence
|
||||
- 'do_not_truncate': Does not truncate (raise an error if the input sequence is longer than max_length)
|
||||
pad_to_max_length: if set to True, the returned sequences will be padded according to the model's padding side and
|
||||
padding index, up to their max length. If no max length is specified, the padding is done up to the model's max length.
|
||||
The tokenizer padding sides are handled by the class attribute `padding_side` which can be set to the following strings:
|
||||
pad_to_max_length (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
If set to True, the returned sequences will be padded according to the model's padding side and
|
||||
padding index, up to their max length. If no max length is specified, the padding is done up to the
|
||||
model's max length. The tokenizer padding sides are handled by the class attribute `padding_side`
|
||||
which can be set to the following strings:
|
||||
|
||||
- 'left': pads on the left of the sequences
|
||||
- 'right': pads on the right of the sequences
|
||||
Defaults to False: no padding.
|
||||
return_tensors: (optional) can be set to 'tf' or 'pt' to return respectively TensorFlow tf.constant
|
||||
or PyTorch torch.Tensor instead of a list of python integers.
|
||||
add_prefix_space: Only applies to GPT-2 and RoBERTa tokenizers. When `True`, this ensures that the sequence
|
||||
begins with an empty space. False by default except for when using RoBERTa with `add_special_tokens=True`.
|
||||
return_token_type_ids: (optional) Set to False to avoid returning token_type_ids (default True).
|
||||
return_attention_mask: (optional) Set to False to avoid returning attention mask (default True)
|
||||
return_overflowing_tokens: (optional) Set to True to return overflowing token information (default False).
|
||||
return_special_tokens_mask: (optional) Set to True to return special tokens mask information (default False).
|
||||
return_offsets_mapping: (optional) Set to True to return (char_start, char_end) for each token (default False).
|
||||
return_tensors (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
Can be set to 'tf' or 'pt' to return respectively TensorFlow :obj:`tf.constant`
|
||||
or PyTorch :obj:`torch.Tensor` instead of a list of python integers.
|
||||
return_token_type_ids (:obj:`bool`, `optional`, defaults to :obj:`None`):
|
||||
Whether to return token type IDs. If left to the default, will return the token type IDs according
|
||||
to the specific tokenizer's default, defined by the :obj:`return_outputs` attribute.
|
||||
|
||||
`What are token type IDs? <../glossary.html#token-type-ids>`_
|
||||
return_attention_mask (:obj:`bool`, `optional`, defaults to :obj:`none`):
|
||||
Whether to return the attention mask. If left to the default, will return the attention mask according
|
||||
to the specific tokenizer's default, defined by the :obj:`return_outputs` attribute.
|
||||
|
||||
`What are attention masks? <../glossary.html#attention-mask>`__
|
||||
return_overflowing_tokens (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Set to True to return overflowing token information (default False).
|
||||
return_special_tokens_mask (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Set to True to return special tokens mask information (default False).
|
||||
return_offsets_mapping (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Set to True to return (char_start, char_end) for each token (default False).
|
||||
If using Python's tokenizer, this method will raise NotImplementedError. This one is only available on
|
||||
Rust-based tokenizers inheriting from PreTrainedTokenizerFast.
|
||||
**kwargs: passed to the `self.tokenize()` method
|
||||
@@ -981,13 +1013,14 @@ class PreTrainedTokenizer(object):
|
||||
}
|
||||
|
||||
With the fields:
|
||||
``input_ids``: list of token ids to be fed to a model
|
||||
``token_type_ids``: list of token type ids to be fed to a model
|
||||
``attention_mask``: list of indices specifying which tokens should be attended to by the model
|
||||
``overflowing_tokens``: list of overflowing tokens if a max length is specified.
|
||||
``num_truncated_tokens``: number of overflowing tokens a ``max_length`` is specified
|
||||
``special_tokens_mask``: if adding special tokens, this is a list of [0, 1], with 0 specifying special added
|
||||
tokens and 1 specifying sequence tokens.
|
||||
|
||||
- ``input_ids``: list of token ids to be fed to a model
|
||||
- ``token_type_ids``: list of token type ids to be fed to a model
|
||||
- ``attention_mask``: list of indices specifying which tokens should be attended to by the model
|
||||
- ``overflowing_tokens``: list of overflowing tokens if a max length is specified.
|
||||
- ``num_truncated_tokens``: number of overflowing tokens a ``max_length`` is specified
|
||||
- ``special_tokens_mask``: if adding special tokens, this is a list of [0, 1], with 0 specifying special added
|
||||
tokens and 1 specifying sequence tokens.
|
||||
"""
|
||||
|
||||
def get_input_ids(text):
|
||||
@@ -1038,19 +1071,19 @@ class PreTrainedTokenizer(object):
|
||||
|
||||
def batch_encode_plus(
|
||||
self,
|
||||
batch_text_or_text_pairs=None,
|
||||
add_special_tokens=True,
|
||||
max_length=None,
|
||||
stride=0,
|
||||
truncation_strategy="longest_first",
|
||||
pad_to_max_length=False,
|
||||
return_tensors=None,
|
||||
return_token_type_ids=True,
|
||||
return_attention_masks=True,
|
||||
return_overflowing_tokens=False,
|
||||
return_special_tokens_masks=False,
|
||||
return_offsets_mapping=False,
|
||||
return_input_lengths=False,
|
||||
batch_text_or_text_pairs: Union[str, List[str]],
|
||||
add_special_tokens: bool = True,
|
||||
max_length: Optional[int] = None,
|
||||
stride: int = 0,
|
||||
truncation_strategy: str = "longest_first",
|
||||
pad_to_max_length: bool = False,
|
||||
return_tensors: Optional[str] = None,
|
||||
return_token_type_ids: Optional[bool] = None,
|
||||
return_attention_masks: Optional[bool] = None,
|
||||
return_overflowing_tokens: bool = False,
|
||||
return_special_tokens_masks: bool = False,
|
||||
return_offsets_mapping: bool = False,
|
||||
return_input_lengths: bool = False,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
@@ -1058,32 +1091,59 @@ class PreTrainedTokenizer(object):
|
||||
the mask for sequence classification and the overflowing elements if a ``max_length`` is specified.
|
||||
|
||||
Args:
|
||||
batch_text_or_text_pairs: Batch of sequences or pair of sequences to be encoded.
|
||||
batch_text_or_text_pairs (:obj:`List[str]` or :obj:`List[List[str]]`):
|
||||
Batch of sequences or pair of sequences to be encoded.
|
||||
This can be a list of string/string-sequences/int-sequences or a list of pair of
|
||||
string/string-sequences/int-sequence (see details in encode_plus)
|
||||
add_special_tokens: if set to ``True``, the sequences will be encoded with the special tokens relative
|
||||
add_special_tokens (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
||||
If set to ``True``, the sequences will be encoded with the special tokens relative
|
||||
to their model.
|
||||
max_length: if set to a number, will limit the total sequence returned so that it has a maximum length.
|
||||
If there are overflowing tokens, those will be added to the returned dictionary`
|
||||
stride: if set to a number along with max_length, the overflowing tokens returned will contain some tokens
|
||||
max_length (:obj:`int`, `optional`, defaults to :obj:`None`):
|
||||
If set to a number, will limit the total sequence returned so that it has a maximum length.
|
||||
If there are overflowing tokens, those will be added to the returned dictionary
|
||||
stride (:obj:`int`, `optional`, defaults to ``0``):
|
||||
If set to a number along with max_length, the overflowing tokens returned will contain some tokens
|
||||
from the main sequence returned. The value of this argument defines the number of additional tokens.
|
||||
truncation_strategy: string selected in the following options:
|
||||
truncation_strategy (:obj:`str`, `optional`, defaults to `longest_first`):
|
||||
String selected in the following options:
|
||||
|
||||
- 'longest_first' (default) Iteratively reduce the inputs sequence until the input is under max_length
|
||||
starting from the longest one at each token (when there is a pair of input sequences)
|
||||
starting from the longest one at each token (when there is a pair of input sequences)
|
||||
- 'only_first': Only truncate the first sequence
|
||||
- 'only_second': Only truncate the second sequence
|
||||
- 'do_not_truncate': Does not truncate (raise an error if the input sequence is longer than max_length)
|
||||
pad_to_max_length: if set to True, the returned sequences will be padded according to the model's padding side and
|
||||
padding index, up to their max length. If no max length is specified, the padding is done up to the model's max length.
|
||||
The tokenizer padding sides are handled by the class attribute `padding_side` which can be set to the following strings:
|
||||
pad_to_max_length (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
If set to True, the returned sequences will be padded according to the model's padding side and
|
||||
padding index, up to their max length. If no max length is specified, the padding is done up to the
|
||||
model's max length. The tokenizer padding sides are handled by the class attribute `padding_side`
|
||||
which can be set to the following strings:
|
||||
|
||||
- 'left': pads on the left of the sequences
|
||||
- 'right': pads on the right of the sequences
|
||||
Defaults to False: no padding.
|
||||
return_tensors: (optional) can be set to 'tf' or 'pt' to return respectively TensorFlow tf.constant
|
||||
or PyTorch torch.Tensor instead of a list of python integers.
|
||||
return_input_lengths: (optional) If set the resulting dictionary will include the length of each sample
|
||||
return_attention_masks: (optional) Set to True to return the attention mask (default False)
|
||||
return_offsets_mapping: (optional) Not available, should be set to False or it will throw NotImplementError
|
||||
return_tensors (:obj:`str`, `optional`, defaults to :obj:`None`):
|
||||
Can be set to 'tf' or 'pt' to return respectively TensorFlow :obj:`tf.constant`
|
||||
or PyTorch :obj:`torch.Tensor` instead of a list of python integers.
|
||||
return_token_type_ids (:obj:`bool`, `optional`, defaults to :obj:`None`):
|
||||
Whether to return token type IDs. If left to the default, will return the token type IDs according
|
||||
to the specific tokenizer's default, defined by the :obj:`return_outputs` attribute.
|
||||
|
||||
`What are token type IDs? <../glossary.html#token-type-ids>`_
|
||||
return_attention_masks (:obj:`bool`, `optional`, defaults to :obj:`none`):
|
||||
Whether to return the attention mask. If left to the default, will return the attention mask according
|
||||
to the specific tokenizer's default, defined by the :obj:`return_outputs` attribute.
|
||||
|
||||
`What are attention masks? <../glossary.html#attention-mask>`__
|
||||
return_overflowing_tokens (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Set to True to return overflowing token information (default False).
|
||||
return_special_tokens_masks (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Set to True to return special tokens mask information (default False).
|
||||
return_offsets_mapping (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
Set to True to return (char_start, char_end) for each token (default False).
|
||||
If using Python's tokenizer, this method will raise NotImplementedError. This one is only available on
|
||||
Rust-based tokenizers inheriting from PreTrainedTokenizerFast.
|
||||
return_input_lengths (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
||||
If set the resulting dictionary will include the length of each sample
|
||||
**kwargs: passed to the `self.tokenize()` method
|
||||
|
||||
Return:
|
||||
@@ -1099,13 +1159,14 @@ class PreTrainedTokenizer(object):
|
||||
}
|
||||
|
||||
With the fields:
|
||||
``input_ids``: list of token ids to be fed to a model
|
||||
``token_type_ids``: list of token type ids to be fed to a model
|
||||
``attention_mask``: list of indices specifying which tokens should be attended to by the model
|
||||
``overflowing_tokens``: list of overflowing tokens if a max length is specified.
|
||||
``num_truncated_tokens``: number of overflowing tokens a ``max_length`` is specified
|
||||
``special_tokens_mask``: if adding special tokens, this is a list of [0, 1], with 0 specifying special added
|
||||
tokens and 1 specifying sequence tokens.
|
||||
|
||||
- ``input_ids``: list of token ids to be fed to a model
|
||||
- ``token_type_ids``: list of token type ids to be fed to a model
|
||||
- ``attention_mask``: list of indices specifying which tokens should be attended to by the model
|
||||
- ``overflowing_tokens``: list of overflowing tokens if a max length is specified.
|
||||
- ``num_truncated_tokens``: number of overflowing tokens a ``max_length`` is specified
|
||||
- ``special_tokens_mask``: if adding special tokens, this is a list of [0, 1], with 0 specifying special added
|
||||
tokens and 1 specifying sequence tokens.
|
||||
"""
|
||||
|
||||
def get_input_ids(text):
|
||||
@@ -1220,18 +1281,18 @@ class PreTrainedTokenizer(object):
|
||||
|
||||
def prepare_for_model(
|
||||
self,
|
||||
ids,
|
||||
pair_ids=None,
|
||||
max_length=None,
|
||||
add_special_tokens=True,
|
||||
stride=0,
|
||||
truncation_strategy="longest_first",
|
||||
pad_to_max_length=False,
|
||||
return_tensors=None,
|
||||
return_token_type_ids=True,
|
||||
return_attention_mask=True,
|
||||
return_overflowing_tokens=False,
|
||||
return_special_tokens_mask=False,
|
||||
ids: List[int],
|
||||
pair_ids: Optional[List[int]] = None,
|
||||
max_length: Optional[int] = None,
|
||||
add_special_tokens: bool = True,
|
||||
stride: int = 0,
|
||||
truncation_strategy: str = "longest_first",
|
||||
pad_to_max_length: bool = False,
|
||||
return_tensors: Optional[str] = None,
|
||||
return_token_type_ids: Optional[bool] = None,
|
||||
return_attention_mask: Optional[bool] = None,
|
||||
return_overflowing_tokens: bool = False,
|
||||
return_special_tokens_mask: bool = False,
|
||||
):
|
||||
"""
|
||||
Prepares a sequence of input id, or a pair of sequences of inputs ids so that it can be used by the model.
|
||||
@@ -1292,6 +1353,11 @@ class PreTrainedTokenizer(object):
|
||||
len_ids = len(ids)
|
||||
len_pair_ids = len(pair_ids) if pair else 0
|
||||
|
||||
if return_token_type_ids is None:
|
||||
return_token_type_ids = "token_type_ids" in self.model_input_names
|
||||
if return_attention_mask is None:
|
||||
return_attention_mask = "attention_mask" in self.model_input_names
|
||||
|
||||
encoded_inputs = {}
|
||||
|
||||
# Handle max sequence length
|
||||
@@ -1617,6 +1683,9 @@ class PreTrainedTokenizer(object):
|
||||
|
||||
|
||||
class PreTrainedTokenizerFast(PreTrainedTokenizer):
|
||||
|
||||
model_input_names = ["token_type_ids", "attention_mask"]
|
||||
|
||||
def __init__(self, tokenizer: BaseTokenizer, **kwargs):
|
||||
if tokenizer is None:
|
||||
raise ValueError("Provided tokenizer cannot be None")
|
||||
@@ -1685,16 +1754,21 @@ class PreTrainedTokenizerFast(PreTrainedTokenizer):
|
||||
if self._tokenizer is not None:
|
||||
self._tokenizer.add_special_tokens(self.all_special_tokens)
|
||||
|
||||
@staticmethod
|
||||
def _convert_encoding(
|
||||
self,
|
||||
encoding,
|
||||
return_tensors=None,
|
||||
return_token_type_ids=True,
|
||||
return_attention_mask=True,
|
||||
return_token_type_ids=None,
|
||||
return_attention_mask=None,
|
||||
return_overflowing_tokens=False,
|
||||
return_special_tokens_mask=False,
|
||||
return_offsets_mapping=False,
|
||||
):
|
||||
if return_token_type_ids is None:
|
||||
return_token_type_ids = "token_type_ids" in self.model_input_names
|
||||
if return_attention_mask is None:
|
||||
return_attention_mask = "attention_mask" in self.model_input_names
|
||||
|
||||
if return_overflowing_tokens and encoding.overflowing is not None:
|
||||
encodings = [encoding] + encoding.overflowing
|
||||
else:
|
||||
@@ -1774,18 +1848,18 @@ class PreTrainedTokenizerFast(PreTrainedTokenizer):
|
||||
|
||||
def batch_encode_plus(
|
||||
self,
|
||||
batch_text_or_text_pairs=None,
|
||||
add_special_tokens=True,
|
||||
max_length=None,
|
||||
stride=0,
|
||||
truncation_strategy="longest_first",
|
||||
pad_to_max_length=False,
|
||||
return_tensors=None,
|
||||
return_token_type_ids=True,
|
||||
return_attention_mask=True,
|
||||
return_overflowing_tokens=False,
|
||||
return_special_tokens_mask=False,
|
||||
return_offsets_mapping=False,
|
||||
batch_text_or_text_pairs: Optional[Union[List[str], List[Tuple[str]]]] = None,
|
||||
add_special_tokens: bool = True,
|
||||
max_length: Optional[int] = None,
|
||||
stride: int = 0,
|
||||
truncation_strategy: str = "longest_first",
|
||||
pad_to_max_length: bool = False,
|
||||
return_tensors: Optional[str] = None,
|
||||
return_token_type_ids: Optional[bool] = None,
|
||||
return_attention_mask: Optional[bool] = None,
|
||||
return_overflowing_tokens: bool = False,
|
||||
return_special_tokens_mask: bool = False,
|
||||
return_offsets_mapping: bool = False,
|
||||
**kwargs
|
||||
):
|
||||
if not add_special_tokens:
|
||||
@@ -1852,8 +1926,8 @@ class PreTrainedTokenizerFast(PreTrainedTokenizer):
|
||||
stack = tf.stack(stack, axis=0)
|
||||
elif return_tensors == "pt":
|
||||
stack = torch.stack(stack, dim=0)
|
||||
# elif not return_tensors and len(stack) == 1:
|
||||
# stack = stack[0]
|
||||
elif not return_tensors and len(stack) == 1:
|
||||
stack = stack[0]
|
||||
|
||||
sanitized[key] = stack
|
||||
|
||||
@@ -1868,19 +1942,19 @@ class PreTrainedTokenizerFast(PreTrainedTokenizer):
|
||||
|
||||
def encode_plus(
|
||||
self,
|
||||
text,
|
||||
text_pair=None,
|
||||
add_special_tokens=False,
|
||||
max_length=None,
|
||||
pad_to_max_length=False,
|
||||
stride=0,
|
||||
truncation_strategy="longest_first",
|
||||
return_tensors=None,
|
||||
return_token_type_ids=True,
|
||||
return_attention_mask=True,
|
||||
return_overflowing_tokens=False,
|
||||
return_special_tokens_mask=False,
|
||||
return_offsets_mapping=False,
|
||||
text: str,
|
||||
text_pair: Optional[str] = None,
|
||||
add_special_tokens: bool = False,
|
||||
max_length: Optional[int] = None,
|
||||
pad_to_max_length: bool = False,
|
||||
stride: int = 0,
|
||||
truncation_strategy: str = "longest_first",
|
||||
return_tensors: Optional[bool] = None,
|
||||
return_token_type_ids: Optional[bool] = None,
|
||||
return_attention_mask: Optional[bool] = None,
|
||||
return_overflowing_tokens: bool = False,
|
||||
return_special_tokens_mask: bool = False,
|
||||
return_offsets_mapping: bool = False,
|
||||
**kwargs
|
||||
):
|
||||
batched_input = [(text, text_pair)] if text_pair else [text]
|
||||
@@ -1902,10 +1976,7 @@ class PreTrainedTokenizerFast(PreTrainedTokenizer):
|
||||
|
||||
# Return tensor is None, then we can remove the leading batch axis
|
||||
if not return_tensors:
|
||||
return {
|
||||
key: value[0] if len(value) > 0 and isinstance(value[0], list) else value
|
||||
for key, value in batched_output.items()
|
||||
}
|
||||
return {key: value[0] if isinstance(value[0], list) else value for key, value in batched_output.items()}
|
||||
else:
|
||||
return batched_output
|
||||
|
||||
|
||||
+15
-2
@@ -21,7 +21,7 @@ import unittest
|
||||
import requests
|
||||
from requests.exceptions import HTTPError
|
||||
|
||||
from transformers.hf_api import HfApi, HfFolder, PresignedUrl, S3Obj
|
||||
from transformers.hf_api import HfApi, HfFolder, ModelInfo, PresignedUrl, S3Obj
|
||||
|
||||
|
||||
USER = "__DUMMY_TRANSFORMERS_USER__"
|
||||
@@ -36,10 +36,11 @@ FILES = [
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures/empty.txt"),
|
||||
),
|
||||
]
|
||||
ENDPOINT_STAGING = "https://moon-staging.huggingface.co"
|
||||
|
||||
|
||||
class HfApiCommonTest(unittest.TestCase):
|
||||
_api = HfApi(endpoint="https://moon-staging.huggingface.co")
|
||||
_api = HfApi(endpoint=ENDPOINT_STAGING)
|
||||
|
||||
|
||||
class HfApiLoginTest(HfApiCommonTest):
|
||||
@@ -92,6 +93,18 @@ class HfApiEndpointsTest(HfApiCommonTest):
|
||||
self.assertIsInstance(o, S3Obj)
|
||||
|
||||
|
||||
class HfApiPublicTest(unittest.TestCase):
|
||||
def test_staging_model_list(self):
|
||||
_api = HfApi(endpoint=ENDPOINT_STAGING)
|
||||
_ = _api.model_list()
|
||||
|
||||
def test_model_list(self):
|
||||
_api = HfApi()
|
||||
models = _api.model_list()
|
||||
self.assertGreater(len(models), 100)
|
||||
self.assertIsInstance(models[0], ModelInfo)
|
||||
|
||||
|
||||
class HfFolderTest(unittest.TestCase):
|
||||
def test_token_workflow(self):
|
||||
"""
|
||||
|
||||
@@ -78,8 +78,6 @@ class AutoModelTest(unittest.TestCase):
|
||||
model, loading_info = AutoModelForPreTraining.from_pretrained(model_name, output_loading_info=True)
|
||||
self.assertIsNotNone(model)
|
||||
self.assertIsInstance(model, BertForPreTraining)
|
||||
for value in loading_info.values():
|
||||
self.assertEqual(len(value), 0)
|
||||
|
||||
@slow
|
||||
def test_lmhead_model_from_pretrained(self):
|
||||
|
||||
@@ -37,6 +37,7 @@ if is_torch_available():
|
||||
BART_PRETRAINED_MODEL_ARCHIVE_MAP,
|
||||
shift_tokens_right,
|
||||
_prepare_bart_decoder_inputs,
|
||||
LARGE_NEGATIVE,
|
||||
)
|
||||
from transformers.tokenization_bart import BartTokenizer
|
||||
|
||||
@@ -303,6 +304,38 @@ class BartHeadTests(unittest.TestCase):
|
||||
lm_model = BartForConditionalGeneration(config).eval().to(torch_device).half()
|
||||
lm_model.generate(input_ids, attention_mask)
|
||||
|
||||
def test_prepare_bart_decoder_inputs(self):
|
||||
config, *_ = self._get_config_and_data(output_past=False)
|
||||
input_ids = _long_tensor(([4, 4, 2])) # only used for .device if decoder_input_ids is passed
|
||||
decoder_input_ids = _long_tensor([[26388, 2, config.pad_token_id]])
|
||||
ignore = LARGE_NEGATIVE
|
||||
decoder_input_ids, decoder_attn_mask = _prepare_bart_decoder_inputs(config, input_ids, decoder_input_ids)
|
||||
expected_mask = torch.tensor(
|
||||
[
|
||||
[0, ignore, ignore],
|
||||
[0, 0, ignore],
|
||||
[ignore, ignore, ignore], # never attend to the final token, because its pad
|
||||
]
|
||||
).to(input_ids.device)
|
||||
self.assertEqual(decoder_attn_mask.size(), (1, 1, 3, 3))
|
||||
self.assertTrue(torch.eq(expected_mask, decoder_attn_mask).all())
|
||||
|
||||
# Test no causal mask
|
||||
config, *_ = self._get_config_and_data(output_past=True)
|
||||
expected_just_padding_mask = torch.tensor(
|
||||
[[0, 0, 0], [0, 0, 0], [ignore, ignore, ignore]] # never attend to the final token, because its pad
|
||||
).to(input_ids.device)
|
||||
_, decoder_attn_mask_no_causal_mask = _prepare_bart_decoder_inputs(config, input_ids, decoder_input_ids)
|
||||
self.assertEqual(decoder_attn_mask_no_causal_mask.size(), (1, 1, 3, 3))
|
||||
self.assertTrue(torch.eq(expected_just_padding_mask, decoder_attn_mask_no_causal_mask).all())
|
||||
|
||||
decoder_input_ids = _long_tensor([[0, 26388, 4133, 2]])
|
||||
# Attend to everything if no pad tokens and no causal mask
|
||||
_, decoder_attn_mask_no_padding_no_causal_mask = _prepare_bart_decoder_inputs(
|
||||
config, input_ids, decoder_input_ids
|
||||
)
|
||||
self.assertTrue(torch.eq(decoder_attn_mask_no_padding_no_causal_mask, 0).all())
|
||||
|
||||
|
||||
def _assert_tensors_equal(a, b, atol=1e-12, prefix=""):
|
||||
"""If tensors not close, or a and b arent both tensors, raise a nice Assertion error."""
|
||||
|
||||
@@ -19,6 +19,7 @@ import os
|
||||
import random
|
||||
import tempfile
|
||||
import unittest
|
||||
from importlib import import_module
|
||||
|
||||
from transformers import is_tf_available, is_torch_available
|
||||
|
||||
@@ -89,13 +90,49 @@ class TFModelTesterMixin:
|
||||
model = model_class.from_pretrained(tmpdirname)
|
||||
after_outputs = model(inputs_dict)
|
||||
|
||||
# Make sure we don't have nans
|
||||
out_1 = after_outputs[0].numpy()
|
||||
out_2 = outputs[0].numpy()
|
||||
out_1 = out_1[~np.isnan(out_1)]
|
||||
out_2 = out_2[~np.isnan(out_2)]
|
||||
max_diff = np.amax(np.abs(out_1 - out_2))
|
||||
self.assertLessEqual(max_diff, 1e-5)
|
||||
self.assert_outputs_same(after_outputs, outputs)
|
||||
|
||||
def test_keras_save_load(self):
|
||||
config, inputs_dict = self.model_tester.prepare_config_and_inputs_for_common()
|
||||
|
||||
tf_main_layer_classes = set(
|
||||
module_member
|
||||
for model_class in self.all_model_classes
|
||||
for module in (import_module(model_class.__module__),)
|
||||
for module_member_name in dir(module)
|
||||
if module_member_name.endswith("MainLayer")
|
||||
for module_member in (getattr(module, module_member_name),)
|
||||
if isinstance(module_member, type)
|
||||
and tf.keras.layers.Layer in module_member.__bases__
|
||||
and getattr(module_member, "_keras_serializable", False)
|
||||
)
|
||||
for main_layer_class in tf_main_layer_classes:
|
||||
main_layer = main_layer_class(config)
|
||||
symbolic_inputs = {
|
||||
name: tf.keras.Input(tensor.shape[1:], dtype=tensor.dtype) for name, tensor in inputs_dict.items()
|
||||
}
|
||||
model = tf.keras.Model(symbolic_inputs, outputs=main_layer(symbolic_inputs))
|
||||
outputs = model(inputs_dict)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
filepath = os.path.join(tmpdirname, "keras_model.h5")
|
||||
model.save(filepath)
|
||||
model = tf.keras.models.load_model(
|
||||
filepath, custom_objects={main_layer_class.__name__: main_layer_class}
|
||||
)
|
||||
assert isinstance(model, tf.keras.Model)
|
||||
after_outputs = model(inputs_dict)
|
||||
self.assert_outputs_same(after_outputs, outputs)
|
||||
|
||||
def assert_outputs_same(self, after_outputs, outputs):
|
||||
# Make sure we don't have nans
|
||||
out_1 = after_outputs[0].numpy()
|
||||
out_2 = outputs[0].numpy()
|
||||
self.assertEqual(out_1.shape, out_2.shape)
|
||||
out_1 = out_1[~np.isnan(out_1)]
|
||||
out_2 = out_2[~np.isnan(out_2)]
|
||||
max_diff = np.amax(np.abs(out_1 - out_2))
|
||||
self.assertLessEqual(max_diff, 1e-5)
|
||||
|
||||
def test_pt_tf_model_equivalence(self):
|
||||
if not is_torch_available():
|
||||
|
||||
+2
-36
@@ -2,16 +2,9 @@ import unittest
|
||||
from typing import Iterable, List, Optional
|
||||
|
||||
from transformers import pipeline
|
||||
from transformers.pipelines import (
|
||||
FeatureExtractionPipeline,
|
||||
FillMaskPipeline,
|
||||
NerPipeline,
|
||||
Pipeline,
|
||||
QuestionAnsweringPipeline,
|
||||
TextClassificationPipeline,
|
||||
)
|
||||
from transformers.pipelines import Pipeline
|
||||
|
||||
from .utils import require_tf, require_torch, slow
|
||||
from .utils import require_tf, require_torch
|
||||
|
||||
|
||||
QA_FINETUNED_MODELS = [
|
||||
@@ -311,30 +304,3 @@ class MultiColumnInputTestCase(unittest.TestCase):
|
||||
for tokenizer, model, config in TF_QA_FINETUNED_MODELS:
|
||||
nlp = pipeline(task="question-answering", model=model, config=config, tokenizer=tokenizer, framework="tf")
|
||||
self._test_multicolumn_pipeline(nlp, valid_samples, invalid_samples, mandatory_output_keys)
|
||||
|
||||
|
||||
class PipelineCommonTests(unittest.TestCase):
|
||||
|
||||
pipelines = (
|
||||
NerPipeline,
|
||||
FeatureExtractionPipeline,
|
||||
QuestionAnsweringPipeline,
|
||||
FillMaskPipeline,
|
||||
TextClassificationPipeline,
|
||||
)
|
||||
|
||||
@slow
|
||||
@require_tf
|
||||
def test_tf_defaults(self):
|
||||
# Test that pipelines can be correctly loaded without any argument
|
||||
for default_pipeline in self.pipelines:
|
||||
with self.subTest(msg="Testing Torch defaults with PyTorch and {}".format(default_pipeline.task)):
|
||||
default_pipeline(framework="tf")
|
||||
|
||||
@slow
|
||||
@require_torch
|
||||
def test_pt_defaults(self):
|
||||
# Test that pipelines can be correctly loaded without any argument
|
||||
for default_pipeline in self.pipelines:
|
||||
with self.subTest(msg="Testing Torch defaults with PyTorch and {}".format(default_pipeline.task)):
|
||||
default_pipeline(framework="pt")
|
||||
@@ -130,6 +130,7 @@ class BertJapaneseTokenizationTest(TokenizerTesterMixin, unittest.TestCase):
|
||||
assert encoded_pair == [2] + text + [3] + text_2 + [3]
|
||||
|
||||
|
||||
@custom_tokenizers
|
||||
class BertJapaneseCharacterTokenizationTest(TokenizerTesterMixin, unittest.TestCase):
|
||||
|
||||
tokenizer_class = BertJapaneseTokenizer
|
||||
|
||||
@@ -48,7 +48,7 @@ class TokenizerTesterMixin:
|
||||
# to the concatenated encode_plus format: [{'input_ids': [...], ...}, {'input_ids': [...], ...}]
|
||||
return [
|
||||
{value: batch_encode_plus_sequences[value][i] for value in batch_encode_plus_sequences.keys()}
|
||||
for i in range(len(batch_encode_plus_sequences))
|
||||
for i in range(len(batch_encode_plus_sequences["input_ids"]))
|
||||
]
|
||||
|
||||
def test_tokenizers_common_properties(self):
|
||||
@@ -261,7 +261,10 @@ class TokenizerTesterMixin:
|
||||
def test_mask_output(self):
|
||||
tokenizer = self.get_tokenizer()
|
||||
|
||||
if tokenizer.build_inputs_with_special_tokens.__qualname__.split(".")[0] != "PreTrainedTokenizer":
|
||||
if (
|
||||
tokenizer.build_inputs_with_special_tokens.__qualname__.split(".")[0] != "PreTrainedTokenizer"
|
||||
and "token_type_ids" in tokenizer.model_input_names
|
||||
):
|
||||
seq_0 = "Test this method."
|
||||
seq_1 = "With these inputs."
|
||||
information = tokenizer.encode_plus(seq_0, seq_1, add_special_tokens=True)
|
||||
@@ -504,51 +507,58 @@ class TokenizerTesterMixin:
|
||||
|
||||
encoded_sequence = tokenizer.encode_plus(sequence, return_special_tokens_mask=True)
|
||||
input_ids = encoded_sequence["input_ids"]
|
||||
token_type_ids = encoded_sequence["token_type_ids"]
|
||||
attention_mask = encoded_sequence["attention_mask"]
|
||||
special_tokens_mask = encoded_sequence["special_tokens_mask"]
|
||||
sequence_length = len(input_ids)
|
||||
|
||||
# Test right padding
|
||||
tokenizer.padding_side = "right"
|
||||
|
||||
padded_sequence = tokenizer.encode_plus(
|
||||
right_padded_sequence = tokenizer.encode_plus(
|
||||
sequence,
|
||||
max_length=sequence_length + padding_size,
|
||||
pad_to_max_length=True,
|
||||
return_special_tokens_mask=True,
|
||||
)
|
||||
padded_input_ids = padded_sequence["input_ids"]
|
||||
padded_token_type_ids = padded_sequence["token_type_ids"]
|
||||
padded_attention_mask = padded_sequence["attention_mask"]
|
||||
padded_special_tokens_mask = padded_sequence["special_tokens_mask"]
|
||||
padded_sequence_length = len(padded_input_ids)
|
||||
right_padded_input_ids = right_padded_sequence["input_ids"]
|
||||
|
||||
assert sequence_length + padding_size == padded_sequence_length
|
||||
assert input_ids + [padding_idx] * padding_size == padded_input_ids
|
||||
assert token_type_ids + [token_type_padding_idx] * padding_size == padded_token_type_ids
|
||||
assert attention_mask + [0] * padding_size == padded_attention_mask
|
||||
assert special_tokens_mask + [1] * padding_size == padded_special_tokens_mask
|
||||
right_padded_special_tokens_mask = right_padded_sequence["special_tokens_mask"]
|
||||
right_padded_sequence_length = len(right_padded_input_ids)
|
||||
|
||||
assert sequence_length + padding_size == right_padded_sequence_length
|
||||
assert input_ids + [padding_idx] * padding_size == right_padded_input_ids
|
||||
assert special_tokens_mask + [1] * padding_size == right_padded_special_tokens_mask
|
||||
|
||||
# Test left padding
|
||||
tokenizer.padding_side = "left"
|
||||
padded_sequence = tokenizer.encode_plus(
|
||||
left_padded_sequence = tokenizer.encode_plus(
|
||||
sequence,
|
||||
max_length=sequence_length + padding_size,
|
||||
pad_to_max_length=True,
|
||||
return_special_tokens_mask=True,
|
||||
)
|
||||
padded_input_ids = padded_sequence["input_ids"]
|
||||
padded_token_type_ids = padded_sequence["token_type_ids"]
|
||||
padded_attention_mask = padded_sequence["attention_mask"]
|
||||
padded_special_tokens_mask = padded_sequence["special_tokens_mask"]
|
||||
padded_sequence_length = len(padded_input_ids)
|
||||
left_padded_input_ids = left_padded_sequence["input_ids"]
|
||||
left_padded_special_tokens_mask = left_padded_sequence["special_tokens_mask"]
|
||||
left_padded_sequence_length = len(left_padded_input_ids)
|
||||
|
||||
assert sequence_length + padding_size == padded_sequence_length
|
||||
assert [padding_idx] * padding_size + input_ids == padded_input_ids
|
||||
assert [token_type_padding_idx] * padding_size + token_type_ids == padded_token_type_ids
|
||||
assert [0] * padding_size + attention_mask == padded_attention_mask
|
||||
assert [1] * padding_size + special_tokens_mask == padded_special_tokens_mask
|
||||
assert sequence_length + padding_size == left_padded_sequence_length
|
||||
assert [padding_idx] * padding_size + input_ids == left_padded_input_ids
|
||||
assert [1] * padding_size + special_tokens_mask == left_padded_special_tokens_mask
|
||||
|
||||
if "token_type_ids" in tokenizer.model_input_names:
|
||||
token_type_ids = encoded_sequence["token_type_ids"]
|
||||
left_padded_token_type_ids = left_padded_sequence["token_type_ids"]
|
||||
right_padded_token_type_ids = right_padded_sequence["token_type_ids"]
|
||||
|
||||
assert token_type_ids + [token_type_padding_idx] * padding_size == right_padded_token_type_ids
|
||||
assert [token_type_padding_idx] * padding_size + token_type_ids == left_padded_token_type_ids
|
||||
|
||||
if "attention_mask" in tokenizer.model_input_names:
|
||||
attention_mask = encoded_sequence["attention_mask"]
|
||||
right_padded_attention_mask = right_padded_sequence["attention_mask"]
|
||||
left_padded_attention_mask = left_padded_sequence["attention_mask"]
|
||||
|
||||
assert attention_mask + [0] * padding_size == right_padded_attention_mask
|
||||
assert [0] * padding_size + attention_mask == left_padded_attention_mask
|
||||
|
||||
def test_separate_tokenizers(self):
|
||||
# This tests that tokenizers don't impact others. Unfortunately the case where it fails is when
|
||||
|
||||
@@ -272,30 +272,6 @@ class FastTokenizerMatchingTest(unittest.TestCase):
|
||||
# self.assertEqual(getattr(tokenizer_rp, key), getattr(tokenizer_pp, key))
|
||||
# self.assertEqual(getattr(tokenizer_rp, key + "_id"), getattr(tokenizer_pp, key + "_id"))
|
||||
|
||||
def assert_empty_output_no_special_tokens(self, ru_class, py_class, model):
|
||||
tokenizer_r = ru_class.from_pretrained(model, add_special_tokens=False)
|
||||
tokenizer_p = py_class.from_pretrained(model)
|
||||
|
||||
# add_special_tokens=False makes nothing for now.
|
||||
self.assertEqual(
|
||||
tokenizer_p.tokenize(" ", add_special_tokens=False), tokenizer_r.tokenize(" ", add_special_tokens=False)
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
tokenizer_p.encode_plus(" ", add_special_tokens=False),
|
||||
tokenizer_r.encode_plus(" ", add_special_tokens=False),
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
tokenizer_p.encode_plus(" ", add_special_tokens=False),
|
||||
tokenizer_r.encode_plus(" ", add_special_tokens=False),
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
tokenizer_p.batch_encode_plus([" "], add_special_tokens=False),
|
||||
tokenizer_r.batch_encode_plus([" "], add_special_tokens=False),
|
||||
)
|
||||
|
||||
def test_bert(self):
|
||||
for tokenizer_name in BertTokenizer.pretrained_vocab_files_map["vocab_file"].keys():
|
||||
tokenizer_p = BertTokenizer.from_pretrained(tokenizer_name)
|
||||
@@ -337,9 +313,6 @@ class FastTokenizerMatchingTest(unittest.TestCase):
|
||||
# Check for padding
|
||||
self.assert_padding(tokenizer_r, tokenizer_p)
|
||||
|
||||
# Check for space-only input
|
||||
self.assert_empty_output_no_special_tokens(tokenizer_r.__class__, tokenizer_p.__class__, tokenizer_name)
|
||||
|
||||
@require_torch
|
||||
def test_transfoxl(self):
|
||||
for tokenizer_name in TransfoXLTokenizer.pretrained_vocab_files_map["pretrained_vocab_file"].keys():
|
||||
@@ -396,9 +369,6 @@ class FastTokenizerMatchingTest(unittest.TestCase):
|
||||
# self.assertIsNotNone(tokenizer_p.__class__.from_pretrained('./'))
|
||||
self.assertIsNotNone(tokenizer_r.__class__.from_pretrained("./"))
|
||||
|
||||
# Check for space-only input
|
||||
self.assert_empty_output_no_special_tokens(tokenizer_r.__class__, tokenizer_p.__class__, tokenizer_name)
|
||||
|
||||
def test_distilbert(self):
|
||||
for tokenizer_name in DistilBertTokenizer.pretrained_vocab_files_map["vocab_file"].keys():
|
||||
tokenizer_p = DistilBertTokenizer.from_pretrained(tokenizer_name)
|
||||
@@ -441,9 +411,6 @@ class FastTokenizerMatchingTest(unittest.TestCase):
|
||||
# Check for padding
|
||||
self.assert_padding(tokenizer_r, tokenizer_p)
|
||||
|
||||
# Check for space-only input
|
||||
self.assert_empty_output_no_special_tokens(tokenizer_r.__class__, tokenizer_p.__class__, tokenizer_name)
|
||||
|
||||
def test_gpt2(self):
|
||||
for tokenizer_name in GPT2Tokenizer.pretrained_vocab_files_map["vocab_file"].keys():
|
||||
tokenizer_p = GPT2Tokenizer.from_pretrained(tokenizer_name)
|
||||
@@ -485,9 +452,6 @@ class FastTokenizerMatchingTest(unittest.TestCase):
|
||||
# Check for padding
|
||||
self.assertRaises(ValueError, self.assert_padding, tokenizer_r, tokenizer_p)
|
||||
|
||||
# Check for space-only input
|
||||
self.assert_empty_output_no_special_tokens(tokenizer_r.__class__, tokenizer_p.__class__, tokenizer_name)
|
||||
|
||||
def test_roberta(self):
|
||||
for tokenizer_name in RobertaTokenizer.pretrained_vocab_files_map["vocab_file"].keys():
|
||||
tokenizer_p = RobertaTokenizer.from_pretrained(tokenizer_name)
|
||||
@@ -530,9 +494,6 @@ class FastTokenizerMatchingTest(unittest.TestCase):
|
||||
# TODO: Re-enable this test as soon as Roberta align with the python tokenizer.
|
||||
# self.assert_padding(tokenizer_r, tokenizer_p)
|
||||
|
||||
# Check for space-only input
|
||||
self.assert_empty_output_no_special_tokens(tokenizer_r.__class__, tokenizer_p.__class__, tokenizer_name)
|
||||
|
||||
def test_openai(self):
|
||||
for tokenizer_name in OpenAIGPTTokenizer.pretrained_vocab_files_map["vocab_file"].keys():
|
||||
tokenizer_p = OpenAIGPTTokenizer.from_pretrained(tokenizer_name)
|
||||
@@ -575,6 +536,3 @@ class FastTokenizerMatchingTest(unittest.TestCase):
|
||||
|
||||
# Check the number of returned files for save_vocabulary
|
||||
self.assert_save_pretrained(tokenizer_r, tokenizer_p)
|
||||
|
||||
# Check for space-only input
|
||||
self.assert_empty_output_no_special_tokens(tokenizer_r.__class__, tokenizer_p.__class__, tokenizer_name)
|
||||
Reference in new issue
Block a user