From 47a98fc4cb6a561576309a57b315b042977d194c Mon Sep 17 00:00:00 2001 From: Patrick von Platen Date: Tue, 1 Jun 2021 19:07:37 +0100 Subject: [PATCH] ByT5 model (#11971) * allow tf to use uneven num of layers * add tokenizer * finish docs * finish docs * Apply suggestions from code review * include in index * finish * Update docs/source/model_doc/byt5.rst Co-authored-by: NielsRogge <48327001+NielsRogge@users.noreply.github.com> * apply sylvais suggestions * make style Co-authored-by: NielsRogge <48327001+NielsRogge@users.noreply.github.com> --- README.md | 1 + docs/source/index.rst | 100 +++---- docs/source/model_doc/byt5.rst | 83 ++++++ src/transformers/__init__.py | 2 + .../models/auto/tokenization_auto.py | 2 + src/transformers/models/byt5/__init__.py | 47 +++ ..._byt5_original_tf_checkpoint_to_pytorch.py | 59 ++++ .../models/byt5/tokenization_byt5.py | 268 ++++++++++++++++++ src/transformers/models/t5/modeling_tf_t5.py | 2 + tests/test_modeling_t5.py | 26 +- tests/test_modeling_tf_t5.py | 26 +- tests/test_tokenization_byt5.py | 178 ++++++++++++ 12 files changed, 744 insertions(+), 50 deletions(-) create mode 100644 docs/source/model_doc/byt5.rst create mode 100644 src/transformers/models/byt5/__init__.py create mode 100755 src/transformers/models/byt5/convert_byt5_original_tf_checkpoint_to_pytorch.py create mode 100644 src/transformers/models/byt5/tokenization_byt5.py create mode 100644 tests/test_tokenization_byt5.py diff --git a/README.md b/README.md index 3d1684b117..d88a0f1d66 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,7 @@ Current number of checkpoints: ![](https://img.shields.io/endpoint?url=https://h 1. **[Blenderbot](https://huggingface.co/transformers/model_doc/blenderbot.html)** (from Facebook) released with the paper [Recipes for building an open-domain chatbot](https://arxiv.org/abs/2004.13637) by Stephen Roller, Emily Dinan, Naman Goyal, Da Ju, Mary Williamson, Yinhan Liu, Jing Xu, Myle Ott, Kurt Shuster, Eric M. Smith, Y-Lan Boureau, Jason Weston. 1. **[BlenderbotSmall](https://huggingface.co/transformers/model_doc/blenderbot_small.html)** (from Facebook) released with the paper [Recipes for building an open-domain chatbot](https://arxiv.org/abs/2004.13637) by Stephen Roller, Emily Dinan, Naman Goyal, Da Ju, Mary Williamson, Yinhan Liu, Jing Xu, Myle Ott, Kurt Shuster, Eric M. Smith, Y-Lan Boureau, Jason Weston. 1. **[BORT](https://huggingface.co/transformers/model_doc/bort.html)** (from Alexa) released with the paper [Optimal Subarchitecture Extraction For BERT](https://arxiv.org/abs/2010.10499) by Adrian de Wynter and Daniel J. Perry. +1. **[ByT5](https://huggingface.co/transformers/model_doc/byt5.html)** (from Google Research) released with the paper [ByT5: Towards a token-free future with pre-trained byte-to-byte models](https://arxiv.org/abs/2105.13626) by Linting Xue, Aditya Barua, Noah Constant, Rami Al-Rfou, Sharan Narang, Mihir Kale, Adam Roberts, Colin Raffel. 1. **[CamemBERT](https://huggingface.co/transformers/model_doc/camembert.html)** (from Inria/Facebook/Sorbonne) released with the paper [CamemBERT: a Tasty French Language Model](https://arxiv.org/abs/1911.03894) by Louis Martin*, Benjamin Muller*, Pedro Javier Ortiz Suárez*, Yoann Dupont, Laurent Romary, Éric Villemonte de la Clergerie, Djamé Seddah and Benoît Sagot. 1. **[CLIP](https://huggingface.co/transformers/model_doc/clip.html)** from (OpenAI) released with the paper [Learning Transferable Visual Models From Natural Language Supervision](https://arxiv.org/abs/2103.00020) by Alec Radford, Jong Wook Kim, Chris Hallacy, Aditya Ramesh, Gabriel Goh, Sandhini Agarwal, Girish Sastry, Amanda Askell, Pamela Mishkin, Jack Clark, Gretchen Krueger, Ilya Sutskever. 1. **[ConvBERT](https://huggingface.co/transformers/model_doc/convbert.html)** (from YituTech) released with the paper [ConvBERT: Improving BERT with Span-based Dynamic Convolution](https://arxiv.org/abs/2008.02496) by Zihang Jiang, Weihao Yu, Daquan Zhou, Yunpeng Chen, Jiashi Feng, Shuicheng Yan. diff --git a/docs/source/index.rst b/docs/source/index.rst index d1bd89988f..188a2a406d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -123,152 +123,155 @@ Supported models Williamson, Yinhan Liu, Jing Xu, Myle Ott, Kurt Shuster, Eric M. Smith, Y-Lan Boureau, Jason Weston. 10. :doc:`BORT ` (from Alexa) released with the paper `Optimal Subarchitecture Extraction For BERT `__ by Adrian de Wynter and Daniel J. Perry. -11. :doc:`CamemBERT ` (from Inria/Facebook/Sorbonne) released with the paper `CamemBERT: a Tasty +11. :doc:`ByT5 ` (from Google Research) released with the paper `ByT5: Towards a token-free future with + pre-trained byte-to-byte models `__ by Linting Xue, Aditya Barua, Noah Constant, + Rami Al-Rfou, Sharan Narang, Mihir Kale, Adam Roberts, Colin Raffel. +12. :doc:`CamemBERT ` (from Inria/Facebook/Sorbonne) released with the paper `CamemBERT: a Tasty French Language Model `__ by Louis Martin*, Benjamin Muller*, Pedro Javier Ortiz Suárez*, Yoann Dupont, Laurent Romary, Éric Villemonte de la Clergerie, Djamé Seddah and Benoît Sagot. -12. :doc:`CLIP ` from (OpenAI) released with the paper `Learning Transferable Visual Models From +13. :doc:`CLIP ` from (OpenAI) released with the paper `Learning Transferable Visual Models From Natural Language Supervision `__ by Alec Radford, Jong Wook Kim, Chris Hallacy, Aditya Ramesh, Gabriel Goh, Sandhini Agarwal, Girish Sastry, Amanda Askell, Pamela Mishkin, Jack Clark, Gretchen Krueger, Ilya Sutskever. -13. :doc:`ConvBERT ` (from YituTech) released with the paper `ConvBERT: Improving BERT with +14. :doc:`ConvBERT ` (from YituTech) released with the paper `ConvBERT: Improving BERT with Span-based Dynamic Convolution `__ by Zihang Jiang, Weihao Yu, Daquan Zhou, Yunpeng Chen, Jiashi Feng, Shuicheng Yan. -14. :doc:`CPM ` (from Tsinghua University) released with the paper `CPM: A Large-scale Generative +15. :doc:`CPM ` (from Tsinghua University) released with the paper `CPM: A Large-scale Generative Chinese Pre-trained Language Model `__ by Zhengyan Zhang, Xu Han, Hao Zhou, Pei Ke, Yuxian Gu, Deming Ye, Yujia Qin, Yusheng Su, Haozhe Ji, Jian Guan, Fanchao Qi, Xiaozhi Wang, Yanan Zheng, Guoyang Zeng, Huanqi Cao, Shengqi Chen, Daixuan Li, Zhenbo Sun, Zhiyuan Liu, Minlie Huang, Wentao Han, Jie Tang, Juanzi Li, Xiaoyan Zhu, Maosong Sun. -15. :doc:`CTRL ` (from Salesforce) released with the paper `CTRL: A Conditional Transformer Language +16. :doc:`CTRL ` (from Salesforce) released with the paper `CTRL: A Conditional Transformer Language Model for Controllable Generation `__ by Nitish Shirish Keskar*, Bryan McCann*, Lav R. Varshney, Caiming Xiong and Richard Socher. -16. :doc:`DeBERTa ` (from Microsoft) released with the paper `DeBERTa: Decoding-enhanced BERT with +17. :doc:`DeBERTa ` (from Microsoft) released with the paper `DeBERTa: Decoding-enhanced BERT with Disentangled Attention `__ by Pengcheng He, Xiaodong Liu, Jianfeng Gao, Weizhu Chen. -17. :doc:`DeBERTa-v2 ` (from Microsoft) released with the paper `DeBERTa: Decoding-enhanced BERT +18. :doc:`DeBERTa-v2 ` (from Microsoft) released with the paper `DeBERTa: Decoding-enhanced BERT with Disentangled Attention `__ by Pengcheng He, Xiaodong Liu, Jianfeng Gao, Weizhu Chen. -18. :doc:`DeiT ` (from Facebook) released with the paper `Training data-efficient image transformers & +19. :doc:`DeiT ` (from Facebook) released with the paper `Training data-efficient image transformers & distillation through attention `__ by Hugo Touvron, Matthieu Cord, Matthijs Douze, Francisco Massa, Alexandre Sablayrolles, Hervé Jégou. -19. :doc:`DialoGPT ` (from Microsoft Research) released with the paper `DialoGPT: Large-Scale +20. :doc:`DialoGPT ` (from Microsoft Research) released with the paper `DialoGPT: Large-Scale Generative Pre-training for Conversational Response Generation `__ by Yizhe Zhang, Siqi Sun, Michel Galley, Yen-Chun Chen, Chris Brockett, Xiang Gao, Jianfeng Gao, Jingjing Liu, Bill Dolan. -20. :doc:`DistilBERT ` (from HuggingFace), released together with the paper `DistilBERT, a +21. :doc:`DistilBERT ` (from HuggingFace), released together with the paper `DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter `__ by Victor Sanh, Lysandre Debut and Thomas Wolf. The same method has been applied to compress GPT2 into `DistilGPT2 `__, RoBERTa into `DistilRoBERTa `__, Multilingual BERT into `DistilmBERT `__ and a German version of DistilBERT. -21. :doc:`DPR ` (from Facebook) released with the paper `Dense Passage Retrieval for Open-Domain +22. :doc:`DPR ` (from Facebook) released with the paper `Dense Passage Retrieval for Open-Domain Question Answering `__ by Vladimir Karpukhin, Barlas Oğuz, Sewon Min, Patrick Lewis, Ledell Wu, Sergey Edunov, Danqi Chen, and Wen-tau Yih. -22. :doc:`ELECTRA ` (from Google Research/Stanford University) released with the paper `ELECTRA: +23. :doc:`ELECTRA ` (from Google Research/Stanford University) released with the paper `ELECTRA: Pre-training text encoders as discriminators rather than generators `__ by Kevin Clark, Minh-Thang Luong, Quoc V. Le, Christopher D. Manning. -23. :doc:`FlauBERT ` (from CNRS) released with the paper `FlauBERT: Unsupervised Language Model +24. :doc:`FlauBERT ` (from CNRS) released with the paper `FlauBERT: Unsupervised Language Model Pre-training for French `__ by Hang Le, Loïc Vial, Jibril Frej, Vincent Segonne, Maximin Coavoux, Benjamin Lecouteux, Alexandre Allauzen, Benoît Crabbé, Laurent Besacier, Didier Schwab. -24. :doc:`Funnel Transformer ` (from CMU/Google Brain) released with the paper `Funnel-Transformer: +25. :doc:`Funnel Transformer ` (from CMU/Google Brain) released with the paper `Funnel-Transformer: Filtering out Sequential Redundancy for Efficient Language Processing `__ by Zihang Dai, Guokun Lai, Yiming Yang, Quoc V. Le. -25. :doc:`GPT ` (from OpenAI) released with the paper `Improving Language Understanding by Generative +26. :doc:`GPT ` (from OpenAI) released with the paper `Improving Language Understanding by Generative Pre-Training `__ by Alec Radford, Karthik Narasimhan, Tim Salimans and Ilya Sutskever. -26. :doc:`GPT-2 ` (from OpenAI) released with the paper `Language Models are Unsupervised Multitask +27. :doc:`GPT-2 ` (from OpenAI) released with the paper `Language Models are Unsupervised Multitask Learners `__ by Alec Radford*, Jeffrey Wu*, Rewon Child, David Luan, Dario Amodei** and Ilya Sutskever**. -27. :doc:`GPT Neo ` (from EleutherAI) released in the repository `EleutherAI/gpt-neo +28. :doc:`GPT Neo ` (from EleutherAI) released in the repository `EleutherAI/gpt-neo `__ by Sid Black, Stella Biderman, Leo Gao, Phil Wang and Connor Leahy. -28. :doc:`I-BERT ` (from Berkeley) released with the paper `I-BERT: Integer-only BERT Quantization +29. :doc:`I-BERT ` (from Berkeley) released with the paper `I-BERT: Integer-only BERT Quantization `__ by Sehoon Kim, Amir Gholami, Zhewei Yao, Michael W. Mahoney, Kurt Keutzer -29. :doc:`LayoutLM ` (from Microsoft Research Asia) released with the paper `LayoutLM: Pre-training +30. :doc:`LayoutLM ` (from Microsoft Research Asia) released with the paper `LayoutLM: Pre-training of Text and Layout for Document Image Understanding `__ by Yiheng Xu, Minghao Li, Lei Cui, Shaohan Huang, Furu Wei, Ming Zhou. -30. :doc:`LED ` (from AllenAI) released with the paper `Longformer: The Long-Document Transformer +31. :doc:`LED ` (from AllenAI) released with the paper `Longformer: The Long-Document Transformer `__ by Iz Beltagy, Matthew E. Peters, Arman Cohan. -31. :doc:`Longformer ` (from AllenAI) released with the paper `Longformer: The Long-Document +32. :doc:`Longformer ` (from AllenAI) released with the paper `Longformer: The Long-Document Transformer `__ by Iz Beltagy, Matthew E. Peters, Arman Cohan. -32. :doc:`LUKE ` (from Studio Ousia) released with the paper `LUKE: Deep Contextualized Entity +33. :doc:`LUKE ` (from Studio Ousia) released with the paper `LUKE: Deep Contextualized Entity Representations with Entity-aware Self-attention `__ by Ikuya Yamada, Akari Asai, Hiroyuki Shindo, Hideaki Takeda, Yuji Matsumoto. -33. :doc:`LXMERT ` (from UNC Chapel Hill) released with the paper `LXMERT: Learning Cross-Modality +34. :doc:`LXMERT ` (from UNC Chapel Hill) released with the paper `LXMERT: Learning Cross-Modality Encoder Representations from Transformers for Open-Domain Question Answering `__ by Hao Tan and Mohit Bansal. -34. :doc:`M2M100 ` (from Facebook) released with the paper `Beyond English-Centric Multilingual +35. :doc:`M2M100 ` (from Facebook) released with the paper `Beyond English-Centric Multilingual Machine Translation `__ by by Angela Fan, Shruti Bhosale, Holger Schwenk, Zhiyi Ma, Ahmed El-Kishky, Siddharth Goyal, Mandeep Baines, Onur Celebi, Guillaume Wenzek, Vishrav Chaudhary, Naman Goyal, Tom Birch, Vitaliy Liptchinsky, Sergey Edunov, Edouard Grave, Michael Auli, Armand Joulin. -35. :doc:`MarianMT ` Machine translation models trained using `OPUS `__ data by +36. :doc:`MarianMT ` Machine translation models trained using `OPUS `__ data by Jörg Tiedemann. The `Marian Framework `__ is being developed by the Microsoft Translator Team. -36. :doc:`MBart ` (from Facebook) released with the paper `Multilingual Denoising Pre-training for +37. :doc:`MBart ` (from Facebook) released with the paper `Multilingual Denoising Pre-training for Neural Machine Translation `__ by Yinhan Liu, Jiatao Gu, Naman Goyal, Xian Li, Sergey Edunov, Marjan Ghazvininejad, Mike Lewis, Luke Zettlemoyer. -37. :doc:`MBart-50 ` (from Facebook) released with the paper `Multilingual Translation with Extensible +38. :doc:`MBart-50 ` (from Facebook) released with the paper `Multilingual Translation with Extensible Multilingual Pretraining and Finetuning `__ by Yuqing Tang, Chau Tran, Xian Li, Peng-Jen Chen, Naman Goyal, Vishrav Chaudhary, Jiatao Gu, Angela Fan. -38. :doc:`Megatron-BERT ` (from NVIDIA) released with the paper `Megatron-LM: Training +39. :doc:`Megatron-BERT ` (from NVIDIA) released with the paper `Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism `__ by Mohammad Shoeybi, Mostofa Patwary, Raul Puri, Patrick LeGresley, Jared Casper and Bryan Catanzaro. -39. :doc:`Megatron-GPT2 ` (from NVIDIA) released with the paper `Megatron-LM: Training +40. :doc:`Megatron-GPT2 ` (from NVIDIA) released with the paper `Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism `__ by Mohammad Shoeybi, Mostofa Patwary, Raul Puri, Patrick LeGresley, Jared Casper and Bryan Catanzaro. -40. :doc:`MPNet ` (from Microsoft Research) released with the paper `MPNet: Masked and Permuted +41. :doc:`MPNet ` (from Microsoft Research) released with the paper `MPNet: Masked and Permuted Pre-training for Language Understanding `__ by Kaitao Song, Xu Tan, Tao Qin, Jianfeng Lu, Tie-Yan Liu. -41. :doc:`MT5 ` (from Google AI) released with the paper `mT5: A massively multilingual pre-trained +42. :doc:`MT5 ` (from Google AI) released with the paper `mT5: A massively multilingual pre-trained text-to-text transformer `__ by Linting Xue, Noah Constant, Adam Roberts, Mihir Kale, Rami Al-Rfou, Aditya Siddhant, Aditya Barua, Colin Raffel. -42. :doc:`Pegasus ` (from Google) released with the paper `PEGASUS: Pre-training with Extracted +43. :doc:`Pegasus ` (from Google) released with the paper `PEGASUS: Pre-training with Extracted Gap-sentences for Abstractive Summarization `__> by Jingqing Zhang, Yao Zhao, Mohammad Saleh and Peter J. Liu. -43. :doc:`ProphetNet ` (from Microsoft Research) released with the paper `ProphetNet: Predicting +44. :doc:`ProphetNet ` (from Microsoft Research) released with the paper `ProphetNet: Predicting Future N-gram for Sequence-to-Sequence Pre-training `__ by Yu Yan, Weizhen Qi, Yeyun Gong, Dayiheng Liu, Nan Duan, Jiusheng Chen, Ruofei Zhang and Ming Zhou. -44. :doc:`Reformer ` (from Google Research) released with the paper `Reformer: The Efficient +45. :doc:`Reformer ` (from Google Research) released with the paper `Reformer: The Efficient Transformer `__ by Nikita Kitaev, Łukasz Kaiser, Anselm Levskaya. -45. :doc:`RoBERTa ` (from Facebook), released together with the paper a `Robustly Optimized BERT +46. :doc:`RoBERTa ` (from Facebook), released together with the paper a `Robustly Optimized BERT Pretraining Approach `__ by Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar Joshi, Danqi Chen, Omer Levy, Mike Lewis, Luke Zettlemoyer, Veselin Stoyanov. -46. :doc:`RoFormer ` (from ZhuiyiTechnology), released together with the paper a `RoFormer: +47. :doc:`RoFormer ` (from ZhuiyiTechnology), released together with the paper a `RoFormer: Enhanced Transformer with Rotary Position Embedding `__ by Jianlin Su and Yu Lu and Shengfeng Pan and Bo Wen and Yunfeng Liu. -47. :doc:`SpeechToTextTransformer ` (from Facebook), released together with the paper +48. :doc:`SpeechToTextTransformer ` (from Facebook), released together with the paper `fairseq S2T: Fast Speech-to-Text Modeling with fairseq `__ by Changhan Wang, Yun Tang, Xutai Ma, Anne Wu, Dmytro Okhonko, Juan Pino. -48. :doc:`SqueezeBert ` released with the paper `SqueezeBERT: What can computer vision teach NLP +49. :doc:`SqueezeBert ` released with the paper `SqueezeBERT: What can computer vision teach NLP about efficient neural networks? `__ by Forrest N. Iandola, Albert E. Shaw, Ravi Krishna, and Kurt W. Keutzer. -49. :doc:`T5 ` (from Google AI) released with the paper `Exploring the Limits of Transfer Learning with a +50. :doc:`T5 ` (from Google AI) released with the paper `Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer `__ by Colin Raffel and Noam Shazeer and Adam Roberts and Katherine Lee and Sharan Narang and Michael Matena and Yanqi Zhou and Wei Li and Peter J. Liu. -50. :doc:`TAPAS ` (from Google AI) released with the paper `TAPAS: Weakly Supervised Table Parsing via +51. :doc:`TAPAS ` (from Google AI) released with the paper `TAPAS: Weakly Supervised Table Parsing via Pre-training `__ by Jonathan Herzig, Paweł Krzysztof Nowak, Thomas Müller, Francesco Piccinno and Julian Martin Eisenschlos. -51. :doc:`Transformer-XL ` (from Google/CMU) released with the paper `Transformer-XL: +52. :doc:`Transformer-XL ` (from Google/CMU) released with the paper `Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context `__ by Zihang Dai*, Zhilin Yang*, Yiming Yang, Jaime Carbonell, Quoc V. Le, Ruslan Salakhutdinov. -52. :doc:`Vision Transformer (ViT) ` (from Google AI) released with the paper `An Image is Worth 16x16 +53. :doc:`Vision Transformer (ViT) ` (from Google AI) released with the paper `An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale `__ by Alexey Dosovitskiy, Lucas Beyer, Alexander Kolesnikov, Dirk Weissenborn, Xiaohua Zhai, Thomas Unterthiner, Mostafa Dehghani, Matthias Minderer, Georg Heigold, Sylvain Gelly, Jakob Uszkoreit, Neil Houlsby. -53. :doc:`Wav2Vec2 ` (from Facebook AI) released with the paper `wav2vec 2.0: A Framework for +54. :doc:`Wav2Vec2 ` (from Facebook AI) released with the paper `wav2vec 2.0: A Framework for Self-Supervised Learning of Speech Representations `__ by Alexei Baevski, Henry Zhou, Abdelrahman Mohamed, Michael Auli. -54. :doc:`XLM ` (from Facebook) released together with the paper `Cross-lingual Language Model +55. :doc:`XLM ` (from Facebook) released together with the paper `Cross-lingual Language Model Pretraining `__ by Guillaume Lample and Alexis Conneau. -55. :doc:`XLM-ProphetNet ` (from Microsoft Research) released with the paper `ProphetNet: +56. :doc:`XLM-ProphetNet ` (from Microsoft Research) released with the paper `ProphetNet: Predicting Future N-gram for Sequence-to-Sequence Pre-training `__ by Yu Yan, Weizhen Qi, Yeyun Gong, Dayiheng Liu, Nan Duan, Jiusheng Chen, Ruofei Zhang and Ming Zhou. -56. :doc:`XLM-RoBERTa ` (from Facebook AI), released together with the paper `Unsupervised +57. :doc:`XLM-RoBERTa ` (from Facebook AI), released together with the paper `Unsupervised Cross-lingual Representation Learning at Scale `__ by Alexis Conneau*, Kartikay Khandelwal*, Naman Goyal, Vishrav Chaudhary, Guillaume Wenzek, Francisco Guzmán, Edouard Grave, Myle Ott, Luke Zettlemoyer and Veselin Stoyanov. -57. :doc:`XLNet ` (from Google/CMU) released with the paper `​XLNet: Generalized Autoregressive +58. :doc:`XLNet ` (from Google/CMU) released with the paper `​XLNet: Generalized Autoregressive Pretraining for Language Understanding `__ by Zhilin Yang*, Zihang Dai*, Yiming Yang, Jaime Carbonell, Ruslan Salakhutdinov, Quoc V. Le. -58. :doc:`XLSR-Wav2Vec2 ` (from Facebook AI) released with the paper `Unsupervised +59. :doc:`XLSR-Wav2Vec2 ` (from Facebook AI) released with the paper `Unsupervised Cross-Lingual Representation Learning For Speech Recognition `__ by Alexis Conneau, Alexei Baevski, Ronan Collobert, Abdelrahman Mohamed, Michael Auli. @@ -484,6 +487,7 @@ Flax), PyTorch, and/or TensorFlow. model_doc/blenderbot model_doc/blenderbot_small model_doc/bort + model_doc/byt5 model_doc/camembert model_doc/clip model_doc/convbert diff --git a/docs/source/model_doc/byt5.rst b/docs/source/model_doc/byt5.rst new file mode 100644 index 0000000000..ad8e272d0e --- /dev/null +++ b/docs/source/model_doc/byt5.rst @@ -0,0 +1,83 @@ +.. + Copyright 2021 The HuggingFace Team. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + specific language governing permissions and limitations under the License. + +ByT5 +----------------------------------------------------------------------------------------------------------------------- + +Overview +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ByT5 model was presented in `ByT5: Towards a token-free future with pre-trained byte-to-byte models +`_ by Linting Xue, Aditya Barua, Noah Constant, Rami Al-Rfou, Sharan Narang, Mihir +Kale, Adam Roberts, Colin Raffel. + +The abstract from the paper is the following: + +*Most widely-used pre-trained language models operate on sequences of tokens corresponding to word or subword units. +Encoding text as a sequence of tokens requires a tokenizer, which is typically created as an independent artifact from +the model. Token-free models that instead operate directly on raw text (bytes or characters) have many benefits: they +can process text in any language out of the box, they are more robust to noise, and they minimize technical debt by +removing complex and error-prone text preprocessing pipelines. Since byte or character sequences are longer than token +sequences, past work on token-free models has often introduced new model architectures designed to amortize the cost of +operating directly on raw text. In this paper, we show that a standard Transformer architecture can be used with +minimal modifications to process byte sequences. We carefully characterize the trade-offs in terms of parameter count, +training FLOPs, and inference speed, and show that byte-level models are competitive with their token-level +counterparts. We also demonstrate that byte-level models are significantly more robust to noise and perform better on +tasks that are sensitive to spelling and pronunciation. As part of our contribution, we release a new set of +pre-trained byte-level Transformer models based on the T5 architecture, as well as all code and data used in our +experiments.* + +This model was contributed by `patrickvonplaten `__. The original code can be +found `here `__. + + +ByT5's architecture is based on the T5 model, so one can refer to :doc:`T5's documentation page `. + + +Example +_______________________________________________________________________________________________________________________ + +ByT5 works on raw UTF-8 bytes, so it can be used without a tokenizer: + +.. code-block:: + + from transformers import T5ForConditionalGeneration + import torch + + model = T5ForConditionalGeneration.from_pretrained('google/byt5-small') + + input_ids = torch.tensor([list("Life is like a box of chocolates.".encode("utf-8"))]) + 3 # add 3 for special tokens + labels = torch.tensor([list("La vie est comme une boîte de chocolat.".encode("utf-8"))]) + 3 # add 3 for special tokens + + loss = model(input_ids, labels=labels).loss # forward pass + + +For batched inference and training it is however recommended to make use of the tokenizer: + +.. code-block:: + + from transformers import T5ForConditionalGeneration, AutoTokenizer + + model = T5ForConditionalGeneration.from_pretrained('google/byt5-small') + tokenizer = AutoTokenizer.from_pretrained('google/byt5-small') + + model_inputs = tokenizer(["Life is like a box of chocolates.", "Today is Monday."], padding="longest", return_tensors="pt") + labels = tokenizer(["La vie est comme une boîte de chocolat.", "Aujourd'hui c'est lundi."], padding="longest", return_tensors="pt").input_ids + + loss = model(**model_inputs, labels=labels).loss # forward pass + +ByT5Tokenizer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. autoclass:: transformers.ByT5Tokenizer + +See :class:`~transformers.ByT5Tokenizer` for all details. diff --git a/src/transformers/__init__.py b/src/transformers/__init__.py index 76c715c525..d7c7b23720 100755 --- a/src/transformers/__init__.py +++ b/src/transformers/__init__.py @@ -165,6 +165,7 @@ _import_structure = { "BlenderbotSmallConfig", "BlenderbotSmallTokenizer", ], + "models.byt5": ["ByT5Tokenizer"], "models.camembert": ["CAMEMBERT_PRETRAINED_CONFIG_ARCHIVE_MAP", "CamembertConfig"], "models.clip": [ "CLIP_PRETRAINED_CONFIG_ARCHIVE_MAP", @@ -1636,6 +1637,7 @@ if TYPE_CHECKING: BlenderbotSmallConfig, BlenderbotSmallTokenizer, ) + from .models.byt5 import ByT5Tokenizer from .models.camembert import CAMEMBERT_PRETRAINED_CONFIG_ARCHIVE_MAP, CamembertConfig from .models.clip import ( CLIP_PRETRAINED_CONFIG_ARCHIVE_MAP, diff --git a/src/transformers/models/auto/tokenization_auto.py b/src/transformers/models/auto/tokenization_auto.py index bd2210af11..7434a7d663 100644 --- a/src/transformers/models/auto/tokenization_auto.py +++ b/src/transformers/models/auto/tokenization_auto.py @@ -27,6 +27,7 @@ from ..bert_japanese.tokenization_bert_japanese import BertJapaneseTokenizer from ..bertweet.tokenization_bertweet import BertweetTokenizer from ..blenderbot.tokenization_blenderbot import BlenderbotTokenizer from ..blenderbot_small.tokenization_blenderbot_small import BlenderbotSmallTokenizer +from ..byt5.tokenization_byt5 import ByT5Tokenizer from ..convbert.tokenization_convbert import ConvBertTokenizer from ..ctrl.tokenization_ctrl import CTRLTokenizer from ..deberta.tokenization_deberta import DebertaTokenizer @@ -287,6 +288,7 @@ TOKENIZER_MAPPING = OrderedDict( NO_CONFIG_TOKENIZER = [ BertJapaneseTokenizer, BertweetTokenizer, + ByT5Tokenizer, CpmTokenizer, HerbertTokenizer, HerbertTokenizerFast, diff --git a/src/transformers/models/byt5/__init__.py b/src/transformers/models/byt5/__init__.py new file mode 100644 index 0000000000..4998bf6a0d --- /dev/null +++ b/src/transformers/models/byt5/__init__.py @@ -0,0 +1,47 @@ +# flake8: noqa +# There's no way to ignore "F401 '...' imported but unused" warnings in this +# module, but to preserve other warnings. So, don't check this module at all. + +# Copyright 2021 The HuggingFace Team. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import TYPE_CHECKING + +from ...file_utils import _BaseLazyModule + + +_import_structure = { + "tokenization_byt5": ["ByT5Tokenizer"], +} + + +if TYPE_CHECKING: + from .tokenization_byt5 import ByT5Tokenizer +else: + import importlib + import os + import sys + + class _LazyModule(_BaseLazyModule): + """ + Module class that surfaces all objects but only performs associated imports when the objects are requested. + """ + + __file__ = globals()["__file__"] + __path__ = [os.path.dirname(__file__)] + + def _get_module(self, module_name: str): + return importlib.import_module("." + module_name, self.__name__) + + sys.modules[__name__] = _LazyModule(__name__, _import_structure) diff --git a/src/transformers/models/byt5/convert_byt5_original_tf_checkpoint_to_pytorch.py b/src/transformers/models/byt5/convert_byt5_original_tf_checkpoint_to_pytorch.py new file mode 100755 index 0000000000..a002030168 --- /dev/null +++ b/src/transformers/models/byt5/convert_byt5_original_tf_checkpoint_to_pytorch.py @@ -0,0 +1,59 @@ +# coding=utf-8 +# Copyright 2018 The T5 authors and HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Convert T5 checkpoint.""" + + +import argparse + +from transformers import T5Config, T5ForConditionalGeneration, load_tf_weights_in_t5 +from transformers.utils import logging + + +logging.set_verbosity_info() + + +def convert_tf_checkpoint_to_pytorch(tf_checkpoint_path, config_file, pytorch_dump_path): + # Initialise PyTorch model + config = T5Config.from_json_file(config_file) + print(f"Building PyTorch model from configuration: {config}") + model = T5ForConditionalGeneration(config) + + # Load weights from tf checkpoint + load_tf_weights_in_t5(model, config, tf_checkpoint_path) + + # Save pytorch-model + print(f"Save PyTorch model to {pytorch_dump_path}") + model.save_pretrained(pytorch_dump_path) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + # Required parameters + parser.add_argument( + "--tf_checkpoint_path", default=None, type=str, required=True, help="Path to the TensorFlow checkpoint path." + ) + parser.add_argument( + "--config_file", + default=None, + type=str, + required=True, + help="The config json file corresponding to the pre-trained T5 model. \n" + "This specifies the model architecture.", + ) + parser.add_argument( + "--pytorch_dump_path", default=None, type=str, required=True, help="Path to the output PyTorch model." + ) + args = parser.parse_args() + convert_tf_checkpoint_to_pytorch(args.tf_checkpoint_path, args.config_file, args.pytorch_dump_path) diff --git a/src/transformers/models/byt5/tokenization_byt5.py b/src/transformers/models/byt5/tokenization_byt5.py new file mode 100644 index 0000000000..d89762a28e --- /dev/null +++ b/src/transformers/models/byt5/tokenization_byt5.py @@ -0,0 +1,268 @@ +# coding=utf-8 +# Copyright 2021 T5 Authors and HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" Tokenization class for model ByT5.""" + + +import re +import warnings +from typing import Dict, List, Optional, Tuple + +from ...tokenization_utils import AddedToken, PreTrainedTokenizer +from ...utils import logging + + +logger = logging.get_logger(__name__) + + +class ByT5Tokenizer(PreTrainedTokenizer): + """ + Construct a ByT5 tokenizer. ByT5 simply uses raw bytes utf-8 encoding. + + This tokenizer inherits from :class:`~transformers.PreTrainedTokenizer` which contains most of the main methods. + Users should refer to this superclass for more information regarding those methods. + + Args: + eos_token (:obj:`str`, `optional`, defaults to :obj:`""`): + The end of sequence token. + + .. note:: + + When building a sequence using special tokens, this is not the token that is used for the end of + sequence. The token used is the :obj:`sep_token`. + unk_token (:obj:`str`, `optional`, defaults to :obj:`""`): + The unknown token. A token that is not in the vocabulary cannot be converted to an ID and is set to be this + token instead. + pad_token (:obj:`str`, `optional`, defaults to :obj:`""`): + The token used for padding, for example when batching sequences of different lengths. + extra_ids (:obj:`int`, `optional`, defaults to 100): + Add a number of extra ids added to the end of the vocabulary for use as sentinels. These tokens are + accessible as "" where "{%d}" is a number between 0 and extra_ids-1. Extra tokens are + indexed from the end of the vocabulary up to beginning ("" is the last token in the vocabulary + like in ByT5 preprocessing see `here + `__). + additional_special_tokens (:obj:`List[str]`, `optional`): + Additional special tokens used by the tokenizer. + """ + + model_input_names = ["input_ids", "attention_mask"] + + def __init__( + self, + eos_token="", + unk_token="", + pad_token="", + extra_ids=125, + additional_special_tokens=None, + **kwargs + ) -> None: + # Add extra_ids to the special token list + if extra_ids > 0 and additional_special_tokens is None: + additional_special_tokens = [f"" for i in range(extra_ids)] + elif extra_ids > 0 and additional_special_tokens is not None: + # Check that we have the right number of extra_id special tokens + extra_tokens = len(set(filter(lambda x: bool("extra_id" in str(x)), additional_special_tokens))) + if extra_tokens != extra_ids: + raise ValueError( + f"Both extra_ids ({extra_ids}) and additional_special_tokens ({additional_special_tokens}) are provided to ByT5Tokenizer. " + "In this case the additional_special_tokens must include the extra_ids tokens" + ) + + pad_token = AddedToken(pad_token, lstrip=False, rstrip=False) if isinstance(pad_token, str) else pad_token + eos_token = AddedToken(eos_token, lstrip=False, rstrip=False) if isinstance(eos_token, str) else eos_token + unk_token = AddedToken(unk_token, lstrip=False, rstrip=False) if isinstance(unk_token, str) else unk_token + + super().__init__( + eos_token=eos_token, + unk_token=unk_token, + pad_token=pad_token, + extra_ids=extra_ids, + additional_special_tokens=additional_special_tokens, + **kwargs, + ) + + # define special tokens dict + self.special_tokens_encoder: Dict[int, str] = { + self.pad_token: 0, + self.eos_token: 1, + self.unk_token: 2, + } + self.special_tokens_decoder: Dict[str, int] = {v: k for k, v in self.special_tokens_encoder.items()} + + self._num_special_tokens = len(self.special_tokens_encoder) + self._utf_vocab_size = 2 ** 8 # utf is 8 bits + self._extra_ids = extra_ids + + @property + def vocab_size(self): + return self._utf_vocab_size + self._num_special_tokens + self._extra_ids + + def get_special_tokens_mask( + self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None, already_has_special_tokens: bool = False + ) -> List[int]: + """ + Retrieve sequence ids from a token list that has no special tokens added. This method is called when adding + special tokens using the tokenizer ``prepare_for_model`` method. + + Args: + token_ids_0 (:obj:`List[int]`): + List of IDs. + token_ids_1 (:obj:`List[int]`, `optional`): + Optional second list of IDs for sequence pairs. + already_has_special_tokens (:obj:`bool`, `optional`, defaults to :obj:`False`): + Whether or not the token list is already formatted with special tokens for the model. + + Returns: + :obj:`List[int]`: A list of integers in the range [0, 1]: 1 for a special token, 0 for a sequence token. + """ + if already_has_special_tokens: + return super().get_special_tokens_mask( + token_ids_0=token_ids_0, token_ids_1=token_ids_1, already_has_special_tokens=True + ) + + # normal case: some special tokens + if token_ids_1 is None: + return ([0] * len(token_ids_0)) + [1] + return ([0] * len(token_ids_0)) + [1] + ([0] * len(token_ids_1)) + [1] + + def _add_eos_if_not_present(self, token_ids: List[int]) -> List[int]: + """Do not add eos again if user already added it.""" + if len(token_ids) > 0 and token_ids[-1] == self.eos_token_id: + warnings.warn( + f"This sequence already has {self.eos_token}. In future versions this behavior may lead to duplicated eos tokens being added." + ) + return token_ids + else: + return token_ids + [self.eos_token_id] + + def create_token_type_ids_from_sequences( + self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None + ) -> List[int]: + """ + Create a mask from the two sequences passed to be used in a sequence-pair classification task. ByT5 does not + make use of token type ids, therefore a list of zeros is returned. + + Args: + token_ids_0 (:obj:`List[int]`): + List of IDs. + token_ids_1 (:obj:`List[int]`, `optional`): + Optional second list of IDs for sequence pairs. + + Returns: + :obj:`List[int]`: List of zeros. + """ + eos = [self.eos_token_id] + + if token_ids_1 is None: + return len(token_ids_0 + eos) * [0] + return len(token_ids_0 + eos + token_ids_1 + eos) * [0] + + def build_inputs_with_special_tokens( + self, token_ids_0: List[int], token_ids_1: Optional[List[int]] = None + ) -> List[int]: + """ + Build model inputs from a sequence or a pair of sequence for sequence classification tasks by concatenating and + adding special tokens. A sequence has the following format: + + - single sequence: ``X `` + - pair of sequences: ``A B `` + + Args: + token_ids_0 (:obj:`List[int]`): + List of IDs to which the special tokens will be added. + token_ids_1 (:obj:`List[int]`, `optional`): + Optional second list of IDs for sequence pairs. + + Returns: + :obj:`List[int]`: List of `input IDs <../glossary.html#input-ids>`__ with the appropriate special tokens. + """ + token_ids_0 = self._add_eos_if_not_present(token_ids_0) + if token_ids_1 is None: + return token_ids_0 + else: + token_ids_1 = self._add_eos_if_not_present(token_ids_1) + return token_ids_0 + token_ids_1 + + def _tokenize(self, text: str) -> List[str]: + """Take as input a string and return a list of strings (tokens) for words/sub-words""" + + def _sub_tokenize(sub_text): + character_list = list(sub_text) + utf_tokens_lists = [list(char.encode("utf-8")) for char in character_list] + sub_tokens = [chr(utf_token) for utf_tokens in utf_tokens_lists for utf_token in utf_tokens] + return sub_tokens + + # split on special characters + pattern = f"({'|'.join(self.special_tokens_encoder.keys())})" + sub_texts = list(filter(None, re.split(pattern, text))) + tokens = [] + for sub_text in sub_texts: + if sub_text in self.special_tokens_encoder.keys(): + tokens += [sub_text] + else: + tokens += _sub_tokenize(sub_text) + + return tokens + + def _convert_token_to_id(self, token): + """Converts a token (str) in an id using the vocab.""" + if token.startswith("", token) + num = int(match.group(1)) + token_id = self.vocab_size - num - 1 + elif token in self.special_tokens_encoder: + token_id = self.special_tokens_encoder[token] + elif len(token) > 1: + # token of length > 1 must be newly added tokens => set them to unk token + token_id = self.unk_token_id + else: + token_id = ord(token) + self._num_special_tokens + return token_id + + def _convert_id_to_token(self, index): + """Converts an index (integer) in a token (str) using the vocab.""" + if index < self._num_special_tokens: + token = self.special_tokens_decoder[index] + elif index < self._utf_vocab_size + self._num_special_tokens: + token = chr(index - self._num_special_tokens) + else: + token = f"" + return token + + def convert_tokens_to_string(self, tokens): + """Converts a sequence of tokens (string) in a single string.""" + + def _convert_sub_string(sub_chars): + byte_string = bytes([ord(char) for char in sub_chars]) + return byte_string.decode("utf-8", errors="ignore") + + string = "" + sub_chars = [] + for token in tokens: + # if is special token + if len(token) > 1: + string += _convert_sub_string(sub_chars) + string += token + sub_chars = [] + else: + sub_chars.append(token) + + # add remaining chars + string += _convert_sub_string(sub_chars) + + return string + + # ByT5Tokenizer has no vocab file + def save_vocabulary(self, save_directory: str, filename_prefix: Optional[str] = None) -> Tuple[str]: + return () diff --git a/src/transformers/models/t5/modeling_tf_t5.py b/src/transformers/models/t5/modeling_tf_t5.py index 284fdb1573..e6de2e4c48 100644 --- a/src/transformers/models/t5/modeling_tf_t5.py +++ b/src/transformers/models/t5/modeling_tf_t5.py @@ -1092,6 +1092,7 @@ class TFT5Model(TFT5PreTrainedModel): decoder_config = copy.deepcopy(config) decoder_config.is_decoder = True + decoder_config.num_layers = config.num_decoder_layers self.decoder = TFT5MainLayer(decoder_config, embed_tokens, name="decoder") def get_encoder(self): @@ -1255,6 +1256,7 @@ class TFT5ForConditionalGeneration(TFT5PreTrainedModel, TFCausalLanguageModeling decoder_config = copy.deepcopy(config) decoder_config.is_decoder = True + decoder_config.num_layers = config.num_decoder_layers self.decoder = TFT5MainLayer(decoder_config, embed_tokens, name="decoder") if not config.tie_word_embeddings: diff --git a/tests/test_modeling_t5.py b/tests/test_modeling_t5.py index f020447d00..c8fe6717ab 100644 --- a/tests/test_modeling_t5.py +++ b/tests/test_modeling_t5.py @@ -30,7 +30,7 @@ from .test_modeling_common import ModelTesterMixin, ids_tensor if is_torch_available(): import torch - from transformers import T5Config, T5EncoderModel, T5ForConditionalGeneration, T5Model, T5Tokenizer + from transformers import ByT5Tokenizer, T5Config, T5EncoderModel, T5ForConditionalGeneration, T5Model, T5Tokenizer from transformers.models.t5.modeling_t5 import T5_PRETRAINED_MODEL_ARCHIVE_LIST @@ -846,6 +846,30 @@ class T5ModelIntegrationTests(unittest.TestCase): EXPECTED_SCORE = -59.0293 self.assertTrue(abs(mtf_score - EXPECTED_SCORE) < 1e-4) + @slow + def test_small_byt5_integration_test(self): + """ + For comparision run: + >>> import t5 # pip install t5==0.9.1 + + >>> path_to_byt5_small_checkpoint = '' + >>> t5_model = t5.models.MtfModel(model_dir=path_to_tf_checkpoint, batch_size=1, tpu=None) + >>> vocab = t5.data.ByteVocabulary() + >>> score = t5_model.score(inputs=["Hello there"], targets=["Hi I am"], vocabulary=vocab) + """ + + model = T5ForConditionalGeneration.from_pretrained("google/byt5-small").to(torch_device) + tokenizer = ByT5Tokenizer.from_pretrained("google/byt5-small") + + input_ids = tokenizer("Hello there", return_tensors="pt").input_ids + labels = tokenizer("Hi I am", return_tensors="pt").input_ids + + loss = model(input_ids.to(torch_device), labels=labels.to(torch_device)).loss + mtf_score = -(labels.shape[-1] * loss.item()) + + EXPECTED_SCORE = -60.7397 + self.assertTrue(abs(mtf_score - EXPECTED_SCORE) < 1e-4) + @slow def test_summarization(self): model = self.model diff --git a/tests/test_modeling_tf_t5.py b/tests/test_modeling_tf_t5.py index a902363fbd..55f7c86277 100644 --- a/tests/test_modeling_tf_t5.py +++ b/tests/test_modeling_tf_t5.py @@ -26,7 +26,7 @@ from .test_modeling_tf_common import TFModelTesterMixin, ids_tensor if is_tf_available(): import tensorflow as tf - from transformers import T5Tokenizer, TFT5EncoderModel, TFT5ForConditionalGeneration, TFT5Model + from transformers import ByT5Tokenizer, T5Tokenizer, TFT5EncoderModel, TFT5ForConditionalGeneration, TFT5Model class TFT5ModelTester: @@ -499,6 +499,30 @@ class TFT5ModelIntegrationTests(unittest.TestCase): EXPECTED_SCORE = -59.0293 self.assertTrue(abs(mtf_score - EXPECTED_SCORE) < 1e-4) + @slow + def test_small_byt5_integration_test(self): + """ + For comparision run: + >>> import t5 # pip install t5==0.9.1 + + >>> path_to_byt5_small_checkpoint = '' + >>> t5_model = t5.models.MtfModel(model_dir=path_to_tf_checkpoint, batch_size=1, tpu=None) + >>> vocab = t5.data.ByteVocabulary() + >>> score = t5_model.score(inputs=["Hello there"], targets=["Hi I am"], vocabulary=vocab) + """ + + model = TFT5ForConditionalGeneration.from_pretrained("google/byt5-small") + tokenizer = ByT5Tokenizer.from_pretrained("google/byt5-small") + + input_ids = tokenizer("Hello there", return_tensors="tf").input_ids + labels = tokenizer("Hi I am", return_tensors="tf").input_ids + + loss = model(input_ids, labels=labels).loss + mtf_score = -tf.math.reduce_sum(loss).numpy() + + EXPECTED_SCORE = -60.7397 + self.assertTrue(abs(mtf_score - EXPECTED_SCORE) < 1e-4) + @slow def test_summarization(self): model = self.model diff --git a/tests/test_tokenization_byt5.py b/tests/test_tokenization_byt5.py new file mode 100644 index 0000000000..79c2f0005c --- /dev/null +++ b/tests/test_tokenization_byt5.py @@ -0,0 +1,178 @@ +# coding=utf-8 +# Copyright 2020 Google T5 Authors and HuggingFace Inc. team. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import shutil +import tempfile +import unittest + +from transformers import BatchEncoding, ByT5Tokenizer +from transformers.file_utils import cached_property, is_tf_available, is_torch_available + +from .test_tokenization_common import TokenizerTesterMixin + + +if is_torch_available(): + FRAMEWORK = "pt" +elif is_tf_available(): + FRAMEWORK = "tf" +else: + FRAMEWORK = "jax" + + +class ByT5TokenizationTest(TokenizerTesterMixin, unittest.TestCase): + + tokenizer_class = ByT5Tokenizer + test_rust_tokenizer = False + + def setUp(self): + super().setUp() + tokenizer = ByT5Tokenizer() + tokenizer.save_pretrained(self.tmpdirname) + + @cached_property + def t5_base_tokenizer(self): + return ByT5Tokenizer.from_pretrained("google/byt5-small") + + def get_tokenizer(self, **kwargs) -> ByT5Tokenizer: + return self.tokenizer_class.from_pretrained(self.tmpdirname, **kwargs) + + def test_eos_treatment(self): + tokenizer = self.t5_base_tokenizer + batch_with_eos_added = tokenizer(["hi", "I went to the gym", ""]) + batch_without_eos_added = tokenizer(["hi", "I went to the gym", ""]) + self.assertListEqual(batch_with_eos_added["input_ids"], batch_without_eos_added["input_ids"]) + + def test_prepare_batch_integration(self): + tokenizer = self.t5_base_tokenizer + src_text = ["A long paragraph for summarization.", "Another paragraph for summarization."] + # fmt: off + expected_src_tokens = [68, 35, 111, 114, 113, 106, 35, 115, 100, 117, 100, 106, 117, 100, 115, 107, 35, 105, 114, 117, 35, 118, 120, 112, 112, 100, 117, 108, 125, 100, 119, 108, 114, 113, 49, 1, 0] + # fmt: on + batch = tokenizer(src_text, padding=True, return_tensors=FRAMEWORK) + self.assertIsInstance(batch, BatchEncoding) + + if FRAMEWORK != "jax": + result = list(batch.input_ids.numpy()[0]) + else: + result = list(batch.input_ids.tolist()[0]) + + self.assertListEqual(expected_src_tokens, result) + + self.assertEqual((2, 37), batch.input_ids.shape) + self.assertEqual((2, 37), batch.attention_mask.shape) + + def test_empty_target_text(self): + tokenizer = self.t5_base_tokenizer + src_text = ["A long paragraph for summarization.", "Another paragraph for summarization."] + batch = tokenizer(src_text, padding=True, return_tensors=FRAMEWORK) + # check if input_ids are returned and no decoder_input_ids + self.assertIn("input_ids", batch) + self.assertIn("attention_mask", batch) + self.assertNotIn("decoder_input_ids", batch) + self.assertNotIn("decoder_attention_mask", batch) + + def test_max_length_integration(self): + tokenizer = self.t5_base_tokenizer + tgt_text = [ + "Summary of the text.", + "Another summary.", + ] + with tokenizer.as_target_tokenizer(): + targets = tokenizer( + tgt_text, max_length=32, padding="max_length", truncation=True, return_tensors=FRAMEWORK + ) + self.assertEqual(32, targets["input_ids"].shape[1]) + + def test_eos_in_input(self): + tokenizer = self.t5_base_tokenizer + src_text = ["A long paragraph for summarization. "] + tgt_text = ["Summary of the text. "] + # fmt: off + expected_src_tokens = [68, 35, 111, 114, 113, 106, 35, 115, 100, 117, 100, 106, 117, 100, 115, 107, 35, 105, 114, 117, 35, 118, 120, 112, 112, 100, 117, 108, 125, 100, 119, 108, 114, 113, 49, 35, 1] + expected_tgt_tokens = [86, 120, 112, 112, 100, 117, 124, 35, 114, 105, 35, 119, 107, 104, 35, 119, 104, 123, 119, 49, 35, 1] + # fmt: on + + batch = tokenizer(src_text) + with tokenizer.as_target_tokenizer(): + targets = tokenizer(tgt_text) + + self.assertEqual(expected_src_tokens, batch["input_ids"][0]) + self.assertEqual(expected_tgt_tokens, targets["input_ids"][0]) + + # cannot use default save_and_load_tokenzier test method because tokenzier has no vocab + def test_save_and_load_tokenizer(self): + # safety check on max_len default value so we are sure the test works + tokenizers = self.get_tokenizers() + for tokenizer in tokenizers: + with self.subTest(f"{tokenizer.__class__.__name__}"): + self.assertNotEqual(tokenizer.model_max_length, 42) + + # Now let's start the test + tokenizers = self.get_tokenizers() + for tokenizer in tokenizers: + with self.subTest(f"{tokenizer.__class__.__name__}"): + # Isolate this from the other tests because we save additional tokens/etc + tmpdirname = tempfile.mkdtemp() + + sample_text = " He is very happy, UNwant\u00E9d,running" + before_tokens = tokenizer.encode(sample_text, add_special_tokens=False) + tokenizer.save_pretrained(tmpdirname) + + after_tokenizer = tokenizer.__class__.from_pretrained(tmpdirname) + after_tokens = after_tokenizer.encode(sample_text, add_special_tokens=False) + self.assertListEqual(before_tokens, after_tokens) + + shutil.rmtree(tmpdirname) + + tokenizers = self.get_tokenizers(model_max_length=42) + for tokenizer in tokenizers: + with self.subTest(f"{tokenizer.__class__.__name__}"): + # Isolate this from the other tests because we save additional tokens/etc + tmpdirname = tempfile.mkdtemp() + + sample_text = " He is very happy, UNwant\u00E9d,running" + tokenizer.add_tokens(["bim", "bambam"]) + additional_special_tokens = tokenizer.additional_special_tokens + additional_special_tokens.append("new_additional_special_token") + tokenizer.add_special_tokens({"additional_special_tokens": additional_special_tokens}) + before_tokens = tokenizer.encode(sample_text, add_special_tokens=False) + tokenizer.save_pretrained(tmpdirname) + + after_tokenizer = tokenizer.__class__.from_pretrained(tmpdirname) + after_tokens = after_tokenizer.encode(sample_text, add_special_tokens=False) + self.assertListEqual(before_tokens, after_tokens) + self.assertIn("new_additional_special_token", after_tokenizer.additional_special_tokens) + self.assertEqual(after_tokenizer.model_max_length, 42) + + tokenizer = tokenizer.__class__.from_pretrained(tmpdirname, model_max_length=43) + self.assertEqual(tokenizer.model_max_length, 43) + + shutil.rmtree(tmpdirname) + + # tokenizer can be instantiated without any pretrained files, so no need for pretrained tokenizer list + def test_pretrained_model_lists(self): + pass + + # tokenizer does not have vocabulary + def test_get_vocab(self): + pass + + # inputs cannot be pretokenized since ids depend on whole input string and not just on single characters + def test_pretokenized_inputs(self): + pass + + # tests all ids in vocab => vocab doesn't exist so unnecessary to test + def test_conversion_reversible(self): + pass