Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
112571f2f3 |
No files matched your search
@@ -77,7 +77,6 @@ jobs:
|
||||
- v0.3-torch_and_tf-{{ checksum "setup.py" }}
|
||||
- v0.3-{{ checksum "setup.py" }}
|
||||
- run: pip install --upgrade pip
|
||||
- run: pip install git+https://github.com/huggingface/nlp
|
||||
- run: pip install .[sklearn,tf-cpu,torch,testing]
|
||||
- run: pip install codecov pytest-cov
|
||||
- save_cache:
|
||||
@@ -104,7 +103,6 @@ jobs:
|
||||
- v0.3-torch-{{ checksum "setup.py" }}
|
||||
- v0.3-{{ checksum "setup.py" }}
|
||||
- run: pip install --upgrade pip
|
||||
- run: pip install git+https://github.com/huggingface/nlp
|
||||
- run: pip install .[sklearn,torch,testing]
|
||||
- save_cache:
|
||||
key: v0.3-torch-{{ checksum "setup.py" }}
|
||||
@@ -129,7 +127,6 @@ jobs:
|
||||
- v0.3-tf-{{ checksum "setup.py" }}
|
||||
- v0.3-{{ checksum "setup.py" }}
|
||||
- run: pip install --upgrade pip
|
||||
- run: pip install git+https://github.com/huggingface/nlp
|
||||
- run: pip install .[sklearn,tf-cpu,testing]
|
||||
- save_cache:
|
||||
key: v0.3-tf-{{ checksum "setup.py" }}
|
||||
@@ -153,7 +150,6 @@ jobs:
|
||||
- v0.3-{{ checksum "setup.py" }}
|
||||
- run: pip install --upgrade pip
|
||||
- run: pip install .[ja,testing]
|
||||
- run: python -m unidic download
|
||||
- save_cache:
|
||||
key: v0.3-custom_tokenizers-{{ checksum "setup.py" }}
|
||||
paths:
|
||||
@@ -238,7 +234,8 @@ jobs:
|
||||
- v0.3-code_quality-{{ checksum "setup.py" }}
|
||||
- v0.3-{{ checksum "setup.py" }}
|
||||
- run: pip install --upgrade pip
|
||||
- run: pip install isort
|
||||
# we need a version of isort with https://github.com/timothycrosley/isort/pull/1000
|
||||
- run: pip install git+git://github.com/timothycrosley/isort.git@e63ae06ec7d70b06df9e528357650281a3d3ec22#egg=isort
|
||||
- run: pip install .[tf,torch,quality]
|
||||
- save_cache:
|
||||
key: v0.3-code_quality-{{ checksum "setup.py" }}
|
||||
|
||||
@@ -45,8 +45,7 @@ assignees: ''
|
||||
TransfoXL/XLNet: @TevenLeScao
|
||||
examples/seq2seq: @sshleifer
|
||||
examples/bert-loses-patience: @JetRunner
|
||||
tensorflow: @jplu
|
||||
examples/token-classification: @stefan-it
|
||||
tensorflow: @jplu
|
||||
documentation: @sgugger
|
||||
-->
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<!-- This line specifies which issue to close after the pull request is merged. -->
|
||||
Fixes #{issue number}
|
||||
@@ -45,8 +45,7 @@ jobs:
|
||||
source .env/bin/activate
|
||||
pip install --upgrade pip
|
||||
pip install torch!=1.6.0
|
||||
pip install .[sklearn,testing,onnxruntime]
|
||||
pip install git+https://github.com/huggingface/nlp
|
||||
pip install .[sklearn,testing]
|
||||
|
||||
- name: Are GPUs recognized by our DL frameworks
|
||||
run: |
|
||||
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
source .env/bin/activate
|
||||
pip install --upgrade pip
|
||||
pip install torch!=1.6.0
|
||||
pip install .[sklearn,testing,onnxruntime]
|
||||
pip install .[sklearn,testing]
|
||||
|
||||
- name: Are GPUs recognized by our DL frameworks
|
||||
run: |
|
||||
@@ -58,7 +58,6 @@ jobs:
|
||||
run: |
|
||||
source .env/bin/activate
|
||||
python -m pytest -n 1 --dist=loadfile -s ./tests/
|
||||
|
||||
- name: Run examples tests on GPU
|
||||
env:
|
||||
TF_FORCE_GPU_ALLOW_GROWTH: "true"
|
||||
|
||||
+17
-19
@@ -65,7 +65,7 @@ Awesome! Please provide the following information:
|
||||
If you are willing to contribute the model yourself, let us know so we can best
|
||||
guide you.
|
||||
|
||||
We have added a **detailed guide and templates** to guide you in the process of adding a new model. You can find them
|
||||
We have added a **detailed guide and templates** to guide you in the process of adding a new model. You can find them
|
||||
in the [`templates`](https://github.com/huggingface/transformers/tree/master/templates) folder.
|
||||
|
||||
### Do you want a new feature (that is not a model)?
|
||||
@@ -87,8 +87,8 @@ A world-class feature request addresses the following points:
|
||||
If your issue is well written we're already 80% of the way there by the time you
|
||||
post it.
|
||||
|
||||
We have added **templates** to guide you in the process of adding a new example script for training or testing the
|
||||
models in the library. You can find them in the [`templates`](https://github.com/huggingface/transformers/tree/master/templates)
|
||||
We have added **templates** to guide you in the process of adding a new example script for training or testing the
|
||||
models in the library. You can find them in the [`templates`](https://github.com/huggingface/transformers/tree/master/templates)
|
||||
folder.
|
||||
|
||||
## Start contributing! (Pull Requests)
|
||||
@@ -134,6 +134,12 @@ Follow these steps to start contributing:
|
||||
it with `pip uninstall transformers` before reinstalling it in editable
|
||||
mode with the `-e` flag.)
|
||||
|
||||
Right now, we need an unreleased version of `isort` to avoid a
|
||||
[bug](https://github.com/timothycrosley/isort/pull/1000):
|
||||
|
||||
```bash
|
||||
$ pip install -U git+git://github.com/timothycrosley/isort.git@e63ae06ec7d70b06df9e528357650281a3d3ec22#egg=isort
|
||||
```
|
||||
5. Develop the features on your branch.
|
||||
|
||||
As you work on the features, you should make sure that the test suite
|
||||
@@ -143,14 +149,6 @@ Follow these steps to start contributing:
|
||||
$ make test
|
||||
```
|
||||
|
||||
Note, that this command uses `-n auto` pytest flag, therefore, it will start as many parallel `pytest` processes as the number of your computer's CPU-cores, and if you have lots of those and a few GPUs and not a great amount of RAM, it's likely to overload your computer. Therefore, to run the test suite, you may want to consider using this command instead:
|
||||
|
||||
```bash
|
||||
$ python -m pytest -n 3 --dist=loadfile -s -v ./tests/
|
||||
```
|
||||
|
||||
Adjust the value of `-n` to fit the load your hardware can support.
|
||||
|
||||
`transformers` relies on `black` and `isort` to format its source code
|
||||
consistently. After you make changes, format them with:
|
||||
|
||||
@@ -210,21 +208,21 @@ Follow these steps to start contributing:
|
||||
are useful to avoid duplicated work, and to differentiate it from PRs ready
|
||||
to be merged;
|
||||
4. Make sure existing tests pass;
|
||||
5. Add high-coverage tests. No quality testing = no merge.
|
||||
- If you are adding a new model, make sure that you use
|
||||
5. Add high-coverage tests. No quality testing = no merge.
|
||||
- If you are adding a new model, make sure that you use
|
||||
`ModelTester.all_model_classes = (MyModel, MyModelWithLMHead,...)`, which triggers the common tests.
|
||||
- If you are adding new `@slow` tests, make sure they pass using
|
||||
`RUN_SLOW=1 python -m pytest tests/test_my_new_model.py`.
|
||||
- If you are adding a new tokenizer, write tests, and make sure
|
||||
- If you are adding new `@slow` tests, make sure they pass using
|
||||
`RUN_SLOW=1 python -m pytest tests/test_my_new_model.py`.
|
||||
- If you are adding a new tokenizer, write tests, and make sure
|
||||
`RUN_SLOW=1 python -m pytest tests/test_tokenization_{your_model_name}.py` passes.
|
||||
CircleCI does not run the slow tests, but github actions does every night!
|
||||
6. All public methods must have informative docstrings that work nicely with sphinx. See `modeling_ctrl.py` for an
|
||||
6. All public methods must have informative docstrings that work nicely with sphinx. See `modeling_ctrl.py` for an
|
||||
example.
|
||||
|
||||
### Tests
|
||||
|
||||
An extensive test suite is included to test the library behavior and several examples. Library tests can be found in
|
||||
the [tests folder](https://github.com/huggingface/transformers/tree/master/tests) and examples tests in the
|
||||
An extensive test suite is included to test the library behavior and several examples. Library tests can be found in
|
||||
the [tests folder](https://github.com/huggingface/transformers/tree/master/tests) and examples tests in the
|
||||
[examples folder](https://github.com/huggingface/transformers/tree/master/examples).
|
||||
|
||||
We like `pytest` and `pytest-xdist` because it's faster. From the root of the
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
quality:
|
||||
black --check --line-length 119 --target-version py35 examples templates tests src utils
|
||||
isort --check-only examples templates tests src utils
|
||||
isort --check-only --recursive examples templates tests src utils
|
||||
flake8 examples templates tests src utils
|
||||
python utils/check_repo.py
|
||||
|
||||
@@ -12,7 +12,7 @@ quality:
|
||||
|
||||
style:
|
||||
black --line-length 119 --target-version py35 examples templates tests src utils
|
||||
isort examples templates tests src utils
|
||||
isort --recursive examples templates tests src utils
|
||||
|
||||
# Run tests for the library
|
||||
|
||||
|
||||
@@ -167,13 +167,8 @@ At some point in the future, you'll be able to seamlessly move from pre-training
|
||||
19. **[Reformer](https://huggingface.co/transformers/model_doc/reformer.html)** (from Google Research) released with the paper [Reformer: The Efficient Transformer](https://arxiv.org/abs/2001.04451) by Nikita Kitaev, Łukasz Kaiser, Anselm Levskaya.
|
||||
20. **[MarianMT](https://huggingface.co/transformers/model_doc/marian.html)** Machine translation models trained using [OPUS](http://opus.nlpl.eu/) data by Jörg Tiedemann. The [Marian Framework](https://marian-nmt.github.io/) is being developed by the Microsoft Translator Team.
|
||||
21. **[Longformer](https://huggingface.co/transformers/model_doc/longformer.html)** (from AllenAI) released with the paper [Longformer: The Long-Document Transformer](https://arxiv.org/abs/2004.05150) by Iz Beltagy, Matthew E. Peters, Arman Cohan.
|
||||
22. **[DPR](https://github.com/facebookresearch/DPR)** (from Facebook) released with the paper [Dense Passage Retrieval
|
||||
for Open-Domain Question Answering](https://arxiv.org/abs/2004.04906) by Vladimir Karpukhin, Barlas Oğuz, Sewon
|
||||
Min, Patrick Lewis, Ledell Wu, Sergey Edunov, Danqi Chen, and Wen-tau Yih.
|
||||
23. **[Pegasus](https://github.com/google-research/pegasus)** (from Google) released with the paper [PEGASUS: Pre-training with Extracted Gap-sentences for Abstractive Summarization](https://arxiv.org/abs/1912.08777)> by Jingqing Zhang, Yao Zhao, Mohammad Saleh and Peter J. Liu.
|
||||
24. **[MBart](https://github.com/pytorch/fairseq/tree/master/examples/mbart)** (from Facebook) released with the paper [Multilingual Denoising Pre-training for Neural Machine Translation](https://arxiv.org/abs/2001.08210) by Yinhan Liu, Jiatao Gu, Naman Goyal, Xian Li, Sergey Edunov, Marjan Ghazvininejad, Mike Lewis, Luke Zettlemoyer.
|
||||
25. **[Other community models](https://huggingface.co/models)**, contributed by the [community](https://huggingface.co/users).
|
||||
26. Want to contribute a new model? We have added a **detailed guide and templates** to guide you in the process of adding a new model. You can find them in the [`templates`](./templates) folder of the repository. Be sure to check the [contributing guidelines](./CONTRIBUTING.md) and contact the maintainers or open an issue to collect feedbacks before starting your PR.
|
||||
22. **[Other community models](https://huggingface.co/models)**, contributed by the [community](https://huggingface.co/users).
|
||||
23. Want to contribute a new model? We have added a **detailed guide and templates** to guide you in the process of adding a new model. You can find them in the [`templates`](./templates) folder of the repository. Be sure to check the [contributing guidelines](./CONTRIBUTING.md) and contact the maintainers or open an issue to collect feedbacks before starting your PR.
|
||||
|
||||
These implementations have been tested on several datasets (see the example scripts) and should match the performances of the original implementations (e.g. ~93 F1 on SQuAD for BERT Whole-Word-Masking, ~88 F1 on RocStories for OpenAI GPT, ~18.3 perplexity on WikiText 103 for Transformer-XL, ~0.916 Pearson R coefficient on STS-B for XLNet). You can find more details on the performances in the Examples section of the [documentation](https://huggingface.co/transformers/examples.html).
|
||||
|
||||
@@ -698,11 +693,11 @@ for batch in train_data:
|
||||
|
||||
## Citation
|
||||
|
||||
We now have a [paper](https://arxiv.org/abs/1910.03771) you can cite for the 🤗 Transformers library:
|
||||
We now have a paper you can cite for the 🤗 Transformers library:
|
||||
```bibtex
|
||||
@article{Wolf2019HuggingFacesTS,
|
||||
title={HuggingFace's Transformers: State-of-the-art Natural Language Processing},
|
||||
author={Thomas Wolf and Lysandre Debut and Victor Sanh and Julien Chaumond and Clement Delangue and Anthony Moi and Pierric Cistac and Tim Rault and Rémi Louf and Morgan Funtowicz and Joe Davison and Sam Shleifer and Patrick von Platen and Clara Ma and Yacine Jernite and Julien Plu and Canwen Xu and Teven Le Scao and Sylvain Gugger and Mariama Drame and Quentin Lhoest and Alexander M. Rush},
|
||||
author={Thomas Wolf and Lysandre Debut and Victor Sanh and Julien Chaumond and Clement Delangue and Anthony Moi and Pierric Cistac and Tim Rault and R'emi Louf and Morgan Funtowicz and Jamie Brew},
|
||||
journal={ArXiv},
|
||||
year={2019},
|
||||
volume={abs/1910.03771}
|
||||
|
||||
@@ -4,7 +4,3 @@ coverage:
|
||||
default:
|
||||
informational: true
|
||||
patch: off
|
||||
comment:
|
||||
require_changes: true # only comment if there was change in coverage
|
||||
require_head: yes # don't report if there is no head coverage report
|
||||
require_base: yes # don't report if there is no base coverage report
|
||||
@@ -24,7 +24,6 @@ const versionMapping = {
|
||||
// The page that have a notebook and therefore should have the open in colab badge.
|
||||
const hasNotebook = [
|
||||
"benchmarks",
|
||||
"custom_datasets",
|
||||
"multilingual",
|
||||
"perplexity",
|
||||
"preprocessing",
|
||||
|
||||
+1
-2
@@ -76,8 +76,7 @@ exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store']
|
||||
pygments_style = None
|
||||
|
||||
# Remove the prompt when copying examples
|
||||
copybutton_prompt_text = r">>> |\.\.\. "
|
||||
copybutton_prompt_is_regexp = True
|
||||
copybutton_prompt_text = ">>> "
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,715 +0,0 @@
|
||||
Fine-tuning with custom datasets
|
||||
================================
|
||||
|
||||
.. note::
|
||||
|
||||
The datasets used in this tutorial are available and can be more easily accessed using the
|
||||
`🤗 NLP library <https://github.com/huggingface/nlp>`_. We do not use this library to access the datasets here
|
||||
since this tutorial meant to illustrate how to work with your own data. A brief of introduction can be found
|
||||
at the end of the tutorial in the section ":ref:`nlplib`".
|
||||
|
||||
This tutorial will take you through several examples of using 🤗 Transformers models with your own datasets. The
|
||||
guide shows one of many valid workflows for using these models and is meant to be illustrative rather than
|
||||
definitive. We show examples of reading in several data formats, preprocessing the data for several types of tasks,
|
||||
and then preparing the data into PyTorch/TensorFlow ``Dataset`` objects which can easily be used either with
|
||||
:class:`~transformers.Trainer`/:class:`~transformers.TFTrainer` or with native PyTorch/TensorFlow.
|
||||
|
||||
We include several examples, each of which demonstrates a different type of common downstream task:
|
||||
|
||||
- :ref:`seq_imdb`
|
||||
- :ref:`tok_ner`
|
||||
- :ref:`qa_squad`
|
||||
- :ref:`resources`
|
||||
|
||||
.. _seq_imdb:
|
||||
|
||||
Sequence Classification with IMDb Reviews
|
||||
-----------------------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
This dataset can be explored in the Hugging Face model hub (`IMDb <https://huggingface.co/datasets/imdb>`_), and can
|
||||
be alternatively downloaded with the 🤗 NLP library with ``load_dataset("imdb")``.
|
||||
|
||||
In this example, we'll show how to download, tokenize, and train a model on the IMDb reviews dataset. This task
|
||||
takes the text of a review and requires the model to predict whether the sentiment of the review is positive or
|
||||
negative. Let's start by downloading the dataset from the
|
||||
`Large Movie Review Dataset <http://ai.stanford.edu/~amaas/data/sentiment/>`_ webpage.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
wget http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
|
||||
tar -xf aclImdb_v1.tar.gz
|
||||
|
||||
This data is organized into ``pos`` and ``neg`` folders with one text file per example. Let's write a function that can
|
||||
read this in.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
def read_imdb_split(split_dir):
|
||||
split_dir = Path(split_dir)
|
||||
texts = []
|
||||
labels = []
|
||||
for label_dir in ["pos", "neg"]:
|
||||
for text_file in (split_dir/label_dir).iterdir():
|
||||
texts.append(text_file.read_text())
|
||||
labels.append(0 if label_dir is "neg" else 1)
|
||||
|
||||
return texts, labels
|
||||
|
||||
train_texts, train_labels = read_imdb_split('aclImdb/train')
|
||||
test_texts, test_labels = read_imdb_split('aclImdb/test')
|
||||
|
||||
We now have a train and test dataset, but let's also also create a validation set which we can use for for
|
||||
evaluation and tuning without training our test set results. Sklearn has a convenient utility for creating such
|
||||
splits:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from sklearn.model_selection import train_test_split
|
||||
train_texts, val_texts, train_labels, val_labels = train_test_split(train_texts, train_labels, test_size=.2)
|
||||
|
||||
Alright, we've read in our dataset. Now let's tackle tokenization. We'll eventually train a classifier using
|
||||
pre-trained DistilBert, so let's use the DistilBert tokenizer.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from transformers import DistilBertTokenizerFast
|
||||
tokenizer = DistilBertTokenizerFast.from_pretrained('distilbert-base-uncased')
|
||||
|
||||
Now we can simply pass our texts to the tokenizer. We'll pass ``truncation=True`` and ``padding=True``, which will
|
||||
ensure that all of our sequences are padded to the same length and are truncated to be no longer model's maximum
|
||||
input length. This will allow us to feed batches of sequences into the model at the same time.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
train_encodings = tokenizer(train_texts, truncation=True, padding=True)
|
||||
val_encodings = tokenizer(val_texts, truncation=True, padding=True)
|
||||
test_encodings = tokenizer(test_texts, truncation=True, padding=True)
|
||||
|
||||
Now, let's turn our labels and encodings into a Dataset object. In PyTorch, this is done by subclassing a
|
||||
``torch.utils.data.Dataset`` object and implementing ``__len__`` and ``__getitem__``. In TensorFlow, we pass our input encodings and
|
||||
labels to the ``from_tensor_slices`` constructor method. We put the data in this format so that the data can be
|
||||
easily batched such that each key in the batch encoding corresponds to a named parameter of the
|
||||
:meth:`~transformers.DistilBertForSequenceClassification.forward` method of the model we will train.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
import torch
|
||||
|
||||
class IMDbDataset(torch.utils.data.Dataset):
|
||||
def __init__(self, encodings, labels):
|
||||
self.encodings = encodings
|
||||
self.labels = labels
|
||||
|
||||
def __getitem__(self, idx):
|
||||
item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
|
||||
item['labels'] = torch.tensor(self.labels[idx])
|
||||
return item
|
||||
|
||||
def __len__(self):
|
||||
return len(self.labels)
|
||||
|
||||
train_dataset = IMDbDataset(train_encodings, train_labels)
|
||||
val_dataset = IMDbDataset(val_encodings, val_labels)
|
||||
test_dataset = IMDbDataset(test_encodings, test_labels)
|
||||
## TENSORFLOW CODE
|
||||
import tensorflow as tf
|
||||
|
||||
train_dataset = tf.data.Dataset.from_tensor_slices((
|
||||
dict(train_encodings),
|
||||
train_labels
|
||||
))
|
||||
val_dataset = tf.data.Dataset.from_tensor_slices((
|
||||
dict(val_encodings),
|
||||
val_labels
|
||||
))
|
||||
test_dataset = tf.data.Dataset.from_tensor_slices((
|
||||
dict(test_encodings),
|
||||
test_labels
|
||||
))
|
||||
|
||||
Now that our datasets our ready, we can fine-tune a model either with the 🤗
|
||||
:class:`~transformers.Trainer`/:class:`~transformers.TFTrainer` or with native PyTorch/TensorFlow. See
|
||||
:doc:`training <training>`.
|
||||
|
||||
.. _ft_trainer:
|
||||
|
||||
Fine-tuning with Trainer
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The steps above prepared the datasets in the way that the trainer is expected. Now all we need to do is create a
|
||||
model to fine-tune, define the :class:`~transformers.TrainingArguments`/:class:`~transformers.TFTrainingArguments`
|
||||
and instantiate a :class:`~transformers.Trainer`/:class:`~transformers.TFTrainer`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
from transformers import DistilBertForSequenceClassification, Trainer, TrainingArguments
|
||||
|
||||
training_args = TrainingArguments(
|
||||
output_dir='./results', # output directory
|
||||
num_train_epochs=3, # total number of training epochs
|
||||
per_device_train_batch_size=16, # batch size per device during training
|
||||
per_device_eval_batch_size=64, # batch size for evaluation
|
||||
warmup_steps=500, # number of warmup steps for learning rate scheduler
|
||||
weight_decay=0.01, # strength of weight decay
|
||||
logging_dir='./logs', # directory for storing logs
|
||||
logging_steps=10,
|
||||
)
|
||||
|
||||
model = DistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased")
|
||||
|
||||
trainer = Trainer(
|
||||
model=model, # the instantiated 🤗 Transformers model to be trained
|
||||
args=training_args, # training arguments, defined above
|
||||
train_dataset=train_dataset, # training dataset
|
||||
eval_dataset=val_dataset # evaluation dataset
|
||||
)
|
||||
|
||||
trainer.train()
|
||||
## TENSORFLOW CODE
|
||||
from transformers import TFDistilBertForSequenceClassification, TFTrainer, TFTrainingArguments
|
||||
|
||||
training_args = TFTrainingArguments(
|
||||
output_dir='./results', # output directory
|
||||
num_train_epochs=3, # total number of training epochs
|
||||
per_device_train_batch_size=16, # batch size per device during training
|
||||
per_device_eval_batch_size=64, # batch size for evaluation
|
||||
warmup_steps=500, # number of warmup steps for learning rate scheduler
|
||||
weight_decay=0.01, # strength of weight decay
|
||||
logging_dir='./logs', # directory for storing logs
|
||||
logging_steps=10,
|
||||
)
|
||||
|
||||
with training_args.strategy.scope():
|
||||
model = TFDistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased")
|
||||
|
||||
trainer = TFTrainer(
|
||||
model=model, # the instantiated 🤗 Transformers model to be trained
|
||||
args=training_args, # training arguments, defined above
|
||||
train_dataset=train_dataset, # training dataset
|
||||
eval_dataset=val_dataset # evaluation dataset
|
||||
)
|
||||
|
||||
trainer.train()
|
||||
|
||||
.. _ft_native:
|
||||
|
||||
Fine-tuning with native PyTorch/TensorFlow
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We can also train use native PyTorch or TensorFlow:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
from torch.utils.data import DataLoader
|
||||
from transformers import DistilBertForSequenceClassification, AdamW
|
||||
|
||||
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
|
||||
|
||||
model = DistilBertForSequenceClassification.from_pretrained('distilbert-base-uncased')
|
||||
model.to(device)
|
||||
model.train()
|
||||
|
||||
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
|
||||
|
||||
optim = AdamW(model.parameters(), lr=5e-5)
|
||||
|
||||
for epoch in range(3):
|
||||
for batch in train_loader:
|
||||
optim.zero_grad()
|
||||
input_ids = batch['input_ids'].to(device)
|
||||
attention_mask = batch['attention_mask'].to(device)
|
||||
labels = batch['labels'].to(device)
|
||||
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
|
||||
loss = outputs[0]
|
||||
loss.backward()
|
||||
optim.step()
|
||||
|
||||
model.eval()
|
||||
## TENSORFLOW CODE
|
||||
from transformers import TFDistilBertForSequenceClassification
|
||||
|
||||
model = TFDistilBertForSequenceClassification.from_pretrained('distilbert-base-uncased')
|
||||
|
||||
optimizer = tf.keras.optimizers.Adam(learning_rate=5e-5)
|
||||
model.compile(optimizer=optimizer, loss=model.compute_loss) # can also use any keras loss fn
|
||||
model.fit(train_dataset.shuffle(1000).batch(16), epochs=3, batch_size=16)
|
||||
|
||||
.. _tok_ner:
|
||||
|
||||
Token Classification with W-NUT Emerging Entities
|
||||
-------------------------------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
This dataset can be explored in the Hugging Face model hub (`WNUT-17 <https://huggingface.co/datasets/wnut_17>`_), and can
|
||||
be alternatively downloaded with the 🤗 NLP library with ``load_dataset("wnut_17")``.
|
||||
|
||||
Next we will look at token classification. Rather than classifying an entire sequence, this task classifies token by
|
||||
token. We'll demonstrate how to do this with
|
||||
`Named Entity Recognition <http://nlpprogress.com/english/named_entity_recognition.html>`_, which involves
|
||||
identifying tokens which correspond to a predefined set of "entities". Specifically, we'll use the
|
||||
`W-NUT Emerging and Rare entities <http://noisy-text.github.io/2017/emerging-rare-entities.html>`_ corpus. The data
|
||||
is given as a collection of pre-tokenized documents where each token is assigned a tag.
|
||||
|
||||
Let's start by downloading the data.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
wget http://noisy-text.github.io/2017/files/wnut17train.conll
|
||||
|
||||
In this case, we'll just download the train set, which is a single text file. Each line of the file contains either
|
||||
(1) a word and tag separated by a tab, or (2) a blank line indicating the end of a document. Let's write a
|
||||
function to read this in. We'll take in the file path and return ``token_docs`` which is a list of lists of token
|
||||
strings, and ``token_tags`` which is a list of lists of tag strings.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
def read_wnut(file_path):
|
||||
file_path = Path(file_path)
|
||||
|
||||
raw_text = file_path.read_text().strip()
|
||||
raw_docs = re.split(r'\n\t?\n', raw_text)
|
||||
token_docs = []
|
||||
tag_docs = []
|
||||
for doc in raw_docs:
|
||||
tokens = []
|
||||
tags = []
|
||||
for line in doc.split('\n'):
|
||||
token, tag = line.split('\t')
|
||||
tokens.append(token)
|
||||
tags.append(tag)
|
||||
token_docs.append(tokens)
|
||||
tag_docs.append(tags)
|
||||
|
||||
return token_docs, tag_docs
|
||||
|
||||
texts, tags = read_wnut('wnut17train.conll')
|
||||
|
||||
Just to see what this data looks like, let's take a look at a segment of the first document.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> print(texts[0][10:17], tags[0][10:17], sep='\n')
|
||||
['for', 'two', 'weeks', '.', 'Empire', 'State', 'Building']
|
||||
['O', 'O', 'O', 'O', 'B-location', 'I-location', 'I-location']
|
||||
|
||||
``location`` is an entity type, ``B-`` indicates the beginning of an entity, and ``I-`` indicates consecutive positions of
|
||||
the same entity ("Empire State Building" is considered one entity). ``O`` indicates the token does not correspond to
|
||||
any entity.
|
||||
|
||||
Now that we've read the data in, let's create a train/validation split:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from sklearn.model_selection import train_test_split
|
||||
train_texts, val_texts, train_tags, val_tags = train_test_split(texts, tags, test_size=.2)
|
||||
|
||||
Next, let's create encodings for our tokens and tags. For the tags, we can start by just create a simple mapping
|
||||
which we'll use in a moment:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
unique_tags = set(tag for doc in tags for tag in doc)
|
||||
tag2id = {tag: id for id, tag in enumerate(unique_tags)}
|
||||
id2tag = {id: tag for tag, id in tag2id.items()}
|
||||
|
||||
To encode the tokens, we'll use a pre-trained DistilBert tokenizer. We can tell the tokenizer that we're dealing
|
||||
with ready-split tokens rather than full sentence strings by passing ``is_pretokenized=True``. We'll also pass
|
||||
``padding=True`` and ``truncation=True`` to pad the sequences to be the same length. Lastly, we can tell the model
|
||||
to return information about the tokens which are split by the wordpiece tokenization process, which we will need in
|
||||
a moment.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from transformers import DistilBertTokenizerFast
|
||||
tokenizer = DistilBertTokenizerFast.from_pretrained('distilbert-base-cased')
|
||||
train_encodings = tokenizer(train_texts, is_pretokenized=True, return_offsets_mapping=True, padding=True, truncation=True)
|
||||
val_encodings = tokenizer(val_texts, is_pretokenized=True, return_offsets_mapping=True, padding=True, truncation=True)
|
||||
|
||||
Great, so now our tokens are nicely encoded in the format that they need to be in to feed them into our DistilBert
|
||||
model below.
|
||||
|
||||
Now we arrive at a common obstacle with using pre-trained models for token-level classification: many of the tokens
|
||||
in the W-NUT corpus are not in DistilBert's vocabulary. Bert and many models like it use a method called WordPiece
|
||||
Tokenization, meaning that single words are split into multiple tokens such that each token is likely to be in
|
||||
the vocabulary. For example, DistilBert's tokenizer would split the Twitter handle ``@huggingface`` into the tokens
|
||||
``['@', 'hugging', '##face']``. This is a problem for us because we have exactly one tag per token. If the tokenizer
|
||||
splits a token into multiple sub-tokens, then we will end up with a mismatch between our tokens and our labels.
|
||||
|
||||
One way to handle this is to only train on the tag labels for the first subtoken of a split token. We can do this in
|
||||
🤗 Transformers by setting the labels we wish to ignore to ``-100``. In the example above, if the label for
|
||||
``@HuggingFace`` is ``3`` (indexing ``B-corporation``), we would set the labels of ``['@', 'hugging', '##face']`` to
|
||||
``[3, -100, -100]``.
|
||||
|
||||
Let's write a function to do this. This is where we will use the ``offset_mapping`` from the tokenizer as mentioned
|
||||
above. For each sub-token returned by the tokenizer, the offset mapping gives us a tuple indicating the sub-token's
|
||||
start position and end position relative to the original token it was split from. That means that if the first
|
||||
position in the tuple is anything other than ``0``, we will set its corresponding label to ``-100``. While we're at
|
||||
it, we can also set labels to ``-100`` if the second position of the offset mapping is ``0``, since this means it must
|
||||
be a special token like ``[PAD]`` or ``[CLS]``.
|
||||
|
||||
.. note::
|
||||
|
||||
Due to a recently fixed bug, -1 must be used instead of -100 when using TensorFlow in 🤗 Transformers <= 3.02.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import numpy as np
|
||||
|
||||
def encode_tags(tags, encodings):
|
||||
labels = [[tag2id[tag] for tag in doc] for doc in tags]
|
||||
encoded_labels = []
|
||||
for doc_labels, doc_offset in zip(labels, encodings.offset_mapping):
|
||||
# create an empty array of -100
|
||||
doc_enc_labels = np.ones(len(doc_offset),dtype=int) * -100
|
||||
arr_offset = np.array(doc_offset)
|
||||
|
||||
# set labels whose first offset position is 0 and the second is not 0
|
||||
doc_enc_labels[(arr_offset[:,0] == 0) & (arr_offset[:,1] != 0)] = doc_labels
|
||||
encoded_labels.append(doc_enc_labels.tolist())
|
||||
|
||||
return encoded_labels
|
||||
|
||||
train_labels = encode_tags(train_tags, train_encodings)
|
||||
val_labels = encode_tags(val_tags, val_encodings)
|
||||
|
||||
The hard part is now done. Just as in the sequence classification example above, we can create a dataset object:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
import torch
|
||||
|
||||
class WNUTDataset(torch.utils.data.Dataset):
|
||||
def __init__(self, encodings, labels):
|
||||
self.encodings = encodings
|
||||
self.labels = labels
|
||||
|
||||
def __getitem__(self, idx):
|
||||
item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
|
||||
item['labels'] = torch.tensor(self.labels[idx])
|
||||
return item
|
||||
|
||||
def __len__(self):
|
||||
return len(self.labels)
|
||||
|
||||
train_encodings.pop("offset_mapping") # we don't want to pass this to the model
|
||||
val_encodings.pop("offset_mapping")
|
||||
train_dataset = WNUTDataset(train_encodings, train_labels)
|
||||
val_dataset = WNUTDataset(val_encodings, val_labels)
|
||||
## TENSORFLOW CODE
|
||||
import tensorflow as tf
|
||||
|
||||
train_encodings.pop("offset_mapping") # we don't want to pass this to the model
|
||||
val_encodings.pop("offset_mapping")
|
||||
|
||||
train_dataset = tf.data.Dataset.from_tensor_slices((
|
||||
dict(train_encodings),
|
||||
train_labels
|
||||
))
|
||||
val_dataset = tf.data.Dataset.from_tensor_slices((
|
||||
dict(val_encodings),
|
||||
val_labels
|
||||
))
|
||||
|
||||
Now load in a token classification model and specify the number of labels:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
from transformers import DistilBertForTokenClassification
|
||||
model = DistilBertForTokenClassification.from_pretrained('distilbert-base-cased', num_labels=len(unique_tags))
|
||||
## TENSORFLOW CODE
|
||||
from transformers import TFDistilBertForTokenClassification
|
||||
model = TFDistilBertForTokenClassification.from_pretrained('distilbert-base-cased', num_labels=len(unique_tags))
|
||||
|
||||
The data and model are both ready to go. You can train the model either with
|
||||
:class:`~transformers.Trainer`/:class:`~transformers.TFTrainer` or with native PyTorch/TensorFlow, exactly as in the
|
||||
sequence classification example above.
|
||||
|
||||
- :ref:`ft_trainer`
|
||||
- :ref:`ft_native`
|
||||
|
||||
.. _qa_squad:
|
||||
|
||||
Question Answering with SQuAD 2.0
|
||||
---------------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
This dataset can be explored in the Hugging Face model hub (`SQuAD V2 <https://huggingface.co/datasets/squad_v2>`_), and can
|
||||
be alternatively downloaded with the 🤗 NLP library with ``load_dataset("squad_v2")``.
|
||||
|
||||
Question answering comes in many forms. In this example, we'll look at the particular type of extractive QA that
|
||||
involves answering a question about a passage by highlighting the segment of the passage that answers the question.
|
||||
This involves fine-tuning a model which predicts a start position and an end position in the passage. We will use the
|
||||
`Stanford Question Answering Dataset (SQuAD) 2.0 <https://rajpurkar.github.io/SQuAD-explorer/>`_.
|
||||
|
||||
We will start by downloading the data:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir squad
|
||||
wget https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v2.0.json -O squad/train-v2.0.json
|
||||
wget https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v2.0.json -O squad/dev-v2.0.json
|
||||
|
||||
Each split is in a structured json file with a number of questions and answers for each passage (or context). We'll
|
||||
take this apart into parallel lists of contexts, questions, and answers (note that the contexts here are repeated
|
||||
since there are multiple questions per context):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
def read_squad(path):
|
||||
path = Path(path)
|
||||
with open(path, 'rb') as f:
|
||||
squad_dict = json.load(f)
|
||||
|
||||
contexts = []
|
||||
questions = []
|
||||
answers = []
|
||||
for group in squad_dict['data']:
|
||||
for passage in group['paragraphs']:
|
||||
context = passage['context']
|
||||
for qa in passage['qas']:
|
||||
question = qa['question']
|
||||
for answer in qa['answers']:
|
||||
contexts.append(context)
|
||||
questions.append(question)
|
||||
answers.append(answer)
|
||||
|
||||
return contexts, questions, answers
|
||||
|
||||
train_contexts, train_questions, train_answers = read_squad('squad/train-v2.0.json')
|
||||
val_contexts, val_questions, val_answers = read_squad('squad/dev-v2.0.json')
|
||||
|
||||
The contexts and questions are just strings. The answers are dicts containing the subsequence of the passage with
|
||||
the correct answer as well as an integer indicating the character at which the answer begins. In order to train a
|
||||
model on this data we need (1) the tokenized context/question pairs, and (2) integers indicating at which *token*
|
||||
positions the answer begins and ends.
|
||||
|
||||
First, let's get the *character* position at which the answer ends in the passage (we are given the starting
|
||||
position). Sometimes SQuAD answers are off by one or two characters, so we will also adjust for that.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def add_end_idx(answers, contexts):
|
||||
for answer, context in zip(answers, contexts):
|
||||
gold_text = answer['text']
|
||||
start_idx = answer['answer_start']
|
||||
end_idx = start_idx + len(gold_text)
|
||||
|
||||
# sometimes squad answers are off by a character or two – fix this
|
||||
if context[start_idx:end_idx] == gold_text:
|
||||
answer['answer_end'] = end_idx
|
||||
elif context[start_idx-1:end_idx-1] == gold_text:
|
||||
answer['answer_start'] = start_idx - 1
|
||||
answer['answer_end'] = end_idx - 1 # When the gold label is off by one character
|
||||
elif context[start_idx-2:end_idx-2] == gold_text:
|
||||
answer['answer_start'] = start_idx - 2
|
||||
answer['answer_end'] = end_idx - 2 # When the gold label is off by two characters
|
||||
|
||||
add_end_idx(train_answers, train_contexts)
|
||||
add_end_idx(val_answers, val_contexts)
|
||||
|
||||
Now ``train_answers`` and ``val_answers`` include the character end positions and the corrected start positions.
|
||||
Next, let's tokenize our context/question pairs. 🤗 Tokenizers can accept parallel lists of sequences and encode
|
||||
them together as sequence pairs.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from transformers import DistilBertTokenizerFast
|
||||
tokenizer = DistilBertTokenizerFast.from_pretrained('distilbert-base-uncased')
|
||||
|
||||
train_encodings = tokenizer(train_contexts, train_questions, truncation=True, padding=True)
|
||||
val_encodings = tokenizer(val_contexts, val_questions, truncation=True, padding=True)
|
||||
|
||||
Next we need to convert our character start/end positions to token start/end positions. When using 🤗 Fast
|
||||
Tokenizers, we can use the built in :func:`~transformers.BatchEncoding.char_to_token` method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def add_token_positions(encodings, answers):
|
||||
start_positions = []
|
||||
end_positions = []
|
||||
for i in range(len(answers)):
|
||||
start_positions.append(encodings.char_to_token(i, answers[i]['answer_start']))
|
||||
end_positions.append(encodings.char_to_token(i, answers[i]['answer_end'] - 1))
|
||||
# if None, the answer passage has been truncated
|
||||
if start_positions[-1] is None:
|
||||
start_positions[-1] = tokenizer.model_max_length
|
||||
if end_positions[-1] is None:
|
||||
end_positions[-1] = tokenizer.model_max_length
|
||||
encodings.update({'start_positions': start_positions, 'end_positions': end_positions})
|
||||
|
||||
add_token_positions(train_encodings, train_answers)
|
||||
add_token_positions(val_encodings, val_answers)
|
||||
|
||||
Our data is ready. Let's just put it in a PyTorch/TensorFlow dataset so that we can easily use it for
|
||||
training. In PyTorch, we define a custom ``Dataset`` class. In TensorFlow, we pass a tuple of
|
||||
``(inputs_dict, labels_dict)`` to the ``from_tensor_slices`` method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
import torch
|
||||
|
||||
class SquadDataset(torch.utils.data.Dataset):
|
||||
def __init__(self, encodings):
|
||||
self.encodings = encodings
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
|
||||
|
||||
def __len__(self):
|
||||
return len(self.encodings.input_ids)
|
||||
|
||||
train_dataset = SquadDataset(train_encodings)
|
||||
val_dataset = SquadDataset(val_encodings)
|
||||
## TENSORFLOW CODE
|
||||
import tensorflow as tf
|
||||
|
||||
train_dataset = tf.data.Dataset.from_tensor_slices((
|
||||
{key: train_encodings[key] for key in ['input_ids', 'attention_mask']},
|
||||
{key: train_encodings[key] for key in ['start_positions', 'end_positions']}
|
||||
))
|
||||
val_dataset = tf.data.Dataset.from_tensor_slices((
|
||||
{key: val_encodings[key] for key in ['input_ids', 'attention_mask']},
|
||||
{key: val_encodings[key] for key in ['start_positions', 'end_positions']}
|
||||
))
|
||||
|
||||
Now we can use a DistilBert model with a QA head for training:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
from transformers import DistilBertForQuestionAnswering
|
||||
model = DistilBertForQuestionAnswering.from_pretrained("distilbert-base-uncased")
|
||||
## TENSORFLOW CODE
|
||||
from transformers import TFDistilBertForQuestionAnswering
|
||||
model = TFDistilBertForQuestionAnswering.from_pretrained("distilbert-base-uncased")
|
||||
|
||||
|
||||
The data and model are both ready to go. You can train the model with
|
||||
:class:`~transformers.Trainer`/:class:`~transformers.TFTrainer` exactly as in the sequence classification example
|
||||
above. If using native PyTorch, replace ``labels`` with ``start_positions`` and ``end_positions`` in the training
|
||||
example. If using Keras's ``fit``, we need to make a minor modification to handle this example since it involves
|
||||
multiple model outputs.
|
||||
|
||||
- :ref:`ft_trainer`
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
from torch.utils.data import DataLoader
|
||||
from transformers import AdamW
|
||||
|
||||
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
|
||||
|
||||
model.to(device)
|
||||
model.train()
|
||||
|
||||
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
|
||||
|
||||
optim = AdamW(model.parameters(), lr=5e-5)
|
||||
|
||||
for epoch in range(3):
|
||||
for batch in train_loader:
|
||||
optim.zero_grad()
|
||||
input_ids = batch['input_ids'].to(device)
|
||||
attention_mask = batch['attention_mask'].to(device)
|
||||
start_positions = batch['start_positions'].to(device)
|
||||
end_positions = batch['end_positions'].to(device)
|
||||
outputs = model(input_ids, attention_mask=attention_mask, start_positions=start_positions, end_positions=end_positions)
|
||||
loss = outputs[0]
|
||||
loss.backward()
|
||||
optim.step()
|
||||
|
||||
model.eval()
|
||||
## TENSORFLOW CODE
|
||||
# Keras will expect a tuple when dealing with labels
|
||||
train_dataset = train_dataset.map(lambda x, y: (x, (y['start_positions'], y['end_positions'])))
|
||||
|
||||
# Keras will assign a separate loss for each output and add them together. So we'll just use the standard CE loss
|
||||
# instead of using the built-in model.compute_loss, which expects a dict of outputs and averages the two terms.
|
||||
# Note that this means the loss will be 2x of when using TFTrainer since we're adding instead of averaging them.
|
||||
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
|
||||
model.distilbert.return_dict = False # if using 🤗 Transformers >3.02, make sure outputs are tuples
|
||||
|
||||
optimizer = tf.keras.optimizers.Adam(learning_rate=5e-5)
|
||||
model.compile(optimizer=optimizer, loss=loss) # can also use any keras loss fn
|
||||
model.fit(train_dataset.shuffle(1000).batch(16), epochs=3, batch_size=16)
|
||||
|
||||
.. _resources:
|
||||
|
||||
Additional Resources
|
||||
--------------------
|
||||
|
||||
- `How to train a new language model from scratch using Transformers and Tokenizers
|
||||
<https://huggingface.co/blog/how-to-train>`_. Blog post showing the steps to load in Esperanto data and train a
|
||||
masked language model from scratch.
|
||||
- :doc:`Preprocessing <preprocessing>`. Docs page on data preprocessing.
|
||||
- :doc:`Training <training>`. Docs page on training and fine-tuning.
|
||||
|
||||
.. _nlplib:
|
||||
|
||||
Using the 🤗 NLP Datasets & Metrics library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This tutorial demonstrates how to read in datasets from various raw text formats and prepare them for training with
|
||||
🤗 Transformers so that you can do the same thing with your own custom datasets. However, we recommend users use the
|
||||
`🤗 NLP library <https://github.com/huggingface/nlp>`_ for working with the 150+ datasets included in the
|
||||
`hub <https://huggingface.co/datasets>`_, including the three datasets used in this tutorial. As a very brief overview,
|
||||
we will show how to use the NLP library to download and prepare the IMDb dataset from the first example,
|
||||
:ref:`seq_imdb`.
|
||||
|
||||
Start by downloading the dataset:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from nlp import load_dataset
|
||||
train = load_dataset("imdb", split="train")
|
||||
|
||||
Each dataset has multiple columns corresponding to different features. Let's see what our columns are.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> print(train.column_names)
|
||||
['label', 'text']
|
||||
|
||||
Great. Now let's tokenize the text. We can do this using the ``map`` method. We'll also rename the ``label`` column
|
||||
to ``labels`` to match the model's input arguments.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
train = train.map(lambda batch: tokenizer(batch["text"], truncation=True, padding=True), batched=True)
|
||||
train.rename_column_("label", "labels")
|
||||
|
||||
Lastly, we can use the ``set_format`` method to determine which columns and in what data format we want to access
|
||||
dataset elements.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
## PYTORCH CODE
|
||||
>>> train.set_format("torch", columns=["input_ids", "attention_mask", "labels"])
|
||||
>>> {key: val.shape for key, val in train[0].items()})
|
||||
{'labels': torch.Size([]), 'input_ids': torch.Size([512]), 'attention_mask': torch.Size([512])}
|
||||
## TENSORFLOW CODE
|
||||
>>> train.set_format("tensorflow", columns=["input_ids", "attention_mask", "labels"])
|
||||
>>> {key: val.shape for key, val in train[0].items()})
|
||||
{'labels': TensorShape([]), 'input_ids': TensorShape([512]), 'attention_mask': TensorShape([512])}
|
||||
|
||||
We now have a fully-prepared dataset. Check out `the 🤗 NLP docs <https://huggingface.co/nlp/processing.html>`_ for
|
||||
a more thorough introduction.
|
||||
+25
-28
@@ -7,7 +7,7 @@ General terms
|
||||
- autoencoding models: see MLM
|
||||
- autoregressive models: see CLM
|
||||
- CLM: causal language modeling, a pretraining task where the model reads the texts in order and has to predict the
|
||||
next word. It's usually done by reading the whole sentence but using a mask inside the model to hide the future
|
||||
next word. It's usually done by reading the whole sentence but using a mask inside the model to hide the future
|
||||
tokens at a certain timestep.
|
||||
- MLM: masked language modeling, a pretraining task where the model sees a corrupted version of the texts, usually done
|
||||
by masking some tokens randomly, and has to predict the original text.
|
||||
@@ -18,7 +18,7 @@ General terms
|
||||
- NLU: natural language understanding, all tasks related to understanding what is in a text (for instance classifying
|
||||
the whole text, individual words)
|
||||
- pretrained model: a model that has been pretrained on some data (for instance all of Wikipedia). Pretraining methods
|
||||
involve a self-supervised objective, which can be reading the text and trying to predict the next word (see CLM) or
|
||||
involve a self-supervised objective, which can be reading the text and trying to predict the next word (see CLM) or
|
||||
masking some words and trying to predict them (see MLM).
|
||||
- RNN: recurrent neural network, a type of model that uses a loop over a layer to process texts.
|
||||
- seq2seq or sequence-to-sequence: models that generate a new sequence from an input, like translation models, or
|
||||
@@ -57,7 +57,7 @@ The tokenizer takes care of splitting the sequence into tokens available in the
|
||||
>>> tokenized_sequence = tokenizer.tokenize(sequence)
|
||||
|
||||
The tokens are either words or subwords. Here for instance, "VRAM" wasn't in the model vocabulary, so it's been split
|
||||
in "V", "RA" and "M". To indicate those tokens are not separate words but parts of the same word, a double-hash prefix is
|
||||
in "V", "RA" and "M". To indicate those tokens are not separate words but parts of the same word, a double-dash is
|
||||
added for "RA" and "M":
|
||||
|
||||
::
|
||||
@@ -71,27 +71,24 @@ the sentence to the tokenizer, which leverages the Rust implementation of
|
||||
|
||||
::
|
||||
|
||||
>>> inputs = tokenizer(sequence)
|
||||
>>> encoded_sequence = tokenizer(sequence)["input_ids"]
|
||||
|
||||
The tokenizer returns a dictionary with all the arguments necessary for its corresponding model to work properly. The
|
||||
token indices are under the key "input_ids":
|
||||
|
||||
::
|
||||
|
||||
>>> encoded_sequence = inputs["input_ids"]
|
||||
>>> print(encoded_sequence)
|
||||
[101, 138, 18696, 155, 1942, 3190, 1144, 1572, 13745, 1104, 159, 9664, 2107, 102]
|
||||
|
||||
Note that the tokenizer automatically adds "special tokens" (if the associated model relies on them) which are special
|
||||
IDs the model sometimes uses.
|
||||
|
||||
If we decode the previous sequence of ids,
|
||||
Note that the tokenizer automatically adds "special tokens" (if the associated model rely on them) which are special
|
||||
IDs the model sometimes uses. If we decode the previous sequence of ids,
|
||||
|
||||
::
|
||||
|
||||
>>> decoded_sequence = tokenizer.decode(encoded_sequence)
|
||||
|
||||
we will see
|
||||
we will see
|
||||
|
||||
::
|
||||
|
||||
@@ -147,7 +144,7 @@ We can see that 0s have been added on the right of the first sentence to make it
|
||||
|
||||
This can then be converted into a tensor in PyTorch or TensorFlow. The attention mask is a binary tensor indicating
|
||||
the position of the padded indices so that the model does not attend to them. For the
|
||||
:class:`~transformers.BertTokenizer`, :obj:`1` indicates a value that should be attended to, while :obj:`0` indicates
|
||||
:class:`~transformers.BertTokenizer`, :obj:`1` indicate a value that should be attended to while :obj:`0` indicate
|
||||
a padded value. This attention mask is in the dictionary returned by the tokenizer under the key "attention_mask":
|
||||
|
||||
::
|
||||
@@ -161,15 +158,15 @@ Token Type IDs
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Some models' purpose is to do sequence classification or question answering. These require two different sequences to
|
||||
be joined in a single "input_ids" entry, which usually is performed with the help of special tokens, such as the classifier (``[CLS]``) and separator (``[SEP]``)
|
||||
be encoded in the same input IDs. They are usually separated by special tokens, such as the classifier and separator
|
||||
tokens. For example, the BERT model builds its two sequence input as such:
|
||||
|
||||
::
|
||||
|
||||
>>> # [CLS] SEQUENCE_A [SEP] SEQUENCE_B [SEP]
|
||||
|
||||
We can use our tokenizer to automatically generate such a sentence by passing the two sequences to ``tokenizer`` as two arguments (and
|
||||
not a list, like before) like this:
|
||||
We can use our tokenizer to automatically generate such a sentence by passing the two sequences as two arguments (and
|
||||
not a list like before) like this:
|
||||
|
||||
::
|
||||
|
||||
@@ -188,31 +185,31 @@ which will return:
|
||||
>>> print(decoded)
|
||||
[CLS] HuggingFace is based in NYC [SEP] Where is HuggingFace based? [SEP]
|
||||
|
||||
This is enough for some models to understand where one sequence ends and where another begins. However, other models,
|
||||
such as BERT, also deploy token type IDs (also called segment IDs). They are represented as a binary
|
||||
mask identifying the two types of sequence in the model.
|
||||
This is enough for some models to understand where one sequence ends and where another begins. However, other models
|
||||
such as BERT have an additional mechanism, which are the token type IDs (also called segment IDs). They are a binary
|
||||
mask identifying the different sequences in the model.
|
||||
|
||||
The tokenizer returns this mask as the "token_type_ids" entry:
|
||||
The tokenizer returns in the dictionary under the key "token_type_ids":
|
||||
|
||||
::
|
||||
|
||||
>>> encoded_dict['token_type_ids']
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
|
||||
The first sequence, the "context" used for the question, has all its tokens represented by a :obj:`0`, whereas the
|
||||
second sequence, corresponding to the "question", has all its tokens represented by a :obj:`1`.
|
||||
|
||||
Some models, like :class:`~transformers.XLNetModel` use an additional token represented by a :obj:`2`.
|
||||
The first sequence, the "context" used for the question, has all its tokens represented by :obj:`0`, whereas the
|
||||
question has all its tokens represented by :obj:`1`. Some models, like :class:`~transformers.XLNetModel` use an
|
||||
additional token represented by a :obj:`2`.
|
||||
|
||||
.. _position-ids:
|
||||
|
||||
Position IDs
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Contrary to RNNs that have the position of each token embedded within them,
|
||||
transformers are unaware of the position of each token. Therefore, the position IDs (``position_ids``) are used by the model to identify each token's position in the list of tokens.
|
||||
The position IDs are used by the model to identify which token is at which position. Contrary to RNNs that have the
|
||||
position of each token embedded within them, transformers are unaware of the position of each token. The position
|
||||
IDs are created for this purpose.
|
||||
|
||||
They are an optional parameter. If no ``position_ids`` is passed to the model, the IDs are automatically created as absolute
|
||||
They are an optional parameter. If no position IDs are passed to the model, they are automatically created as absolute
|
||||
positional embeddings.
|
||||
|
||||
Absolute positional embeddings are selected in the range ``[0, config.max_position_embeddings - 1]``. Some models
|
||||
@@ -223,15 +220,15 @@ use other types of positional embeddings, such as sinusoidal position embeddings
|
||||
Feed Forward Chunking
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In each residual attention block in transformers the self-attention layer is usually followed by 2 feed forward layers.
|
||||
In transformers two feed forward layers usually follows the self attention layer in each residual attention block.
|
||||
The intermediate embedding size of the feed forward layers is often bigger than the hidden size of the model (e.g.,
|
||||
for ``bert-base-uncased``).
|
||||
for ``bert-base-uncased``).
|
||||
|
||||
For an input of size ``[batch_size, sequence_length]``, the memory required to store the intermediate feed forward
|
||||
embeddings ``[batch_size, sequence_length, config.intermediate_size]`` can account for a large fraction of the memory
|
||||
use. The authors of `Reformer: The Efficient Transformer <https://arxiv.org/abs/2001.04451>`_ noticed that since the
|
||||
computation is independent of the ``sequence_length`` dimension, it is mathematically equivalent to compute the output
|
||||
embeddings of both feed forward layers ``[batch_size, config.hidden_size]_0, ..., [batch_size, config.hidden_size]_n``
|
||||
embeddings of both feed forward layers ``[batch_size, config.hidden_size]_0, ..., [batch_size, config.hidden_size]_n``
|
||||
individually and concat them afterward to ``[batch_size, sequence_length, config.hidden_size]`` with
|
||||
``n = sequence_length``, which trades increased computation time against reduced memory use, but yields a
|
||||
mathematically **equivalent** result.
|
||||
|
||||
@@ -126,7 +126,7 @@ conversion utilities for the following models:
|
||||
Min, Patrick Lewis, Ledell Wu, Sergey Edunov, Danqi Chen, and Wen-tau Yih.
|
||||
23. `Pegasus <https://github.com/google-research/pegasus>`_ (from Google) released with the paper `PEGASUS: Pre-training with Extracted Gap-sentences for Abstractive Summarization
|
||||
<https://arxiv.org/abs/1912.08777>`_ by Jingqing Zhang, Yao Zhao, Mohammad Saleh and Peter J. Liu.
|
||||
24. `MBart <https://github.com/pytorch/fairseq/tree/master/examples/mbart>`_ (from Facebook) released with the paper `Multilingual Denoising Pre-training for Neural Machine Translation <https://arxiv.org/abs/2001.08210>`_ by Yinhan Liu, Jiatao Gu, Naman Goyal, Xian Li, Sergey Edunov,
|
||||
24. `MBart <https://github.com/pytorch/fairseq/tree/master/examples/mbart>`_ (from Facebook) released with the paper `Multilingual Denoising Pre-training for Neural Machine Translation <https://arxiv.org/abs/2001.08210>`_ by Yinhan Liu, Jiatao Gu, Naman Goyal, Xian Li, Sergey Edunov
|
||||
Marjan Ghazvininejad, Mike Lewis, Luke Zettlemoyer.
|
||||
25. `Other community models <https://huggingface.co/models>`_, contributed by the `community
|
||||
<https://huggingface.co/users>`_.
|
||||
@@ -158,7 +158,6 @@ conversion utilities for the following models:
|
||||
|
||||
pretrained_models
|
||||
examples
|
||||
custom_datasets
|
||||
notebooks
|
||||
converting_tensorflow_models
|
||||
migration
|
||||
|
||||
@@ -22,13 +22,13 @@ When TensorFlow 2.0 and/or PyTorch has been installed, 🤗 Transformers can be
|
||||
pip install transformers
|
||||
```
|
||||
|
||||
Alternatively, for CPU-support only, you can install 🤗 Transformers and PyTorch in one line with:
|
||||
Alternatively, for CPU-support only, you can install 🤗 Transformers and PyTorch in one line with
|
||||
|
||||
```bash
|
||||
pip install transformers[torch]
|
||||
```
|
||||
|
||||
or 🤗 Transformers and TensorFlow 2.0 in one line with:
|
||||
or 🤗 Transformers and TensorFlow 2.0 in one line with
|
||||
|
||||
```bash
|
||||
pip install transformers[tf-cpu]
|
||||
@@ -73,8 +73,8 @@ This library provides pretrained models that will be downloaded and cached local
|
||||
folder given by the shell environment variable ``TRANSFORMERS_CACHE``. The default value for it will be the PyTorch
|
||||
cache home followed by ``/transformers/`` (even if you don't have PyTorch installed). This is (by order of priority):
|
||||
|
||||
* shell environment variable ``TORCH_HOME``
|
||||
* shell environment variable ``XDG_CACHE_HOME`` + ``/torch/``
|
||||
* shell environment variable ``ENV_TORCH_HOME``
|
||||
* shell environment variable ``ENV_XDG_CACHE_HOME`` + ``/torch/``
|
||||
* default: ``~/.cache/torch/``
|
||||
|
||||
So if you don't have any specific environment variable set, the cache directory will be at
|
||||
|
||||
@@ -32,7 +32,7 @@ BartForConditionalGeneration
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.BartForConditionalGeneration
|
||||
:members: forward
|
||||
:members: generate, forward
|
||||
|
||||
|
||||
BartConfig
|
||||
|
||||
@@ -49,13 +49,6 @@ CamembertModel
|
||||
:members:
|
||||
|
||||
|
||||
CamembertForCausalLM
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: transformers.CamembertForCausalLM
|
||||
:members:
|
||||
|
||||
|
||||
CamembertForMaskedLM
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
MarianMT
|
||||
----------------------------------------------------
|
||||
**Bugs:** If you see something strange,
|
||||
file a `Github Issue <https://github.com/huggingface/transformers/issues/new?assignees=sshleifer&labels=&template=bug-report.md&title>`__ and assign
|
||||
**DISCLAIMER:** If you see something strange,
|
||||
file a `Github Issue <https://github.com/huggingface/transformers/issues/new?assignees=&labels=&template=bug-report.md&title>`__ and assign
|
||||
@sshleifer. Translations should be similar, but not identical to, output in the test set linked to in each model card.
|
||||
|
||||
Implementation Notes
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
- Each model is about 298 MB on disk, there are 1,000+ models.
|
||||
- The list of supported language pairs can be found `here <https://huggingface.co/Helsinki-NLP>`__.
|
||||
- models were originally trained by `Jörg Tiedemann <https://researchportal.helsinki.fi/en/persons/j%C3%B6rg-tiedemann>`__ using the `Marian <https://marian-nmt.github.io/>`_ C++ library, which supports fast training and translation.
|
||||
- The 1,000+ models were originally trained by `Jörg Tiedemann <https://researchportal.helsinki.fi/en/persons/j%C3%B6rg-tiedemann>`__ using the `Marian <https://marian-nmt.github.io/>`_ C++ library, which supports fast training and translation.
|
||||
- All models are transformer encoder-decoders with 6 layers in each component. Each model's performance is documented in a model card.
|
||||
- The 80 opus models that require BPE preprocessing are not supported.
|
||||
- The modeling code is the same as ``BartForConditionalGeneration`` with a few minor modifications:
|
||||
|
||||
@@ -14,45 +14,6 @@ MBART is a sequence-to-sequence denoising auto-encoder pre-trained on large-scal
|
||||
The Authors' code can be found `here <https://github.com/pytorch/fairseq/tree/master/examples/mbart>`__
|
||||
|
||||
|
||||
Training
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
MBart is a multilingual encoder-decoder (seq-to-seq) model primarily intended for translation task.
|
||||
As the model is multilingual it expects the sequences in a different format. A special language id token
|
||||
is added in both the source and target text. The source text format is ``X [eos, src_lang_code]``
|
||||
where ``X`` is the source text. The target text format is ```[tgt_lang_code] X [eos]```. ```bos``` is never used.
|
||||
The ```MBartTokenizer.prepare_seq2seq_batch``` handles this automatically and should be used to encode
|
||||
the sequences for seq-2-seq fine-tuning.
|
||||
|
||||
- Supervised training
|
||||
|
||||
::
|
||||
|
||||
example_english_phrase = "UN Chief Says There Is No Military Solution in Syria"
|
||||
expected_translation_romanian = "Şeful ONU declară că nu există o soluţie militară în Siria"
|
||||
batch = tokenizer.prepare_seq2seq_batch(example_english_phrase, src_lang="en_XX", tgt_lang="ro_RO", tgt_texts=expected_translation_romanian)
|
||||
input_ids = batch["input_ids"]
|
||||
target_ids = batch["decoder_input_ids"]
|
||||
decoder_input_ids = target_ids[:, :-1].contiguous()
|
||||
labels = target_ids[:, 1:].clone()
|
||||
model(input_ids=input_ids, decoder_input_ids=decoder_input_ids, labels=labels) #forward
|
||||
|
||||
- Generation
|
||||
|
||||
While generating the target text set the `decoder_start_token_id` to the target language id.
|
||||
The following example shows how to translate English to Romanian using the ```facebook/mbart-large-en-ro``` model.
|
||||
|
||||
::
|
||||
|
||||
from transformers import MBartForConditionalGeneration, MBartTokenizer
|
||||
model = MBartForConditionalGeneration.from_pretrained("facebook/mbart-large-en-ro")
|
||||
tokenizer = MBartTokenizer.from_pretrained("facebook/mbart-large-en-ro")
|
||||
article = "UN Chief Says There Is No Military Solution in Syria"
|
||||
batch = tokenizer.prepare_seq2seq_batch(src_texts=[article], src_lang="en_XX")
|
||||
translated_tokens = model.generate(**batch, decoder_start_token_id=tokenizer.lang_code_to_id["ro_RO"])
|
||||
translation = tokenizer.batch_decode(translated_tokens, skip_special_tokens=True)[0]
|
||||
assert translation == "Şeful ONU declară că nu există o soluţie militară în Siria"
|
||||
|
||||
|
||||
MBartConfig
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -8,19 +8,18 @@ file a `Github Issue <https://github.com/huggingface/transformers/issues/new?ass
|
||||
Overview
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Pegasus model was proposed in `PEGASUS: Pre-training with Extracted Gap-sentences for
|
||||
Abstractive Summarization <https://arxiv.org/pdf/1912.08777.pdf>`_ by Jingqing Zhang, Yao Zhao, Mohammad Saleh and Peter J. Liu on Dec 18, 2019.
|
||||
The Pegasus model was `proposed <https://arxiv.org/abs/1910.13461>`_ by Jingqing Zhang, Yao Zhao, Mohammad Saleh and Peter J. Liu on Dec 18, 2019.
|
||||
According to the abstract,
|
||||
|
||||
- Pegasus' pretraining task is intentionally similar to summarization: important sentences are removed/masked from an input document and are generated together as one output sequence from the remaining sentences, similar to an extractive summary.
|
||||
- Pegasus achieves SOTA summarization performance on all 12 downstream tasks, as measured by ROUGE and human eval.
|
||||
|
||||
The Authors' code can be found `here <https://github.com/google-research/pegasus>`_.
|
||||
The Authors' code can be found `here <https://github.com/google-research/pegasus>`_
|
||||
|
||||
|
||||
Checkpoints
|
||||
~~~~~~~~~~~
|
||||
All the `checkpoints <https://huggingface.co/models?search=pegasus>`_ are finetuned for summarization, besides ``pegasus-large``, whence the other checkpoints are finetuned.
|
||||
The `checkpoints <https://huggingface.co/models?search=pegasus>`_ all checkpoints are finetuned for summarization, besides ``pegasus-large``, whence the other checkpoints are finetuned.
|
||||
- Each checkpoint is 2.2 GB on disk and 568M parameters.
|
||||
- FP16 is not supported (help/ideas on this appreciated!).
|
||||
- Summarizing xsum in fp32 takes about 400ms/sample, with default parameters on a v100 GPU.
|
||||
@@ -48,7 +47,6 @@ Usage Example
|
||||
.. code-block:: python
|
||||
|
||||
from transformers import PegasusForConditionalGeneration, PegasusTokenizer
|
||||
import torch
|
||||
src_text = [
|
||||
""" PG&E stated it scheduled the blackouts in response to forecasts for high winds amid dry conditions. The aim is to reduce the risk of wildfires. Nearly 800 thousand customers were scheduled to be affected by the shutoffs which were expected to last through at least midday tomorrow."""
|
||||
]
|
||||
|
||||
+137
-216
@@ -1,11 +1,11 @@
|
||||
Summary of the models
|
||||
================================================
|
||||
|
||||
This is a summary of the models available in 🤗 Transformers. It assumes you’re familiar with the original
|
||||
`transformer model <https://arxiv.org/abs/1706.03762>`_. For a gentle introduction check the `annotated transformer
|
||||
This is a summary of the models available in 🤗 Transformers. It assumes you’re familiar with the original
|
||||
`transformer model <https://arxiv.org/abs/1706.03762>`_. For a gentle introduction check the `annotated transformer
|
||||
<http://nlp.seas.harvard.edu/2018/04/03/attention.html>`_. Here we focus on the high-level differences between the
|
||||
models. You can check them more in detail in their respective documentation. Also checkout the
|
||||
:doc:`pretrained model page </pretrained_models>` to see the checkpoints available for each type of model and all `the
|
||||
models. You can check them more in detail in their respective documentation. Also checkout the
|
||||
:doc:`pretrained model page </pretrained_models>` to see the checkpoints available for each type of model and all `the
|
||||
community models <https://huggingface.co/models>`_.
|
||||
|
||||
Each one of the models in the library falls into one of the following categories:
|
||||
@@ -14,39 +14,38 @@ Each one of the models in the library falls into one of the following categories
|
||||
* :ref:`autoencoding-models`
|
||||
* :ref:`seq-to-seq-models`
|
||||
* :ref:`multimodal-models`
|
||||
* :ref:`retrieval-based-models`
|
||||
|
||||
Autoregressive models are pretrained on the classic language modeling task: guess the next token having read all the
|
||||
previous ones. They correspond to the decoder of the original transformer model, and a mask is used on top of the full
|
||||
sentence so that the attention heads can only see what was before in the next, and not what’s after. Although those
|
||||
models can be fine-tuned and achieve great results on many tasks, the most natural application is text generation.
|
||||
Autoregressive models are pretrained on the classic language modeling task: guess the next token having read all the
|
||||
previous ones. They correspond to the decoder of the original transformer model, and a mask is used on top of the full
|
||||
sentence so that the attention heads can only see what was before in the next, and not what’s after. Although those
|
||||
models can be fine-tuned and achieve great results on many tasks, the most natural application is text generation.
|
||||
A typical example of such models is GPT.
|
||||
|
||||
Autoencoding models are pretrained by corrupting the input tokens in some way and trying to reconstruct the original
|
||||
sentence. They correspond to the encoder of the original transformer model in the sense that they get access to the
|
||||
full inputs without any mask. Those models usually build a bidirectional representation of the whole sentence. They can
|
||||
be fine-tuned and achieve great results on many tasks such as text generation, but their most natural application is
|
||||
Autoencoding models are pretrained by corrupting the input tokens in some way and trying to reconstruct the original
|
||||
sentence. They correspond to the encoder of the original transformer model in the sense that they get access to the
|
||||
full inputs without any mask. Those models usually build a bidirectional representation of the whole sentence. They can
|
||||
be fine-tuned and achieve great results on many tasks such as text generation, but their most natural application is
|
||||
sentence classification or token classification. A typical example of such models is BERT.
|
||||
|
||||
Note that the only difference between autoregressive models and autoencoding models is in the way the model is
|
||||
Note that the only difference between autoregressive models and autoencoding models is in the way the model is
|
||||
pretrained. Therefore, the same architecture can be used for both autoregressive and autoencoding models. When a given
|
||||
model has been used for both types of pretraining, we have put it in the category corresponding to the article where it was first
|
||||
model has been used for both pretraining, we have put it in the category corresponding to the article it was first
|
||||
introduced.
|
||||
|
||||
Sequence-to-sequence models use both the encoder and the decoder of the original transformer, either for translation
|
||||
tasks or by transforming other tasks to sequence-to-sequence problems. They can be fine-tuned to many tasks but their
|
||||
most natural applications are translation, summarization and question answering. The original transformer model is an
|
||||
Sequence-to-sequence models use both the encoder and the decoder of the original transformer, either for translation
|
||||
tasks or by transforming other tasks to sequence-to-sequence problems. They can be fine-tuned to many tasks but their
|
||||
most natural applications are translation, summarization and question answering. The original transformer model is an
|
||||
example of such a model (only for translation), T5 is an example that can be fine-tuned on other tasks.
|
||||
|
||||
Multimodal models mix text inputs with other kinds (e.g. images) and are more specific to a given task.
|
||||
Multimodal models mix text inputs with other kinds (like image) and are more specific to a given task.
|
||||
|
||||
.. _autoregressive-models:
|
||||
|
||||
Autoregressive models
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As mentioned before, these models rely on the decoder part of the original transformer and use an attention mask so
|
||||
that at each position, the model can only look at the tokens before the attention heads.
|
||||
As mentioned before, these models rely on the decoder part of the original transformer and use an attention mask so
|
||||
that at each position, the model can only look at the tokens before in the attention heads.
|
||||
|
||||
Original GPT
|
||||
----------------------------------------------
|
||||
@@ -60,12 +59,12 @@ Original GPT
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-openai--gpt-blueviolet">
|
||||
</a>
|
||||
|
||||
`Improving Language Understanding by Generative Pre-Training <https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf>`_,
|
||||
`Improving Language Understanding by Generative Pre-Training <https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf>`_,
|
||||
Alec Radford et al.
|
||||
|
||||
The first autoregressive model based on the transformer architecture, pretrained on the Book Corpus dataset.
|
||||
|
||||
The library provides versions of the model for language modeling and multitask language modeling/multiple choice
|
||||
The library provides versions of the model for language modeling and multitask language modeling/multiple choice
|
||||
classification.
|
||||
|
||||
GPT-2
|
||||
@@ -80,13 +79,13 @@ GPT-2
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-gpt2-blueviolet">
|
||||
</a>
|
||||
|
||||
`Language Models are Unsupervised Multitask Learners <https://d4mucfpksywv.cloudfront.net/better-language-models/language_models_are_unsupervised_multitask_learners.pdf>`_,
|
||||
`Language Models are Unsupervised Multitask Learners <https://d4mucfpksywv.cloudfront.net/better-language-models/language_models_are_unsupervised_multitask_learners.pdf>`_,
|
||||
Alec Radford et al.
|
||||
|
||||
A bigger and better version of GPT, pretrained on WebText (web pages from outgoing links in Reddit with 3 karmas or
|
||||
A bigger and better version of GPT, pretrained on WebText (web pages from outgoing links in Reddit with 3 karmas or
|
||||
more).
|
||||
|
||||
The library provides versions of the model for language modeling and multitask language modeling/multiple choice
|
||||
The library provides versions of the model for language modeling and multitask language modeling/multiple choice
|
||||
classification.
|
||||
|
||||
CTRL
|
||||
@@ -101,11 +100,11 @@ CTRL
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-ctrl-blueviolet">
|
||||
</a>
|
||||
|
||||
`CTRL: A Conditional Transformer Language Model for Controllable Generation <https://arxiv.org/abs/1909.05858>`_,
|
||||
`CTRL: A Conditional Transformer Language Model for Controllable Generation <https://arxiv.org/abs/1909.05858>`_,
|
||||
Nitish Shirish Keskar et al.
|
||||
|
||||
Same as the GPT model but adds the idea of control codes. Text is generated from a prompt (can be empty) and one (or
|
||||
several) of those control codes which are then used to influence the text generation: generate with the style of
|
||||
Same as the GPT model but adds the idea of control codes. Text is generated from a prompt (can be empty) and one (or
|
||||
several) of those control codes which are then used to influence the text generation: generate with the style of
|
||||
wikipedia article, a book or a movie review.
|
||||
|
||||
The library provides a version of the model for language modeling only.
|
||||
@@ -122,19 +121,19 @@ Transformer-XL
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-transfo--xl-blueviolet">
|
||||
</a>
|
||||
|
||||
`Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context <https://arxiv.org/abs/1901.02860>`_,
|
||||
`Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context <https://arxiv.org/abs/1901.02860>`_,
|
||||
Zihang Dai et al.
|
||||
|
||||
Same as a regular GPT model, but introduces a recurrence mechanism for two consecutive segments (similar to a regular
|
||||
RNNs with two consecutive inputs). In this context, a segment is a number of consecutive tokens (for instance 512) that
|
||||
Same as a regular GPT model, but introduces a recurrence mechanism for two consecutive segments (similar to a regular
|
||||
RNNs with two consecutive inputs). In this context, a segment is a number of consecutive tokens (for instance 512) that
|
||||
may span across multiple documents, and segments are fed in order to the model.
|
||||
|
||||
Basically, the hidden states of the previous segment are concatenated to the current input to compute the attention
|
||||
scores. This allows the model to pay attention to information that was in the previous segment as well as the current
|
||||
Basically, the hidden states of the previous segment are concatenated to the current input to compute the attention
|
||||
scores. This allows the model to pay attention to information that was in the previous segment as well as the current
|
||||
one. By stacking multiple attention layers, the receptive field can be increased to multiple previous segments.
|
||||
|
||||
This changes the positional embeddings to positional relative embeddings (as the regular positional embeddings would
|
||||
give the same results in the current input and the current hidden state at a given position) and needs to make some
|
||||
This changes the positional embeddings to positional relative embeddings (as the regular positional embeddings would
|
||||
give the same results in the current input and the current hidden state at a given position) and needs to make some
|
||||
adjustments in the way attention scores are computed.
|
||||
|
||||
The library provides a version of the model for language modeling only.
|
||||
@@ -156,16 +155,16 @@ Reformer
|
||||
`Reformer: The Efficient Transformer <https://arxiv.org/abs/2001.04451>`_,
|
||||
Nikita Kitaev et al .
|
||||
|
||||
An autoregressive transformer model with lots of tricks to reduce memory footprint and compute time. Those tricks
|
||||
An autoregressive transformer model with lots of tricks to reduce memory footprint and compute time. Those tricks
|
||||
include:
|
||||
|
||||
* Use :ref:`Axial position encoding <axial-pos-encoding>` (see below for more details). It’s a mechanism to avoid
|
||||
having a huge positional encoding matrix (when the sequence length is very big) by factorizing it into smaller
|
||||
* Use :ref:`Axial position encoding <axial-pos-encoding>` (see below for more details). It’s a mechanism to avoid
|
||||
having a huge positional encoding matrix (when the sequence length is very big) by factorizing it in smaller
|
||||
matrices.
|
||||
* Replace traditional attention by :ref:`LSH (local-sensitive hashing) attention <lsh-attention>` (see below for more
|
||||
details). It's a technique to avoid computing the full product query-key in the attention layers.
|
||||
* Avoid storing the intermediate results of each layer by using reversible transformer layers to obtain them during
|
||||
the backward pass (subtracting the residuals from the input of the next layer gives them back) or recomputing them
|
||||
* Replace traditional attention by :ref:`LSH (local-sensitive hashing) attention <lsh-attention>` (see below for more
|
||||
details). It's a technique to avoid compute the full product query-key in the attention layers.
|
||||
* Avoid storing the intermediate results of each layer by using reversible transformer layers to obtain them during
|
||||
the backward pass (subtracting the residuals from the input of the next layer gives them back) or recomputing them
|
||||
for results inside a given layer (less efficient than storing them but saves memory).
|
||||
* Compute the feedforward operations by chunks and not on the whole batch.
|
||||
|
||||
@@ -191,14 +190,14 @@ XLNet
|
||||
`XLNet: Generalized Autoregressive Pretraining for Language Understanding <https://arxiv.org/abs/1906.08237>`_,
|
||||
Zhilin Yang et al.
|
||||
|
||||
XLNet is not a traditional autoregressive model but uses a training strategy that builds on that. It permutes the
|
||||
tokens in the sentence, then allows the model to use the last n tokens to predict the token n+1. Since this is all done
|
||||
with a mask, the sentence is actually fed in the model in the right order, but instead of masking the first n tokens
|
||||
XLNet is not a traditional autoregressive model but uses a training strategy that builds on that. It permutes the
|
||||
tokens in the sentence, then allows the model to use the last n tokens to predict the token n+1. Since this is all done
|
||||
with a mask, the sentence is actually fed in the model in the right order, but instead of masking the first n tokens
|
||||
for n+1, XLNet uses a mask that hides the previous tokens in some given permutation of 1,...,sequence length.
|
||||
|
||||
XLNet also uses the same recurrence mechanism as Transformer-XL to build long-term dependencies.
|
||||
XLNet also uses the same recurrence mechanism as Transformer-XL to build long-term dependencies.
|
||||
|
||||
The library provides a version of the model for language modeling, token classification, sentence classification,
|
||||
The library provides a version of the model for language modeling, token classification, sentence classification,
|
||||
multiple choice classification and question answering.
|
||||
|
||||
.. _autoencoding-models:
|
||||
@@ -207,7 +206,8 @@ Autoencoding models
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As mentioned before, these models rely on the encoder part of the original transformer and use no mask so the model can
|
||||
look at all the tokens in the attention heads. For pretraining, targets are the original sentences and inputs are their corrupted versions.
|
||||
look at all the tokens in the attention heads. For pretraining, inputs are a corrupted version of the sentence, usually
|
||||
obtained by masking tokens, and targets are the original sentences.
|
||||
|
||||
BERT
|
||||
----------------------------------------------
|
||||
@@ -224,18 +224,18 @@ BERT
|
||||
`BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding <https://arxiv.org/abs/1810.04805>`_,
|
||||
Jacob Devlin et al.
|
||||
|
||||
Corrupts the inputs by using random masking, more precisely, during pretraining, a given percentage of tokens (usually
|
||||
15%) is masked by:
|
||||
|
||||
Corrupts the inputs by using random masking, more precisely, during pretraining, a given percentage of tokens (usually
|
||||
15%) are masked by
|
||||
|
||||
* a special mask token with probability 0.8
|
||||
* a random token different from the one masked with probability 0.1
|
||||
* the same token with probability 0.1
|
||||
|
||||
The model must predict the original sentence, but has a second objective: inputs are two sentences A and B (with a
|
||||
separation token in between). With probability 50%, the sentences are consecutive in the corpus, in the remaining 50%
|
||||
The model must predict the original sentence, but has a second objective: inputs are two sentences A and B (with a
|
||||
separation token in between). With probability 50%, the sentences are consecutive in the corpus, in the remaining 50%
|
||||
they are not related. The model has to predict if the sentences are consecutive or not.
|
||||
|
||||
The library provides a version of the model for language modeling (traditional or masked), next sentence prediction,
|
||||
The library provides a version of the model for language modeling (traditional or masked), next sentence prediction,
|
||||
token classification, sentence classification, multiple choice classification and question answering.
|
||||
|
||||
ALBERT
|
||||
@@ -255,16 +255,16 @@ Zhenzhong Lan et al.
|
||||
|
||||
Same as BERT but with a few tweaks:
|
||||
|
||||
* Embedding size E is different from hidden size H justified because the embeddings are context independent (one
|
||||
embedding vector represents one token), whereas hidden states are context dependent (one hidden state represents a
|
||||
sequence of tokens) so it's more logical to have H >> E. Also, the embedding matrix is large since it's V x E (V
|
||||
* Embedding size E is different from hidden size H justified because the embeddings are context independent (one
|
||||
embedding vector represents one token) whereas hidden states are context dependent (one hidden state represents a
|
||||
sequence of tokens) so it's more logical to have H >> E. Als, the embedding matrix is large since it's V x E (V
|
||||
being the vocab size). If E < H, it has less parameters.
|
||||
* Layers are split in groups that share parameters (to save memory).
|
||||
* Next sentence prediction is replaced by a sentence ordering prediction: in the inputs, we have two sentences A and B
|
||||
(that are consecutive) and we either feed A followed by B or B followed by A. The model must predict if they have
|
||||
* Next sentence prediction is replaced by a sentence ordering prediction: in the inputs, we have two sentences A et B
|
||||
(that are consecutive) and we either feed A followed by B or B followed by A. The model must predict if they have
|
||||
been swapped or not.
|
||||
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence
|
||||
classification, multiple choice classification and question answering.
|
||||
|
||||
RoBERTa
|
||||
@@ -284,13 +284,13 @@ Yinhan Liu et al.
|
||||
|
||||
Same as BERT with better pretraining tricks:
|
||||
|
||||
* dynamic masking: tokens are masked differently at each epoch, whereas BERT does it once and for all
|
||||
* no NSP (next sentence prediction) loss and instead of putting just two sentences together, put a chunk of
|
||||
contiguous texts together to reach 512 tokens (so the sentences are in an order than may span several documents)
|
||||
* dynamic masking: tokens are masked differently at each epoch whereas BERT does it once and for all
|
||||
* no NSP (next sentence prediction) loss and instead of putting just two sentences together, put a chunk of
|
||||
contiguous texts together to reach 512 tokens (so sentences in in an order than may span other several documents)
|
||||
* train with larger batches
|
||||
* use BPE with bytes as a subunit and not characters (because of unicode characters)
|
||||
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence
|
||||
classification, multiple choice classification and question answering.
|
||||
|
||||
DistilBERT
|
||||
@@ -308,14 +308,14 @@ DistilBERT
|
||||
`DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter <https://arxiv.org/abs/1910.01108>`_,
|
||||
Victor Sanh et al.
|
||||
|
||||
Same as BERT but smaller. Trained by distillation of the pretrained BERT model, meaning it's been trained to predict
|
||||
Same as BERT but smaller. Trained by distillation of the pretrained BERT model, meaning it's been trained to predict
|
||||
the same probabilities as the larger model. The actual objective is a combination of:
|
||||
|
||||
* finding the same probabilities as the teacher model
|
||||
* predicting the masked tokens correctly (but no next-sentence objective)
|
||||
* a cosine similarity between the hidden states of the student and the teacher model
|
||||
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence classification
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence classification
|
||||
and question answering.
|
||||
|
||||
XLM
|
||||
@@ -332,24 +332,25 @@ XLM
|
||||
|
||||
`Cross-lingual Language Model Pretraining <https://arxiv.org/abs/1901.07291>`_, Guillaume Lample and Alexis Conneau
|
||||
|
||||
A transformer model trained on several languages. There are three different type of training for this model and the
|
||||
A transformer model trained on several languages. There are three different type of training for this model and the
|
||||
library provides checkpoints for all of them:
|
||||
|
||||
* Causal language modeling (CLM) which is the traditional autoregressive training (so this model could be in the
|
||||
previous section as well). One of the languages is selected for each training sample, and the model input is a
|
||||
sentence of 256 tokens, that may span over several documents in one of those languages.
|
||||
* Masked language modeling (MLM) which is like RoBERTa. One of the languages is selected for each training sample,
|
||||
and the model input is a sentence of 256 tokens, that may span over several documents in one of those languages, with
|
||||
* Causal language modeling (CLM) which is the traditional autoregressive training (so this model could be in the
|
||||
previous section as well). One of the languages is selected for each training sample, and the model input is a
|
||||
sentence of 256 tokens that may span on several documents in one one those languages.
|
||||
* Masked language modeling (MLM) which is like RoBERTa. One of the languages is selected for each training sample,
|
||||
and the model input is a sentence of 256 tokens that may span on several documents in one one those languages, with
|
||||
dynamic masking of the tokens.
|
||||
* A combination of MLM and translation language modeling (TLM). This consists of concatenating a sentence in two
|
||||
different languages, with random masking. To predict one of the masked tokens, the model can use both, the
|
||||
surrounding context in language 1 and the context given by language 2.
|
||||
* A combination of MLM and translation language modeling (TLM). This consists of concatenating a sentence in two
|
||||
different languages, with random masking. To predict one of the masked token, the model can use both the
|
||||
surrounding context in language 1 as well as the context given by language 2.
|
||||
|
||||
Checkpoints refer to which method was used for pretraining by having `clm`, `mlm` or `mlm-tlm` in their names. On top
|
||||
of positional embeddings, the model has language embeddings. When training using MLM/CLM, this gives the model an
|
||||
indication of the language used, and when training using MLM+TLM, an indication of the language used for each part.
|
||||
indication of the language used, and when training using MLM+TLM, an indication of which part of the input is in which
|
||||
language.
|
||||
|
||||
The library provides a version of the model for language modeling, token classification, sentence classification and
|
||||
The library provides a version of the model for language modeling, token classification, sentence classification and
|
||||
question answering.
|
||||
|
||||
XLM-RoBERTa
|
||||
@@ -364,14 +365,14 @@ XLM-RoBERTa
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-xlm--roberta-blueviolet">
|
||||
</a>
|
||||
|
||||
`Unsupervised Cross-lingual Representation Learning at Scale <https://arxiv.org/abs/1911.02116>`_, Alexis Conneau et
|
||||
`Unsupervised Cross-lingual Representation Learning at Scale <https://arxiv.org/abs/1911.02116>`_, Alexis Conneau et
|
||||
al.
|
||||
|
||||
Uses RoBERTa tricks on the XLM approach, but does not use the translation language modeling objective. It only uses
|
||||
masked language modeling on sentences coming from one language. However, the model is trained on many more languages
|
||||
Uses RoBERTa tricks on the XLM approach, but does not use the translation language modeling objective, only using
|
||||
masked language modeling on sentences coming from one language. However, the model is trained on many more languages
|
||||
(100) and doesn't use the language embeddings, so it's capable of detecting the input language by itself.
|
||||
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence
|
||||
classification, multiple choice classification and question answering.
|
||||
|
||||
FlauBERT
|
||||
@@ -404,16 +405,16 @@ ELECTRA
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-electra-blueviolet">
|
||||
</a>
|
||||
|
||||
`ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators <https://arxiv.org/abs/2003.10555>`_,
|
||||
`ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators <https://arxiv.org/abs/2003.10555>`_,
|
||||
Kevin Clark et al.
|
||||
|
||||
ELECTRA is a transformer model pretrained with the use of another (small) masked language model. The inputs are
|
||||
corrupted by that language model, which takes an input text that is randomly masked and outputs a text in which ELECTRA
|
||||
has to predict which token is an original and which one has been replaced. Like for GAN training, the small language
|
||||
model is trained for a few steps (but with the original texts as objective, not to fool the ELECTRA model like in a
|
||||
ELECTRA is a transformer model pretrained with the use of another (small) masked language model. The inputs are
|
||||
corrupted by that language model, which takes an input text that is randomly masked and outputs a text in which ELECTRA
|
||||
has to predict which token is an original and which one has been replaced. Like for GAN training, the small language
|
||||
model is trained for a few steps (but with the original texts as objective, not to fool the ELECTRA model like in a
|
||||
traditional GAN setting) then the ELECTRA model is trained for a few steps.
|
||||
|
||||
The library provides a version of the model for masked language modeling, token classification and sentence
|
||||
The library provides a version of the model for masked language modeling, token classification and sentence
|
||||
classification.
|
||||
|
||||
.. _longformer:
|
||||
@@ -432,9 +433,9 @@ Longformer
|
||||
|
||||
`Longformer: The Long-Document Transformer <https://arxiv.org/abs/2004.05150>`_, Iz Beltagy et al.
|
||||
|
||||
A transformer model replacing the attention matrices by sparse matrices to go faster. Often, the local context (e.g.,
|
||||
what are the two tokens left and right?) is enough to take action for a given token. Some preselected input tokens are
|
||||
still given global attention, but the attention matrix has way less parameters, resulting in a speed-up. See the
|
||||
A transformer model replacing the attention matrices by sparse matrices to go faster. Often, the local context (e.g.,
|
||||
what are the two tokens left and right?) is enough to take action for a given token. Some preselected input tokens are
|
||||
still given global attention, but the attention matrix has way less parameters, resulting in a speed-up. See the
|
||||
:ref:`local attention section <local-attention>` for more information.
|
||||
|
||||
It is pretrained the same way a RoBERTa otherwise.
|
||||
@@ -442,7 +443,7 @@ It is pretrained the same way a RoBERTa otherwise.
|
||||
**Note:** This model could be very well be used in an autoregressive setting, there is no checkpoint for such a
|
||||
pretraining yet, though.
|
||||
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence
|
||||
The library provides a version of the model for masked language modeling, token classification, sentence
|
||||
classification, multiple choice classification and question answering.
|
||||
|
||||
.. _seq-to-seq-models:
|
||||
@@ -464,46 +465,21 @@ BART
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-bart-blueviolet">
|
||||
</a>
|
||||
|
||||
`BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension
|
||||
`BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension
|
||||
<https://arxiv.org/abs/1910.13461>`_, Mike Lewis et al.
|
||||
|
||||
Sequence-to-sequence model with an encoder and a decoder. Encoder is fed a corrupted version of the tokens, decoder is
|
||||
fed the original tokens (but has a mask to hide the future words like a regular transformers decoder). For the encoder, on the
|
||||
Sequence-to-sequence model with an encoder and a decoder. Encoder is fed a corrupted version of the tokens, decoder is
|
||||
fed the tokens (but has a mask to hide the future words like a regular transformers decoder). For the encoder, on the
|
||||
pretraining tasks, a composition of the following transformations are applied:
|
||||
|
||||
* mask random tokens (like in BERT)
|
||||
* delete random tokens
|
||||
* mask a span of k tokens with a single mask token (a span of 0 tokens is an insertion of a mask token)
|
||||
* permute sentences
|
||||
* rotate the document to make it start at a specific token
|
||||
* rotate the document to make it start by a specific token
|
||||
|
||||
The library provides a version of this model for conditional generation and sequence classification.
|
||||
|
||||
Pegasus
|
||||
----------------------------------------------
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<a href="https://huggingface.co/models?filter=pegasus">
|
||||
<img alt="Models" src="https://img.shields.io/badge/All_model_pages-pegasus-blueviolet">
|
||||
</a>
|
||||
<a href="model_doc/pegasus.html">
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-pegasus-blueviolet">
|
||||
</a>
|
||||
|
||||
`PEGASUS: Pre-training with Extracted Gap-sentences forAbstractive Summarization
|
||||
<https://arxiv.org/pdf/1912.08777.pdf>`_, Jingqing Zhang, Yao Zhao, Mohammad Saleh and Peter J. Liu on Dec 18, 2019.
|
||||
|
||||
Sequence-to-sequence model with the same encoder-decoder model architecture as BART. Pegasus is pre-trained jointly on two self-supervised objective functions: Masked Language Modeling (MLM) and a novel summarization specific pre-training objective, called Gap Sentence Generation (GSG).
|
||||
|
||||
* MLM: encoder input tokens are randomely replaced by a mask tokens and have to be predicted by the encoder (like in BERT)
|
||||
* GSG: whole encoder input sentences are replaced by a second mask token and fed to the decoder, but which has a causal mask to hide the future words like a regular auto-regressive transformer decoder.
|
||||
|
||||
In contrast to BART, Pegasus' pretraining task is intentionally similar to summarization: important sentences are masked and are generated together as one output sequence from the remaining sentences, similar to an extractive summary.
|
||||
|
||||
The library provides a version of this model for conditional generation, which should be used for summarization.
|
||||
|
||||
|
||||
MarianMT
|
||||
----------------------------------------------
|
||||
|
||||
@@ -534,71 +510,47 @@ T5
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-t5-blueviolet">
|
||||
</a>
|
||||
|
||||
`Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer <https://arxiv.org/abs/1910.10683>`_,
|
||||
`Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer <https://arxiv.org/abs/1910.10683>`_,
|
||||
Colin Raffel et al.
|
||||
|
||||
Uses the traditional transformer model (with a slight change in the positional embeddings, which are learned at
|
||||
each layer). To be able to operate on all NLP tasks, it transforms them into text-to-text problems by using specific
|
||||
prefixes: “summarize: ”, “question: ”, “translate English to German: ” and so forth.
|
||||
Uses the traditional transformer model (except a slight change with the positional embeddings, which are learned at
|
||||
each layer). To be able to operate on all NLP tasks, it transforms them in text-to-text problems by using certain
|
||||
prefixes: “Summarize: …”, “question: …”, “translate English to German: …” and so forth.
|
||||
|
||||
The pretraining includes both supervised and self-supervised training. Supervised training is conducted on downstream
|
||||
tasks provided by the GLUE and SuperGLUE benchmarks (converting them into text-to-text tasks as explained above).
|
||||
The pretraining includes both supervised and self-supervised training. Supervised training is conducted on downstream
|
||||
tasks provided by the GLUE and SuperGLUE benchmarks (changing them to text-to-text tasks as explained above).
|
||||
|
||||
Self-supervised training uses corrupted tokens, by randomly removing 15% of the tokens and
|
||||
replacing them with individual sentinel tokens (if several consecutive tokens are marked for removal, the whole group is replaced with a single sentinel token). The input of the encoder is the corrupted sentence, the input of the decoder is the
|
||||
Self-supervised training consists of corrupted pretrained, which means randomly removing 15% of the tokens and
|
||||
replacing them by individual sentinel tokens (if several consecutive tokens are marked for removal, they are replaced
|
||||
by one single sentinel token). The input of the encoder is the corrupted sentence, the input of the decoder the
|
||||
original sentence and the target is then the dropped out tokens delimited by their sentinel tokens.
|
||||
|
||||
For instance, if we have the sentence “My dog is very cute .”, and we decide to remove the tokens: "dog", "is" and "cute", the encoder
|
||||
input becomes “My <x> very <y> .” and the target input becomes “<x> dog is <y> cute .<z>”
|
||||
For instance, if we have the sentence “My dog is very cute .”, and we decide to remove the token dog, is and cute, the
|
||||
input becomes “My <x> very <y> .” and the target is “<x> dog is <y> . <z>”
|
||||
|
||||
The library provides a version of this model for conditional generation.
|
||||
|
||||
MBart
|
||||
----------------------------------------------
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<a href="https://huggingface.co/models?filter=mbart">
|
||||
<img alt="Models" src="https://img.shields.io/badge/All_model_pages-mbart-blueviolet">
|
||||
</a>
|
||||
<a href="model_doc/mbart.html">
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-mbart-blueviolet">
|
||||
</a>
|
||||
|
||||
`Multilingual Denoising Pre-training for Neural Machine Translation <https://arxiv.org/abs/2001.08210>`_ by Yinhan Liu, Jiatao Gu, Naman Goyal, Xian Li, Sergey Edunov
|
||||
Marjan Ghazvininejad, Mike Lewis, Luke Zettlemoyer.
|
||||
|
||||
The model architecture and pre-training objective is same as BART, but MBart is trained on 25 languages
|
||||
and is intended for supervised and unsupervised machine translation. MBart is one of the first methods
|
||||
for pre-training a complete sequence-to-sequence model by denoising full texts in multiple languages,
|
||||
|
||||
The library provides a version of this model for conditional generation.
|
||||
|
||||
The `mbart-large-en-ro checkpoint <https://huggingface.co/facebook/mbart-large-en-ro>`_ can be used for english -> romanian translation.
|
||||
|
||||
The `mbart-large-cc25 <https://huggingface.co/facebook/mbart-large-cc25>`_ checkpoint can be finetuned for other translation and summarization tasks, using code in ```examples/seq2seq/``` , but is not very useful without finetuning.
|
||||
|
||||
.. _multimodal-models:
|
||||
|
||||
Multimodal models
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There is one multimodal model in the library which has not been pretrained in the self-supervised fashion like the
|
||||
There is one multimodal model in the library which has not been pretrained in the self-supervised fashion like the
|
||||
others.
|
||||
|
||||
MMBT
|
||||
----------------------------------------------
|
||||
|
||||
`Supervised Multimodal Bitransformers for Classifying Images and Text <https://arxiv.org/abs/1909.02950>`_, Douwe Kiela
|
||||
`Supervised Multimodal Bitransformers for Classifying Images and Text <https://arxiv.org/abs/1909.02950>`_, Douwe Kiela
|
||||
et al.
|
||||
|
||||
A transformers model used in multimodal settings, combining a text and an image to make predictions. The transformer
|
||||
model takes as inputs the embeddings of the tokenized text and the final activations of a pretrained on images resnet
|
||||
(after the pooling layer) that goes through a linear layer (to go from number of features at the end of the
|
||||
A transformers model used in multimodal settings, combining a text and an image to make predictions. The transformer
|
||||
model takes as inputs the embeddings of the tokenized text and a the final activations of a pretrained resnet on the
|
||||
images (after the pooling layer) that goes through a linear layer (to go from number of features at the end of the
|
||||
resnet to the hidden state dimension of the transformer).
|
||||
|
||||
The different inputs are concatenated, and on top of the positional embeddings, a segment embedding is added to let the
|
||||
model know which part of the input vector corresponds to the text and which to the image.
|
||||
The different inputs are concatenated, and on top of the positional embeddings, a segment embedding is added to let the
|
||||
model know which part of the input vector corresponds to the text or the image.
|
||||
|
||||
The pretrained model only works for classification.
|
||||
|
||||
@@ -606,79 +558,45 @@ The pretrained model only works for classification.
|
||||
More information in this :doc:`model documentation </model_doc/mmbt.html>`.
|
||||
TODO: write this page
|
||||
|
||||
.. _retrieval-based-models:
|
||||
|
||||
Retrieval-based models
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Some models use documents retrieval during (pre)training and inference for open-domain question answering, for example.
|
||||
|
||||
|
||||
DPR
|
||||
----------------------------------------------
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<a href="https://huggingface.co/models?filter=dpr">
|
||||
<img alt="Models" src="https://img.shields.io/badge/All_model_pages-dpr-blueviolet">
|
||||
</a>
|
||||
<a href="model_doc/ctrl.dpr">
|
||||
<img alt="Doc" src="https://img.shields.io/badge/Model_documentation-dpr-blueviolet">
|
||||
</a>
|
||||
|
||||
`Dense Passage Retrieval for Open-Domain Question Answering <https://arxiv.org/abs/2004.04906>`_,
|
||||
Vladimir Karpukhin et al.
|
||||
|
||||
Dense Passage Retrieval (DPR) - is a set of tools and models for state-of-the-art open-domain question-answering research.
|
||||
|
||||
|
||||
DPR consists in three models:
|
||||
|
||||
* Question encoder: encode questions as vectors
|
||||
* Context encoder: encode contexts as vectors
|
||||
* Reader: extract the answer of the questions inside retrieved contexts, along with a relevance score (high if the inferred span actually answers the question).
|
||||
|
||||
DPR's pipeline (not implemented yet) uses a retrieval step to find the top k contexts given a certain question, and then it calls the reader with the question and the retrieved documents to get the answer.
|
||||
|
||||
More technical aspects
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Full vs sparse attention
|
||||
----------------------------------------------
|
||||
|
||||
Most transformer models use full attention in the sense that the attention matrix is square. It can be a big
|
||||
computational bottleneck when you have long texts. Longformer and reformer are models that try to be more efficient and
|
||||
Most transformer models use full attention in the sense that the attention matrix is square. It can be a big
|
||||
computational bottleneck when you have long texts. Longformer and reformer are models that try to be more efficient and
|
||||
use a sparse version of the attention matrix to speed up training.
|
||||
|
||||
.. _lsh-attention:
|
||||
|
||||
**LSH attention**
|
||||
|
||||
:ref:`Reformer <reformer>` uses LSH attention. In the softmax(QK^t), only the biggest elements (in the softmax
|
||||
dimension) of the matrix QK^t are going to give useful contributions. So for each query q in Q, we can consider only
|
||||
the keys k in K that are close to q. A hash function is used to determine if q and k are close. The attention mask is
|
||||
modified to mask the current token (except at the first position), because it will give a query and a key equal (so very
|
||||
similar to each other). Since the hash can be a bit random, several hash functions are used in practice (determined by
|
||||
a n_rounds parameter) and then are averaged together.
|
||||
:ref:`Reformer <reformer>` uses LSH attention. In the softmax(QK^t), only the biggest elements (in the softmax
|
||||
dimension) of the matrix QK^t are going to give useful contributions. So for each query q in Q, we can only consider
|
||||
the keys k in K that are close to q. A hash function is used to determine if q and k are close. The attention mask is
|
||||
modified to mask the current token (except at the first position) because it will give a query and key equal (so very
|
||||
similar to each other). Since the hash can be a bit random, several hash functions are used in practice (determined by
|
||||
a n_rounds parameter) then are averaged together.
|
||||
|
||||
.. _local-attention:
|
||||
|
||||
**Local attention**
|
||||
|
||||
:ref:`Longformer <longformer>` uses local attention: often, the local context (e.g., what are the two tokens to the left and
|
||||
right?) is enough to take action for a given token. Also, by stacking attention layers that have a small window, the
|
||||
last layer will have a receptive field of more than just the tokens in the window, allowing them to build a
|
||||
:ref:`Longformer <longformer>` uses local attention: often, the local context (e.g., what are the two tokens left and
|
||||
right?) is enough to take action for a given token. Also, by stacking attention layers that have a small window, the
|
||||
last layer will have a receptive field of more than just the tokens on the window, allowing them to build a
|
||||
representation of the whole sentence.
|
||||
|
||||
Some preselected input tokens are also given global attention: for those few tokens, the attention matrix can access
|
||||
all tokens and this process is symmetric: all other tokens have access to those specific tokens (on top of the ones in
|
||||
Some preselected input tokens are also given global attention: for those few tokens, the attention matrix can access
|
||||
all tokens and this process is symmetric: all other tokens have access to those specific tokens (on top of the ones in
|
||||
their local window). This is shown in Figure 2d of the paper, see below for a sample attention mask:
|
||||
|
||||
.. image:: imgs/local_attention_mask.png
|
||||
:scale: 50 %
|
||||
:align: center
|
||||
|
||||
Using those attention matrices with less parameters then allows the model to have inputs having a bigger sequence
|
||||
Using those attention matrices with less parameters then allows the model to have inputs having a bigger sequence
|
||||
length.
|
||||
|
||||
Other tricks
|
||||
@@ -688,10 +606,13 @@ Other tricks
|
||||
|
||||
**Axial positional encodings**
|
||||
|
||||
:ref:`Reformer <reformer>` uses axial positional encodings: in traditional transformer models, the positional encoding
|
||||
E is a matrix of size :math:`l` by :math:`d`, :math:`l` being the sequence length and :math:`d` the dimension of the
|
||||
hidden state. If you have very long texts, this matrix can be huge and take way too much space on the GPU. To alleviate that, axial positional encodings consist of factorizing that big matrix E in two smaller matrices E1 and
|
||||
:ref:`Reformer <reformer>` uses axial positional encodings: in traditional transformer models, the positional encoding
|
||||
E is a matrix of size :math:`l` by :math:`d`, :math:`l` being the sequence length and :math:`d` the dimension of the
|
||||
hidden state. If you have very long texts, this matrix can be huge and take way too much space on the GPU.
|
||||
|
||||
To alleviate that, axial positional encodings consists in factorizing that big matrix E in two smaller matrices E1 and
|
||||
E2, with dimensions :math:`l_{1} \times d_{1}` and :math:`l_{2} \times d_{2}`, such that :math:`l_{1} \times l_{2} = l`
|
||||
and :math:`d_{1} + d_{2} = d` (with the product for the lengths, this ends up being way smaller). The embedding for
|
||||
time step :math:`j` in E is obtained by concatenating the embeddings for timestep :math:`j \% l1` in E1 and
|
||||
and :math:`d_{1} + d_{2} = d` (with the product for the lengths, this ends up being way smaller). The embedding for
|
||||
time step :math:`j` in E is obtained by concatenating the embeddings for timestep :math:`j \% l1` in E1 and
|
||||
:math:`j // l1` in E2.
|
||||
|
||||
@@ -45,12 +45,12 @@ A few other goals:
|
||||
- A simple/consistent way to add new tokens to the vocabulary and embeddings for fine-tuning.
|
||||
- Simple ways to mask and prune transformer heads.
|
||||
|
||||
- Switch easily between PyTorch and TensorFlow 2.0, allowing training using one framework and inference using another.
|
||||
- Switch easily between PyTorch and TensorFlow 2.0, allowing training using one framwork and inference using another.
|
||||
|
||||
Main concepts
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The library is built around three types of classes for each model:
|
||||
The library is build around three types of classes for each model:
|
||||
|
||||
- **Model classes** such as :class:`~transformers.BertModel`, which are 30+ PyTorch models
|
||||
(`torch.nn.Module <https://pytorch.org/docs/stable/nn.html#torch.nn.Module>`__) or Keras models
|
||||
@@ -65,9 +65,9 @@ The library is built around three types of classes for each model:
|
||||
|
||||
All these classes can be instantiated from pretrained instances and saved locally using two methods:
|
||||
|
||||
- :obj:`from_pretrained()` lets you instantiate a model/configuration/tokenizer from a pretrained version either
|
||||
- :obj:`from_pretrained()` let you instantiate a model/configuration/tokenizer from a pretrained version either
|
||||
provided by the library itself (the suported models are provided in the list :doc:`here <pretrained_models>`
|
||||
or stored locally (or on a server) by the user,
|
||||
- :obj:`save_pretrained()` lets you save a model/configuration/tokenizer locally so that it can be reloaded using
|
||||
- :obj:`save_pretrained()` let you save a model/configuration/tokenizer locally so that it can be reloaded using
|
||||
:obj:`from_pretrained()`.
|
||||
|
||||
@@ -53,6 +53,7 @@ The tokenizer can decode a list of token ids in a proper sentence:
|
||||
|
||||
As you can see, the tokenizer automatically added some special tokens that the model expect. Not all model need special
|
||||
tokens; for instance, if we had used` gtp2-medium` instead of `bert-base-cased` to create our tokenizer, we would have
|
||||
|
||||
seen the same sentence as the original one here. You can disable this behavior (which is only advised if you have added
|
||||
those special tokens yourself) by passing ``add_special_tokens=False``.
|
||||
|
||||
@@ -284,12 +285,6 @@ The tokenizer also accept pre-tokenized inputs. This is particularly useful when
|
||||
predictions in `named entity recognition (NER) <https://en.wikipedia.org/wiki/Named-entity_recognition>`__ or
|
||||
`part-of-speech tagging (POS tagging) <https://en.wikipedia.org/wiki/Part-of-speech_tagging>`__.
|
||||
|
||||
.. warning::
|
||||
|
||||
Pre-tokenized does not mean your inputs are already tokenized (you wouldn't need to pass them though the tokenizer
|
||||
if that was the case) but just split into words (which is often the first step in subword tokenization algorithms
|
||||
like BPE).
|
||||
|
||||
If you want to use pre-tokenized inputs, just set :obj:`is_pretokenized=True` when passing your inputs to the
|
||||
tokenizer. For instance, we have:
|
||||
|
||||
|
||||
@@ -331,6 +331,9 @@ For a list that includes community-uploaded models, refer to `https://huggingfac
|
||||
| +------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| | ``facebook/bart-large-cnn`` | | 12-layer, 1024-hidden, 16-heads, 406M parameters (same as base) |
|
||||
| | | | bart-large base architecture finetuned on cnn summarization task |
|
||||
| +------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| | ``facebook/mbart-large-en-ro`` | | 12-layer, 1024-hidden, 16-heads, 880M parameters |
|
||||
| | | | bart-large architecture pretrained on cc25 multilingual data , finetuned on WMT english romanian translation. |
|
||||
+-------------------+------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| DialoGPT | ``DialoGPT-small`` | | 12-layer, 768-hidden, 12-heads, 124M parameters |
|
||||
| | | | Trained on English text: 147M conversation-like exchanges extracted from Reddit. |
|
||||
@@ -358,9 +361,3 @@ For a list that includes community-uploaded models, refer to `https://huggingfac
|
||||
| | ``allenai/longformer-large-4096`` | | 24-layer, 1024-hidden, 16-heads, ~435M parameters |
|
||||
| | | | Starting from RoBERTa-large checkpoint, trained on documents of max length 4,096 |
|
||||
+-------------------+------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| MBart | ``facebook/mbart-large-cc25`` | | 24-layer, 1024-hidden, 16-heads, 610M parameters |
|
||||
| | | | mBART (bart-large architecture) model trained on 25 languages' monolingual corpus |
|
||||
| +------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| | ``facebook/mbart-large-en-ro`` | | 24-layer, 1024-hidden, 16-heads, 610M parameters |
|
||||
| | | | mbart-large-cc25 model finetuned on WMT english romanian translation. |
|
||||
+-------------------+------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
||||
@@ -52,17 +52,15 @@ Below are some of the operators which can be enabled to speed up inference throu
|
||||
* Skip connection LayerNormalization fusing
|
||||
* FastGeLU approximation
|
||||
|
||||
Some of the optimizations performed by ONNX runtime can be hardware specific and thus lead to different performances
|
||||
if used on another machine with a different hardware configuration than the one used for exporting the model.
|
||||
For this reason, when using ``convert_graph_to_onnx.py`` optimizations are not enabled,
|
||||
ensuring the model can be easily exported to various hardware.
|
||||
Optimizations can then be enabled when loading the model through ONNX runtime for inference.
|
||||
|
||||
Fortunately, you can let ONNXRuntime find all the possible optimized operators for you. Simply add ``--optimize``
|
||||
when exporting your model through ``convert_graph_to_onnx.py``.
|
||||
|
||||
.. note::
|
||||
When quantization is enabled (see below), ``convert_graph_to_onnx.py`` script will enable optimizations on the model
|
||||
because quantization would modify the underlying graph making it impossible for ONNX runtime to do the optimizations
|
||||
afterwards.
|
||||
Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python convert_graph_to_onnx.py --framework <pt, tf> --model bert-base-cased --optimize bert-base-cased.onnx
|
||||
|
||||
.. note::
|
||||
For more information about the optimizations enabled by ONNXRuntime, please have a look at the (`ONNXRuntime Github <https://github.com/microsoft/onnxruntime/tree/master/onnxruntime/python/tools/transformers>`_)
|
||||
@@ -114,6 +112,8 @@ Example of quantized BERT model export:
|
||||
above command will contain the original ONNX model storing `float32` weights.
|
||||
The second one, with ``-quantized`` suffix, will hold the quantized parameters.
|
||||
|
||||
.. note::
|
||||
The quantization export gives the best performances when used in combination with ``--optimize``.
|
||||
|
||||
TorchScript
|
||||
=======================================
|
||||
@@ -130,12 +130,13 @@ Pytorch's two modules `JIT and TRACE <https://pytorch.org/docs/stable/jit.html>`
|
||||
their model to be re-used in other programs, such as efficiency-oriented C++ programs.
|
||||
|
||||
We have provided an interface that allows the export of 🤗 Transformers models to TorchScript so that they can
|
||||
be reused in a different environment than a Pytorch-based python program. Here we explain how to export and use our models using TorchScript.
|
||||
be reused in a different environment than a Pytorch-based python program. Here we explain how to use our models so that
|
||||
they can be exported, and what to be mindful of when using these models with TorchScript.
|
||||
|
||||
Exporting a model requires two things:
|
||||
Exporting a model needs two things:
|
||||
|
||||
* a forward pass with dummy inputs.
|
||||
* model instantiation with the ``torchscript`` flag.
|
||||
* dummy inputs to execute a model forward pass.
|
||||
* the model needs to be instantiated with the ``torchscript`` flag.
|
||||
|
||||
These necessities imply several things developers should be careful about. These are detailed below.
|
||||
|
||||
@@ -146,8 +147,8 @@ Implications
|
||||
TorchScript flag and tied weights
|
||||
------------------------------------------------
|
||||
This flag is necessary because most of the language models in this repository have tied weights between their
|
||||
``Embedding`` layer and their ``Decoding`` layer. TorchScript does not allow the export of models that have tied weights, therefore
|
||||
it is necessary to untie and clone the weights beforehand.
|
||||
``Embedding`` layer and their ``Decoding`` layer. TorchScript does not allow the export of models that have tied weights,
|
||||
it is therefore necessary to untie the weights beforehand.
|
||||
|
||||
This implies that models instantiated with the ``torchscript`` flag have their ``Embedding`` layer and ``Decoding`` layer
|
||||
separate, which means that they should not be trained down the line. Training would de-synchronize the two layers,
|
||||
@@ -180,7 +181,7 @@ when exporting varying sequence-length models.
|
||||
Using TorchScript in Python
|
||||
-------------------------------------------------
|
||||
|
||||
Below is an example, showing how to save, load models as well as how to use the trace for inference.
|
||||
Below are examples of using the Python to save, load models as well as how to use the trace for inference.
|
||||
|
||||
Saving a model
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -236,10 +237,10 @@ We are re-using the previously initialised ``dummy_input``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
loaded_model = torch.jit.load("traced_bert.pt")
|
||||
loaded_model = torch.jit.load("traced_model.pt")
|
||||
loaded_model.eval()
|
||||
|
||||
all_encoder_layers, pooled_output = loaded_model(*dummy_input)
|
||||
all_encoder_layers, pooled_output = loaded_model(dummy_input)
|
||||
|
||||
Using a traced model for inference
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
+106
-123
@@ -15,17 +15,18 @@ checkpoints are usually pre-trained on a large corpus of data and fine-tuned on
|
||||
following:
|
||||
|
||||
- Not all models were fine-tuned on all tasks. If you want to fine-tune a model on a specific task, you can leverage
|
||||
one of the `run_$TASK.py` scripts in the
|
||||
`examples <https://github.com/huggingface/transformers/tree/master/examples>`__ directory.
|
||||
one of the `run_$TASK.py` script in the
|
||||
`examples <https://github.com/huggingface/transformers/tree/master/examples>`_ directory.
|
||||
- Fine-tuned models were fine-tuned on a specific dataset. This dataset may or may not overlap with your use-case
|
||||
and domain. As mentioned previously, you may leverage the
|
||||
`examples <https://github.com/huggingface/transformers/tree/master/examples>`__ scripts to fine-tune your model, or you
|
||||
`examples <https://github.com/huggingface/transformers/tree/master/examples>`_ scripts to fine-tune your model, or you
|
||||
may create your own training script.
|
||||
|
||||
In order to do an inference on a task, several mechanisms are made available by the library:
|
||||
|
||||
- Pipelines: very easy-to-use abstractions, which require as little as two lines of code.
|
||||
- Direct model use: Less abstractions, but more flexibility and power via a direct access to a tokenizer (PyTorch/TensorFlow) and full inference capacity.
|
||||
- Using a model directly with a tokenizer (PyTorch/TensorFlow): the full inference using the model. Less abstraction,
|
||||
but much more powerful.
|
||||
|
||||
Both approaches are showcased here.
|
||||
|
||||
@@ -43,11 +44,10 @@ Sequence Classification
|
||||
Sequence classification is the task of classifying sequences according to a given number of classes. An example
|
||||
of sequence classification is the GLUE dataset, which is entirely based on that task. If you would like to fine-tune
|
||||
a model on a GLUE sequence classification task, you may leverage the
|
||||
`run_glue.py <https://github.com/huggingface/transformers/tree/master/examples/text-classification/run_glue.py>`__ and
|
||||
`run_pl_glue.py <https://github.com/huggingface/transformers/tree/master/examples/text-classification/run_pl_glue.py>`__ or
|
||||
`run_tf_glue.py <https://github.com/huggingface/transformers/tree/master/examples/text-classification/run_tf_glue.py>`__ scripts.
|
||||
`run_glue.py <https://github.com/huggingface/transformers/tree/master/examples/text-classification/run_glue.py>`_ or
|
||||
`run_tf_glue.py <https://github.com/huggingface/transformers/tree/master/examples/text-classification/run_tf_glue.py>`_ scripts.
|
||||
|
||||
Here is an example of using pipelines to do sentiment analysis: identifying if a sequence is positive or negative.
|
||||
Here is an example using the pipelines do to sentiment analysis: identifying if a sequence is positive or negative.
|
||||
It leverages a fine-tuned model on sst2, which is a GLUE task.
|
||||
|
||||
This returns a label ("POSITIVE" or "NEGATIVE") alongside a score, as follows:
|
||||
@@ -70,17 +70,15 @@ This returns a label ("POSITIVE" or "NEGATIVE") alongside a score, as follows:
|
||||
Here is an example of doing a sequence classification using a model to determine if two sequences are paraphrases
|
||||
of each other. The process is the following:
|
||||
|
||||
1. Instantiate a tokenizer and a model from the checkpoint name. The model is
|
||||
identified as a BERT model and loads it with the weights stored in the
|
||||
checkpoint.
|
||||
2. Build a sequence from the two sentences, with the correct model-specific
|
||||
separators token type ids and attention masks
|
||||
(:func:`~transformers.PreTrainedTokenizer.encode` and
|
||||
:func:`~transformers.PreTrainedTokenizer.__call__` take care of this).
|
||||
3. Pass this sequence through the model so that it is classified in one of the
|
||||
two available classes: 0 (not a paraphrase) and 1 (is a paraphrase).
|
||||
4. Compute the softmax of the result to get probabilities over the classes.
|
||||
5. Print the results.
|
||||
- Instantiate a tokenizer and a model from the checkpoint name. The model is identified as a BERT model and loads it
|
||||
with the weights stored in the checkpoint.
|
||||
- Build a sequence from the two sentences, with the correct model-specific separators token type ids
|
||||
and attention masks (:func:`~transformers.PreTrainedTokenizer.encode` and
|
||||
:func:`~transformers.PreTrainedTokenizer.__call__` take care of this)
|
||||
- Pass this sequence through the model so that it is classified in one of the two available classes: 0
|
||||
(not a paraphrase) and 1 (is a paraphrase)
|
||||
- Compute the softmax of the result to get probabilities over the classes
|
||||
- Print the results
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -156,12 +154,9 @@ Extractive Question Answering
|
||||
|
||||
Extractive Question Answering is the task of extracting an answer from a text given a question. An example of a
|
||||
question answering dataset is the SQuAD dataset, which is entirely based on that task. If you would like to fine-tune
|
||||
a model on a SQuAD task, you may leverage the
|
||||
`run_squad.py <https://github.com/huggingface/transformers/tree/master/examples/question-answering/run_squad.py>`__ and
|
||||
`run_tf_squad.py <https://github.com/huggingface/transformers/tree/master/examples/question-answering/run_tf_squad.py>`__ scripts.
|
||||
a model on a SQuAD task, you may leverage the `run_squad.py`.
|
||||
|
||||
|
||||
Here is an example of using pipelines to do question answering: extracting an answer from a text given a question.
|
||||
Here is an example using the pipelines do to question answering: extracting an answer from a text given a question.
|
||||
It leverages a fine-tuned model on SQuAD.
|
||||
|
||||
.. code-block::
|
||||
@@ -176,7 +171,7 @@ It leverages a fine-tuned model on SQuAD.
|
||||
... a model on a SQuAD task, you may leverage the examples/question-answering/run_squad.py script.
|
||||
... """
|
||||
|
||||
This returns an answer extracted from the text, a confidence score, alongside "start" and "end" values, which
|
||||
This returns an answer extracted from the text, a confidence score, alongside "start" and "end" values which
|
||||
are the positions of the extracted answer in the text.
|
||||
|
||||
.. code-block::
|
||||
@@ -192,19 +187,16 @@ are the positions of the extracted answer in the text.
|
||||
|
||||
Here is an example of question answering using a model and a tokenizer. The process is the following:
|
||||
|
||||
1. Instantiate a tokenizer and a model from the checkpoint name. The model is
|
||||
identified as a BERT model and loads it with the weights stored in the
|
||||
checkpoint.
|
||||
2. Define a text and a few questions.
|
||||
3. Iterate over the questions and build a sequence from the text and the current
|
||||
question, with the correct model-specific separators token type ids and
|
||||
attention masks.
|
||||
4. Pass this sequence through the model. This outputs a range of scores across
|
||||
the entire sequence tokens (question and text), for both the start and end
|
||||
positions.
|
||||
5. Compute the softmax of the result to get probabilities over the tokens.
|
||||
6. Fetch the tokens from the identified start and stop values, convert those tokens to a string.
|
||||
7. Print the results.
|
||||
- Instantiate a tokenizer and a model from the checkpoint name. The model is identified as a BERT model and loads it
|
||||
with the weights stored in the checkpoint.
|
||||
- Define a text and a few questions.
|
||||
- Iterate over the questions and build a sequence from the text and the current question, with the correct
|
||||
model-specific separators token type ids and attention masks
|
||||
- Pass this sequence through the model. This outputs a range of scores across the entire sequence tokens (question and
|
||||
text), for both the start and end positions.
|
||||
- Compute the softmax of the result to get probabilities over the tokens
|
||||
- Fetch the tokens from the identified start and stop values, convert those tokens to a string.
|
||||
- Print the results
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -299,8 +291,8 @@ Here is an example of question answering using a model and a tokenizer. The proc
|
||||
Language Modeling
|
||||
----------------------------------------------------
|
||||
|
||||
Language modeling is the task of fitting a model to a corpus, which can be domain specific. All popular transformer-based
|
||||
models are trained using a variant of language modeling, e.g. BERT with masked language modeling, GPT-2 with
|
||||
Language modeling is the task of fitting a model to a corpus, which can be domain specific. All popular transformer
|
||||
based models are trained using a variant of language modeling, e.g. BERT with masked language modeling, GPT-2 with
|
||||
causal language modeling.
|
||||
|
||||
Language modeling can be useful outside of pre-training as well, for example to shift the model distribution to be
|
||||
@@ -313,7 +305,7 @@ Masked Language Modeling
|
||||
Masked language modeling is the task of masking tokens in a sequence with a masking token, and prompting the model to
|
||||
fill that mask with an appropriate token. This allows the model to attend to both the right context (tokens on the
|
||||
right of the mask) and the left context (tokens on the left of the mask). Such a training creates a strong basis
|
||||
for downstream tasks, requiring bi-directional context such as SQuAD (question answering,
|
||||
for downstream tasks requiring bi-directional context such as SQuAD (question answering,
|
||||
see `Lewis, Lui, Goyal et al. <https://arxiv.org/abs/1910.13461>`__, part 4.2).
|
||||
|
||||
Here is an example of using pipelines to replace a mask from a sequence:
|
||||
@@ -324,7 +316,7 @@ Here is an example of using pipelines to replace a mask from a sequence:
|
||||
|
||||
>>> nlp = pipeline("fill-mask")
|
||||
|
||||
This outputs the sequences with the mask filled, the confidence score, and the token id in the tokenizer
|
||||
This outputs the sequences with the mask filled, the confidence score as well as the token id in the tokenizer
|
||||
vocabulary:
|
||||
|
||||
.. code-block::
|
||||
@@ -357,19 +349,17 @@ vocabulary:
|
||||
'token': 17715,
|
||||
'token_str': 'Ġprototype'}]
|
||||
|
||||
Here is an example of doing masked language modeling using a model and a tokenizer. The process is the following:
|
||||
Here is an example doing masked language modeling using a model and a tokenizer. The process is the following:
|
||||
|
||||
1. Instantiate a tokenizer and a model from the checkpoint name. The model is
|
||||
identified as a DistilBERT model and loads it with the weights stored in the
|
||||
checkpoint.
|
||||
2. Define a sequence with a masked token, placing the :obj:`tokenizer.mask_token` instead of a word.
|
||||
3. Encode that sequence into a list of IDs and find the position of the masked token in that list.
|
||||
4. Retrieve the predictions at the index of the mask token: this tensor has the
|
||||
same size as the vocabulary, and the values are the scores attributed to each
|
||||
token. The model gives higher score to tokens it deems probable in that
|
||||
context.
|
||||
5. Retrieve the top 5 tokens using the PyTorch :obj:`topk` or TensorFlow :obj:`top_k` methods.
|
||||
6. Replace the mask token by the tokens and print the results
|
||||
- Instantiate a tokenizer and a model from the checkpoint name. The model is identified as a DistilBERT model and
|
||||
loads it with the weights stored in the checkpoint.
|
||||
- Define a sequence with a masked token, placing the :obj:`tokenizer.mask_token` instead of a word.
|
||||
- Encode that sequence into IDs and find the position of the masked token in that list of IDs.
|
||||
- Retrieve the predictions at the index of the mask token: this tensor has the same size as the vocabulary, and the
|
||||
values are the scores attributed to each token. The model gives higher score to tokens he deems probable in that
|
||||
context.
|
||||
- Retrieve the top 5 tokens using the PyTorch :obj:`topk` or TensorFlow :obj:`top_k` methods.
|
||||
- Replace the mask token by the tokens and print the results
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -429,7 +419,7 @@ for generation tasks.
|
||||
|
||||
Usually, the next token is predicted by sampling from the logits of the last hidden state the model produces from the input sequence.
|
||||
|
||||
Here is an example of using the tokenizer and model and leveraging the :func:`~transformers.PreTrainedModel.top_k_top_p_filtering` method to sample the next token following an input sequence of tokens.
|
||||
Here is an example using the tokenizer and model and leveraging the :func:`~transformers.PreTrainedModel.top_k_top_p_filtering` method to sample the next token following an input sequence of tokens.
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -483,7 +473,7 @@ Here is an example of using the tokenizer and model and leveraging the :func:`~t
|
||||
>>> resulting_string = tokenizer.decode(generated.numpy().tolist()[0])
|
||||
|
||||
|
||||
This outputs a (hopefully) coherent next token following the original sequence, which in our case is the word *has*:
|
||||
This outputs a (hopefully) coherent next token following the original sequence, which is in our case is the word *has*:
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -495,7 +485,7 @@ In the next section, we show how this functionality is leveraged in :func:`~tran
|
||||
Text Generation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In text generation (*a.k.a* *open-ended text generation*) the goal is to create a coherent portion of text that is a continuation from the given context. The following example shows how *GPT-2* can be used in pipelines to generate text. As a default all models apply *Top-K* sampling when used in pipelines, as configured in their respective configurations (see `gpt-2 config <https://s3.amazonaws.com/models.huggingface.co/bert/gpt2-config.json>`__ for example).
|
||||
In text generation (*a.k.a* *open-ended text generation*) the goal is to create a coherent portion of text that is a continuation from the given context. As an example, is it shown how *GPT-2* can be used in pipelines to generate text. As a default all models apply *Top-K* sampling when used in pipelines as configured in their respective configurations (see `gpt-2 config <https://s3.amazonaws.com/models.huggingface.co/bert/gpt2-config.json>`_ for example).
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -507,10 +497,10 @@ In text generation (*a.k.a* *open-ended text generation*) the goal is to create
|
||||
|
||||
|
||||
|
||||
Here, the model generates a random text with a total maximal length of *50* tokens from context *"As far as I am concerned, I will"*.
|
||||
The default arguments of ``PreTrainedModel.generate()`` can be directly overriden in the pipeline, as is shown above for the argument ``max_length``.
|
||||
Here the model generates a random text with a total maximal length of *50* tokens from context *"As far as I am concerned, I will"*.
|
||||
The default arguments of ``PreTrainedModel.generate()`` can directly be overriden in the pipeline as is shown above for the argument ``max_length``.
|
||||
|
||||
Here is an example of text generation using ``XLNet`` and its tokenzier.
|
||||
Here is an example for text generation using XLNet and its tokenzier.
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -566,27 +556,24 @@ Here is an example of text generation using ``XLNet`` and its tokenzier.
|
||||
|
||||
.. code-block::
|
||||
|
||||
>>> print(generated)
|
||||
Today the weather is really nice and I am planning on anning on taking a nice...... of a great time!<eop>...............
|
||||
print(generated)
|
||||
|
||||
Text generation is currently possible with *GPT-2*, *OpenAi-GPT*, *CTRL*, *XLNet*, *Transfo-XL* and *Reformer* in PyTorch and for most models in Tensorflow as well. As can be seen in the example above *XLNet* and *Transfo-XL* often need to be padded to work well.
|
||||
GPT-2 is usually a good choice for *open-ended text generation* because it was trained on millions of webpages with a causal language modeling objective.
|
||||
Text generation is currently possible with *GPT-2*, *OpenAi-GPT*, *CTRL*, *XLNet*, *Transfo-XL* and *Reformer* in PyTorch and for most models in Tensorflow as well. As can be seen in the example above *XLNet* and *Transfo-xl* often need to be padded to work well.
|
||||
GPT-2 is usually a good choice for *open-ended text generation* because it was trained on millions on webpages with a causal language modeling objective.
|
||||
|
||||
For more information on how to apply different decoding strategies for text generation, please also refer to our text generation blog post `here <https://huggingface.co/blog/how-to-generate>`__.
|
||||
For more information on how to apply different decoding strategies for text generation, please also refer to our generation blog post `here <https://huggingface.co/blog/how-to-generate>`_.
|
||||
|
||||
|
||||
Named Entity Recognition
|
||||
----------------------------------------------------
|
||||
|
||||
Named Entity Recognition (NER) is the task of classifying tokens according to a class, for example, identifying a
|
||||
Named Entity Recognition (NER) is the task of classifying tokens according to a class, for example identifying a
|
||||
token as a person, an organisation or a location.
|
||||
An example of a named entity recognition dataset is the CoNLL-2003 dataset, which is entirely based on that task.
|
||||
If you would like to fine-tune a model on an NER task, you may leverage the
|
||||
`run_ner.py <https://github.com/huggingface/transformers/tree/master/examples/token-classification/run_ner.py>`__ (PyTorch),
|
||||
`run_pl_ner.py <https://github.com/huggingface/transformers/tree/master/examples/token-classification/run_pl_ner.py>`__ (leveraging pytorch-lightning) or the
|
||||
`run_tf_ner.py <https://github.com/huggingface/transformers/tree/master/examples/token-classification/run_tf_ner.py>`__ (TensorFlow) scripts.
|
||||
If you would like to fine-tune a model on an NER task, you may leverage the `ner/run_ner.py` (PyTorch),
|
||||
`ner/run_pl_ner.py` (leveraging pytorch-lightning) or the `ner/run_tf_ner.py` (TensorFlow) scripts.
|
||||
|
||||
Here is an example of using pipelines to do named entity recognition, specifically, trying to identify tokens as belonging to one
|
||||
Here is an example using the pipelines do to named entity recognition, trying to identify tokens as belonging to one
|
||||
of 9 classes:
|
||||
|
||||
- O, Outside of a named entity
|
||||
@@ -612,7 +599,7 @@ It leverages a fine-tuned model on CoNLL-2003, fine-tuned by `@stefan-it <https:
|
||||
... "close to the Manhattan Bridge which is visible from the window."
|
||||
|
||||
|
||||
This outputs a list of all words that have been identified as one of the entities from the 9 classes defined above. Here are the
|
||||
This outputs a list of all words that have been identified as an entity from the 9 classes defined above. Here is the
|
||||
expected results:
|
||||
|
||||
.. code-block::
|
||||
@@ -633,25 +620,22 @@ expected results:
|
||||
{'word': 'Bridge', 'score': 0.990249514579773, 'entity': 'I-LOC'}
|
||||
]
|
||||
|
||||
Note, how the tokens of the sequence "Hugging Face" have been identified as an organisation, and "New York City", "DUMBO" and
|
||||
Note how the words "Hugging Face" have been identified as an organisation, and "New York City", "DUMBO" and
|
||||
"Manhattan Bridge" have been identified as locations.
|
||||
|
||||
Here is an example of doing named entity recognition, using a model and a tokenizer. The process is the following:
|
||||
Here is an example doing named entity recognition using a model and a tokenizer. The process is the following:
|
||||
|
||||
1. Instantiate a tokenizer and a model from the checkpoint name. The model is
|
||||
identified as a BERT model and loads it with the weights stored in the
|
||||
checkpoint.
|
||||
2. Define the label list with which the model was trained on.
|
||||
3. Define a sequence with known entities, such as "Hugging Face" as an organisation and "New York City" as a location.
|
||||
4. Split words into tokens so that they can be mapped to predictions. We use a
|
||||
small hack by, first, completely encoding and decoding the sequence, so that
|
||||
we're left with a string that contains the special tokens.
|
||||
5. Encode that sequence into IDs (special tokens are added automatically).
|
||||
6. Retrieve the predictions by passing the input to the model and getting the
|
||||
first output. This results in a distribution over the 9 possible classes for
|
||||
each token. We take the argmax to retrieve the most likely class for each
|
||||
token.
|
||||
7. Zip together each token with its prediction and print it.
|
||||
- Instantiate a tokenizer and a model from the checkpoint name. The model is identified as a BERT model and
|
||||
loads it with the weights stored in the checkpoint.
|
||||
- Define the label list with which the model was trained on.
|
||||
- Define a sequence with known entities, such as "Hugging Face" as an organisation and "New York City" as a location.
|
||||
- Split words into tokens so that they can be mapped to the predictions. We use a small hack by firstly completely
|
||||
encoding and decoding the sequence, so that we're left with a string that contains the special tokens.
|
||||
- Encode that sequence into IDs (special tokens are added automatically).
|
||||
- Retrieve the predictions by passing the input to the model and getting the first output. This results in a
|
||||
distribution over the 9 possible classes for each token. We take the argmax to retrieve the most likely class
|
||||
for each token.
|
||||
- Zip together each token with its prediction and print it.
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -713,8 +697,8 @@ Here is an example of doing named entity recognition, using a model and a tokeni
|
||||
>>> predictions = tf.argmax(outputs, axis=2)
|
||||
|
||||
|
||||
This outputs a list of each token mapped to its corresponding prediction. Differently from the pipeline, here every token has
|
||||
a prediction as we didn't remove the "0"th class, which means that no particular entity was found on that token. The
|
||||
This outputs a list of each token mapped to their prediction. Differently from the pipeline, here every token has
|
||||
a prediction as we didn't remove the "0" class which means that no particular entity was found on that token. The
|
||||
following array should be the output:
|
||||
|
||||
.. code-block::
|
||||
@@ -725,13 +709,13 @@ following array should be the output:
|
||||
Summarization
|
||||
----------------------------------------------------
|
||||
|
||||
Summarization is the task of summarizing a document or an article into a shorter text.
|
||||
Summarization is the task of summarizing a text / an article into a shorter text.
|
||||
|
||||
An example of a summarization dataset is the CNN / Daily Mail dataset, which consists of long news articles and was created for the task of summarization.
|
||||
If you would like to fine-tune a model on a summarization task, various approaches are described in this
|
||||
`document <https://github.com/huggingface/transformers/blob/master/examples/seq2seq/README.md>`__.
|
||||
If you would like to fine-tune a model on a summarization task, you may leverage the ``examples/summarization/bart/run_train.sh`` (leveraging pytorch-lightning) script.
|
||||
|
||||
Here is an example of using the pipelines to do summarization. It leverages a Bart model that was fine-tuned on the CNN / Daily Mail data set.
|
||||
Here is an example using the pipelines do to summarization.
|
||||
It leverages a Bart model that was fine-tuned on the CNN / Daily Mail data set.
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -758,8 +742,8 @@ Here is an example of using the pipelines to do summarization. It leverages a Ba
|
||||
... If convicted, Barrientos faces up to four years in prison. Her next court appearance is scheduled for May 18.
|
||||
... """
|
||||
|
||||
Because the summarization pipeline depends on the ``PretrainedModel.generate()`` method, we can override the default arguments
|
||||
of ``PretrainedModel.generate()`` directly in the pipeline for ``max_length`` and ``min_length`` as shown below.
|
||||
Because the summarization pipeline depends on the ``PretrainedModel.generate()`` method, we can override the default arguments
|
||||
of ``PretrainedModel.generate()`` directly in the pipeline as is shown for ``max_length`` and ``min_length`` above.
|
||||
This outputs the following summary:
|
||||
|
||||
.. code-block::
|
||||
@@ -767,15 +751,14 @@ This outputs the following summary:
|
||||
>>> print(summarizer(ARTICLE, max_length=130, min_length=30, do_sample=False))
|
||||
[{'summary_text': 'Liana Barrientos, 39, is charged with two counts of "offering a false instrument for filing in the first degree" In total, she has been married 10 times, with nine of her marriages occurring between 1999 and 2002. She is believed to still be married to four men.'}]
|
||||
|
||||
Here is an example of doing summarization using a model and a tokenizer. The process is the following:
|
||||
Here is an example doing summarization using a model and a tokenizer. The process is the following:
|
||||
|
||||
1. Instantiate a tokenizer and a model from the checkpoint name. Summarization is usually done using an encoder-decoder model, such as ``Bart`` or ``T5``.
|
||||
2. Define the article that should be summarized.
|
||||
3. Add the T5 specific prefix "summarize: ".
|
||||
4. Use the ``PretrainedModel.generate()`` method to generate the summary.
|
||||
|
||||
In this example we use Google`s T5 model. Even though it was pre-trained only on a multi-task mixed dataset (including CNN / Daily Mail), it yields very good results.
|
||||
- Instantiate a tokenizer and a model from the checkpoint name. Summarization is usually done using an encoder-decoder model, such as ``Bart`` or ``T5``.
|
||||
- Define the article that should be summarizaed.
|
||||
- Leverage the ``PretrainedModel.generate()`` method.
|
||||
- Add the T5 specific prefix "summarize: ".
|
||||
|
||||
Here Google`s T5 model is used that was only pre-trained on a multi-task mixed data set (including CNN / Daily Mail), but nevertheless yields very good results.
|
||||
.. code-block::
|
||||
|
||||
>>> ## PYTORCH CODE
|
||||
@@ -802,14 +785,12 @@ Translation
|
||||
|
||||
Translation is the task of translating a text from one language to another.
|
||||
|
||||
An example of a translation dataset is the WMT English to German dataset, which has sentences in English as the input data
|
||||
and the corresponding sentences in German as the target data.
|
||||
If you would like to fine-tune a model on a translation task, various approaches are described in this
|
||||
`document <https://github.com/huggingface/transformers/blob/master/examples/seq2seq/README.md>`__.
|
||||
An example of a translation dataset is the WMT English to German dataset, which has English sentences as the input data
|
||||
and German sentences as the target data.
|
||||
|
||||
Here is an example of using the pipelines to do translation.
|
||||
It leverages a T5 model that was only pre-trained on a multi-task mixture dataset (including WMT), yet, yielding impressive
|
||||
translation results.
|
||||
Here is an example using the pipelines do to translation.
|
||||
It leverages a T5 model that was only pre-trained on a multi-task mixture dataset (including WMT), but yields impressive
|
||||
translation results nevertheless.
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -819,15 +800,15 @@ translation results.
|
||||
>>> print(translator("Hugging Face is a technology company based in New York and Paris", max_length=40))
|
||||
[{'translation_text': 'Hugging Face ist ein Technologieunternehmen mit Sitz in New York und Paris.'}]
|
||||
|
||||
Because the translation pipeline depends on the ``PretrainedModel.generate()`` method, we can override the default arguments
|
||||
Because the translation pipeline depends on the ``PretrainedModel.generate()`` method, we can override the default arguments
|
||||
of ``PretrainedModel.generate()`` directly in the pipeline as is shown for ``max_length`` above.
|
||||
|
||||
Here is an example doing translation using a model and a tokenizer. The process is the following:
|
||||
|
||||
Here is an example of doing translation using a model and a tokenizer. The process is the following:
|
||||
|
||||
1. Instantiate a tokenizer and a model from the checkpoint name. Summarization is usually done using an encoder-decoder model, such as ``Bart`` or ``T5``.
|
||||
2. Define the article that should be summarizaed.
|
||||
3. Add the T5 specific prefix "translate English to German: "
|
||||
4. Use the ``PretrainedModel.generate()`` method to perform the translation.
|
||||
- Instantiate a tokenizer and a model from the checkpoint name. Summarization is usually done using an encoder-decoder model, such as ``Bart`` or ``T5``.
|
||||
- Define the article that should be summarizaed.
|
||||
- Leverage the ``PretrainedModel.generate()`` method.
|
||||
- Add the T5 specific prefix "translate English to German: "
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -839,6 +820,10 @@ Here is an example of doing translation using a model and a tokenizer. The proce
|
||||
|
||||
>>> inputs = tokenizer.encode("translate English to German: Hugging Face is a technology company based in New York and Paris", return_tensors="pt")
|
||||
>>> outputs = model.generate(inputs, max_length=40, num_beams=4, early_stopping=True)
|
||||
|
||||
>>> print(outputs)
|
||||
tensor([[ 0, 11560, 3896, 8881, 229, 236, 3, 14366, 15377, 181,
|
||||
11216, 16, 368, 1060, 64, 1919, 5]])
|
||||
>>> ## TENSORFLOW CODE
|
||||
>>> from transformers import TFAutoModelWithLMHead, AutoTokenizer
|
||||
|
||||
@@ -848,9 +833,7 @@ Here is an example of doing translation using a model and a tokenizer. The proce
|
||||
>>> inputs = tokenizer.encode("translate English to German: Hugging Face is a technology company based in New York and Paris", return_tensors="tf")
|
||||
>>> outputs = model.generate(inputs, max_length=40, num_beams=4, early_stopping=True)
|
||||
|
||||
As with the pipeline example, we get the same translation:
|
||||
|
||||
.. code-block::
|
||||
|
||||
>>> print(tokenizer.decode(outputs[0]))
|
||||
Hugging Face ist ein Technologieunternehmen mit Sitz in New York und Paris.
|
||||
>>> print(outputs)
|
||||
tf.Tensor(
|
||||
[[ 0 11560 3896 8881 229 236 3 14366 15377 181 11216 16
|
||||
368 1060 64 1919 5]], shape=(1, 17), dtype=int32)
|
||||
@@ -130,7 +130,7 @@ Then the base vocabulary is ['b', 'g', 'h', 'n', 'p', 's', 'u'] and all our word
|
||||
|
||||
We then take each pair of symbols and look at the most frequent. For instance 'hu' is present `10 + 5 = 15` times (10
|
||||
times in the 10 occurrences of 'hug', 5 times in the 5 occurrences of 'hugs'). The most frequent here is 'ug', present
|
||||
`10 + 5 + 5 = 20` times in total. So the first merge rule the tokenizer learns is to group all 'u' and 'g' together
|
||||
`10 + 5 + 2 + 5 = 22` times in total. So the first merge rule the tokenizer learns is to group all 'u' and 'g' together
|
||||
then it adds 'ug' to the vocabulary. Our corpus then becomes
|
||||
|
||||
::
|
||||
|
||||
@@ -20,8 +20,8 @@ from dataclasses import dataclass
|
||||
from typing import List, Optional, Union
|
||||
|
||||
import tqdm
|
||||
|
||||
from filelock import FileLock
|
||||
|
||||
from transformers import (
|
||||
BartTokenizer,
|
||||
BartTokenizerFast,
|
||||
@@ -112,10 +112,7 @@ if is_torch_available():
|
||||
cached_features_file = os.path.join(
|
||||
data_dir,
|
||||
"cached_{}_{}_{}_{}".format(
|
||||
"dev" if evaluate else "train",
|
||||
tokenizer.__class__.__name__,
|
||||
str(max_seq_length),
|
||||
task,
|
||||
"dev" if evaluate else "train", tokenizer.__class__.__name__, str(max_seq_length), task,
|
||||
),
|
||||
)
|
||||
label_list = processor.get_labels()
|
||||
@@ -281,10 +278,7 @@ class HansProcessor(DataProcessor):
|
||||
|
||||
|
||||
def hans_convert_examples_to_features(
|
||||
examples: List[InputExample],
|
||||
label_list: List[str],
|
||||
max_length: int,
|
||||
tokenizer: PreTrainedTokenizer,
|
||||
examples: List[InputExample], label_list: List[str], max_length: int, tokenizer: PreTrainedTokenizer,
|
||||
):
|
||||
"""
|
||||
Loads a data file into a list of ``InputFeatures``
|
||||
|
||||
@@ -20,9 +20,7 @@ class PlotArguments:
|
||||
Arguments pertaining to which model/config/tokenizer we are going to fine-tune, or train from scratch.
|
||||
"""
|
||||
|
||||
csv_file: str = field(
|
||||
metadata={"help": "The csv file to plot."},
|
||||
)
|
||||
csv_file: str = field(metadata={"help": "The csv file to plot."},)
|
||||
plot_along_batch: bool = field(
|
||||
default=False,
|
||||
metadata={"help": "Whether to plot along batch size or sequence lengh. Defaults to sequence length."},
|
||||
@@ -32,8 +30,7 @@ class PlotArguments:
|
||||
metadata={"help": "Whether the csv file has time results or memory results. Defaults to memory results."},
|
||||
)
|
||||
no_log_scale: bool = field(
|
||||
default=False,
|
||||
metadata={"help": "Disable logarithmic scale when plotting"},
|
||||
default=False, metadata={"help": "Disable logarithmic scale when plotting"},
|
||||
)
|
||||
is_train: bool = field(
|
||||
default=False,
|
||||
@@ -42,8 +39,7 @@ class PlotArguments:
|
||||
},
|
||||
)
|
||||
figure_png_file: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={"help": "Filename under which the plot will be saved. If unused no plot is saved."},
|
||||
default=None, metadata={"help": "Filename under which the plot will be saved. If unused no plot is saved."},
|
||||
)
|
||||
short_model_names: Optional[List[str]] = list_field(
|
||||
default=None, metadata={"help": "List of model names that are used instead of the ones in the csv file."}
|
||||
|
||||
@@ -101,30 +101,30 @@ class AlbertModelWithPabee(AlbertModel):
|
||||
regression=False,
|
||||
):
|
||||
r"""
|
||||
Return:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.AlbertConfig`) and inputs:
|
||||
last_hidden_state (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`):
|
||||
Sequence of hidden-states at the output of the last layer of the model.
|
||||
pooler_output (:obj:`torch.FloatTensor`: of shape :obj:`(batch_size, hidden_size)`):
|
||||
Last layer hidden-state of the first token of the sequence (classification token)
|
||||
further processed by a Linear layer and a Tanh activation function. The Linear
|
||||
layer weights are trained from the next sentence prediction (classification)
|
||||
objective during pre-training.
|
||||
Return:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.AlbertConfig`) and inputs:
|
||||
last_hidden_state (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`):
|
||||
Sequence of hidden-states at the output of the last layer of the model.
|
||||
pooler_output (:obj:`torch.FloatTensor`: of shape :obj:`(batch_size, hidden_size)`):
|
||||
Last layer hidden-state of the first token of the sequence (classification token)
|
||||
further processed by a Linear layer and a Tanh activation function. The Linear
|
||||
layer weights are trained from the next sentence prediction (classification)
|
||||
objective during pre-training.
|
||||
|
||||
This output is usually *not* a good summary
|
||||
of the semantic content of the input, you're often better with averaging or pooling
|
||||
the sequence of hidden-states for the whole input sequence.
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
This output is usually *not* a good summary
|
||||
of the semantic content of the input, you're often better with averaging or pooling
|
||||
the sequence of hidden-states for the whole input sequence.
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
"""
|
||||
|
||||
if input_ids is not None and inputs_embeds is not None:
|
||||
@@ -157,10 +157,7 @@ class AlbertModelWithPabee(AlbertModel):
|
||||
res = []
|
||||
for i in range(self.config.num_hidden_layers):
|
||||
encoder_outputs = self.encoder.adaptive_forward(
|
||||
encoder_outputs,
|
||||
current_layer=i,
|
||||
attention_mask=extended_attention_mask,
|
||||
head_mask=head_mask,
|
||||
encoder_outputs, current_layer=i, attention_mask=extended_attention_mask, head_mask=head_mask,
|
||||
)
|
||||
|
||||
pooled_output = self.pooler_activation(self.pooler(encoder_outputs[0][:, 0]))
|
||||
@@ -177,10 +174,7 @@ class AlbertModelWithPabee(AlbertModel):
|
||||
for i in range(self.config.num_hidden_layers):
|
||||
calculated_layer_num += 1
|
||||
encoder_outputs = self.encoder.adaptive_forward(
|
||||
encoder_outputs,
|
||||
current_layer=i,
|
||||
attention_mask=extended_attention_mask,
|
||||
head_mask=head_mask,
|
||||
encoder_outputs, current_layer=i, attention_mask=extended_attention_mask, head_mask=head_mask,
|
||||
)
|
||||
|
||||
pooled_output = self.pooler_activation(self.pooler(encoder_outputs[0][:, 0]))
|
||||
@@ -242,42 +236,42 @@ class AlbertForSequenceClassificationWithPabee(AlbertPreTrainedModel):
|
||||
labels=None,
|
||||
):
|
||||
r"""
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in ``[0, ..., config.num_labels - 1]``.
|
||||
If ``config.num_labels == 1`` a regression loss is computed (Mean-Square loss),
|
||||
If ``config.num_labels > 1`` a classification loss is computed (Cross-Entropy).
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in ``[0, ..., config.num_labels - 1]``.
|
||||
If ``config.num_labels == 1`` a regression loss is computed (Mean-Square loss),
|
||||
If ``config.num_labels > 1`` a classification loss is computed (Cross-Entropy).
|
||||
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.AlbertConfig`) and inputs:
|
||||
loss: (`optional`, returned when ``labels`` is provided) ``torch.FloatTensor`` of shape ``(1,)``:
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits ``torch.FloatTensor`` of shape ``(batch_size, config.num_labels)``
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.AlbertConfig`) and inputs:
|
||||
loss: (`optional`, returned when ``labels`` is provided) ``torch.FloatTensor`` of shape ``(1,)``:
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits ``torch.FloatTensor`` of shape ``(batch_size, config.num_labels)``
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
|
||||
Examples::
|
||||
Examples::
|
||||
|
||||
from transformers import AlbertTokenizer
|
||||
from pabee import AlbertForSequenceClassificationWithPabee
|
||||
import torch
|
||||
from transformers import AlbertTokenizer
|
||||
from pabee import AlbertForSequenceClassificationWithPabee
|
||||
import torch
|
||||
|
||||
tokenizer = AlbertTokenizer.from_pretrained('albert-base-v2')
|
||||
model = AlbertForSequenceClassificationWithPabee.from_pretrained('albert-base-v2')
|
||||
input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute")).unsqueeze(0) # Batch size 1
|
||||
labels = torch.tensor([1]).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, labels=labels)
|
||||
loss, logits = outputs[:2]
|
||||
tokenizer = AlbertTokenizer.from_pretrained('albert-base-v2')
|
||||
model = AlbertForSequenceClassificationWithPabee.from_pretrained('albert-base-v2')
|
||||
input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute")).unsqueeze(0) # Batch size 1
|
||||
labels = torch.tensor([1]).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, labels=labels)
|
||||
loss, logits = outputs[:2]
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@@ -108,30 +108,30 @@ class BertModelWithPabee(BertModel):
|
||||
regression=False,
|
||||
):
|
||||
r"""
|
||||
Return:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BertConfig`) and inputs:
|
||||
last_hidden_state (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`):
|
||||
Sequence of hidden-states at the output of the last layer of the model.
|
||||
pooler_output (:obj:`torch.FloatTensor`: of shape :obj:`(batch_size, hidden_size)`):
|
||||
Last layer hidden-state of the first token of the sequence (classification token)
|
||||
further processed by a Linear layer and a Tanh activation function. The Linear
|
||||
layer weights are trained from the next sentence prediction (classification)
|
||||
objective during pre-training.
|
||||
Return:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BertConfig`) and inputs:
|
||||
last_hidden_state (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`):
|
||||
Sequence of hidden-states at the output of the last layer of the model.
|
||||
pooler_output (:obj:`torch.FloatTensor`: of shape :obj:`(batch_size, hidden_size)`):
|
||||
Last layer hidden-state of the first token of the sequence (classification token)
|
||||
further processed by a Linear layer and a Tanh activation function. The Linear
|
||||
layer weights are trained from the next sentence prediction (classification)
|
||||
objective during pre-training.
|
||||
|
||||
This output is usually *not* a good summary
|
||||
of the semantic content of the input, you're often better with averaging or pooling
|
||||
the sequence of hidden-states for the whole input sequence.
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
This output is usually *not* a good summary
|
||||
of the semantic content of the input, you're often better with averaging or pooling
|
||||
the sequence of hidden-states for the whole input sequence.
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
"""
|
||||
|
||||
if input_ids is not None and inputs_embeds is not None:
|
||||
@@ -266,44 +266,44 @@ class BertForSequenceClassificationWithPabee(BertPreTrainedModel):
|
||||
labels=None,
|
||||
):
|
||||
r"""
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in :obj:`[0, ..., config.num_labels - 1]`.
|
||||
If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss),
|
||||
If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in :obj:`[0, ..., config.num_labels - 1]`.
|
||||
If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss),
|
||||
If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
||||
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided):
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`):
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided):
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`):
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
|
||||
Examples::
|
||||
Examples::
|
||||
|
||||
from transformers import BertTokenizer, BertForSequenceClassification
|
||||
from pabee import BertForSequenceClassificationWithPabee
|
||||
import torch
|
||||
from transformers import BertTokenizer, BertForSequenceClassification
|
||||
from pabee import BertForSequenceClassificationWithPabee
|
||||
import torch
|
||||
|
||||
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
|
||||
model = BertForSequenceClassificationWithPabee.from_pretrained('bert-base-uncased')
|
||||
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
|
||||
model = BertForSequenceClassificationWithPabee.from_pretrained('bert-base-uncased')
|
||||
|
||||
input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute", add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||
labels = torch.tensor([1]).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, labels=labels)
|
||||
input_ids = torch.tensor(tokenizer.encode("Hello, my dog is cute", add_special_tokens=True)).unsqueeze(0) # Batch size 1
|
||||
labels = torch.tensor([1]).unsqueeze(0) # Batch size 1
|
||||
outputs = model(input_ids, labels=labels)
|
||||
|
||||
loss, logits = outputs[:2]
|
||||
loss, logits = outputs[:2]
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@@ -120,10 +120,7 @@ def train(args, train_dataset, model, tokenizer):
|
||||
# Distributed training (should be after apex fp16 initialization)
|
||||
if args.local_rank != -1:
|
||||
model = torch.nn.parallel.DistributedDataParallel(
|
||||
model,
|
||||
device_ids=[args.local_rank],
|
||||
output_device=args.local_rank,
|
||||
find_unused_parameters=True,
|
||||
model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True,
|
||||
)
|
||||
|
||||
# Train!
|
||||
@@ -154,17 +151,13 @@ def train(args, train_dataset, model, tokenizer):
|
||||
logger.info(" Continuing training from epoch %d", epochs_trained)
|
||||
logger.info(" Continuing training from global step %d", global_step)
|
||||
logger.info(
|
||||
" Will skip the first %d steps in the first epoch",
|
||||
steps_trained_in_current_epoch,
|
||||
" Will skip the first %d steps in the first epoch", steps_trained_in_current_epoch,
|
||||
)
|
||||
|
||||
tr_loss, logging_loss = 0.0, 0.0
|
||||
model.zero_grad()
|
||||
train_iterator = trange(
|
||||
epochs_trained,
|
||||
int(args.num_train_epochs),
|
||||
desc="Epoch",
|
||||
disable=args.local_rank not in [-1, 0],
|
||||
epochs_trained, int(args.num_train_epochs), desc="Epoch", disable=args.local_rank not in [-1, 0],
|
||||
)
|
||||
set_seed(args) # Added here for reproductibility
|
||||
for _ in train_iterator:
|
||||
@@ -379,11 +372,7 @@ def load_and_cache_examples(args, task, tokenizer, evaluate=False):
|
||||
processor.get_dev_examples(args.data_dir) if evaluate else processor.get_train_examples(args.data_dir)
|
||||
)
|
||||
features = convert_examples_to_features(
|
||||
examples,
|
||||
tokenizer,
|
||||
label_list=label_list,
|
||||
max_length=args.max_seq_length,
|
||||
output_mode=output_mode,
|
||||
examples, tokenizer, label_list=label_list, max_length=args.max_seq_length, output_mode=output_mode,
|
||||
)
|
||||
if args.local_rank in [-1, 0]:
|
||||
logger.info("Saving features into cached file %s", cached_features_file)
|
||||
@@ -445,24 +434,15 @@ def main():
|
||||
help="The output directory where the model predictions and checkpoints will be written.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--patience",
|
||||
default="0",
|
||||
type=str,
|
||||
required=False,
|
||||
"--patience", default="0", type=str, required=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--regression_threshold",
|
||||
default=0,
|
||||
type=float,
|
||||
required=False,
|
||||
"--regression_threshold", default=0, type=float, required=False,
|
||||
)
|
||||
|
||||
# Other parameters
|
||||
parser.add_argument(
|
||||
"--config_name",
|
||||
default="",
|
||||
type=str,
|
||||
help="Pretrained config name or path if not the same as model_name",
|
||||
"--config_name", default="", type=str, help="Pretrained config name or path if not the same as model_name",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--tokenizer_name",
|
||||
@@ -486,27 +466,17 @@ def main():
|
||||
parser.add_argument("--do_train", action="store_true", help="Whether to run training.")
|
||||
parser.add_argument("--do_eval", action="store_true", help="Whether to run eval on the dev set.")
|
||||
parser.add_argument(
|
||||
"--evaluate_during_training",
|
||||
action="store_true",
|
||||
help="Run evaluation during training at each logging step.",
|
||||
"--evaluate_during_training", action="store_true", help="Run evaluation during training at each logging step.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--do_lower_case",
|
||||
action="store_true",
|
||||
help="Set this flag if you are using an uncased model.",
|
||||
"--do_lower_case", action="store_true", help="Set this flag if you are using an uncased model.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--per_gpu_train_batch_size",
|
||||
default=8,
|
||||
type=int,
|
||||
help="Batch size per GPU/CPU for training.",
|
||||
"--per_gpu_train_batch_size", default=8, type=int, help="Batch size per GPU/CPU for training.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--per_gpu_eval_batch_size",
|
||||
default=1,
|
||||
type=int,
|
||||
help="Batch size per GPU/CPU for evaluation.",
|
||||
"--per_gpu_eval_batch_size", default=1, type=int, help="Batch size per GPU/CPU for evaluation.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--gradient_accumulation_steps",
|
||||
@@ -515,19 +485,13 @@ def main():
|
||||
help="Number of updates steps to accumulate before performing a backward/update pass.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--learning_rate",
|
||||
default=5e-5,
|
||||
type=float,
|
||||
help="The initial learning rate for Adam.",
|
||||
"--learning_rate", default=5e-5, type=float, help="The initial learning rate for Adam.",
|
||||
)
|
||||
parser.add_argument("--weight_decay", default=0.0, type=float, help="Weight decay if we apply some.")
|
||||
parser.add_argument("--adam_epsilon", default=1e-8, type=float, help="Epsilon for Adam optimizer.")
|
||||
parser.add_argument("--max_grad_norm", default=1.0, type=float, help="Max gradient norm.")
|
||||
parser.add_argument(
|
||||
"--num_train_epochs",
|
||||
default=3.0,
|
||||
type=float,
|
||||
help="Total number of training epochs to perform.",
|
||||
"--num_train_epochs", default=3.0, type=float, help="Total number of training epochs to perform.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--max_steps",
|
||||
@@ -539,10 +503,7 @@ def main():
|
||||
|
||||
parser.add_argument("--logging_steps", type=int, default=500, help="Log every X updates steps.")
|
||||
parser.add_argument(
|
||||
"--save_steps",
|
||||
type=int,
|
||||
default=500,
|
||||
help="Save checkpoint every X updates steps.",
|
||||
"--save_steps", type=int, default=500, help="Save checkpoint every X updates steps.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--eval_all_checkpoints",
|
||||
@@ -551,14 +512,10 @@ def main():
|
||||
)
|
||||
parser.add_argument("--no_cuda", action="store_true", help="Avoid using CUDA when available")
|
||||
parser.add_argument(
|
||||
"--overwrite_output_dir",
|
||||
action="store_true",
|
||||
help="Overwrite the content of the output directory",
|
||||
"--overwrite_output_dir", action="store_true", help="Overwrite the content of the output directory",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--overwrite_cache",
|
||||
action="store_true",
|
||||
help="Overwrite the cached training and evaluation sets",
|
||||
"--overwrite_cache", action="store_true", help="Overwrite the cached training and evaluation sets",
|
||||
)
|
||||
parser.add_argument("--seed", type=int, default=42, help="random seed for initialization")
|
||||
|
||||
@@ -575,10 +532,7 @@ def main():
|
||||
"See details at https://nvidia.github.io/apex/amp.html",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--local_rank",
|
||||
type=int,
|
||||
default=-1,
|
||||
help="For distributed training: local_rank",
|
||||
"--local_rank", type=int, default=-1, help="For distributed training: local_rank",
|
||||
)
|
||||
parser.add_argument("--server_ip", type=str, default="", help="For distant debugging.")
|
||||
parser.add_argument("--server_port", type=str, default="", help="For distant debugging.")
|
||||
@@ -680,8 +634,7 @@ def main():
|
||||
print("Output Layers Parameters:", output_layers_param_num)
|
||||
single_output_layer_param_num = sum(param.numel() for param in model.classifiers[0].parameters())
|
||||
print(
|
||||
"Added Output Layers Parameters:",
|
||||
output_layers_param_num - single_output_layer_param_num,
|
||||
"Added Output Layers Parameters:", output_layers_param_num - single_output_layer_param_num,
|
||||
)
|
||||
|
||||
logger.info("Training/evaluation parameters %s", args)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import argparse
|
||||
import logging
|
||||
import shutil
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import run_glue_with_pabee
|
||||
from transformers.testing_utils import TestCasePlus
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
@@ -19,19 +20,20 @@ def get_setup_file():
|
||||
return args.f
|
||||
|
||||
|
||||
class PabeeTests(TestCasePlus):
|
||||
def clean_test_dir(path):
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
|
||||
|
||||
class PabeeTests(unittest.TestCase):
|
||||
def test_run_glue(self):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
tmp_dir = self.get_auto_remove_tmp_dir()
|
||||
testargs = f"""
|
||||
testargs = """
|
||||
run_glue_with_pabee.py
|
||||
--model_type albert
|
||||
--model_name_or_path albert-base-v2
|
||||
--data_dir ./tests/fixtures/tests_samples/MRPC/
|
||||
--output_dir {tmp_dir}
|
||||
--overwrite_output_dir
|
||||
--task_name mrpc
|
||||
--do_train
|
||||
--do_eval
|
||||
@@ -40,11 +42,16 @@ class PabeeTests(TestCasePlus):
|
||||
--learning_rate=2e-5
|
||||
--max_steps=50
|
||||
--warmup_steps=2
|
||||
--overwrite_output_dir
|
||||
--seed=42
|
||||
--max_seq_length=128
|
||||
""".split()
|
||||
|
||||
"""
|
||||
output_dir = "./tests/fixtures/tests_samples/temp_dir_{}".format(hash(testargs))
|
||||
testargs += "--output_dir " + output_dir
|
||||
testargs = testargs.split()
|
||||
with patch.object(sys, "argv", testargs):
|
||||
result = run_glue_with_pabee.main()
|
||||
for value in result.values():
|
||||
self.assertGreaterEqual(value, 0.75)
|
||||
|
||||
clean_test_dir(output_dir)
|
||||
@@ -66,9 +66,9 @@ def print_2d_tensor(tensor):
|
||||
def compute_heads_importance(
|
||||
args, model, eval_dataloader, compute_entropy=True, compute_importance=True, head_mask=None, actually_pruned=False
|
||||
):
|
||||
"""This method shows how to compute:
|
||||
- head attention entropy
|
||||
- head importance scores according to http://arxiv.org/abs/1905.10650
|
||||
""" This method shows how to compute:
|
||||
- head attention entropy
|
||||
- head importance scores according to http://arxiv.org/abs/1905.10650
|
||||
"""
|
||||
# Prepare our tensors
|
||||
n_layers, n_heads = model.config.num_hidden_layers, model.config.num_attention_heads
|
||||
@@ -150,8 +150,8 @@ def compute_heads_importance(
|
||||
|
||||
|
||||
def mask_heads(args, model, eval_dataloader):
|
||||
"""This method shows how to mask head (set some heads to zero), to test the effect on the network,
|
||||
based on the head importance scores, as described in Michel et al. (http://arxiv.org/abs/1905.10650)
|
||||
""" This method shows how to mask head (set some heads to zero), to test the effect on the network,
|
||||
based on the head importance scores, as described in Michel et al. (http://arxiv.org/abs/1905.10650)
|
||||
"""
|
||||
_, head_importance, preds, labels = compute_heads_importance(args, model, eval_dataloader, compute_entropy=False)
|
||||
preds = np.argmax(preds, axis=1) if args.output_mode == "classification" else np.squeeze(preds)
|
||||
@@ -201,8 +201,8 @@ def mask_heads(args, model, eval_dataloader):
|
||||
|
||||
|
||||
def prune_heads(args, model, eval_dataloader, head_mask):
|
||||
"""This method shows how to prune head (remove heads weights) based on
|
||||
the head importance scores as described in Michel et al. (http://arxiv.org/abs/1905.10650)
|
||||
""" This method shows how to prune head (remove heads weights) based on
|
||||
the head importance scores as described in Michel et al. (http://arxiv.org/abs/1905.10650)
|
||||
"""
|
||||
# Try pruning and test time speedup
|
||||
# Pruning is like masking but we actually remove the masked weights
|
||||
@@ -395,8 +395,7 @@ def main():
|
||||
cache_dir=args.cache_dir,
|
||||
)
|
||||
tokenizer = AutoTokenizer.from_pretrained(
|
||||
args.tokenizer_name if args.tokenizer_name else args.model_name_or_path,
|
||||
cache_dir=args.cache_dir,
|
||||
args.tokenizer_name if args.tokenizer_name else args.model_name_or_path, cache_dir=args.cache_dir,
|
||||
)
|
||||
model = AutoModelForSequenceClassification.from_pretrained(
|
||||
args.model_name_or_path,
|
||||
|
||||
@@ -138,9 +138,6 @@ def get_image_transforms():
|
||||
transforms.Resize(256),
|
||||
transforms.CenterCrop(224),
|
||||
transforms.ToTensor(),
|
||||
transforms.Normalize(
|
||||
mean=[0.46777044, 0.44531429, 0.40661017],
|
||||
std=[0.12221994, 0.12145835, 0.14380469],
|
||||
),
|
||||
transforms.Normalize(mean=[0.46777044, 0.44531429, 0.40661017], std=[0.12221994, 0.12145835, 0.14380469],),
|
||||
]
|
||||
)
|
||||
@@ -30,11 +30,7 @@ def fill_mask(masked_input, model, tokenizer, topk=5):
|
||||
)
|
||||
else:
|
||||
topk_filled_outputs.append(
|
||||
(
|
||||
masked_input.replace(masked_token, predicted_token),
|
||||
values[index].item(),
|
||||
predicted_token,
|
||||
)
|
||||
(masked_input.replace(masked_token, predicted_token), values[index].item(), predicted_token,)
|
||||
)
|
||||
return topk_filled_outputs
|
||||
|
||||
|
||||
@@ -71,10 +71,10 @@ def load_rocstories_dataset(dataset_path):
|
||||
|
||||
|
||||
def pre_process_datasets(encoded_datasets, input_len, cap_length, start_token, delimiter_token, clf_token):
|
||||
"""Pre-process datasets containing lists of tuples(story, 1st continuation, 2nd continuation, label)
|
||||
""" Pre-process datasets containing lists of tuples(story, 1st continuation, 2nd continuation, label)
|
||||
|
||||
To Transformer inputs of shape (n_batch, n_alternative, length) comprising for each batch, continuation:
|
||||
input_ids[batch, alternative, :] = [start_token] + story[:cap_length] + [delimiter_token] + cont1[:cap_length] + [clf_token]
|
||||
To Transformer inputs of shape (n_batch, n_alternative, length) comprising for each batch, continuation:
|
||||
input_ids[batch, alternative, :] = [start_token] + story[:cap_length] + [delimiter_token] + cont1[:cap_length] + [clf_token]
|
||||
"""
|
||||
tensor_datasets = []
|
||||
for dataset in encoded_datasets:
|
||||
@@ -83,10 +83,7 @@ def pre_process_datasets(encoded_datasets, input_len, cap_length, start_token, d
|
||||
mc_token_ids = np.zeros((n_batch, 2), dtype=np.int64)
|
||||
lm_labels = np.full((n_batch, 2, input_len), fill_value=-100, dtype=np.int64)
|
||||
mc_labels = np.zeros((n_batch,), dtype=np.int64)
|
||||
for (
|
||||
i,
|
||||
(story, cont1, cont2, mc_label),
|
||||
) in enumerate(dataset):
|
||||
for i, (story, cont1, cont2, mc_label), in enumerate(dataset):
|
||||
with_cont1 = [start_token] + story[:cap_length] + [delimiter_token] + cont1[:cap_length] + [clf_token]
|
||||
with_cont2 = [start_token] + story[:cap_length] + [delimiter_token] + cont2[:cap_length] + [clf_token]
|
||||
input_ids[i, 0, : len(with_cont1)] = with_cont1
|
||||
|
||||
@@ -629,9 +629,7 @@ def main():
|
||||
torch.distributed.barrier() # Make sure only the first process in distributed training will download model & vocab
|
||||
|
||||
config = AutoConfig.from_pretrained(args.config_name if args.config_name else args.model_name_or_path)
|
||||
tokenizer = AutoTokenizer.from_pretrained(
|
||||
args.tokenizer_name if args.tokenizer_name else args.model_name_or_path,
|
||||
)
|
||||
tokenizer = AutoTokenizer.from_pretrained(args.tokenizer_name if args.tokenizer_name else args.model_name_or_path,)
|
||||
model = AutoModelForMultipleChoice.from_pretrained(
|
||||
args.model_name_or_path, from_tf=bool(".ckpt" in args.model_name_or_path), config=config
|
||||
)
|
||||
|
||||
@@ -358,11 +358,7 @@ def load_and_cache_examples(args, task, tokenizer, evaluate=False):
|
||||
processor.get_dev_examples(args.data_dir) if evaluate else processor.get_train_examples(args.data_dir)
|
||||
)
|
||||
features = convert_examples_to_features(
|
||||
examples,
|
||||
tokenizer,
|
||||
label_list=label_list,
|
||||
max_length=args.max_seq_length,
|
||||
output_mode=output_mode,
|
||||
examples, tokenizer, label_list=label_list, max_length=args.max_seq_length, output_mode=output_mode,
|
||||
)
|
||||
if args.local_rank in [-1, 0]:
|
||||
logger.info("Saving features into cached file %s", cached_features_file)
|
||||
|
||||
@@ -14,7 +14,8 @@ from transformers.modeling_bert import (
|
||||
|
||||
|
||||
def entropy(x):
|
||||
"""Calculate entropy of a pre-softmax logit Tensor"""
|
||||
""" Calculate entropy of a pre-softmax logit Tensor
|
||||
"""
|
||||
exp_x = torch.exp(x)
|
||||
A = torch.sum(exp_x, dim=1) # sum of exp(x_i)
|
||||
B = torch.sum(x * exp_x, dim=1) # sum of x_i * exp(x_i)
|
||||
@@ -103,8 +104,7 @@ class DeeBertEncoder(nn.Module):
|
||||
|
||||
|
||||
@add_start_docstrings(
|
||||
"The Bert Model transformer with early exiting (DeeBERT). ",
|
||||
BERT_START_DOCSTRING,
|
||||
"The Bert Model transformer with early exiting (DeeBERT). ", BERT_START_DOCSTRING,
|
||||
)
|
||||
class DeeBertModel(BertPreTrainedModel):
|
||||
def __init__(self, config):
|
||||
@@ -127,9 +127,9 @@ class DeeBertModel(BertPreTrainedModel):
|
||||
self.embeddings.word_embeddings = value
|
||||
|
||||
def _prune_heads(self, heads_to_prune):
|
||||
"""Prunes heads of the model.
|
||||
heads_to_prune: dict of {layer_num: list of heads to prune in this layer}
|
||||
See base class PreTrainedModel
|
||||
""" Prunes heads of the model.
|
||||
heads_to_prune: dict of {layer_num: list of heads to prune in this layer}
|
||||
See base class PreTrainedModel
|
||||
"""
|
||||
for layer, heads in heads_to_prune.items():
|
||||
self.encoder.layer[layer].attention.prune_heads(heads)
|
||||
@@ -147,33 +147,33 @@ class DeeBertModel(BertPreTrainedModel):
|
||||
encoder_attention_mask=None,
|
||||
):
|
||||
r"""
|
||||
Return:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BertConfig`) and inputs:
|
||||
last_hidden_state (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`):
|
||||
Sequence of hidden-states at the output of the last layer of the model.
|
||||
pooler_output (:obj:`torch.FloatTensor`: of shape :obj:`(batch_size, hidden_size)`):
|
||||
Last layer hidden-state of the first token of the sequence (classification token)
|
||||
further processed by a Linear layer and a Tanh activation function. The Linear
|
||||
layer weights are trained from the next sentence prediction (classification)
|
||||
objective during pre-training.
|
||||
Return:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BertConfig`) and inputs:
|
||||
last_hidden_state (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`):
|
||||
Sequence of hidden-states at the output of the last layer of the model.
|
||||
pooler_output (:obj:`torch.FloatTensor`: of shape :obj:`(batch_size, hidden_size)`):
|
||||
Last layer hidden-state of the first token of the sequence (classification token)
|
||||
further processed by a Linear layer and a Tanh activation function. The Linear
|
||||
layer weights are trained from the next sentence prediction (classification)
|
||||
objective during pre-training.
|
||||
|
||||
This output is usually *not* a good summary
|
||||
of the semantic content of the input, you're often better with averaging or pooling
|
||||
the sequence of hidden-states for the whole input sequence.
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_hidden_states=True`` is passed or when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
This output is usually *not* a good summary
|
||||
of the semantic content of the input, you're often better with averaging or pooling
|
||||
the sequence of hidden-states for the whole input sequence.
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_hidden_states=True`` is passed or when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_attentions=True`` is passed or when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_attentions=True`` is passed or when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
highway_exits (:obj:`tuple(tuple(torch.Tensor))`:
|
||||
Tuple of each early exit's results (total length: number of layers)
|
||||
Each tuple is again, a tuple of length 2 - the first entry is logits and the second entry is hidden states.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
highway_exits (:obj:`tuple(tuple(torch.Tensor))`:
|
||||
Tuple of each early exit's results (total length: number of layers)
|
||||
Each tuple is again, a tuple of length 2 - the first entry is logits and the second entry is hidden states.
|
||||
"""
|
||||
if input_ids is not None and inputs_embeds is not None:
|
||||
raise ValueError("You cannot specify both input_ids and inputs_embeds at the same time")
|
||||
@@ -302,32 +302,32 @@ class DeeBertForSequenceClassification(BertPreTrainedModel):
|
||||
train_highway=False,
|
||||
):
|
||||
r"""
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in :obj:`[0, ..., config.num_labels - 1]`.
|
||||
If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss),
|
||||
If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in :obj:`[0, ..., config.num_labels - 1]`.
|
||||
If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss),
|
||||
If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
||||
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided):
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`):
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_hidden_states=True`` is passed or when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.BertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided):
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`):
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_hidden_states=True`` is passed or when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_attentions=True`` is passed or when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_attentions=True`` is passed or when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
highway_exits (:obj:`tuple(tuple(torch.Tensor))`:
|
||||
Tuple of each early exit's results (total length: number of layers)
|
||||
Each tuple is again, a tuple of length 2 - the first entry is logits and the second entry is hidden states.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
highway_exits (:obj:`tuple(tuple(torch.Tensor))`:
|
||||
Tuple of each early exit's results (total length: number of layers)
|
||||
Each tuple is again, a tuple of length 2 - the first entry is logits and the second entry is hidden states.
|
||||
"""
|
||||
|
||||
exit_layer = self.num_layers
|
||||
|
||||
@@ -11,8 +11,7 @@ from .modeling_highway_bert import BertPreTrainedModel, DeeBertModel, HighwayExc
|
||||
|
||||
|
||||
@add_start_docstrings(
|
||||
"The RoBERTa Model transformer with early exiting (DeeRoBERTa). ",
|
||||
ROBERTA_START_DOCSTRING,
|
||||
"The RoBERTa Model transformer with early exiting (DeeRoBERTa). ", ROBERTA_START_DOCSTRING,
|
||||
)
|
||||
class DeeRobertaModel(DeeBertModel):
|
||||
|
||||
@@ -59,32 +58,32 @@ class DeeRobertaForSequenceClassification(BertPreTrainedModel):
|
||||
train_highway=False,
|
||||
):
|
||||
r"""
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in :obj:`[0, ..., config.num_labels - 1]`.
|
||||
If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss),
|
||||
If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in :obj:`[0, ..., config.num_labels - 1]`.
|
||||
If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss),
|
||||
If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
||||
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.RobertaConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided):
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`):
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_hidden_states=True`` is passed or when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~transformers.RobertaConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided):
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`):
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_hidden_states=True`` is passed or when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_attentions=True`` is passed or when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``output_attentions=True`` is passed or when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
highway_exits (:obj:`tuple(tuple(torch.Tensor))`:
|
||||
Tuple of each early exit's results (total length: number of layers)
|
||||
Each tuple is again, a tuple of length 2 - the first entry is logits and the second entry is hidden states.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
highway_exits (:obj:`tuple(tuple(torch.Tensor))`:
|
||||
Tuple of each early exit's results (total length: number of layers)
|
||||
Each tuple is again, a tuple of length 2 - the first entry is logits and the second entry is hidden states.
|
||||
"""
|
||||
|
||||
exit_layer = self.num_layers
|
||||
|
||||
@@ -228,20 +228,14 @@ def train(args, train_dataset, model, tokenizer, teacher=None):
|
||||
assert end_logits_tea.size() == end_logits_stu.size()
|
||||
|
||||
loss_fct = nn.KLDivLoss(reduction="batchmean")
|
||||
loss_start = (
|
||||
loss_fct(
|
||||
F.log_softmax(start_logits_stu / args.temperature, dim=-1),
|
||||
F.softmax(start_logits_tea / args.temperature, dim=-1),
|
||||
)
|
||||
* (args.temperature ** 2)
|
||||
)
|
||||
loss_end = (
|
||||
loss_fct(
|
||||
F.log_softmax(end_logits_stu / args.temperature, dim=-1),
|
||||
F.softmax(end_logits_tea / args.temperature, dim=-1),
|
||||
)
|
||||
* (args.temperature ** 2)
|
||||
)
|
||||
loss_start = loss_fct(
|
||||
F.log_softmax(start_logits_stu / args.temperature, dim=-1),
|
||||
F.softmax(start_logits_tea / args.temperature, dim=-1),
|
||||
) * (args.temperature ** 2)
|
||||
loss_end = loss_fct(
|
||||
F.log_softmax(end_logits_stu / args.temperature, dim=-1),
|
||||
F.softmax(end_logits_tea / args.temperature, dim=-1),
|
||||
) * (args.temperature ** 2)
|
||||
loss_ce = (loss_start + loss_end) / 2.0
|
||||
|
||||
loss = args.alpha_ce * loss_ce + args.alpha_squad * loss
|
||||
|
||||
@@ -118,8 +118,7 @@ def init_gpu_params(params):
|
||||
if params.multi_gpu:
|
||||
logger.info("Initializing PyTorch distributed")
|
||||
torch.distributed.init_process_group(
|
||||
init_method="env://",
|
||||
backend="nccl",
|
||||
init_method="env://", backend="nccl",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -233,9 +233,7 @@ def main():
|
||||
eval_dataset = get_dataset(data_args, tokenizer=tokenizer, evaluate=True) if training_args.do_eval else None
|
||||
if config.model_type == "xlnet":
|
||||
data_collator = DataCollatorForPermutationLanguageModeling(
|
||||
tokenizer=tokenizer,
|
||||
plm_probability=data_args.plm_probability,
|
||||
max_span_length=data_args.max_span_length,
|
||||
tokenizer=tokenizer, plm_probability=data_args.plm_probability, max_span_length=data_args.max_span_length,
|
||||
)
|
||||
else:
|
||||
data_collator = DataCollatorForLanguageModeling(
|
||||
|
||||
+11
-27
@@ -150,20 +150,15 @@ class BaseTransformer(pl.LightningModule):
|
||||
def test_epoch_end(self, outputs):
|
||||
return self.validation_end(outputs)
|
||||
|
||||
@property
|
||||
def total_steps(self) -> int:
|
||||
"""The number of total training steps that will be run. Used for lr scheduler purposes."""
|
||||
num_devices = max(1, self.hparams.gpus) # TODO: consider num_tpu_cores
|
||||
effective_batch_size = self.hparams.train_batch_size * self.hparams.accumulate_grad_batches * num_devices
|
||||
dataset_size = len(self.train_loader.dataset)
|
||||
return (dataset_size / effective_batch_size) * self.hparams.max_epochs
|
||||
|
||||
def setup(self, mode):
|
||||
if mode == "fit":
|
||||
self.train_loader = self.get_dataloader("train", self.hparams.train_batch_size, shuffle=True)
|
||||
|
||||
def get_dataloader(self, type_path, batch_size, shuffle=False):
|
||||
raise NotImplementedError("You must implement this for your task")
|
||||
def setup(self, step):
|
||||
train_batch_size = self.hparams.train_batch_size
|
||||
dataloader = self.get_dataloader("train", train_batch_size)
|
||||
self.train_loader = dataloader
|
||||
self.total_steps = (
|
||||
(len(dataloader.dataset) // (train_batch_size * max(1, self.hparams.gpus)))
|
||||
// self.hparams.accumulate_grad_batches
|
||||
* float(self.hparams.max_epochs)
|
||||
)
|
||||
|
||||
def train_dataloader(self):
|
||||
return self.train_loader
|
||||
@@ -226,14 +221,10 @@ class BaseTransformer(pl.LightningModule):
|
||||
help="Decoder layer dropout probability (Optional). Goes into model.config",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dropout",
|
||||
type=float,
|
||||
help="Dropout probability (Optional). Goes into model.config",
|
||||
"--dropout", type=float, help="Dropout probability (Optional). Goes into model.config",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--attention_dropout",
|
||||
type=float,
|
||||
help="Attention dropout probability (Optional). Goes into model.config",
|
||||
"--attention_dropout", type=float, help="Attention dropout probability (Optional). Goes into model.config",
|
||||
)
|
||||
parser.add_argument("--learning_rate", default=5e-5, type=float, help="The initial learning rate for Adam.")
|
||||
parser.add_argument(
|
||||
@@ -313,13 +304,6 @@ def add_generic_args(parser, root_dir) -> None:
|
||||
help="Number of updates steps to accumulate before performing a backward/update pass.",
|
||||
)
|
||||
parser.add_argument("--seed", type=int, default=42, help="random seed for initialization")
|
||||
parser.add_argument(
|
||||
"--data_dir",
|
||||
default=None,
|
||||
type=str,
|
||||
required=True,
|
||||
help="The input data dir. Should contain the training files for the CoNLL-2003 NER task.",
|
||||
)
|
||||
|
||||
|
||||
def generic_train(
|
||||
|
||||
@@ -95,10 +95,7 @@ def make_support(question, source="wiki40b", method="dense", n_results=10):
|
||||
)
|
||||
else:
|
||||
support_doc, hit_lst = query_es_index(
|
||||
question,
|
||||
es_client,
|
||||
index_name="english_wiki40b_snippets_100w",
|
||||
n_results=n_results,
|
||||
question, es_client, index_name="english_wiki40b_snippets_100w", n_results=n_results,
|
||||
)
|
||||
support_list = [
|
||||
(res["article_title"], res["section_title"].strip(), res["score"], res["passage_text"]) for res in hit_lst
|
||||
@@ -157,8 +154,7 @@ header_full = """
|
||||
header_html,
|
||||
)
|
||||
st.sidebar.markdown(
|
||||
header_full,
|
||||
unsafe_allow_html=True,
|
||||
header_full, unsafe_allow_html=True,
|
||||
)
|
||||
|
||||
# Long Form QA with ELI5 and Wikipedia
|
||||
@@ -177,17 +173,9 @@ action_list = [
|
||||
]
|
||||
demo_options = st.sidebar.checkbox("Demo options")
|
||||
if demo_options:
|
||||
action_st = st.sidebar.selectbox(
|
||||
"",
|
||||
action_list,
|
||||
index=3,
|
||||
)
|
||||
action_st = st.sidebar.selectbox("", action_list, index=3,)
|
||||
action = action_list.index(action_st)
|
||||
show_type = st.sidebar.selectbox(
|
||||
"",
|
||||
["Show full text of passages", "Show passage section titles"],
|
||||
index=0,
|
||||
)
|
||||
show_type = st.sidebar.selectbox("", ["Show full text of passages", "Show passage section titles"], index=0,)
|
||||
show_passages = show_type == "Show full text of passages"
|
||||
else:
|
||||
action = 3
|
||||
@@ -262,9 +250,7 @@ questions_list = [
|
||||
"How does New Zealand have so many large bird predators?",
|
||||
]
|
||||
question_s = st.selectbox(
|
||||
"What would you like to ask? ---- select <MY QUESTION> to enter a new query",
|
||||
questions_list,
|
||||
index=1,
|
||||
"What would you like to ask? ---- select <MY QUESTION> to enter a new query", questions_list, index=1,
|
||||
)
|
||||
if question_s == "<MY QUESTION>":
|
||||
question = st.text_input("Enter your question here:", "")
|
||||
|
||||
@@ -48,11 +48,7 @@ def make_es_index_snippets(es_client, passages_dset, index_name="english_wiki_ki
|
||||
yield passage
|
||||
|
||||
# create the ES index
|
||||
for ok, action in streaming_bulk(
|
||||
client=es_client,
|
||||
index=index_name,
|
||||
actions=passage_generator(),
|
||||
):
|
||||
for ok, action in streaming_bulk(client=es_client, index=index_name, actions=passage_generator(),):
|
||||
progress.update(1)
|
||||
successes += ok
|
||||
print("Indexed %d documents" % (successes,))
|
||||
@@ -141,11 +137,7 @@ class RetrievalQAEmbedder(torch.nn.Module):
|
||||
|
||||
# define function for checkpointing
|
||||
def partial_encode(*inputs):
|
||||
encoder_outputs = self.sent_encoder.encoder(
|
||||
inputs[0],
|
||||
attention_mask=inputs[1],
|
||||
head_mask=head_mask,
|
||||
)
|
||||
encoder_outputs = self.sent_encoder.encoder(inputs[0], attention_mask=inputs[1], head_mask=head_mask,)
|
||||
sequence_output = encoder_outputs[0]
|
||||
pooled_output = self.sent_encoder.pooler(sequence_output)
|
||||
return pooled_output
|
||||
@@ -242,11 +234,7 @@ def train_qa_retriever_epoch(model, dataset, tokenizer, optimizer, scheduler, ar
|
||||
if step % args.print_freq == 0 or step == 1:
|
||||
print(
|
||||
"{:2d} {:5d} of {:5d} \t L: {:.3f} \t -- {:.3f}".format(
|
||||
e,
|
||||
step,
|
||||
len(dataset) // args.batch_size,
|
||||
loc_loss / loc_steps,
|
||||
time() - st_time,
|
||||
e, step, len(dataset) // args.batch_size, loc_loss / loc_steps, time() - st_time,
|
||||
)
|
||||
)
|
||||
loc_loss = 0
|
||||
@@ -285,11 +273,7 @@ def train_qa_retriever_joint_epoch(model, dataset_list, tokenizer, optimizer, sc
|
||||
if step % args.print_freq == 0:
|
||||
print(
|
||||
"{:2d} {:5d} of {:5d} \t L: {:.3f} \t -- {:.3f}".format(
|
||||
e,
|
||||
step,
|
||||
len(dataset_list[0]) // args.batch_size,
|
||||
loc_loss / loc_steps,
|
||||
time() - st_time,
|
||||
e, step, len(dataset_list[0]) // args.batch_size, loc_loss / loc_steps, time() - st_time,
|
||||
)
|
||||
)
|
||||
loc_loss = 0
|
||||
@@ -370,8 +354,7 @@ class ELI5DatasetS2S(Dataset):
|
||||
self.document_cache[q_id] = self.document_cache.get(q_id, self.make_doc_function(example["title"]))
|
||||
document = self.document_cache[q_id]
|
||||
in_st = "question: {} context: {}".format(
|
||||
question.lower().replace(" --t--", "").strip(),
|
||||
document.lower().strip(),
|
||||
question.lower().replace(" --t--", "").strip(), document.lower().strip(),
|
||||
)
|
||||
out_st = answer
|
||||
return (in_st, out_st)
|
||||
@@ -444,11 +427,7 @@ def train_qa_s2s_epoch(model, dataset, tokenizer, optimizer, scheduler, args, e=
|
||||
if step % args.print_freq == 0 or step == 1:
|
||||
print(
|
||||
"{:2d} {:5d} of {:5d} \t L: {:.3f} \t -- {:.3f}".format(
|
||||
e,
|
||||
step,
|
||||
len(dataset) // args.batch_size,
|
||||
loc_loss / loc_steps,
|
||||
time() - st_time,
|
||||
e, step, len(dataset) // args.batch_size, loc_loss / loc_steps, time() - st_time,
|
||||
)
|
||||
)
|
||||
loc_loss = 0
|
||||
@@ -477,18 +456,10 @@ def eval_qa_s2s_epoch(model, dataset, tokenizer, args):
|
||||
if step % args.print_freq == 0:
|
||||
print(
|
||||
"{:5d} of {:5d} \t L: {:.3f} \t -- {:.3f}".format(
|
||||
step,
|
||||
len(dataset) // args.batch_size,
|
||||
loc_loss / loc_steps,
|
||||
time() - st_time,
|
||||
step, len(dataset) // args.batch_size, loc_loss / loc_steps, time() - st_time,
|
||||
)
|
||||
)
|
||||
print(
|
||||
"Total \t L: {:.3f} \t -- {:.3f}".format(
|
||||
loc_loss / loc_steps,
|
||||
time() - st_time,
|
||||
)
|
||||
)
|
||||
print("Total \t L: {:.3f} \t -- {:.3f}".format(loc_loss / loc_steps, time() - st_time,))
|
||||
|
||||
|
||||
def train_qa_s2s(qa_s2s_model, qa_s2s_tokenizer, s2s_train_dset, s2s_valid_dset, s2s_args):
|
||||
@@ -535,12 +506,7 @@ def qa_s2s_generate(
|
||||
max_input_length=512,
|
||||
device="cuda:0",
|
||||
):
|
||||
model_inputs = make_qa_s2s_batch(
|
||||
[(question_doc, "A")],
|
||||
qa_s2s_tokenizer,
|
||||
max_input_length,
|
||||
device=device,
|
||||
)
|
||||
model_inputs = make_qa_s2s_batch([(question_doc, "A")], qa_s2s_tokenizer, max_input_length, device=device,)
|
||||
n_beams = num_answers if num_beams is None else max(num_beams, num_answers)
|
||||
generated_ids = qa_s2s_model.generate(
|
||||
input_ids=model_inputs["input_ids"],
|
||||
|
||||
@@ -37,7 +37,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BertEmbeddings(nn.Module):
|
||||
"""Construct the embeddings from word, position and token_type embeddings."""
|
||||
"""Construct the embeddings from word, position and token_type embeddings.
|
||||
"""
|
||||
|
||||
def __init__(self, config):
|
||||
super().__init__()
|
||||
@@ -384,8 +385,8 @@ class BertPooler(nn.Module):
|
||||
|
||||
|
||||
class MaskedBertPreTrainedModel(PreTrainedModel):
|
||||
"""An abstract class to handle weights initialization and
|
||||
a simple interface for downloading and loading pretrained models.
|
||||
""" An abstract class to handle weights initialization and
|
||||
a simple interface for downloading and loading pretrained models.
|
||||
"""
|
||||
|
||||
config_class = MaskedBertConfig
|
||||
@@ -491,9 +492,9 @@ class MaskedBertModel(MaskedBertPreTrainedModel):
|
||||
self.embeddings.word_embeddings = value
|
||||
|
||||
def _prune_heads(self, heads_to_prune):
|
||||
"""Prunes heads of the model.
|
||||
heads_to_prune: dict of {layer_num: list of heads to prune in this layer}
|
||||
See base class PreTrainedModel
|
||||
""" Prunes heads of the model.
|
||||
heads_to_prune: dict of {layer_num: list of heads to prune in this layer}
|
||||
See base class PreTrainedModel
|
||||
"""
|
||||
for layer, heads in heads_to_prune.items():
|
||||
self.encoder.layer[layer].attention.prune_heads(heads)
|
||||
@@ -684,31 +685,31 @@ class MaskedBertForSequenceClassification(MaskedBertPreTrainedModel):
|
||||
threshold=None,
|
||||
):
|
||||
r"""
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in :obj:`[0, ..., config.num_labels - 1]`.
|
||||
If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss),
|
||||
If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
||||
threshold (:obj:`float`):
|
||||
Threshold value (see :class:`~emmental.MaskedLinear`).
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the sequence classification/regression loss.
|
||||
Indices should be in :obj:`[0, ..., config.num_labels - 1]`.
|
||||
If :obj:`config.num_labels == 1` a regression loss is computed (Mean-Square loss),
|
||||
If :obj:`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
||||
threshold (:obj:`float`):
|
||||
Threshold value (see :class:`~emmental.MaskedLinear`).
|
||||
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~emmental.MaskedBertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided):
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`):
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~emmental.MaskedBertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`label` is provided):
|
||||
Classification (or regression if config.num_labels==1) loss.
|
||||
logits (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, config.num_labels)`):
|
||||
Classification (or regression if config.num_labels==1) scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
"""
|
||||
|
||||
outputs = self.bert(
|
||||
@@ -769,32 +770,32 @@ class MaskedBertForMultipleChoice(MaskedBertPreTrainedModel):
|
||||
threshold=None,
|
||||
):
|
||||
r"""
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the multiple choice classification loss.
|
||||
Indices should be in ``[0, ..., num_choices]`` where `num_choices` is the size of the second dimension
|
||||
of the input tensors. (see `input_ids` above)
|
||||
threshold (:obj:`float`):
|
||||
Threshold value (see :class:`~emmental.MaskedLinear`).
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the multiple choice classification loss.
|
||||
Indices should be in ``[0, ..., num_choices]`` where `num_choices` is the size of the second dimension
|
||||
of the input tensors. (see `input_ids` above)
|
||||
threshold (:obj:`float`):
|
||||
Threshold value (see :class:`~emmental.MaskedLinear`).
|
||||
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~emmental.MaskedBertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape `(1,)`, `optional`, returned when :obj:`labels` is provided):
|
||||
Classification loss.
|
||||
classification_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, num_choices)`):
|
||||
`num_choices` is the second dimension of the input tensors. (see `input_ids` above).
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~emmental.MaskedBertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape `(1,)`, `optional`, returned when :obj:`labels` is provided):
|
||||
Classification loss.
|
||||
classification_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, num_choices)`):
|
||||
`num_choices` is the second dimension of the input tensors. (see `input_ids` above).
|
||||
|
||||
Classification scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
Classification scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
|
||||
"""
|
||||
num_choices = input_ids.shape[1]
|
||||
@@ -859,29 +860,29 @@ class MaskedBertForTokenClassification(MaskedBertPreTrainedModel):
|
||||
threshold=None,
|
||||
):
|
||||
r"""
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the token classification loss.
|
||||
Indices should be in ``[0, ..., config.num_labels - 1]``.
|
||||
threshold (:obj:`float`):
|
||||
Threshold value (see :class:`~emmental.MaskedLinear`).
|
||||
labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for computing the token classification loss.
|
||||
Indices should be in ``[0, ..., config.num_labels - 1]``.
|
||||
threshold (:obj:`float`):
|
||||
Threshold value (see :class:`~emmental.MaskedLinear`).
|
||||
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~emmental.MaskedBertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when ``labels`` is provided) :
|
||||
Classification loss.
|
||||
scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, config.num_labels)`)
|
||||
Classification scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~emmental.MaskedBertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when ``labels`` is provided) :
|
||||
Classification loss.
|
||||
scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, config.num_labels)`)
|
||||
Classification scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
"""
|
||||
|
||||
outputs = self.bert(
|
||||
@@ -946,36 +947,36 @@ class MaskedBertForQuestionAnswering(MaskedBertPreTrainedModel):
|
||||
threshold=None,
|
||||
):
|
||||
r"""
|
||||
start_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for position (index) of the start of the labelled span for computing the token classification loss.
|
||||
Positions are clamped to the length of the sequence (`sequence_length`).
|
||||
Position outside of the sequence are not taken into account for computing the loss.
|
||||
end_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for position (index) of the end of the labelled span for computing the token classification loss.
|
||||
Positions are clamped to the length of the sequence (`sequence_length`).
|
||||
Position outside of the sequence are not taken into account for computing the loss.
|
||||
threshold (:obj:`float`):
|
||||
Threshold value (see :class:`~emmental.MaskedLinear`).
|
||||
start_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for position (index) of the start of the labelled span for computing the token classification loss.
|
||||
Positions are clamped to the length of the sequence (`sequence_length`).
|
||||
Position outside of the sequence are not taken into account for computing the loss.
|
||||
end_positions (:obj:`torch.LongTensor` of shape :obj:`(batch_size,)`, `optional`, defaults to :obj:`None`):
|
||||
Labels for position (index) of the end of the labelled span for computing the token classification loss.
|
||||
Positions are clamped to the length of the sequence (`sequence_length`).
|
||||
Position outside of the sequence are not taken into account for computing the loss.
|
||||
threshold (:obj:`float`):
|
||||
Threshold value (see :class:`~emmental.MaskedLinear`).
|
||||
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~emmental.MaskedBertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`labels` is provided):
|
||||
Total span extraction loss is the sum of a Cross-Entropy for the start and end positions.
|
||||
start_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length,)`):
|
||||
Span-start scores (before SoftMax).
|
||||
end_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length,)`):
|
||||
Span-end scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
Returns:
|
||||
:obj:`tuple(torch.FloatTensor)` comprising various elements depending on the configuration (:class:`~emmental.MaskedBertConfig`) and inputs:
|
||||
loss (:obj:`torch.FloatTensor` of shape :obj:`(1,)`, `optional`, returned when :obj:`labels` is provided):
|
||||
Total span extraction loss is the sum of a Cross-Entropy for the start and end positions.
|
||||
start_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length,)`):
|
||||
Span-start scores (before SoftMax).
|
||||
end_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length,)`):
|
||||
Span-end scores (before SoftMax).
|
||||
hidden_states (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_hidden_states=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for the output of the embeddings + one for the output of each layer)
|
||||
of shape :obj:`(batch_size, sequence_length, hidden_size)`.
|
||||
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
Hidden-states of the model at the output of each layer plus the initial embedding outputs.
|
||||
attentions (:obj:`tuple(torch.FloatTensor)`, `optional`, returned when ``config.output_attentions=True``):
|
||||
Tuple of :obj:`torch.FloatTensor` (one for each layer) of shape
|
||||
:obj:`(batch_size, num_heads, sequence_length, sequence_length)`.
|
||||
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
Attentions weights after the attention softmax, used to compute the weighted average in the self-attention
|
||||
heads.
|
||||
"""
|
||||
|
||||
outputs = self.bert(
|
||||
@@ -995,10 +996,7 @@ class MaskedBertForQuestionAnswering(MaskedBertPreTrainedModel):
|
||||
start_logits = start_logits.squeeze(-1)
|
||||
end_logits = end_logits.squeeze(-1)
|
||||
|
||||
outputs = (
|
||||
start_logits,
|
||||
end_logits,
|
||||
) + outputs[2:]
|
||||
outputs = (start_logits, end_logits,) + outputs[2:]
|
||||
if start_positions is not None and end_positions is not None:
|
||||
# If we are on multi-GPU, split add a dimension
|
||||
if len(start_positions.size()) > 1:
|
||||
|
||||
@@ -173,10 +173,7 @@ def train(args, train_dataset, model, tokenizer, teacher=None):
|
||||
# Distributed training (should be after apex fp16 initialization)
|
||||
if args.local_rank != -1:
|
||||
model = torch.nn.parallel.DistributedDataParallel(
|
||||
model,
|
||||
device_ids=[args.local_rank],
|
||||
output_device=args.local_rank,
|
||||
find_unused_parameters=True,
|
||||
model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True,
|
||||
)
|
||||
|
||||
# Train!
|
||||
@@ -220,10 +217,7 @@ def train(args, train_dataset, model, tokenizer, teacher=None):
|
||||
tr_loss, logging_loss = 0.0, 0.0
|
||||
model.zero_grad()
|
||||
train_iterator = trange(
|
||||
epochs_trained,
|
||||
int(args.num_train_epochs),
|
||||
desc="Epoch",
|
||||
disable=args.local_rank not in [-1, 0],
|
||||
epochs_trained, int(args.num_train_epochs), desc="Epoch", disable=args.local_rank not in [-1, 0],
|
||||
)
|
||||
set_seed(args) # Added here for reproductibility
|
||||
for _ in train_iterator:
|
||||
@@ -286,14 +280,11 @@ def train(args, train_dataset, model, tokenizer, teacher=None):
|
||||
attention_mask=inputs["attention_mask"],
|
||||
)
|
||||
|
||||
loss_logits = (
|
||||
F.kl_div(
|
||||
input=F.log_softmax(logits_stu / args.temperature, dim=-1),
|
||||
target=F.softmax(logits_tea / args.temperature, dim=-1),
|
||||
reduction="batchmean",
|
||||
)
|
||||
* (args.temperature ** 2)
|
||||
)
|
||||
loss_logits = F.kl_div(
|
||||
input=F.log_softmax(logits_stu / args.temperature, dim=-1),
|
||||
target=F.softmax(logits_tea / args.temperature, dim=-1),
|
||||
reduction="batchmean",
|
||||
) * (args.temperature ** 2)
|
||||
|
||||
loss = args.alpha_distil * loss_logits + args.alpha_ce * loss
|
||||
|
||||
@@ -538,11 +529,7 @@ def load_and_cache_examples(args, task, tokenizer, evaluate=False):
|
||||
processor.get_dev_examples(args.data_dir) if evaluate else processor.get_train_examples(args.data_dir)
|
||||
)
|
||||
features = convert_examples_to_features(
|
||||
examples,
|
||||
tokenizer,
|
||||
max_length=args.max_seq_length,
|
||||
label_list=label_list,
|
||||
output_mode=output_mode,
|
||||
examples, tokenizer, max_length=args.max_seq_length, label_list=label_list, output_mode=output_mode,
|
||||
)
|
||||
if args.local_rank in [-1, 0]:
|
||||
logger.info("Saving features into cached file %s", cached_features_file)
|
||||
@@ -605,10 +592,7 @@ def main():
|
||||
)
|
||||
# Other parameters
|
||||
parser.add_argument(
|
||||
"--config_name",
|
||||
default="",
|
||||
type=str,
|
||||
help="Pretrained config name or path if not the same as model_name",
|
||||
"--config_name", default="", type=str, help="Pretrained config name or path if not the same as model_name",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--tokenizer_name",
|
||||
@@ -632,27 +616,17 @@ def main():
|
||||
parser.add_argument("--do_train", action="store_true", help="Whether to run training.")
|
||||
parser.add_argument("--do_eval", action="store_true", help="Whether to run eval on the dev set.")
|
||||
parser.add_argument(
|
||||
"--evaluate_during_training",
|
||||
action="store_true",
|
||||
help="Run evaluation during training at each logging step.",
|
||||
"--evaluate_during_training", action="store_true", help="Run evaluation during training at each logging step.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--do_lower_case",
|
||||
action="store_true",
|
||||
help="Set this flag if you are using an uncased model.",
|
||||
"--do_lower_case", action="store_true", help="Set this flag if you are using an uncased model.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--per_gpu_train_batch_size",
|
||||
default=8,
|
||||
type=int,
|
||||
help="Batch size per GPU/CPU for training.",
|
||||
"--per_gpu_train_batch_size", default=8, type=int, help="Batch size per GPU/CPU for training.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--per_gpu_eval_batch_size",
|
||||
default=8,
|
||||
type=int,
|
||||
help="Batch size per GPU/CPU for evaluation.",
|
||||
"--per_gpu_eval_batch_size", default=8, type=int, help="Batch size per GPU/CPU for evaluation.",
|
||||
)
|
||||
parser.add_argument("--learning_rate", default=5e-5, type=float, help="The initial learning rate for Adam.")
|
||||
|
||||
@@ -749,10 +723,7 @@ def main():
|
||||
parser.add_argument("--adam_epsilon", default=1e-8, type=float, help="Epsilon for Adam optimizer.")
|
||||
parser.add_argument("--max_grad_norm", default=1.0, type=float, help="Max gradient norm.")
|
||||
parser.add_argument(
|
||||
"--num_train_epochs",
|
||||
default=3.0,
|
||||
type=float,
|
||||
help="Total number of training epochs to perform.",
|
||||
"--num_train_epochs", default=3.0, type=float, help="Total number of training epochs to perform.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--max_steps",
|
||||
@@ -771,14 +742,10 @@ def main():
|
||||
)
|
||||
parser.add_argument("--no_cuda", action="store_true", help="Avoid using CUDA when available")
|
||||
parser.add_argument(
|
||||
"--overwrite_output_dir",
|
||||
action="store_true",
|
||||
help="Overwrite the content of the output directory",
|
||||
"--overwrite_output_dir", action="store_true", help="Overwrite the content of the output directory",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--overwrite_cache",
|
||||
action="store_true",
|
||||
help="Overwrite the cached training and evaluation sets",
|
||||
"--overwrite_cache", action="store_true", help="Overwrite the cached training and evaluation sets",
|
||||
)
|
||||
parser.add_argument("--seed", type=int, default=42, help="random seed for initialization")
|
||||
|
||||
|
||||
@@ -181,10 +181,7 @@ def train(args, train_dataset, model, tokenizer, teacher=None):
|
||||
# Distributed training (should be after apex fp16 initialization)
|
||||
if args.local_rank != -1:
|
||||
model = torch.nn.parallel.DistributedDataParallel(
|
||||
model,
|
||||
device_ids=[args.local_rank],
|
||||
output_device=args.local_rank,
|
||||
find_unused_parameters=True,
|
||||
model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True,
|
||||
)
|
||||
|
||||
# Train!
|
||||
@@ -307,22 +304,16 @@ def train(args, train_dataset, model, tokenizer, teacher=None):
|
||||
attention_mask=inputs["attention_mask"],
|
||||
)
|
||||
|
||||
loss_start = (
|
||||
F.kl_div(
|
||||
input=F.log_softmax(start_logits_stu / args.temperature, dim=-1),
|
||||
target=F.softmax(start_logits_tea / args.temperature, dim=-1),
|
||||
reduction="batchmean",
|
||||
)
|
||||
* (args.temperature ** 2)
|
||||
)
|
||||
loss_end = (
|
||||
F.kl_div(
|
||||
input=F.log_softmax(end_logits_stu / args.temperature, dim=-1),
|
||||
target=F.softmax(end_logits_tea / args.temperature, dim=-1),
|
||||
reduction="batchmean",
|
||||
)
|
||||
* (args.temperature ** 2)
|
||||
)
|
||||
loss_start = F.kl_div(
|
||||
input=F.log_softmax(start_logits_stu / args.temperature, dim=-1),
|
||||
target=F.softmax(start_logits_tea / args.temperature, dim=-1),
|
||||
reduction="batchmean",
|
||||
) * (args.temperature ** 2)
|
||||
loss_end = F.kl_div(
|
||||
input=F.log_softmax(end_logits_stu / args.temperature, dim=-1),
|
||||
target=F.softmax(end_logits_tea / args.temperature, dim=-1),
|
||||
reduction="batchmean",
|
||||
) * (args.temperature ** 2)
|
||||
loss_logits = (loss_start + loss_end) / 2.0
|
||||
|
||||
loss = args.alpha_distil * loss_logits + args.alpha_ce * loss
|
||||
@@ -868,10 +859,7 @@ def main():
|
||||
parser.add_argument("--adam_epsilon", default=1e-8, type=float, help="Epsilon for Adam optimizer.")
|
||||
parser.add_argument("--max_grad_norm", default=1.0, type=float, help="Max gradient norm.")
|
||||
parser.add_argument(
|
||||
"--num_train_epochs",
|
||||
default=3.0,
|
||||
type=float,
|
||||
help="Total number of training epochs to perform.",
|
||||
"--num_train_epochs", default=3.0, type=float, help="Total number of training epochs to perform.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--max_steps",
|
||||
|
||||
@@ -26,8 +26,8 @@ from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
import tqdm
|
||||
|
||||
from filelock import FileLock
|
||||
|
||||
from transformers import PreTrainedTokenizer, is_tf_available, is_torch_available
|
||||
|
||||
|
||||
@@ -100,12 +100,7 @@ if is_torch_available():
|
||||
|
||||
cached_features_file = os.path.join(
|
||||
data_dir,
|
||||
"cached_{}_{}_{}_{}".format(
|
||||
mode.value,
|
||||
tokenizer.__class__.__name__,
|
||||
str(max_seq_length),
|
||||
task,
|
||||
),
|
||||
"cached_{}_{}_{}_{}".format(mode.value, tokenizer.__class__.__name__, str(max_seq_length), task,),
|
||||
)
|
||||
|
||||
# Make sure only the first process in distributed training processes the dataset,
|
||||
@@ -126,12 +121,7 @@ if is_torch_available():
|
||||
else:
|
||||
examples = processor.get_train_examples(data_dir)
|
||||
logger.info("Training examples: %s", len(examples))
|
||||
self.features = convert_examples_to_features(
|
||||
examples,
|
||||
label_list,
|
||||
max_seq_length,
|
||||
tokenizer,
|
||||
)
|
||||
self.features = convert_examples_to_features(examples, label_list, max_seq_length, tokenizer,)
|
||||
logger.info("Saving features into cached file %s", cached_features_file)
|
||||
torch.save(self.features, cached_features_file)
|
||||
|
||||
@@ -174,12 +164,7 @@ if is_tf_available():
|
||||
examples = processor.get_train_examples(data_dir)
|
||||
logger.info("Training examples: %s", len(examples))
|
||||
|
||||
self.features = convert_examples_to_features(
|
||||
examples,
|
||||
label_list,
|
||||
max_seq_length,
|
||||
tokenizer,
|
||||
)
|
||||
self.features = convert_examples_to_features(examples, label_list, max_seq_length, tokenizer,)
|
||||
|
||||
def gen():
|
||||
for (ex_index, ex) in tqdm.tqdm(enumerate(self.features), desc="convert examples to features"):
|
||||
@@ -506,10 +491,7 @@ class ArcProcessor(DataProcessor):
|
||||
|
||||
|
||||
def convert_examples_to_features(
|
||||
examples: List[InputExample],
|
||||
label_list: List[str],
|
||||
max_length: int,
|
||||
tokenizer: PreTrainedTokenizer,
|
||||
examples: List[InputExample], label_list: List[str], max_length: int, tokenizer: PreTrainedTokenizer,
|
||||
) -> List[InputFeatures]:
|
||||
"""
|
||||
Loads a data file into a list of `InputFeatures`
|
||||
|
||||
@@ -137,12 +137,7 @@ def main():
|
||||
)
|
||||
|
||||
# Initialize our Trainer
|
||||
trainer = Trainer(
|
||||
model=model,
|
||||
args=training_args,
|
||||
train_dataset=train_dataset,
|
||||
eval_dataset=eval_dataset,
|
||||
)
|
||||
trainer = Trainer(model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset,)
|
||||
|
||||
# Training
|
||||
if training_args.do_train:
|
||||
|
||||
@@ -231,12 +231,7 @@ def main():
|
||||
eval_dataset = eval_dataset.apply(tf.data.experimental.assert_cardinality(len(eval_examples)))
|
||||
|
||||
# Initialize our Trainer
|
||||
trainer = TFTrainer(
|
||||
model=model,
|
||||
args=training_args,
|
||||
train_dataset=train_dataset,
|
||||
eval_dataset=eval_dataset,
|
||||
)
|
||||
trainer = TFTrainer(model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset,)
|
||||
|
||||
# Training
|
||||
if training_args.do_train:
|
||||
|
||||
@@ -35,15 +35,7 @@ export ENRO_DIR=${PWD}/wmt_en_ro
|
||||
this should make a directory called `wmt_en_ro/` with files like `test.source`.
|
||||
```
|
||||
|
||||
If you are using your own data, it must be formatted as one directory with 6 files:
|
||||
```
|
||||
train.source
|
||||
train.target
|
||||
val.source
|
||||
val.target
|
||||
test.source
|
||||
test.target
|
||||
```
|
||||
If you are using your own data, it must be formatted as one directory with 6 files: train.source, train.target, val.source, val.target, test.source, test.target.
|
||||
The `.source` files are the input, the `.target` files are the desired output.
|
||||
|
||||
|
||||
@@ -71,7 +63,7 @@ Summarization Tips:
|
||||
(It rarely makes sense to start from `bart-large` unless you are a researching finetuning methods).
|
||||
|
||||
**Update 2018-07-18**
|
||||
Datasets: `LegacySeq2SeqDataset` should be used for all tokenizers without a `prepare_seq2seq_batch` method. For those who do (like Marian, MBart), `Seq2SeqDataset` should be used.**
|
||||
Datasets: `Seq2SeqDataset` should be used for all tokenizers without a `prepare_seq2seq_batch` method. For those who do (like Marian, MBart), `TranslationDataset` should be used.**
|
||||
A new dataset is needed to support multilingual tasks.
|
||||
|
||||
|
||||
@@ -106,7 +98,7 @@ The following command should work on a 16GB GPU:
|
||||
--train_batch_size=1 \
|
||||
--eval_batch_size=1 \
|
||||
--output_dir=xsum_results \
|
||||
--num_train_epochs 6 \
|
||||
--num_train_epochs 1 \
|
||||
--model_name_or_path facebook/bart-large
|
||||
```
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ BERTABS_FINETUNED_CONFIG_MAP = {
|
||||
|
||||
|
||||
class BertAbsConfig(PretrainedConfig):
|
||||
r"""Class to store the configuration of the BertAbs model.
|
||||
r""" Class to store the configuration of the BertAbs model.
|
||||
|
||||
Arguments:
|
||||
vocab_size: int
|
||||
|
||||
@@ -62,7 +62,7 @@ BertAbsConfig = namedtuple(
|
||||
|
||||
|
||||
def convert_bertabs_checkpoints(path_to_checkpoints, dump_path):
|
||||
"""Copy/paste and tweak the pre-trained weights provided by the creators
|
||||
""" Copy/paste and tweak the pre-trained weights provided by the creators
|
||||
of BertAbs for the internal architecture.
|
||||
"""
|
||||
|
||||
@@ -164,22 +164,13 @@ def convert_bertabs_checkpoints(path_to_checkpoints, dump_path):
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--bertabs_checkpoint_path",
|
||||
default=None,
|
||||
type=str,
|
||||
required=True,
|
||||
help="Path the official PyTorch dump.",
|
||||
"--bertabs_checkpoint_path", default=None, type=str, required=True, help="Path the official PyTorch dump.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pytorch_dump_folder_path",
|
||||
default=None,
|
||||
type=str,
|
||||
required=True,
|
||||
help="Path to the output PyTorch model.",
|
||||
"--pytorch_dump_folder_path", default=None, type=str, required=True, help="Path to the output PyTorch model.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
convert_bertabs_checkpoints(
|
||||
args.bertabs_checkpoint_path,
|
||||
args.pytorch_dump_folder_path,
|
||||
args.bertabs_checkpoint_path, args.pytorch_dump_folder_path,
|
||||
)
|
||||
@@ -105,17 +105,10 @@ class BertAbs(BertAbsPreTrainedModel):
|
||||
p.data.zero_()
|
||||
|
||||
def forward(
|
||||
self,
|
||||
encoder_input_ids,
|
||||
decoder_input_ids,
|
||||
token_type_ids,
|
||||
encoder_attention_mask,
|
||||
decoder_attention_mask,
|
||||
self, encoder_input_ids, decoder_input_ids, token_type_ids, encoder_attention_mask, decoder_attention_mask,
|
||||
):
|
||||
encoder_output = self.bert(
|
||||
input_ids=encoder_input_ids,
|
||||
token_type_ids=token_type_ids,
|
||||
attention_mask=encoder_attention_mask,
|
||||
input_ids=encoder_input_ids, token_type_ids=token_type_ids, attention_mask=encoder_attention_mask,
|
||||
)
|
||||
encoder_hidden_states = encoder_output[0]
|
||||
dec_state = self.decoder.init_decoder_state(encoder_input_ids, encoder_hidden_states)
|
||||
@@ -124,7 +117,8 @@ class BertAbs(BertAbsPreTrainedModel):
|
||||
|
||||
|
||||
class Bert(nn.Module):
|
||||
"""This class is not really necessary and should probably disappear."""
|
||||
""" This class is not really necessary and should probably disappear.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -313,14 +307,7 @@ class TransformerDecoderLayer(nn.Module):
|
||||
self.register_buffer("mask", mask)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
inputs,
|
||||
memory_bank,
|
||||
src_pad_mask,
|
||||
tgt_pad_mask,
|
||||
previous_input=None,
|
||||
layer_cache=None,
|
||||
step=None,
|
||||
self, inputs, memory_bank, src_pad_mask, tgt_pad_mask, previous_input=None, layer_cache=None, step=None,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
@@ -344,25 +331,13 @@ class TransformerDecoderLayer(nn.Module):
|
||||
all_input = torch.cat((previous_input, input_norm), dim=1)
|
||||
dec_mask = None
|
||||
|
||||
query = self.self_attn(
|
||||
all_input,
|
||||
all_input,
|
||||
input_norm,
|
||||
mask=dec_mask,
|
||||
layer_cache=layer_cache,
|
||||
type="self",
|
||||
)
|
||||
query = self.self_attn(all_input, all_input, input_norm, mask=dec_mask, layer_cache=layer_cache, type="self",)
|
||||
|
||||
query = self.drop(query) + inputs
|
||||
|
||||
query_norm = self.layer_norm_2(query)
|
||||
mid = self.context_attn(
|
||||
memory_bank,
|
||||
memory_bank,
|
||||
query_norm,
|
||||
mask=src_pad_mask,
|
||||
layer_cache=layer_cache,
|
||||
type="context",
|
||||
memory_bank, memory_bank, query_norm, mask=src_pad_mask, layer_cache=layer_cache, type="context",
|
||||
)
|
||||
output = self.feed_forward(self.drop(mid) + query)
|
||||
|
||||
@@ -447,14 +422,7 @@ class MultiHeadedAttention(nn.Module):
|
||||
self.final_linear = nn.Linear(model_dim, model_dim)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
key,
|
||||
value,
|
||||
query,
|
||||
mask=None,
|
||||
layer_cache=None,
|
||||
type=None,
|
||||
predefined_graph_1=None,
|
||||
self, key, value, query, mask=None, layer_cache=None, type=None, predefined_graph_1=None,
|
||||
):
|
||||
"""
|
||||
Compute the context vector and the attention vectors.
|
||||
@@ -660,7 +628,7 @@ def gelu(x):
|
||||
|
||||
|
||||
class PositionwiseFeedForward(nn.Module):
|
||||
"""A two-layer Feed-Forward-Network with residual layer norm.
|
||||
""" A two-layer Feed-Forward-Network with residual layer norm.
|
||||
|
||||
Args:
|
||||
d_model (int): the size of input for the first-layer of the FFN.
|
||||
@@ -802,7 +770,8 @@ class Translator(object):
|
||||
self.max_length = args.max_length
|
||||
|
||||
def translate(self, batch, step, attn_debug=False):
|
||||
"""Generates summaries from one batch of data."""
|
||||
""" Generates summaries from one batch of data.
|
||||
"""
|
||||
self.model.eval()
|
||||
with torch.no_grad():
|
||||
batch_data = self.translate_batch(batch)
|
||||
@@ -829,7 +798,8 @@ class Translator(object):
|
||||
# Where the beam search lives
|
||||
# I have no idea why it is being called from the method above
|
||||
def _fast_translate_batch(self, batch, max_length, min_length=0):
|
||||
"""Beam Search using the encoder inputs contained in `batch`."""
|
||||
""" Beam Search using the encoder inputs contained in `batch`.
|
||||
"""
|
||||
|
||||
# The batch object is funny
|
||||
# Instead of just looking at the size of the arguments we encapsulate
|
||||
@@ -1011,7 +981,7 @@ def tile(x, count, dim=0):
|
||||
|
||||
|
||||
class BertSumOptimizer(object):
|
||||
"""Specific optimizer for BertSum.
|
||||
""" Specific optimizer for BertSum.
|
||||
|
||||
As described in [1], the authors fine-tune BertSum for abstractive
|
||||
summarization using two Adam Optimizers with different warm-up steps and
|
||||
@@ -1029,16 +999,10 @@ class BertSumOptimizer(object):
|
||||
|
||||
self.optimizers = {
|
||||
"encoder": torch.optim.Adam(
|
||||
model.encoder.parameters(),
|
||||
lr=lr["encoder"],
|
||||
betas=(beta_1, beta_2),
|
||||
eps=eps,
|
||||
model.encoder.parameters(), lr=lr["encoder"], betas=(beta_1, beta_2), eps=eps,
|
||||
),
|
||||
"decoder": torch.optim.Adam(
|
||||
model.decoder.parameters(),
|
||||
lr=lr["decoder"],
|
||||
betas=(beta_1, beta_2),
|
||||
eps=eps,
|
||||
model.decoder.parameters(), lr=lr["decoder"], betas=(beta_1, beta_2), eps=eps,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@@ -44,9 +44,8 @@ def evaluate(args):
|
||||
reference_summaries = []
|
||||
generated_summaries = []
|
||||
|
||||
import nltk
|
||||
|
||||
import rouge
|
||||
import nltk
|
||||
|
||||
nltk.download("punkt")
|
||||
rouge_evaluator = rouge.Rouge(
|
||||
@@ -99,7 +98,7 @@ def evaluate(args):
|
||||
|
||||
|
||||
def save_summaries(summaries, path, original_document_name):
|
||||
"""Write the summaries in fies that are prefixed by the original
|
||||
""" Write the summaries in fies that are prefixed by the original
|
||||
files' name with the `_summary` appended.
|
||||
|
||||
Attributes:
|
||||
@@ -125,7 +124,7 @@ def save_summaries(summaries, path, original_document_name):
|
||||
|
||||
|
||||
def format_summary(translation):
|
||||
"""Transforms the output of the `from_batch` function
|
||||
""" Transforms the output of the `from_batch` function
|
||||
into nicely formatted summaries.
|
||||
"""
|
||||
raw_summary, _, _ = translation
|
||||
@@ -190,12 +189,7 @@ def build_data_iterator(args, tokenizer):
|
||||
def collate_fn(data):
|
||||
return collate(data, tokenizer, block_size=512, device=args.device)
|
||||
|
||||
iterator = DataLoader(
|
||||
dataset,
|
||||
sampler=sampler,
|
||||
batch_size=args.batch_size,
|
||||
collate_fn=collate_fn,
|
||||
)
|
||||
iterator = DataLoader(dataset, sampler=sampler, batch_size=args.batch_size, collate_fn=collate_fn,)
|
||||
|
||||
return iterator
|
||||
|
||||
@@ -206,7 +200,7 @@ def load_and_cache_examples(args, tokenizer):
|
||||
|
||||
|
||||
def collate(data, tokenizer, block_size, device):
|
||||
"""Collate formats the data passed to the data loader.
|
||||
""" Collate formats the data passed to the data loader.
|
||||
|
||||
In particular we tokenize the data batch after batch to avoid keeping them
|
||||
all in memory. We output the data as a namedtuple to fit the original BertAbs's
|
||||
@@ -236,7 +230,7 @@ def collate(data, tokenizer, block_size, device):
|
||||
|
||||
|
||||
def decode_summary(summary_tokens, tokenizer):
|
||||
"""Decode the summary and return it in a format
|
||||
""" Decode the summary and return it in a format
|
||||
suitable for evaluation.
|
||||
"""
|
||||
summary_tokens = summary_tokens.to("cpu").numpy()
|
||||
@@ -247,7 +241,8 @@ def decode_summary(summary_tokens, tokenizer):
|
||||
|
||||
|
||||
def main():
|
||||
"""The main function defines the interface with the users."""
|
||||
""" The main function defines the interface with the users.
|
||||
"""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--documents_dir",
|
||||
@@ -272,41 +267,23 @@ def main():
|
||||
)
|
||||
# EVALUATION options
|
||||
parser.add_argument(
|
||||
"--no_cuda",
|
||||
default=False,
|
||||
type=bool,
|
||||
help="Whether to force the execution on CPU.",
|
||||
"--no_cuda", default=False, type=bool, help="Whether to force the execution on CPU.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--batch_size",
|
||||
default=4,
|
||||
type=int,
|
||||
help="Batch size per GPU/CPU for training.",
|
||||
"--batch_size", default=4, type=int, help="Batch size per GPU/CPU for training.",
|
||||
)
|
||||
# BEAM SEARCH arguments
|
||||
parser.add_argument(
|
||||
"--min_length",
|
||||
default=50,
|
||||
type=int,
|
||||
help="Minimum number of tokens for the summaries.",
|
||||
"--min_length", default=50, type=int, help="Minimum number of tokens for the summaries.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--max_length",
|
||||
default=200,
|
||||
type=int,
|
||||
help="Maixmum number of tokens for the summaries.",
|
||||
"--max_length", default=200, type=int, help="Maixmum number of tokens for the summaries.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--beam_size",
|
||||
default=5,
|
||||
type=int,
|
||||
help="The number of beams to start with for each example.",
|
||||
"--beam_size", default=5, type=int, help="The number of beams to start with for each example.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--alpha",
|
||||
default=0.95,
|
||||
type=float,
|
||||
help="The value of alpha for the length penalty in the beam search.",
|
||||
"--alpha", default=0.95, type=float, help="The value of alpha for the length penalty in the beam search.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--block_trigram",
|
||||
|
||||
@@ -43,7 +43,8 @@ class SummarizationDataProcessingTest(unittest.TestCase):
|
||||
self.assertEqual(truncate_or_pad(sequence, self.block_size, 0), expected_output)
|
||||
|
||||
def test_process_story_no_highlights(self):
|
||||
"""Processing a story with no highlights returns an empty list for the summary."""
|
||||
""" Processing a story with no highlights returns an empty list for the summary.
|
||||
"""
|
||||
raw_story = """It was the year of Our Lord one thousand seven hundred and
|
||||
seventy-five.\n\nSpiritual revelations were conceded to England at that
|
||||
favoured period, as at this."""
|
||||
@@ -51,7 +52,8 @@ class SummarizationDataProcessingTest(unittest.TestCase):
|
||||
self.assertEqual(summary_lines, [])
|
||||
|
||||
def test_process_empty_story(self):
|
||||
"""An empty story returns an empty collection of lines."""
|
||||
""" An empty story returns an empty collection of lines.
|
||||
"""
|
||||
raw_story = ""
|
||||
story_lines, summary_lines = process_story(raw_story)
|
||||
self.assertEqual(story_lines, [])
|
||||
|
||||
@@ -11,7 +11,7 @@ from torch.utils.data import Dataset
|
||||
|
||||
|
||||
class CNNDMDataset(Dataset):
|
||||
"""Abstracts the dataset used to train seq2seq models.
|
||||
""" Abstracts the dataset used to train seq2seq models.
|
||||
|
||||
The class will process the documents that are located in the specified
|
||||
folder. The preprocessing will work on any document that is reasonably
|
||||
@@ -31,7 +31,7 @@ class CNNDMDataset(Dataset):
|
||||
"""
|
||||
|
||||
def __init__(self, path="", prefix="train"):
|
||||
"""We initialize the class by listing all the documents to summarize.
|
||||
""" We initialize the class by listing all the documents to summarize.
|
||||
Files are not read in memory due to the size of some datasets (like CNN/DailyMail).
|
||||
"""
|
||||
assert os.path.isdir(path)
|
||||
@@ -60,7 +60,7 @@ class CNNDMDataset(Dataset):
|
||||
|
||||
|
||||
def process_story(raw_story):
|
||||
"""Extract the story and summary from a story file.
|
||||
""" Extract the story and summary from a story file.
|
||||
|
||||
Arguments:
|
||||
raw_story (str): content of the story file as an utf-8 encoded string.
|
||||
@@ -108,7 +108,7 @@ def _add_missing_period(line):
|
||||
|
||||
|
||||
def truncate_or_pad(sequence, block_size, pad_token_id):
|
||||
"""Adapt the source and target sequences' lengths to the block size.
|
||||
""" Adapt the source and target sequences' lengths to the block size.
|
||||
If the sequence is shorter we append padding token to the right of the sequence.
|
||||
"""
|
||||
if len(sequence) > block_size:
|
||||
@@ -119,8 +119,8 @@ def truncate_or_pad(sequence, block_size, pad_token_id):
|
||||
|
||||
|
||||
def build_mask(sequence, pad_token_id):
|
||||
"""Builds the mask. The attention mechanism will only attend to positions
|
||||
with value 1."""
|
||||
""" Builds the mask. The attention mechanism will only attend to positions
|
||||
with value 1. """
|
||||
mask = torch.ones_like(sequence)
|
||||
idx_pad_tokens = sequence == pad_token_id
|
||||
mask[idx_pad_tokens] = 0
|
||||
@@ -128,7 +128,7 @@ def build_mask(sequence, pad_token_id):
|
||||
|
||||
|
||||
def encode_for_summarization(story_lines, summary_lines, tokenizer):
|
||||
"""Encode the story and summary lines, and join them
|
||||
""" Encode the story and summary lines, and join them
|
||||
as specified in [1] by using `[SEP] [CLS]` tokens to separate
|
||||
sentences.
|
||||
"""
|
||||
@@ -141,7 +141,7 @@ def encode_for_summarization(story_lines, summary_lines, tokenizer):
|
||||
|
||||
|
||||
def compute_token_type_ids(batch, separator_token_id):
|
||||
"""Segment embeddings as described in [1]
|
||||
""" Segment embeddings as described in [1]
|
||||
|
||||
The values {0,1} were found in the repository [2].
|
||||
|
||||
|
||||
@@ -97,9 +97,4 @@ def get_checkpoint_callback(output_dir, metric):
|
||||
|
||||
|
||||
def get_early_stopping_callback(metric, patience):
|
||||
return EarlyStopping(
|
||||
monitor=f"val_{metric}",
|
||||
mode="max",
|
||||
patience=patience,
|
||||
verbose=True,
|
||||
)
|
||||
return EarlyStopping(monitor=f"val_{metric}", mode="max", patience=patience, verbose=True,)
|
||||
@@ -1,7 +1,6 @@
|
||||
import argparse
|
||||
import gc
|
||||
import os
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -11,35 +10,39 @@ from torch import nn
|
||||
from torch.nn import functional as F
|
||||
|
||||
from lightning_base import generic_train
|
||||
from transformers import BartConfig, BartForConditionalGeneration, MBartTokenizer, T5Config, T5ForConditionalGeneration
|
||||
from transformers.modeling_bart import shift_tokens_right
|
||||
from transformers import (
|
||||
AdamW,
|
||||
BartConfig,
|
||||
BartForConditionalGeneration,
|
||||
MBartTokenizer,
|
||||
T5Config,
|
||||
T5ForConditionalGeneration,
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
from .finetune import SummarizationModule, TranslationModule
|
||||
from .finetune import main as ft_main
|
||||
from .initialization_utils import copy_layers, init_student
|
||||
from .initialization_utils import init_student, copy_layers
|
||||
from .utils import (
|
||||
any_requires_grad,
|
||||
assert_all_frozen,
|
||||
calculate_bleu,
|
||||
freeze_params,
|
||||
label_smoothed_nll_loss,
|
||||
pickle_load,
|
||||
use_task_specific_params,
|
||||
pickle_load,
|
||||
freeze_params,
|
||||
assert_all_frozen,
|
||||
any_requires_grad,
|
||||
calculate_bleu_score,
|
||||
)
|
||||
from .finetune import main as ft_main
|
||||
except ImportError:
|
||||
from finetune import SummarizationModule, TranslationModule
|
||||
from finetune import main as ft_main
|
||||
from initialization_utils import copy_layers, init_student
|
||||
from initialization_utils import init_student, copy_layers
|
||||
from utils import (
|
||||
any_requires_grad,
|
||||
assert_all_frozen,
|
||||
calculate_bleu,
|
||||
freeze_params,
|
||||
label_smoothed_nll_loss,
|
||||
pickle_load,
|
||||
use_task_specific_params,
|
||||
pickle_load,
|
||||
freeze_params,
|
||||
assert_all_frozen,
|
||||
any_requires_grad,
|
||||
calculate_bleu_score,
|
||||
)
|
||||
|
||||
|
||||
@@ -155,6 +158,24 @@ class BartSummarizationDistiller(SummarizationModule):
|
||||
)
|
||||
return loss_ce, s_logits_slct, t_logits_slct
|
||||
|
||||
def configure_optimizers(self):
|
||||
"Prepare optimizer and schedule (linear warmup and decay)"
|
||||
model = self.model
|
||||
no_decay = ["bias", "LayerNorm.weight"]
|
||||
optimizer_grouped_parameters = [
|
||||
{
|
||||
"params": [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)],
|
||||
"weight_decay": self.hparams.weight_decay,
|
||||
},
|
||||
{
|
||||
"params": [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)],
|
||||
"weight_decay": 0.0,
|
||||
},
|
||||
]
|
||||
optimizer = AdamW(optimizer_grouped_parameters, lr=self.hparams.learning_rate, eps=self.hparams.adam_epsilon)
|
||||
self.opt = optimizer
|
||||
return [optimizer]
|
||||
|
||||
@staticmethod
|
||||
def add_model_specific_args(parser, root_dir):
|
||||
SummarizationModule.add_model_specific_args(parser, root_dir)
|
||||
@@ -164,42 +185,22 @@ class BartSummarizationDistiller(SummarizationModule):
|
||||
def _step(self, batch):
|
||||
# assert is_frozen(self.teacher)
|
||||
pad_token_id = self.tokenizer.pad_token_id
|
||||
input_ids, src_mask = batch["input_ids"], batch["attention_mask"]
|
||||
if "labels" in batch:
|
||||
lm_labels = batch["labels"]
|
||||
decoder_input_ids = shift_tokens_right(lm_labels, pad_token_id)
|
||||
else:
|
||||
raise ValueError()
|
||||
# decoder_input_ids = y[:, :-1].contiguous()
|
||||
# labels = y[:, 1:].clone()
|
||||
# labels[y[:, 1:] == pad_token_id] = -100
|
||||
input_ids, src_mask, y = batch["input_ids"], batch["attention_mask"], batch["decoder_input_ids"]
|
||||
decoder_input_ids = y[:, :-1].contiguous()
|
||||
labels = y[:, 1:].clone()
|
||||
labels[y[:, 1:] == pad_token_id] = -100
|
||||
# noinspection PyCallingNonCallable
|
||||
outputs = self(
|
||||
sloss, slogits, dec_hidden, enc_outputs, enc_hidden_state = self(
|
||||
input_ids,
|
||||
attention_mask=src_mask,
|
||||
decoder_input_ids=decoder_input_ids,
|
||||
# labels=labels,
|
||||
labels=labels,
|
||||
output_hidden_states=True,
|
||||
output_attentions=False,
|
||||
# return_dict=True,
|
||||
use_cache=False,
|
||||
)
|
||||
lm_logits, dec_hidden, enc_outputs, enc_hidden_state = outputs
|
||||
|
||||
if self.hparams.label_smoothing == 0:
|
||||
# Same behavior as modeling_bart.py, besides pad_token_id
|
||||
loss_fct = torch.nn.CrossEntropyLoss(ignore_index=pad_token_id)
|
||||
|
||||
assert lm_logits.shape[-1] == self.model.config.vocab_size
|
||||
student_lm_loss = loss_fct(lm_logits.view(-1, lm_logits.shape[-1]), lm_labels.view(-1))
|
||||
else:
|
||||
lprobs = torch.nn.functional.log_softmax(lm_logits, dim=-1)
|
||||
student_lm_loss, _ = label_smoothed_nll_loss(
|
||||
lprobs, lm_labels, self.hparams.label_smoothing, ignore_index=pad_token_id
|
||||
)
|
||||
|
||||
def zero_tensor():
|
||||
return torch.tensor(0.0).type_as(student_lm_loss)
|
||||
return torch.tensor(0.0).type_as(sloss)
|
||||
|
||||
loss_encoder, hid_loss_enc, hid_loss_dec = zero_tensor(), zero_tensor(), zero_tensor()
|
||||
if self.different_encoder:
|
||||
@@ -223,21 +224,21 @@ class BartSummarizationDistiller(SummarizationModule):
|
||||
attention_mask=src_mask,
|
||||
encoder_outputs=teacher_enc_outputs,
|
||||
decoder_input_ids=decoder_input_ids,
|
||||
lm_labels=lm_labels,
|
||||
lm_labels=labels,
|
||||
output_hidden_states=True,
|
||||
)
|
||||
dec_mask = decoder_input_ids.ne(pad_token_id)
|
||||
loss_ce, s_logits_slct, t_logits_slct = self.calc_ce_loss(dec_mask, lm_logits, tlogits)
|
||||
loss_ce, s_logits_slct, t_logits_slct = self.calc_ce_loss(dec_mask, slogits, tlogits)
|
||||
if self.alpha_hid > 0:
|
||||
hid_loss_dec = self.calc_hidden_loss(dec_mask, dec_hidden, tdec_hidden, self.hparams.d_layer_to_copy)
|
||||
|
||||
blended_loss = (
|
||||
self.alpha_ce * loss_ce
|
||||
+ self.alpha_mlm * student_lm_loss
|
||||
+ self.alpha_mlm * sloss
|
||||
+ self.hparams.alpha_encoder_loss * loss_encoder
|
||||
+ self.hparams.alpha_hid * (hid_loss_enc + hid_loss_dec)
|
||||
)
|
||||
return blended_loss, loss_ce, student_lm_loss, loss_encoder, hid_loss_enc, hid_loss_dec
|
||||
return blended_loss, loss_ce, sloss, loss_encoder, hid_loss_enc, hid_loss_dec
|
||||
|
||||
def calc_hidden_loss(self, attention_mask, hidden_states, hidden_states_T, matches):
|
||||
assert not isinstance(
|
||||
@@ -257,7 +258,7 @@ class BartSummarizationDistiller(SummarizationModule):
|
||||
|
||||
|
||||
def add_distill_args(parser):
|
||||
parser.add_argument("--teacher", type=str)
|
||||
parser.add_argument("--teacher", default="facebook/bart-large-cnn", type=str)
|
||||
parser.add_argument("--alpha_ce", default=0.8, type=float)
|
||||
parser.add_argument("--alpha_mlm", default=0.2, type=float)
|
||||
parser.add_argument("--alpha_encoder_loss", default=0.0, type=float)
|
||||
@@ -270,12 +271,13 @@ def add_distill_args(parser):
|
||||
|
||||
class BartTranslationDistiller(BartSummarizationDistiller):
|
||||
mode = "translation"
|
||||
loss_names = ["loss", "ce_loss", "mlm_loss", "enc_mse_loss", "hid_loss_enc", "hid_loss_dec"]
|
||||
loss_names = ["loss"]
|
||||
metric_names = ["bleu"]
|
||||
val_metric = "bleu"
|
||||
|
||||
def __init__(self, hparams, **kwargs):
|
||||
super().__init__(hparams, **kwargs)
|
||||
assert isinstance(self.tokenizer, MBartTokenizer)
|
||||
assert hparams.src_lang is not None
|
||||
assert hparams.tgt_lang is not None
|
||||
self.dataset_kwargs["src_lang"] = hparams.src_lang
|
||||
@@ -284,7 +286,7 @@ class BartTranslationDistiller(BartSummarizationDistiller):
|
||||
self.decoder_start_token_id = self.tokenizer.lang_code_to_id[hparams.tgt_lang]
|
||||
|
||||
def calc_generative_metrics(self, preds, target) -> dict:
|
||||
return calculate_bleu(preds, target)
|
||||
return calculate_bleu_score(preds, target)
|
||||
|
||||
@staticmethod
|
||||
def add_model_specific_args(parser, root_dir):
|
||||
@@ -371,10 +373,7 @@ class T5SummarizationDistiller(BartSummarizationDistiller):
|
||||
if self.different_encoder:
|
||||
with torch.no_grad():
|
||||
teacher_enc_outputs, teacher_enc_hid = self.teacher.encoder(
|
||||
source_ids,
|
||||
attention_mask=source_mask,
|
||||
output_hidden_states=True,
|
||||
use_cache=False,
|
||||
source_ids, attention_mask=source_mask, output_hidden_states=True, use_cache=False,
|
||||
)
|
||||
if self.hparams.alpha_encoder_loss > 0:
|
||||
loss_encoder = self.calc_mse_loss(enc_outputs, teacher_enc_outputs, source_mask)
|
||||
@@ -392,7 +391,7 @@ class T5SummarizationDistiller(BartSummarizationDistiller):
|
||||
attention_mask=source_mask,
|
||||
encoder_outputs=teacher_enc_outputs,
|
||||
decoder_input_ids=decoder_input_ids,
|
||||
labels=labels,
|
||||
lm_labels=labels,
|
||||
output_hidden_states=True,
|
||||
use_cache=False,
|
||||
)
|
||||
@@ -448,40 +447,33 @@ def evaluate_checkpoint(ckpt_path: Path, dest_dir=None):
|
||||
trainer.test(model)
|
||||
|
||||
|
||||
LAYERS_TO_COPY = {
|
||||
# maps num layers in student -> which teacher layers to copy.
|
||||
# 12:bart, 16: pegasus, 6: marian/Helsinki-NLP
|
||||
12: {
|
||||
1: [0],
|
||||
2: [0, 6],
|
||||
3: [0, 6, 11],
|
||||
4: [0, 4, 8, 11],
|
||||
6: [0, 2, 4, 7, 9, 11],
|
||||
9: [0, 1, 2, 4, 5, 7, 9, 10, 11],
|
||||
12: list(range(12)),
|
||||
},
|
||||
16: { # maps num layers in student -> which teacher layers to copy
|
||||
1: [0],
|
||||
2: [0, 8],
|
||||
3: [0, 8, 15],
|
||||
4: [0, 5, 10, 15],
|
||||
6: [0, 3, 6, 9, 12, 15],
|
||||
8: [0, 2, 4, 6, 8, 10, 12, 15],
|
||||
9: [0, 1, 3, 5, 7, 9, 11, 13, 15],
|
||||
16: list(range(16)),
|
||||
},
|
||||
6: {1: [0], 2: [0, 5], 3: [0, 2, 5], 4: [0, 1, 3, 5], 6: list(range(6))},
|
||||
}
|
||||
|
||||
|
||||
def get_layers_to_copy(n_student, n_teacher):
|
||||
try:
|
||||
return LAYERS_TO_COPY[n_teacher][n_student]
|
||||
except KeyError:
|
||||
warnings.warn(
|
||||
f"no hardcoded layers to copy for teacher {n_teacher} -> student {n_student}, defaulting to first {n_student}"
|
||||
)
|
||||
return list(range(n_student))
|
||||
def get_layers_to_copy(n_to_get, tot):
|
||||
all_layers = list(range(tot))
|
||||
if tot == 12: # Alternating for special cases
|
||||
layers_to_copy = { # maps num layers in student -> which teacher layers to copy
|
||||
1: [0],
|
||||
2: [0, 6],
|
||||
3: [0, 6, 11],
|
||||
4: [0, 4, 8, 11],
|
||||
6: [0, 2, 4, 7, 9, 11],
|
||||
9: [0, 1, 2, 4, 5, 7, 9, 10, 11],
|
||||
12: all_layers,
|
||||
}
|
||||
return layers_to_copy[n_to_get]
|
||||
elif tot == 16:
|
||||
layers_to_copy = { # maps num layers in student -> which teacher layers to copy
|
||||
1: [0],
|
||||
2: [0, 8],
|
||||
3: [0, 8, 15],
|
||||
4: [0, 5, 10, 15],
|
||||
6: [0, 3, 6, 9, 12, 15],
|
||||
8: [0, 2, 4, 6, 8, 10, 12, 15],
|
||||
9: [0, 1, 3, 5, 7, 9, 11, 13, 15],
|
||||
16: all_layers,
|
||||
}
|
||||
return layers_to_copy[n_to_get]
|
||||
else:
|
||||
return all_layers[:n_to_get] # TODO: better version on theseus-bart branch
|
||||
|
||||
|
||||
def distill_main(args):
|
||||
|
||||
@@ -3,6 +3,7 @@ import glob
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple
|
||||
@@ -13,48 +14,48 @@ import torch
|
||||
from torch.utils.data import DataLoader
|
||||
|
||||
from lightning_base import BaseTransformer, add_generic_args, generic_train
|
||||
from transformers import MBartTokenizer, T5ForConditionalGeneration
|
||||
from transformers.modeling_bart import shift_tokens_right
|
||||
from transformers import MarianTokenizer, MBartTokenizer, T5ForConditionalGeneration, get_linear_schedule_with_warmup
|
||||
|
||||
|
||||
try:
|
||||
from .callbacks import Seq2SeqLoggingCallback, get_checkpoint_callback, get_early_stopping_callback
|
||||
from .utils import (
|
||||
ROUGE_KEYS,
|
||||
LegacySeq2SeqDataset,
|
||||
Seq2SeqDataset,
|
||||
assert_all_frozen,
|
||||
calculate_bleu,
|
||||
calculate_rouge,
|
||||
flatten_list,
|
||||
freeze_params,
|
||||
get_git_info,
|
||||
label_smoothed_nll_loss,
|
||||
use_task_specific_params,
|
||||
lmap,
|
||||
flatten_list,
|
||||
pickle_save,
|
||||
save_git_info,
|
||||
save_json,
|
||||
use_task_specific_params,
|
||||
freeze_params,
|
||||
calculate_rouge,
|
||||
get_git_info,
|
||||
ROUGE_KEYS,
|
||||
calculate_bleu_score,
|
||||
Seq2SeqDataset,
|
||||
TranslationDataset,
|
||||
label_smoothed_nll_loss,
|
||||
)
|
||||
|
||||
from .callbacks import Seq2SeqLoggingCallback, get_checkpoint_callback, get_early_stopping_callback
|
||||
except ImportError:
|
||||
from callbacks import Seq2SeqLoggingCallback, get_checkpoint_callback, get_early_stopping_callback
|
||||
from utils import (
|
||||
ROUGE_KEYS,
|
||||
LegacySeq2SeqDataset,
|
||||
Seq2SeqDataset,
|
||||
TranslationDataset,
|
||||
assert_all_frozen,
|
||||
calculate_bleu,
|
||||
calculate_rouge,
|
||||
flatten_list,
|
||||
freeze_params,
|
||||
get_git_info,
|
||||
label_smoothed_nll_loss,
|
||||
use_task_specific_params,
|
||||
lmap,
|
||||
flatten_list,
|
||||
pickle_save,
|
||||
save_git_info,
|
||||
save_json,
|
||||
use_task_specific_params,
|
||||
freeze_params,
|
||||
calculate_rouge,
|
||||
get_git_info,
|
||||
ROUGE_KEYS,
|
||||
calculate_bleu_score,
|
||||
label_smoothed_nll_loss,
|
||||
)
|
||||
from callbacks import Seq2SeqLoggingCallback, get_checkpoint_callback, get_early_stopping_callback
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -103,13 +104,14 @@ class SummarizationModule(BaseTransformer):
|
||||
|
||||
self.hparams.git_sha = get_git_info()["repo_sha"]
|
||||
self.num_workers = hparams.num_workers
|
||||
self.decoder_start_token_id = None # default to config
|
||||
self.decoder_start_token_id = None
|
||||
if self.model.config.decoder_start_token_id is None and isinstance(self.tokenizer, MBartTokenizer):
|
||||
self.decoder_start_token_id = self.tokenizer.lang_code_to_id[hparams.tgt_lang]
|
||||
self.model.config.decoder_start_token_id = self.decoder_start_token_id
|
||||
self.dataset_class = (
|
||||
Seq2SeqDataset if hasattr(self.tokenizer, "prepare_seq2seq_batch") else LegacySeq2SeqDataset
|
||||
)
|
||||
if isinstance(self.tokenizer, MBartTokenizer) or isinstance(self.tokenizer, MarianTokenizer):
|
||||
self.dataset_class = TranslationDataset
|
||||
else:
|
||||
self.dataset_class = Seq2SeqDataset
|
||||
|
||||
def freeze_embeds(self):
|
||||
"""Freeze token embeddings and positional embeddings for bart, just token embeddings for t5."""
|
||||
@@ -134,24 +136,19 @@ class SummarizationModule(BaseTransformer):
|
||||
|
||||
def _step(self, batch: dict) -> Tuple:
|
||||
pad_token_id = self.tokenizer.pad_token_id
|
||||
source_ids, source_mask = batch["input_ids"], batch["attention_mask"] # , batch["decoder_input_ids"]
|
||||
source_ids, source_mask, target_ids = batch["input_ids"], batch["attention_mask"], batch["decoder_input_ids"]
|
||||
|
||||
if "labels" in batch:
|
||||
lm_labels = batch["labels"]
|
||||
decoder_input_ids = shift_tokens_right(lm_labels, pad_token_id)
|
||||
elif isinstance(self.model, T5ForConditionalGeneration):
|
||||
lm_labels = batch["labels"]
|
||||
decoder_input_ids = self.model._shift_right(lm_labels)
|
||||
if isinstance(self.model, T5ForConditionalGeneration):
|
||||
decoder_input_ids = self.model._shift_right(target_ids)
|
||||
lm_labels = target_ids
|
||||
else:
|
||||
target_ids = batch["decoder_input_ids"]
|
||||
# This is a slightly worse way of shifting tokens right -- it deletes token 0 from target_id
|
||||
decoder_input_ids = target_ids[:, :-1].contiguous()
|
||||
lm_labels = target_ids[:, 1:].clone()
|
||||
decoder_input_ids = target_ids[:, :-1].contiguous() # Why this line?
|
||||
lm_labels = target_ids[:, 1:].clone() # why clone?
|
||||
|
||||
outputs = self(source_ids, attention_mask=source_mask, decoder_input_ids=decoder_input_ids, use_cache=False)
|
||||
|
||||
if self.hparams.label_smoothing == 0:
|
||||
# Same behavior as modeling_bart.py, besides ignoring pad_token_id
|
||||
# Same behavior as modeling_bart.py
|
||||
loss_fct = torch.nn.CrossEntropyLoss(ignore_index=pad_token_id)
|
||||
lm_logits = outputs[0]
|
||||
assert lm_logits.shape[-1] == self.model.config.vocab_size
|
||||
@@ -172,7 +169,7 @@ class SummarizationModule(BaseTransformer):
|
||||
|
||||
logs = {name: loss for name, loss in zip(self.loss_names, loss_tensors)}
|
||||
# tokens per batch
|
||||
logs["tpb"] = batch["input_ids"].ne(self.pad).sum() + batch["labels"].ne(self.pad).sum()
|
||||
logs["tpb"] = batch["input_ids"].ne(self.pad).sum() + batch["decoder_input_ids"].ne(self.pad).sum()
|
||||
return {"loss": loss_tensors[0], "log": logs}
|
||||
|
||||
def validation_step(self, batch, batch_idx) -> Dict:
|
||||
@@ -209,7 +206,7 @@ class SummarizationModule(BaseTransformer):
|
||||
)
|
||||
gen_time = (time.time() - t0) / batch["input_ids"].shape[0]
|
||||
preds: List[str] = self.ids_to_clean_text(generated_ids)
|
||||
target: List[str] = self.ids_to_clean_text(batch["labels"])
|
||||
target: List[str] = self.ids_to_clean_text(batch["decoder_input_ids"])
|
||||
loss_tensors = self._step(batch)
|
||||
base_metrics = {name: loss for name, loss in zip(self.loss_names, loss_tensors)}
|
||||
rouge: Dict = self.calc_generative_metrics(preds, target)
|
||||
@@ -255,6 +252,17 @@ class SummarizationModule(BaseTransformer):
|
||||
|
||||
def train_dataloader(self) -> DataLoader:
|
||||
dataloader = self.get_dataloader("train", batch_size=self.hparams.train_batch_size, shuffle=True)
|
||||
t_total = (
|
||||
(len(dataloader.dataset) // (self.hparams.train_batch_size * max(1, self.hparams.gpus)))
|
||||
// self.hparams.accumulate_grad_batches
|
||||
* float(self.hparams.max_epochs)
|
||||
)
|
||||
scheduler = get_linear_schedule_with_warmup(
|
||||
self.opt, num_warmup_steps=self.hparams.warmup_steps, num_training_steps=t_total
|
||||
)
|
||||
if max(scheduler.get_last_lr()) > 0:
|
||||
warnings.warn("All learning rates are 0")
|
||||
self.lr_scheduler = scheduler
|
||||
return dataloader
|
||||
|
||||
def val_dataloader(self) -> DataLoader:
|
||||
@@ -295,6 +303,12 @@ class SummarizationModule(BaseTransformer):
|
||||
help="The maximum total input sequence length after tokenization. Sequences longer "
|
||||
"than this will be truncated, sequences shorter will be padded.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--data_dir",
|
||||
type=str,
|
||||
required=True,
|
||||
help="The input data dir. Should contain train.source, train.target, val.source, val.target, test.source, test.target",
|
||||
)
|
||||
parser.add_argument("--freeze_encoder", action="store_true")
|
||||
parser.add_argument("--freeze_embeds", action="store_true")
|
||||
parser.add_argument("--sortish_sampler", action="store_true", default=False)
|
||||
@@ -330,7 +344,7 @@ class TranslationModule(SummarizationModule):
|
||||
self.dataset_kwargs["tgt_lang"] = hparams.tgt_lang
|
||||
|
||||
def calc_generative_metrics(self, preds, target) -> dict:
|
||||
return calculate_bleu(preds, target)
|
||||
return calculate_bleu_score(preds, target)
|
||||
|
||||
|
||||
def main(args, model=None) -> SummarizationModule:
|
||||
|
||||
@@ -11,4 +11,4 @@ python finetune.py \
|
||||
--do_predict \
|
||||
--n_val 1000 \
|
||||
--val_check_interval 0.1 \
|
||||
"$@"
|
||||
$@
|
||||
@@ -23,7 +23,7 @@ python finetune.py \
|
||||
--output_dir=$OUTPUT_DIR \
|
||||
--num_train_epochs=1 \
|
||||
--gpus=0 \
|
||||
--do_train "$@"
|
||||
--do_train $@
|
||||
|
||||
rm -rf cnn_tiny
|
||||
rm -rf $OUTPUT_DIR
|
||||
|
||||
@@ -11,4 +11,4 @@ python finetune.py \
|
||||
--val_check_interval 0.25 \
|
||||
--max_source_length 512 --max_target_length 56 \
|
||||
--freeze_embeds --max_target_length 56 --label_smoothing 0.1 \
|
||||
"$@"
|
||||
$@
|
||||
@@ -11,4 +11,4 @@ python finetune.py \
|
||||
--max_target_length=56 \
|
||||
--val_check_interval=0.1 --n_val=200 \
|
||||
--do_train --do_predict \
|
||||
"$@"
|
||||
$@
|
||||
@@ -7,4 +7,4 @@ python distillation.py \
|
||||
--do_predict \
|
||||
--fp16 \
|
||||
--val_check_interval 0.1 \
|
||||
"$@"
|
||||
$@
|
||||
@@ -9,9 +9,9 @@ from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
|
||||
|
||||
|
||||
try:
|
||||
from .utils import calculate_bleu, calculate_rouge, trim_batch, use_task_specific_params
|
||||
from .utils import calculate_rouge, use_task_specific_params, calculate_bleu_score, trim_batch
|
||||
except ImportError:
|
||||
from utils import calculate_bleu, calculate_rouge, trim_batch, use_task_specific_params
|
||||
from utils import calculate_rouge, use_task_specific_params, calculate_bleu_score, trim_batch
|
||||
|
||||
DEFAULT_DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
||||
|
||||
@@ -103,7 +103,7 @@ def run_generate():
|
||||
if args.reference_path is None:
|
||||
return
|
||||
# Compute scores
|
||||
score_fn = calculate_bleu if "translation" in args.task else calculate_rouge
|
||||
score_fn = calculate_bleu_score if "translation" in args.task else calculate_rouge
|
||||
output_lns = [x.rstrip() for x in open(args.save_path).readlines()]
|
||||
reference_lns = [x.rstrip() for x in open(args.reference_path).readlines()][: len(output_lns)]
|
||||
scores: dict = score_fn(output_lns, reference_lns)
|
||||
|
||||
@@ -15,14 +15,13 @@ from torch.utils.data import DataLoader
|
||||
|
||||
import lightning_base
|
||||
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
|
||||
from transformers.modeling_bart import shift_tokens_right
|
||||
from transformers.testing_utils import CaptureStderr, CaptureStdout, require_multigpu
|
||||
|
||||
from .distillation import distill_main, evaluate_checkpoint
|
||||
from .finetune import SummarizationModule, main
|
||||
from .pack_dataset import pack_data_dir
|
||||
from .run_eval import generate_summaries_or_translations, run_generate
|
||||
from .utils import LegacySeq2SeqDataset, Seq2SeqDataset, label_smoothed_nll_loss, lmap, load_json
|
||||
from .utils import Seq2SeqDataset, TranslationDataset, label_smoothed_nll_loss, lmap, load_json
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
@@ -118,12 +117,7 @@ class TestSummarizationDistiller(unittest.TestCase):
|
||||
|
||||
@require_multigpu
|
||||
def test_multigpu(self):
|
||||
updates = dict(
|
||||
no_teacher=True,
|
||||
freeze_encoder=True,
|
||||
gpus=2,
|
||||
sortish_sampler=False,
|
||||
)
|
||||
updates = dict(no_teacher=True, freeze_encoder=True, gpus=2, sortish_sampler=False,)
|
||||
self._test_distiller_cli(updates)
|
||||
|
||||
def test_distill_no_teacher(self):
|
||||
@@ -267,8 +261,7 @@ def test_run_eval_bart(model):
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
["model"],
|
||||
[pytest.param(T5_TINY), pytest.param(BART_TINY), pytest.param(MBART_TINY), pytest.param(MARIAN_TINY)],
|
||||
["model"], [pytest.param(T5_TINY), pytest.param(BART_TINY), pytest.param(MBART_TINY), pytest.param(MARIAN_TINY)],
|
||||
)
|
||||
def test_finetune(model):
|
||||
args_d: dict = CHEAP_ARGS.copy()
|
||||
@@ -336,8 +329,7 @@ def test_finetune_extra_model_args():
|
||||
output_dir = tempfile.mkdtemp(prefix="output_1_")
|
||||
args_d1 = args_d.copy()
|
||||
args_d1.update(
|
||||
model_name_or_path=model,
|
||||
output_dir=output_dir,
|
||||
model_name_or_path=model, output_dir=output_dir,
|
||||
)
|
||||
extra_model_params = ("encoder_layerdrop", "decoder_layerdrop", "dropout", "attention_dropout")
|
||||
for p in extra_model_params:
|
||||
@@ -352,8 +344,7 @@ def test_finetune_extra_model_args():
|
||||
output_dir = tempfile.mkdtemp(prefix="output_2_")
|
||||
args_d2 = args_d.copy()
|
||||
args_d2.update(
|
||||
model_name_or_path=model,
|
||||
output_dir=output_dir,
|
||||
model_name_or_path=model, output_dir=output_dir,
|
||||
)
|
||||
unsupported_param = "encoder_layerdrop"
|
||||
args_d2[unsupported_param] = 0.5
|
||||
@@ -440,20 +431,18 @@ def test_pack_dataset():
|
||||
assert orig_paths == new_paths
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
["tok_name"], [pytest.param(MBART_TINY), pytest.param(MARIAN_TINY), pytest.param(T5_TINY), pytest.param(BART_TINY)]
|
||||
)
|
||||
def test_seq2seq_dataset_truncation(tok_name):
|
||||
@pytest.mark.parametrize(["tok_name"], [pytest.param(MBART_TINY), pytest.param(MARIAN_TINY)])
|
||||
def test_mbart_dataset_truncation(tok_name):
|
||||
tokenizer = AutoTokenizer.from_pretrained(tok_name)
|
||||
tmp_dir = make_test_data_dir()
|
||||
max_len_source = max(len(tokenizer.encode(a)) for a in ARTICLES)
|
||||
max_len_target = max(len(tokenizer.encode(a)) for a in SUMMARIES)
|
||||
max_src_len = 4
|
||||
max_tgt_len = 8
|
||||
assert max_len_target > max_src_len # Will be truncated
|
||||
assert max_len_source > max_src_len # Will be truncated
|
||||
src_lang, tgt_lang = "ro_RO", "de_DE" # ignored for all but mbart, but never causes error.
|
||||
train_dataset = Seq2SeqDataset(
|
||||
assert max_len_target > max_src_len # Truncated
|
||||
assert max_len_source > max_src_len
|
||||
src_lang, tgt_lang = "ro_RO", "de_DE" # NOT WHAT IT WAS TRAINED ON
|
||||
train_dataset = TranslationDataset(
|
||||
tokenizer,
|
||||
data_dir=tmp_dir,
|
||||
type_path="train",
|
||||
@@ -469,11 +458,10 @@ def test_seq2seq_dataset_truncation(tok_name):
|
||||
# show that articles were trimmed.
|
||||
assert batch["input_ids"].shape[1] == max_src_len
|
||||
# show that targets are the same len
|
||||
assert batch["labels"].shape[1] == max_tgt_len
|
||||
if tok_name != MBART_TINY:
|
||||
assert batch["decoder_input_ids"].shape[1] == max_tgt_len
|
||||
if tok_name == MARIAN_TINY:
|
||||
continue
|
||||
# check language codes in correct place
|
||||
batch["decoder_input_ids"] = shift_tokens_right(batch["labels"], tokenizer.pad_token_id)
|
||||
assert batch["decoder_input_ids"][0, 0].item() == tokenizer.lang_code_to_id[tgt_lang]
|
||||
assert batch["decoder_input_ids"][0, -1].item() == tokenizer.eos_token_id
|
||||
assert batch["input_ids"][0, -2].item() == tokenizer.eos_token_id
|
||||
@@ -483,18 +471,14 @@ def test_seq2seq_dataset_truncation(tok_name):
|
||||
|
||||
|
||||
@pytest.mark.parametrize(["tok"], [pytest.param(T5_TINY), pytest.param(BART_TINY), param(MARIAN_TINY)])
|
||||
def test_legacy_dataset_truncation(tok):
|
||||
def test_summarization_dataset_truncation(tok):
|
||||
tokenizer = AutoTokenizer.from_pretrained(tok)
|
||||
tmp_dir = make_test_data_dir()
|
||||
max_len_source = max(len(tokenizer.encode(a)) for a in ARTICLES)
|
||||
max_len_target = max(len(tokenizer.encode(a)) for a in SUMMARIES)
|
||||
trunc_target = 4
|
||||
train_dataset = LegacySeq2SeqDataset(
|
||||
tokenizer,
|
||||
data_dir=tmp_dir,
|
||||
type_path="train",
|
||||
max_source_length=20,
|
||||
max_target_length=trunc_target,
|
||||
train_dataset = Seq2SeqDataset(
|
||||
tokenizer, data_dir=tmp_dir, type_path="train", max_source_length=20, max_target_length=trunc_target,
|
||||
)
|
||||
dataloader = DataLoader(train_dataset, batch_size=2, collate_fn=train_dataset.collate_fn)
|
||||
for batch in dataloader:
|
||||
|
||||
@@ -20,5 +20,5 @@ python finetune.py \
|
||||
--tokenizer_name facebook/bart-large \
|
||||
--warmup_steps 500 \
|
||||
--output_dir distilbart-cnn-12-6 \
|
||||
"$@"
|
||||
$@
|
||||
|
||||
@@ -18,4 +18,4 @@ python distillation.py \
|
||||
--tokenizer_name facebook/bart-large \
|
||||
--warmup_steps 500 \
|
||||
--output_dir distilbart_xsum_12_6 \
|
||||
"$@"
|
||||
$@
|
||||
@@ -15,4 +15,4 @@ python finetune.py \
|
||||
--warmup_steps 500 \
|
||||
--freeze_embeds \
|
||||
--model_name_or_path=facebook/mbart-large-cc25 \
|
||||
"$@"
|
||||
$@
|
||||
@@ -57,15 +57,13 @@ def lmap(f: Callable, x: Iterable) -> List:
|
||||
return list(map(f, x))
|
||||
|
||||
|
||||
def calculate_bleu(output_lns, refs_lns, **kwargs) -> dict:
|
||||
def calculate_bleu_score(output_lns, refs_lns, **kwargs) -> dict:
|
||||
"""Uses sacrebleu's corpus_bleu implementation."""
|
||||
return {"bleu": round(corpus_bleu(output_lns, [refs_lns], **kwargs).score, 4)}
|
||||
return {"bleu": corpus_bleu(output_lns, [refs_lns], **kwargs).score}
|
||||
|
||||
|
||||
def trim_batch(
|
||||
input_ids,
|
||||
pad_token_id,
|
||||
attention_mask=None,
|
||||
input_ids, pad_token_id, attention_mask=None,
|
||||
):
|
||||
"""Remove columns that are populated exclusively by pad_token_id"""
|
||||
keep_column_mask = input_ids.ne(pad_token_id).any(dim=0)
|
||||
@@ -75,7 +73,7 @@ def trim_batch(
|
||||
return (input_ids[:, keep_column_mask], attention_mask[:, keep_column_mask])
|
||||
|
||||
|
||||
class LegacySeq2SeqDataset(Dataset):
|
||||
class Seq2SeqDataset(Dataset):
|
||||
def __init__(
|
||||
self,
|
||||
tokenizer,
|
||||
@@ -146,7 +144,7 @@ class LegacySeq2SeqDataset(Dataset):
|
||||
return SortishSampler(self.src_lens, batch_size)
|
||||
|
||||
|
||||
class Seq2SeqDataset(LegacySeq2SeqDataset):
|
||||
class TranslationDataset(Seq2SeqDataset):
|
||||
"""A dataset that calls prepare_seq2seq_batch."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -176,7 +174,6 @@ class Seq2SeqDataset(LegacySeq2SeqDataset):
|
||||
tgt_lang=self.tgt_lang,
|
||||
max_length=self.max_source_length,
|
||||
max_target_length=self.max_target_length,
|
||||
return_tensors="pt",
|
||||
)
|
||||
return batch_encoding.data
|
||||
|
||||
@@ -274,7 +271,7 @@ def calculate_rouge(output_lns: List[str], reference_lns: List[str], use_stemmer
|
||||
aggregator.add_scores(scores)
|
||||
|
||||
result = aggregator.aggregate()
|
||||
return {k: round(v.mid.fmeasure * 100, 4) for k, v in result.items()}
|
||||
return {k: v.mid.fmeasure * 100 for k, v in result.items()}
|
||||
|
||||
|
||||
def freeze_params(model: nn.Module):
|
||||
|
||||
+27
-41
@@ -17,14 +17,13 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import torch
|
||||
|
||||
from transformers.file_utils import is_apex_available
|
||||
from transformers.testing_utils import TestCasePlus, torch_device
|
||||
|
||||
|
||||
SRC_DIRS = [
|
||||
os.path.join(os.path.dirname(__file__), dirname)
|
||||
@@ -36,8 +35,8 @@ sys.path.extend(SRC_DIRS)
|
||||
if SRC_DIRS is not None:
|
||||
import run_generation
|
||||
import run_glue
|
||||
import run_language_modeling
|
||||
import run_pl_glue
|
||||
import run_language_modeling
|
||||
import run_squad
|
||||
|
||||
|
||||
@@ -53,23 +52,19 @@ def get_setup_file():
|
||||
return args.f
|
||||
|
||||
|
||||
def is_cuda_and_apex_avaliable():
|
||||
is_using_cuda = torch.cuda.is_available() and torch_device == "cuda"
|
||||
return is_using_cuda and is_apex_available()
|
||||
def clean_test_dir(path):
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
|
||||
|
||||
class ExamplesTests(TestCasePlus):
|
||||
class ExamplesTests(unittest.TestCase):
|
||||
def test_run_glue(self):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
tmp_dir = self.get_auto_remove_tmp_dir()
|
||||
testargs = f"""
|
||||
testargs = """
|
||||
run_glue.py
|
||||
--model_name_or_path distilbert-base-uncased
|
||||
--data_dir ./tests/fixtures/tests_samples/MRPC/
|
||||
--output_dir {tmp_dir}
|
||||
--overwrite_output_dir
|
||||
--task_name mrpc
|
||||
--do_train
|
||||
--do_eval
|
||||
@@ -78,32 +73,28 @@ class ExamplesTests(TestCasePlus):
|
||||
--learning_rate=1e-4
|
||||
--max_steps=10
|
||||
--warmup_steps=2
|
||||
--overwrite_output_dir
|
||||
--seed=42
|
||||
--max_seq_length=128
|
||||
"""
|
||||
output_dir = "./tests/fixtures/tests_samples/temp_dir_{}".format(hash(testargs))
|
||||
testargs += "--output_dir " + output_dir
|
||||
testargs = testargs.split()
|
||||
|
||||
if is_cuda_and_apex_avaliable():
|
||||
testargs.append("--fp16")
|
||||
|
||||
with patch.object(sys, "argv", testargs):
|
||||
result = run_glue.main()
|
||||
del result["eval_loss"]
|
||||
for value in result.values():
|
||||
self.assertGreaterEqual(value, 0.75)
|
||||
clean_test_dir(output_dir)
|
||||
|
||||
def test_run_pl_glue(self):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
tmp_dir = self.get_auto_remove_tmp_dir()
|
||||
testargs = f"""
|
||||
testargs = """
|
||||
run_pl_glue.py
|
||||
--model_name_or_path bert-base-cased
|
||||
--data_dir ./tests/fixtures/tests_samples/MRPC/
|
||||
--output_dir {tmp_dir}
|
||||
--task mrpc
|
||||
--do_train
|
||||
--do_predict
|
||||
@@ -112,7 +103,11 @@ class ExamplesTests(TestCasePlus):
|
||||
--num_train_epochs=1
|
||||
--seed=42
|
||||
--max_seq_length=128
|
||||
""".split()
|
||||
"""
|
||||
output_dir = "./tests/fixtures/tests_samples/temp_dir_{}".format(hash(testargs))
|
||||
testargs += "--output_dir " + output_dir
|
||||
testargs = testargs.split()
|
||||
|
||||
if torch.cuda.is_available():
|
||||
testargs += ["--fp16", "--gpus=1"]
|
||||
|
||||
@@ -128,13 +123,13 @@ class ExamplesTests(TestCasePlus):
|
||||
# for k, v in result.items():
|
||||
# self.assertGreaterEqual(v, 0.75, f"({k})")
|
||||
#
|
||||
clean_test_dir(output_dir)
|
||||
|
||||
def test_run_language_modeling(self):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
tmp_dir = self.get_auto_remove_tmp_dir()
|
||||
testargs = f"""
|
||||
testargs = """
|
||||
run_language_modeling.py
|
||||
--model_name_or_path distilroberta-base
|
||||
--model_type roberta
|
||||
@@ -142,35 +137,29 @@ class ExamplesTests(TestCasePlus):
|
||||
--line_by_line
|
||||
--train_data_file ./tests/fixtures/sample_text.txt
|
||||
--eval_data_file ./tests/fixtures/sample_text.txt
|
||||
--output_dir {tmp_dir}
|
||||
--overwrite_output_dir
|
||||
--do_train
|
||||
--do_eval
|
||||
--num_train_epochs=1
|
||||
--no_cuda
|
||||
"""
|
||||
output_dir = "./tests/fixtures/tests_samples/temp_dir_{}".format(hash(testargs))
|
||||
testargs += "--output_dir " + output_dir
|
||||
testargs = testargs.split()
|
||||
|
||||
if torch_device != "cuda":
|
||||
testargs.append("--no_cuda")
|
||||
|
||||
with patch.object(sys, "argv", testargs):
|
||||
result = run_language_modeling.main()
|
||||
self.assertLess(result["perplexity"], 35)
|
||||
clean_test_dir(output_dir)
|
||||
|
||||
def test_run_squad(self):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
tmp_dir = self.get_auto_remove_tmp_dir()
|
||||
testargs = f"""
|
||||
testargs = """
|
||||
run_squad.py
|
||||
--model_type=distilbert
|
||||
--model_name_or_path=sshleifer/tiny-distilbert-base-cased-distilled-squad
|
||||
--data_dir=./tests/fixtures/tests_samples/SQUAD
|
||||
--output_dir {tmp_dir}
|
||||
--overwrite_output_dir
|
||||
--max_steps=10
|
||||
--warmup_steps=2
|
||||
--do_train
|
||||
@@ -179,27 +168,24 @@ class ExamplesTests(TestCasePlus):
|
||||
--learning_rate=2e-4
|
||||
--per_gpu_train_batch_size=2
|
||||
--per_gpu_eval_batch_size=1
|
||||
--overwrite_output_dir
|
||||
--seed=42
|
||||
""".split()
|
||||
|
||||
"""
|
||||
output_dir = "./tests/fixtures/tests_samples/temp_dir_{}".format(hash(testargs))
|
||||
testargs += "--output_dir " + output_dir
|
||||
testargs = testargs.split()
|
||||
with patch.object(sys, "argv", testargs):
|
||||
result = run_squad.main()
|
||||
self.assertGreaterEqual(result["f1"], 25)
|
||||
self.assertGreaterEqual(result["exact"], 21)
|
||||
clean_test_dir(output_dir)
|
||||
|
||||
def test_generation(self):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
testargs = ["run_generation.py", "--prompt=Hello", "--length=10", "--seed=42"]
|
||||
|
||||
if is_cuda_and_apex_avaliable():
|
||||
testargs.append("--fp16")
|
||||
|
||||
model_type, model_name = (
|
||||
"--model_type=gpt2",
|
||||
"--model_name_or_path=sshleifer/tiny-gpt2",
|
||||
)
|
||||
model_type, model_name = ("--model_type=gpt2", "--model_name_or_path=sshleifer/tiny-gpt2")
|
||||
with patch.object(sys, "argv", testargs + [model_type, model_name]):
|
||||
result = run_generation.main()
|
||||
self.assertGreaterEqual(len(result[0]), 10)
|
||||
@@ -269,7 +269,7 @@ on a single tesla V100 16GB. The data for XNLI can be downloaded with the follow
|
||||
`$XNLI_DIR` directory.
|
||||
|
||||
* [XNLI 1.0](https://www.nyu.edu/projects/bowman/xnli/XNLI-1.0.zip)
|
||||
* [XNLI-MT 1.0](https://dl.fbaipublicfiles.com/XNLI/XNLI-MT-1.0.zip)
|
||||
* [XNLI-MT 1.0](https://www.nyu.edu/projects/bowman/xnli/XNLI-MT-1.0.zip)
|
||||
|
||||
```bash
|
||||
export XNLI_DIR=/path/to/XNLI
|
||||
|
||||
@@ -75,7 +75,7 @@ class GLUETransformer(BaseTransformer):
|
||||
logger.info("Saving features into cached file %s", cached_features_file)
|
||||
torch.save(features, cached_features_file)
|
||||
|
||||
def get_dataloader(self, mode: str, batch_size: int, shuffle: bool = False) -> DataLoader:
|
||||
def get_dataloader(self, mode: int, batch_size: int, shuffle: bool = False) -> DataLoader:
|
||||
"Load datasets. Called after prepare data."
|
||||
|
||||
# We test on dev set to compare to benchmarks without having to submit to GLUE server
|
||||
@@ -153,11 +153,7 @@ class GLUETransformer(BaseTransformer):
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--task",
|
||||
default="",
|
||||
type=str,
|
||||
required=True,
|
||||
help="The GLUE task to run",
|
||||
"--task", default="", type=str, required=True, help="The GLUE task to run",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--gpus",
|
||||
@@ -165,6 +161,13 @@ class GLUETransformer(BaseTransformer):
|
||||
type=int,
|
||||
help="The number of GPUs allocated for this, it is by default 0 meaning none",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--data_dir",
|
||||
default=None,
|
||||
type=str,
|
||||
required=True,
|
||||
help="The input data dir. Should contain the training files for the CoNLL-2003 NER task.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--overwrite_cache", action="store_true", help="Overwrite the cached training and evaluation sets"
|
||||
@@ -181,10 +184,7 @@ def main():
|
||||
|
||||
# If output_dir not provided, a folder will be generated in pwd
|
||||
if args.output_dir is None:
|
||||
args.output_dir = os.path.join(
|
||||
"./results",
|
||||
f"{args.task}_{time.strftime('%Y%m%d_%H%M%S')}",
|
||||
)
|
||||
args.output_dir = os.path.join("./results", f"{args.task}_{time.strftime('%Y%m%d_%H%M%S')}",)
|
||||
os.makedirs(args.output_dir)
|
||||
|
||||
model = GLUETransformer(args)
|
||||
|
||||
@@ -328,11 +328,7 @@ def load_and_cache_examples(args, task, tokenizer, evaluate=False):
|
||||
processor.get_test_examples(args.data_dir) if evaluate else processor.get_train_examples(args.data_dir)
|
||||
)
|
||||
features = convert_examples_to_features(
|
||||
examples,
|
||||
tokenizer,
|
||||
max_length=args.max_seq_length,
|
||||
label_list=label_list,
|
||||
output_mode=output_mode,
|
||||
examples, tokenizer, max_length=args.max_seq_length, label_list=label_list, output_mode=output_mode,
|
||||
)
|
||||
if args.local_rank in [-1, 0]:
|
||||
logger.info("Saving features into cached file %s", cached_features_file)
|
||||
|
||||
@@ -698,9 +698,7 @@ def run_pplm_example(
|
||||
for word_id in pert_gen_tok_text.tolist()[0]:
|
||||
if word_id in bow_word_ids:
|
||||
pert_gen_text += "{}{}{}".format(
|
||||
colorama.Fore.RED,
|
||||
tokenizer.decode([word_id]),
|
||||
colorama.Style.RESET_ALL,
|
||||
colorama.Fore.RED, tokenizer.decode([word_id]), colorama.Style.RESET_ALL,
|
||||
)
|
||||
else:
|
||||
pert_gen_text += tokenizer.decode([word_id])
|
||||
@@ -731,10 +729,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("--cond_text", type=str, default="The lake", help="Prefix texts to condition on")
|
||||
parser.add_argument("--uncond", action="store_true", help="Generate from end-of-text as prefix")
|
||||
parser.add_argument(
|
||||
"--num_samples",
|
||||
type=int,
|
||||
default=1,
|
||||
help="Number of samples to generate from the modified latents",
|
||||
"--num_samples", type=int, default=1, help="Number of samples to generate from the modified latents",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--bag_of_words",
|
||||
@@ -756,22 +751,13 @@ if __name__ == "__main__":
|
||||
help="Discriminator to use",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--discrim_weights",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Weights for the generic discriminator",
|
||||
"--discrim_weights", type=str, default=None, help="Weights for the generic discriminator",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--discrim_meta",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Meta information for the generic discriminator",
|
||||
"--discrim_meta", type=str, default=None, help="Meta information for the generic discriminator",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--class_label",
|
||||
type=int,
|
||||
default=-1,
|
||||
help="Class label used for the discriminator",
|
||||
"--class_label", type=int, default=-1, help="Class label used for the discriminator",
|
||||
)
|
||||
parser.add_argument("--length", type=int, default=100)
|
||||
parser.add_argument("--stepsize", type=float, default=0.02)
|
||||
@@ -787,10 +773,7 @@ if __name__ == "__main__":
|
||||
help="Length of past which is being optimized; 0 corresponds to infinite window length",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--horizon_length",
|
||||
type=int,
|
||||
default=1,
|
||||
help="Length of future to optimize over",
|
||||
"--horizon_length", type=int, default=1, help="Length of future to optimize over",
|
||||
)
|
||||
parser.add_argument("--decay", action="store_true", help="whether to decay or not")
|
||||
parser.add_argument("--gamma", type=float, default=1.5)
|
||||
@@ -800,10 +783,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("--no_cuda", action="store_true", help="no cuda")
|
||||
parser.add_argument("--colorama", action="store_true", help="colors keywords")
|
||||
parser.add_argument(
|
||||
"--repetition_penalty",
|
||||
type=float,
|
||||
default=1.0,
|
||||
help="Penalize repetition. More than 1.0 -> less repetition",
|
||||
"--repetition_penalty", type=float, default=1.0, help="Penalize repetition. More than 1.0 -> less repetition",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -242,12 +242,7 @@ def train_discriminator(
|
||||
|
||||
text = torchtext_data.Field()
|
||||
label = torchtext_data.Field(sequential=False)
|
||||
train_data, val_data, test_data = datasets.SST.splits(
|
||||
text,
|
||||
label,
|
||||
fine_grained=True,
|
||||
train_subtrees=True,
|
||||
)
|
||||
train_data, val_data, test_data = datasets.SST.splits(text, label, fine_grained=True, train_subtrees=True,)
|
||||
|
||||
x = []
|
||||
y = []
|
||||
|
||||
@@ -41,9 +41,7 @@ from transformers import (
|
||||
|
||||
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
|
||||
datefmt="%m/%d/%Y %H:%M:%S",
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", datefmt="%m/%d/%Y %H:%M:%S", level=logging.INFO,
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -188,23 +186,11 @@ def main():
|
||||
parser.add_argument("--seed", type=int, default=42, help="random seed for initialization")
|
||||
parser.add_argument("--no_cuda", action="store_true", help="Avoid using CUDA when available")
|
||||
parser.add_argument("--num_return_sequences", type=int, default=1, help="The number of samples to generate.")
|
||||
parser.add_argument(
|
||||
"--fp16",
|
||||
action="store_true",
|
||||
help="Whether to use 16-bit (mixed) precision (through NVIDIA apex) instead of 32-bit",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
args.device = torch.device("cuda" if torch.cuda.is_available() and not args.no_cuda else "cpu")
|
||||
args.n_gpu = 0 if args.no_cuda else torch.cuda.device_count()
|
||||
|
||||
logger.warning(
|
||||
"device: %s, n_gpu: %s, 16-bits training: %s",
|
||||
args.device,
|
||||
args.n_gpu,
|
||||
args.fp16,
|
||||
)
|
||||
|
||||
set_seed(args)
|
||||
|
||||
# Initialize the model and tokenizer
|
||||
@@ -218,9 +204,6 @@ def main():
|
||||
model = model_class.from_pretrained(args.model_name_or_path)
|
||||
model.to(args.device)
|
||||
|
||||
if args.fp16:
|
||||
model.half()
|
||||
|
||||
args.length = adjust_length_to_model(args.length, max_sequence_length=model.config.max_position_embeddings)
|
||||
logger.info(args)
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
## The relevant files are currently on a shared Google
|
||||
## drive at https://drive.google.com/drive/folders/1kC0I2UGl2ltrluI9NqDjaQJGw5iliw_J
|
||||
## Monitor for changes and eventually migrate to nlp dataset
|
||||
curl -L 'https://drive.google.com/uc?export=download&id=1Jjhbal535VVz2ap4v4r_rN1UEHTdLK5P' \
|
||||
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-train.tsv?attredirects=0&d=1' \
|
||||
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > train.txt.tmp
|
||||
curl -L 'https://drive.google.com/uc?export=download&id=1ZfRcQThdtAR5PPRjIDtrVP7BtXSCUBbm' \
|
||||
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-dev.tsv?attredirects=0&d=1' \
|
||||
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > dev.txt.tmp
|
||||
curl -L 'https://drive.google.com/uc?export=download&id=1u9mb7kNJHWQCWyweMDRMuTFoOHOfeBTH' \
|
||||
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-test.tsv?attredirects=0&d=1' \
|
||||
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > test.txt.tmp
|
||||
|
||||
export MAX_LENGTH=128
|
||||
|
||||
@@ -3,14 +3,11 @@
|
||||
# for seqeval metrics import
|
||||
pip install -r ../requirements.txt
|
||||
|
||||
## The relevant files are currently on a shared Google
|
||||
## drive at https://drive.google.com/drive/folders/1kC0I2UGl2ltrluI9NqDjaQJGw5iliw_J
|
||||
## Monitor for changes and eventually migrate to nlp dataset
|
||||
curl -L 'https://drive.google.com/uc?export=download&id=1Jjhbal535VVz2ap4v4r_rN1UEHTdLK5P' \
|
||||
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-train.tsv?attredirects=0&d=1' \
|
||||
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > train.txt.tmp
|
||||
curl -L 'https://drive.google.com/uc?export=download&id=1ZfRcQThdtAR5PPRjIDtrVP7BtXSCUBbm' \
|
||||
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-dev.tsv?attredirects=0&d=1' \
|
||||
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > dev.txt.tmp
|
||||
curl -L 'https://drive.google.com/uc?export=download&id=1u9mb7kNJHWQCWyweMDRMuTFoOHOfeBTH' \
|
||||
curl -L 'https://sites.google.com/site/germeval2014ner/data/NER-de-test.tsv?attredirects=0&d=1' \
|
||||
| grep -v "^#" | cut -f 2,3 | tr '\t' ' ' > test.txt.tmp
|
||||
|
||||
export MAX_LENGTH=128
|
||||
@@ -32,6 +29,7 @@ mkdir -p $OUTPUT_DIR
|
||||
export PYTHONPATH="../":"${PYTHONPATH}"
|
||||
|
||||
python3 run_pl_ner.py --data_dir ./ \
|
||||
--model_type bert \
|
||||
--labels ./labels.txt \
|
||||
--model_name_or_path $BERT_MODEL \
|
||||
--output_dir $OUTPUT_DIR \
|
||||
@@ -39,6 +37,5 @@ python3 run_pl_ner.py --data_dir ./ \
|
||||
--num_train_epochs $NUM_EPOCHS \
|
||||
--train_batch_size $BATCH_SIZE \
|
||||
--seed $SEED \
|
||||
--gpus 1 \
|
||||
--do_train \
|
||||
--do_predict
|
||||
@@ -86,7 +86,7 @@ class NERTransformer(BaseTransformer):
|
||||
logger.info("Saving features into cached file %s", cached_features_file)
|
||||
torch.save(features, cached_features_file)
|
||||
|
||||
def get_dataloader(self, mode: int, batch_size: int, shuffle: bool = False) -> DataLoader:
|
||||
def get_dataloader(self, mode: int, batch_size: int) -> DataLoader:
|
||||
"Load datasets. Called after prepare data."
|
||||
cached_features_file = self._feature_file(mode)
|
||||
logger.info("Loading features from cached file %s", cached_features_file)
|
||||
@@ -104,7 +104,8 @@ class NERTransformer(BaseTransformer):
|
||||
)
|
||||
|
||||
def validation_step(self, batch, batch_nb):
|
||||
"""Compute validation""" ""
|
||||
"Compute validation"
|
||||
|
||||
inputs = {"input_ids": batch[0], "attention_mask": batch[1], "labels": batch[3]}
|
||||
if self.config.model_type != "distilbert":
|
||||
inputs["token_type_ids"] = (
|
||||
@@ -190,6 +191,14 @@ class NERTransformer(BaseTransformer):
|
||||
help="The number of GPUs allocated for this, it is by default 0 meaning none",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--data_dir",
|
||||
default=None,
|
||||
type=str,
|
||||
required=True,
|
||||
help="The input data dir. Should contain the training files for the CoNLL-2003 NER task.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--overwrite_cache", action="store_true", help="Overwrite the cached training and evaluation sets"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,6 @@ import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import run_ner
|
||||
from transformers.testing_utils import slow
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
@@ -13,7 +12,6 @@ logger = logging.getLogger()
|
||||
|
||||
|
||||
class ExamplesTests(unittest.TestCase):
|
||||
@slow
|
||||
def test_run_ner(self):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
logger.addHandler(stream_handler)
|
||||
@@ -33,23 +31,3 @@ class ExamplesTests(unittest.TestCase):
|
||||
with patch.object(sys, "argv", ["run.py"] + testargs):
|
||||
result = run_ner.main()
|
||||
self.assertLess(result["eval_loss"], 1.5)
|
||||
|
||||
def test_run_ner_pl(self):
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
logger.addHandler(stream_handler)
|
||||
|
||||
testargs = """
|
||||
--model_name distilbert-base-german-cased
|
||||
--output_dir ./tests/fixtures/tests_samples/temp_dir
|
||||
--overwrite_output_dir
|
||||
--data_dir ./tests/fixtures/tests_samples/GermEval
|
||||
--labels ./tests/fixtures/tests_samples/GermEval/labels.txt
|
||||
--max_seq_length 128
|
||||
--num_train_epochs 6
|
||||
--logging_steps 1
|
||||
--do_train
|
||||
--do_eval
|
||||
""".split()
|
||||
with patch.object(sys, "argv", ["run.py"] + testargs):
|
||||
result = run_ner.main()
|
||||
self.assertLess(result["eval_loss"], 1.5)
|
||||
@@ -23,6 +23,7 @@ from enum import Enum
|
||||
from typing import List, Optional, Union
|
||||
|
||||
from filelock import FileLock
|
||||
|
||||
from transformers import PreTrainedTokenizer, is_tf_available, is_torch_available
|
||||
|
||||
|
||||
@@ -90,11 +91,11 @@ class TokenClassificationTask:
|
||||
sequence_a_segment_id=0,
|
||||
mask_padding_with_zero=True,
|
||||
) -> List[InputFeatures]:
|
||||
"""Loads a data file into a list of `InputFeatures`
|
||||
`cls_token_at_end` define the location of the CLS token:
|
||||
- False (Default, BERT/XLM pattern): [CLS] + A + [SEP] + B + [SEP]
|
||||
- True (XLNet/GPT pattern): A + [SEP] + B + [SEP] + [CLS]
|
||||
`cls_token_segment_id` define the segment id associated to the CLS token (0 for BERT, 2 for XLNet)
|
||||
""" Loads a data file into a list of `InputFeatures`
|
||||
`cls_token_at_end` define the location of the CLS token:
|
||||
- False (Default, BERT/XLM pattern): [CLS] + A + [SEP] + B + [SEP]
|
||||
- True (XLNet/GPT pattern): A + [SEP] + B + [SEP] + [CLS]
|
||||
`cls_token_segment_id` define the segment id associated to the CLS token (0 for BERT, 2 for XLNet)
|
||||
"""
|
||||
# TODO clean up all this to leverage built-in features of tokenizers
|
||||
|
||||
@@ -230,8 +231,7 @@ if is_torch_available():
|
||||
):
|
||||
# Load data features from cache or dataset file
|
||||
cached_features_file = os.path.join(
|
||||
data_dir,
|
||||
"cached_{}_{}_{}".format(mode.value, tokenizer.__class__.__name__, str(max_seq_length)),
|
||||
data_dir, "cached_{}_{}_{}".format(mode.value, tokenizer.__class__.__name__, str(max_seq_length)),
|
||||
)
|
||||
|
||||
# Make sure only the first process in distributed training processes the dataset,
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
language: "id"
|
||||
license: "mit"
|
||||
datasets:
|
||||
- Indonesian Wikipedia
|
||||
widget:
|
||||
- text: "Ibu ku sedang bekerja [MASK] supermarket."
|
||||
---
|
||||
|
||||
# Indonesian BERT base model (uncased)
|
||||
|
||||
## Model description
|
||||
It is BERT-base model pre-trained with indonesian Wikipedia using a masked language modeling (MLM) objective. This
|
||||
model is uncased: it does not make a difference between indonesia and Indonesia.
|
||||
|
||||
This is one of several other language models that have been pre-trained with indonesian datasets. More detail about
|
||||
its usage on downstream tasks (text classification, text generation, etc) is available at [Transformer based Indonesian Language Models](https://github.com/cahya-wirawan/indonesian-language-models/tree/master/Transformers)
|
||||
|
||||
## Intended uses & limitations
|
||||
|
||||
### How to use
|
||||
You can use this model directly with a pipeline for masked language modeling:
|
||||
```python
|
||||
>>> from transformers import pipeline
|
||||
>>> unmasker = pipeline('fill-mask', model='cahya/bert-base-indonesian-522M')
|
||||
>>> unmasker("Ibu ku sedang bekerja [MASK] supermarket")
|
||||
|
||||
[{'sequence': '[CLS] ibu ku sedang bekerja di supermarket [SEP]',
|
||||
'score': 0.7983310222625732,
|
||||
'token': 1495},
|
||||
{'sequence': '[CLS] ibu ku sedang bekerja. supermarket [SEP]',
|
||||
'score': 0.090003103017807,
|
||||
'token': 17},
|
||||
{'sequence': '[CLS] ibu ku sedang bekerja sebagai supermarket [SEP]',
|
||||
'score': 0.025469014421105385,
|
||||
'token': 1600},
|
||||
{'sequence': '[CLS] ibu ku sedang bekerja dengan supermarket [SEP]',
|
||||
'score': 0.017966199666261673,
|
||||
'token': 1555},
|
||||
{'sequence': '[CLS] ibu ku sedang bekerja untuk supermarket [SEP]',
|
||||
'score': 0.016971781849861145,
|
||||
'token': 1572}]
|
||||
```
|
||||
Here is how to use this model to get the features of a given text in PyTorch:
|
||||
```python
|
||||
from transformers import BertTokenizer, BertModel
|
||||
|
||||
model_name='cahya/bert-base-indonesian-522M'
|
||||
tokenizer = BertTokenizer.from_pretrained(model_name)
|
||||
model = BertModel.from_pretrained(model_name)
|
||||
text = "Silakan diganti dengan text apa saja."
|
||||
encoded_input = tokenizer(text, return_tensors='pt')
|
||||
output = model(**encoded_input)
|
||||
```
|
||||
and in Tensorflow:
|
||||
```python
|
||||
from transformers import BertTokenizer, TFBertModel
|
||||
|
||||
model_name='cahya/bert-base-indonesian-522M'
|
||||
tokenizer = BertTokenizer.from_pretrained(model_name)
|
||||
model = TFBertModel.from_pretrained(model_name)
|
||||
text = "Silakan diganti dengan text apa saja."
|
||||
encoded_input = tokenizer(text, return_tensors='tf')
|
||||
output = model(encoded_input)
|
||||
```
|
||||
|
||||
## Training data
|
||||
|
||||
This model was pre-trained with 522MB of indonesian Wikipedia.
|
||||
The texts are lowercased and tokenized using WordPiece and a vocabulary size of 32,000. The inputs of the model are
|
||||
then of the form:
|
||||
|
||||
```[CLS] Sentence A [SEP] Sentence B [SEP]```
|
||||
@@ -1,64 +0,0 @@
|
||||
---
|
||||
language: "id"
|
||||
license: "mit"
|
||||
datasets:
|
||||
- Indonesian Wikipedia
|
||||
widget:
|
||||
- text: "Pulau Dewata sering dikunjungi"
|
||||
---
|
||||
|
||||
# Indonesian GPT2 small model
|
||||
|
||||
## Model description
|
||||
It is GPT2-small model pre-trained with indonesian Wikipedia using a causal language modeling (CLM) objective. This
|
||||
model is uncased: it does not make a difference between indonesia and Indonesia.
|
||||
|
||||
This is one of several other language models that have been pre-trained with indonesian datasets. More detail about
|
||||
its usage on downstream tasks (text classification, text generation, etc) is available at [Transformer based Indonesian Language Models](https://github.com/cahya-wirawan/indonesian-language-models/tree/master/Transformers)
|
||||
|
||||
## Intended uses & limitations
|
||||
|
||||
### How to use
|
||||
You can use this model directly with a pipeline for text generation. Since the generation relies on some randomness,
|
||||
we set a seed for reproducibility:
|
||||
```python
|
||||
>>> from transformers import pipeline, set_seed
|
||||
>>> generator = pipeline('text-generation', model='cahya/gpt2-small-indonesian-522M')
|
||||
>>> set_seed(42)
|
||||
>>> generator("Kerajaan Majapahit adalah", max_length=30, num_return_sequences=5, num_beams=10)
|
||||
|
||||
[{'generated_text': 'Kerajaan Majapahit adalah sebuah kerajaan yang pernah berdiri di Jawa Timur pada abad ke-14 hingga abad ke-15. Kerajaan ini berdiri pada abad ke-14'},
|
||||
{'generated_text': 'Kerajaan Majapahit adalah sebuah kerajaan yang pernah berdiri di Jawa Timur pada abad ke-14 hingga abad ke-16. Kerajaan ini berdiri pada abad ke-14'},
|
||||
{'generated_text': 'Kerajaan Majapahit adalah sebuah kerajaan yang pernah berdiri di Jawa Timur pada abad ke-14 hingga abad ke-15. Kerajaan ini berdiri pada abad ke-15'},
|
||||
{'generated_text': 'Kerajaan Majapahit adalah sebuah kerajaan yang pernah berdiri di Jawa Timur pada abad ke-14 hingga abad ke-16. Kerajaan ini berdiri pada abad ke-15'},
|
||||
{'generated_text': 'Kerajaan Majapahit adalah sebuah kerajaan yang pernah berdiri di Jawa Timur pada abad ke-14 hingga abad ke-15. Kerajaan ini merupakan kelanjutan dari Kerajaan Majapahit yang'}]
|
||||
|
||||
```
|
||||
Here is how to use this model to get the features of a given text in PyTorch:
|
||||
```python
|
||||
from transformers import GPT2Tokenizer, GPT2Model
|
||||
|
||||
model_name='cahya/gpt2-small-indonesian-522M'
|
||||
tokenizer = GPT2Tokenizer.from_pretrained(model_name)
|
||||
model = GPT2Model.from_pretrained(model_name)
|
||||
text = "Silakan diganti dengan text apa saja."
|
||||
encoded_input = tokenizer(text, return_tensors='pt')
|
||||
output = model(**encoded_input)
|
||||
```
|
||||
and in Tensorflow:
|
||||
```python
|
||||
from transformers import GPT2Tokenizer, TFGPT2Model
|
||||
|
||||
model_name='cahya/gpt2-small-indonesian-522M'
|
||||
tokenizer = GPT2Tokenizer.from_pretrained(model_name)
|
||||
model = TFGPT2Model.from_pretrained(model_name)
|
||||
text = "Silakan diganti dengan text apa saja."
|
||||
encoded_input = tokenizer(text, return_tensors='tf')
|
||||
output = model(encoded_input)
|
||||
```
|
||||
|
||||
## Training data
|
||||
|
||||
This model was pre-trained with 522MB of indonesian Wikipedia.
|
||||
The texts are tokenized using a byte-level version of Byte Pair Encoding (BPE) (for unicode characters) and
|
||||
a vocabulary size of 52,000. The inputs are sequences of 128 consecutive tokens.
|
||||
@@ -1,58 +0,0 @@
|
||||
---
|
||||
language: "id"
|
||||
license: "mit"
|
||||
datasets:
|
||||
- Indonesian Wikipedia
|
||||
widget:
|
||||
- text: "Ibu ku sedang bekerja <mask> supermarket."
|
||||
---
|
||||
|
||||
# Indonesian RoBERTa base model (uncased)
|
||||
|
||||
## Model description
|
||||
It is RoBERTa-base model pre-trained with indonesian Wikipedia using a masked language modeling (MLM) objective. This
|
||||
model is uncased: it does not make a difference between indonesia and Indonesia.
|
||||
|
||||
This is one of several other language models that have been pre-trained with indonesian datasets. More detail about
|
||||
its usage on downstream tasks (text classification, text generation, etc) is available at [Transformer based Indonesian Language Models](https://github.com/cahya-wirawan/indonesian-language-models/tree/master/Transformers)
|
||||
|
||||
## Intended uses & limitations
|
||||
|
||||
### How to use
|
||||
You can use this model directly with a pipeline for masked language modeling:
|
||||
```python
|
||||
>>> from transformers import pipeline
|
||||
>>> unmasker = pipeline('fill-mask', model='cahya/roberta-base-indonesian-522M')
|
||||
>>> unmasker("Ibu ku sedang bekerja <mask> supermarket")
|
||||
|
||||
```
|
||||
Here is how to use this model to get the features of a given text in PyTorch:
|
||||
```python
|
||||
from transformers import RobertaTokenizer, RobertaModel
|
||||
|
||||
model_name='cahya/roberta-base-indonesian-522M'
|
||||
tokenizer = RobertaTokenizer.from_pretrained(model_name)
|
||||
model = RobertaModel.from_pretrained(model_name)
|
||||
text = "Silakan diganti dengan text apa saja."
|
||||
encoded_input = tokenizer(text, return_tensors='pt')
|
||||
output = model(**encoded_input)
|
||||
```
|
||||
and in Tensorflow:
|
||||
```python
|
||||
from transformers import RobertaTokenizer, TFRobertaModel
|
||||
|
||||
model_name='cahya/roberta-base-indonesian-522M'
|
||||
tokenizer = RobertaTokenizer.from_pretrained(model_name)
|
||||
model = TFRobertaModel.from_pretrained(model_name)
|
||||
text = "Silakan diganti dengan text apa saja."
|
||||
encoded_input = tokenizer(text, return_tensors='tf')
|
||||
output = model(encoded_input)
|
||||
```
|
||||
|
||||
## Training data
|
||||
|
||||
This model was pre-trained with 522MB of indonesian Wikipedia.
|
||||
The texts are lowercased and tokenized using WordPiece and a vocabulary size of 32,000. The inputs of the model are
|
||||
then of the form:
|
||||
|
||||
```<s> Sentence A </s> Sentence B </s>```
|
||||
@@ -4,7 +4,9 @@ tags:
|
||||
- conversational
|
||||
widget:
|
||||
- text: "bonjour."
|
||||
widget:
|
||||
- text: "mais encore"
|
||||
widget:
|
||||
- text: "est ce que l'argent achete le bonheur?"
|
||||
---
|
||||
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
---
|
||||
language: de
|
||||
license: mit
|
||||
thumbnail: "https://raw.githubusercontent.com/German-NLP-Group/german-transformer-training/master/model_cards/german-electra-logo.png"
|
||||
tags:
|
||||
- electra
|
||||
- commoncrawl
|
||||
- uncased
|
||||
- umlaute
|
||||
---
|
||||
|
||||
# German Electra Uncased
|
||||
<img width="300px" src="https://raw.githubusercontent.com/German-NLP-Group/german-transformer-training/master/model_cards/german-electra-logo.png">
|
||||
[¹]
|
||||
|
||||
|
||||
# Model Info
|
||||
|
||||
This Model is suitable for Training on many downstream tasks in German (Q&A, Sentiment Analysis, etc.).
|
||||
|
||||
It can be used as a drop-in Replacement for **BERT** in most down-stream tasks (**ELECTRA** is even implemented as an extended **BERT** Class).
|
||||
|
||||
At the time of release (August 2020) this Model is the best performing publicly available German NLP Model on various German Evaluation Metrics (CONLL03-DE, GermEval18 Coarse, GermEval18 Fine). For GermEval18 Coarse results see below. More will be published soon.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
---
|
||||
This model is **uncased** but does not use **strip accents**.
|
||||
The necessary parameter is `strip_accents=False`.
|
||||
|
||||
This needs to be set for the tokenizer otherwise the model will perform slightly worse.
|
||||
It was added to Transformers with [PR #6280](https://github.com/huggingface/transformers/pull/6280).
|
||||
|
||||
Since Transformers has not been released since the PR #6280 was merged, you have to install directly from source:
|
||||
|
||||
`pip install git+https://github.com/huggingface/transformers.git -U`
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Uncase and Umlauts ('Ö', 'Ä', 'Ü')
|
||||
This model is uncased. This helps especially for domains where colloquial terms with uncorrect capitalization is often used.
|
||||
|
||||
The special characters 'ö', 'ü', 'ä' are included through the `strip_accent=False` option, as this leads to an improved precision.
|
||||
|
||||
## Creators
|
||||
This model was trained and open sourced in conjunction with the [**German NLP Group**](https://github.com/German-NLP-Group) in equal parts by:
|
||||
- [**Philip May**](https://eniak.de) - [T-Systems on site services GmbH](https://www.t-systems-onsite.de/)
|
||||
- [**Philipp Reißel**](https://www.reissel.eu) - [ambeRoad](https://amberoad.de/)
|
||||
|
||||
## Evaluation: GermEval18 Coarse
|
||||
|
||||
| Model Name |</br>F1 macro<br/> Mean | </br>F1 macro<br/>Median | </br>F1 macro<br/>Std |
|
||||
|---|---|---|---|
|
||||
| <span style="color:red">**ELECTRA-base-german-uncased** (this model) | <span style="color:red">**0.778** | **0.778** | **0.00392** |
|
||||
| dbmdz/bert-base-german-uncased | 0.770 | 0.770 | 0.00572 |
|
||||
| dbmdz/bert-base-german-cased | 0.765 | 0.765 | 0.00523 |
|
||||
| bert-base-german-cased | 0.762 | 0.761 | 0.00597 |
|
||||
| distilbert-base-german-cased | 0.752 | 0.752 | 0.00341 |
|
||||
| dbmdz/electra-base-german-europeana-cased-discriminator | 0.745 | 0.745 | 0.00498 |
|
||||
| dbmdz-bert-base-german-europeana-uncased | 0.736 | 0.737 | 0.00476 |
|
||||
| dbmdz-bert-base-german-europeana-cased | 0.727 | 0.729 | 0.00674 |
|
||||
|
||||
- (1): Hyperparameters taken from the [FARM project](https://farm.deepset.ai/) "[germEval18Coarse_config.json](https://github.com/deepset-ai/FARM/blob/master/experiments/german-bert2.0-eval/germEval18Coarse_config.json)"
|
||||
|
||||

|
||||
|
||||
## Checkpoint evaluation
|
||||
Since it it not guaranteed that the last checkpoint is the best, we evaluated the checkpoints on GermEval18. We found that the last checkpoint is indeed the best. The training was stable and did not overfit the text corpus. Below is a boxplot chart showing the different checkpoints.
|
||||
|
||||

|
||||
|
||||
## Pre-training details
|
||||
|
||||
### Data
|
||||
- Cleaned Common Crawl Corpus 2019-09 German: [CC_net](https://github.com/facebookresearch/cc_net) (Only head coprus and filtered for language_score > 0.98) - 62 GB
|
||||
- German Wikipedia Article Pages Dump (20200701) - 5.5 GB
|
||||
- German Wikipedia Talk Pages Dump (20200620) - 1.1 GB
|
||||
- Subtitles - 823 MB
|
||||
- News 2018 - 4.1 GB
|
||||
|
||||
The sentences were split with [SojaMo](https://github.com/tsproisl/SoMaJo). We took the German Wikipedia Article Pages Dump 3x to oversample. This approach was also used in a similar way in GPT-3 (Table 2.2).
|
||||
|
||||
More Details can be found here [Preperaing Datasets for German Electra Github](https://github.com/German-NLP-Group/german-transformer-training)
|
||||
|
||||
### Electra Branch no_strip_accents
|
||||
Because we do not want to stip accents in our training data we made a change to Electra and used this repo [Electra no_strip_accents](https://github.com/PhilipMay/electra/tree/no_strip_accents) (branch `no_strip_accents`). Then created the tf dataset with:
|
||||
|
||||
```bash
|
||||
python build_pretraining_dataset.py --corpus-dir <corpus_dir> --vocab-file <dir>/vocab.txt --output-dir ./tf_data --max-seq-length 512 --num-processes 8 --do-lower-case --no-strip-accents
|
||||
```
|
||||
|
||||
## The training
|
||||
|
||||
The training itself can be performed with the Original Electra Repo (No special case for this needed).
|
||||
We run it with the following Config:
|
||||
|
||||
|
||||
<details>
|
||||
<summary>The exact Training Config</summary>
|
||||
<br/>debug False
|
||||
<br/>disallow_correct False
|
||||
<br/>disc_weight 50.0
|
||||
<br/>do_eval False
|
||||
<br/>do_lower_case True
|
||||
<br/>do_train True
|
||||
<br/>electra_objective True
|
||||
<br/>embedding_size 768
|
||||
<br/>eval_batch_size 128
|
||||
<br/>gcp_project None
|
||||
<br/>gen_weight 1.0
|
||||
<br/>generator_hidden_size 0.33333
|
||||
<br/>generator_layers 1.0
|
||||
<br/>iterations_per_loop 200
|
||||
<br/>keep_checkpoint_max 0
|
||||
<br/>learning_rate 0.0002
|
||||
<br/>lr_decay_power 1.0
|
||||
<br/>mask_prob 0.15
|
||||
<br/>max_predictions_per_seq 79
|
||||
<br/>max_seq_length 512
|
||||
<br/>model_dir gs://XXX
|
||||
<br/>model_hparam_overrides {}
|
||||
<br/>model_name 02_Electra_Checkpoints_32k_766k_Combined
|
||||
<br/>model_size base
|
||||
<br/>num_eval_steps 100
|
||||
<br/>num_tpu_cores 8
|
||||
<br/>num_train_steps 766000
|
||||
<br/>num_warmup_steps 10000
|
||||
<br/>pretrain_tfrecords gs://XXX
|
||||
<br/>results_pkl gs://XXX
|
||||
<br/>results_txt gs://XXX
|
||||
<br/>save_checkpoints_steps 5000
|
||||
<br/>temperature 1.0
|
||||
<br/>tpu_job_name None
|
||||
<br/>tpu_name electrav5
|
||||
<br/>tpu_zone None
|
||||
<br/>train_batch_size 256
|
||||
<br/>uniform_generator False
|
||||
<br/>untied_generator True
|
||||
<br/>untied_generator_embeddings False
|
||||
<br/>use_tpu True
|
||||
<br/>vocab_file gs://XXX
|
||||
<br/>vocab_size 32767
|
||||
<br/>weight_decay_rate 0.01
|
||||
|
||||
</details>
|
||||
|
||||

|
||||
|
||||
Please Note: *Due to the GAN like strucutre of Electra the loss is not that meaningful*
|
||||
|
||||
It took about 7 Days on a preemtible TPU V3-8. In total, the Model went through approximately 10 Epochs. For an automatically recreation of a cancelled TPUs we used [tpunicorn](https://github.com/shawwn/tpunicorn). The total cost of training summed up to about 450 $ for one run. The Data-pre processing and Vocab Creation needed approximately 500-1000 CPU hours. Servers were fully provided by [T-Systems on site services GmbH](https://www.t-systems-onsite.de/), [ambeRoad](https://amberoad.de/).
|
||||
Special thanks to [Stefan Schweter](https://github.com/stefan-it) for your feedback and providing parts of the text corpus.
|
||||
|
||||
[¹]: Source for the picture [Pinterest](https://www.pinterest.cl/pin/371828512984142193/)
|
||||
|
||||
## Negative Results
|
||||
We tried the following approaches which we found had no positive influence:
|
||||
|
||||
- **Increased Vocab Size**: Leads to more parameters and thus reduced examples/sec while no visible Performance gains were measured
|
||||
- **Decreased Batch-Size**: The original Electra was trained with a Batch Size per TPU Core of 16 whereas this Model was trained with 32 BS / TPU Core. We found out that 32 BS leads to better results when you compare metrics over computation time
|
||||
@@ -1,96 +0,0 @@
|
||||
---
|
||||
language: fr
|
||||
widget:
|
||||
- text: "Face à un choc inédit, les mesures mises en place par le gouvernement ont permis une protection forte et efficace des ménages"
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The *french-camembert-postag-model* is a part of speech tagging model for French that was trained on the *free-french-treebank* dataset available on
|
||||
[github](https://github.com/nicolashernandez/free-french-treebank). The base tokenizer and model used for training is *'camembert-base'*.
|
||||
|
||||
## Supported Tags
|
||||
|
||||
It uses the following tags:
|
||||
|
||||
| Tag | Category | Extra Info |
|
||||
|----------|:------------------------------:|------------:|
|
||||
| ADJ | adjectif | |
|
||||
| ADJWH | adjectif | |
|
||||
| ADV | adverbe | |
|
||||
| ADVWH | adverbe | |
|
||||
| CC | conjonction de coordination | |
|
||||
| CLO | pronom | obj |
|
||||
| CLR | pronom | refl |
|
||||
| CLS | pronom | suj |
|
||||
| CS | conjonction de subordination | |
|
||||
| DET | déterminant | |
|
||||
| DETWH | déterminant | |
|
||||
| ET | mot étranger | |
|
||||
| I | interjection | |
|
||||
| NC | nom commun | |
|
||||
| NPP | nom propre | |
|
||||
| P | préposition | |
|
||||
| P+D | préposition + déterminant | |
|
||||
| PONCT | signe de ponctuation | |
|
||||
| PREF | préfixe | |
|
||||
| PRO | autres pronoms | |
|
||||
| PROREL | autres pronoms | rel |
|
||||
| PROWH | autres pronoms | int |
|
||||
| U | ? | |
|
||||
| V | verbe | |
|
||||
| VIMP | verbe imperatif | |
|
||||
| VINF | verbe infinitif | |
|
||||
| VPP | participe passé | |
|
||||
| VPR | participe présent | |
|
||||
| VS | subjonctif | |
|
||||
|
||||
More information on the tags can be found here:
|
||||
|
||||
http://alpage.inria.fr/statgram/frdep/Publications/crabbecandi-taln2008-final.pdf
|
||||
|
||||
## Usage
|
||||
|
||||
The usage of this model follows the common transformers patterns. Here is a short example of its usage:
|
||||
|
||||
```python
|
||||
from transformers import AutoTokenizer, AutoModelForTokenClassification
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("gilf/french-camembert-postag-model")
|
||||
model = AutoModelForTokenClassification.from_pretrained("gilf/french-camembert-postag-model")
|
||||
|
||||
from transformers import pipeline
|
||||
|
||||
nlp_token_class = pipeline('ner', model=model, tokenizer=tokenizer, grouped_entities=True)
|
||||
|
||||
nlp_token_class('Face à un choc inédit, les mesures mises en place par le gouvernement ont permis une protection forte et efficace des ménages')
|
||||
```
|
||||
|
||||
The lines above would display something like this on a Jupyter notebook:
|
||||
|
||||
```
|
||||
[{'entity_group': 'NC', 'score': 0.5760144591331482, 'word': '<s>'},
|
||||
{'entity_group': 'U', 'score': 0.9946700930595398, 'word': 'Face'},
|
||||
{'entity_group': 'P', 'score': 0.999615490436554, 'word': 'à'},
|
||||
{'entity_group': 'DET', 'score': 0.9995906352996826, 'word': 'un'},
|
||||
{'entity_group': 'NC', 'score': 0.9995531439781189, 'word': 'choc'},
|
||||
{'entity_group': 'ADJ', 'score': 0.999183714389801, 'word': 'inédit'},
|
||||
{'entity_group': 'P', 'score': 0.3710663616657257, 'word': ','},
|
||||
{'entity_group': 'DET', 'score': 0.9995903968811035, 'word': 'les'},
|
||||
{'entity_group': 'NC', 'score': 0.9995649456977844, 'word': 'mesures'},
|
||||
{'entity_group': 'VPP', 'score': 0.9988670349121094, 'word': 'mises'},
|
||||
{'entity_group': 'P', 'score': 0.9996246099472046, 'word': 'en'},
|
||||
{'entity_group': 'NC', 'score': 0.9995329976081848, 'word': 'place'},
|
||||
{'entity_group': 'P', 'score': 0.9996233582496643, 'word': 'par'},
|
||||
{'entity_group': 'DET', 'score': 0.9995935559272766, 'word': 'le'},
|
||||
{'entity_group': 'NC', 'score': 0.9995369911193848, 'word': 'gouvernement'},
|
||||
{'entity_group': 'V', 'score': 0.9993771314620972, 'word': 'ont'},
|
||||
{'entity_group': 'VPP', 'score': 0.9991101026535034, 'word': 'permis'},
|
||||
{'entity_group': 'DET', 'score': 0.9995885491371155, 'word': 'une'},
|
||||
{'entity_group': 'NC', 'score': 0.9995636343955994, 'word': 'protection'},
|
||||
{'entity_group': 'ADJ', 'score': 0.9991781711578369, 'word': 'forte'},
|
||||
{'entity_group': 'CC', 'score': 0.9991298317909241, 'word': 'et'},
|
||||
{'entity_group': 'ADJ', 'score': 0.9992275238037109, 'word': 'efficace'},
|
||||
{'entity_group': 'P+D', 'score': 0.9993300437927246, 'word': 'des'},
|
||||
{'entity_group': 'NC', 'score': 0.8353511393070221, 'word': 'ménages</s>'}]
|
||||
```
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
language: ga
|
||||
tags:
|
||||
- irish
|
||||
---
|
||||
|
||||
## BERTreach
|
||||
|
||||
([beirtreach](https://www.teanglann.ie/en/fgb/beirtreach) means 'oyster bed')
|
||||
|
||||
**Model size:** 84M
|
||||
|
||||
**Training data:**
|
||||
* [PARSEME 1.2](https://gitlab.com/parseme/parseme_corpus_ga/-/blob/master/README.md)
|
||||
* Newscrawl 300k portion of the [Leipzig Corpora](https://wortschatz.uni-leipzig.de/en/download/irish)
|
||||
* Private news corpus crawled with [Corpus Crawler](https://github.com/google/corpuscrawler)
|
||||
|
||||
(2125804 sentences, 47419062 tokens, as reckoned by wc)
|
||||
|
||||
```
|
||||
from transformers import pipeline
|
||||
fill_mask = pipeline("fill-mask", model="jimregan/BERTreach", tokenizer="jimregan/BERTreach")
|
||||
```
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
language: es
|
||||
thumbnail: https://i.imgur.com/uxAvBfh.png
|
||||
|
||||
|
||||
---
|
||||
|
||||
## ELECTRICIDAD: The Spanish Electra [Imgur](https://imgur.com/uxAvBfh)
|
||||
|
||||
**Electricidad-base-discriminator** (uncased) is a ```base``` Electra like model (discriminator in this case) trained on a + 20 GB of the [OSCAR](https://oscar-corpus.com/) Spanish corpus.
|
||||
|
||||
As mentioned in the original [paper](https://openreview.net/pdf?id=r1xMH1BtvB):
|
||||
**ELECTRA** is a new method for self-supervised language representation learning. It can be used to pre-train transformer networks using relatively little compute. ELECTRA models are trained to distinguish "real" input tokens vs "fake" input tokens generated by another neural network, similar to the discriminator of a [GAN](https://arxiv.org/pdf/1406.2661.pdf). At small scale, ELECTRA achieves strong results even when trained on a single GPU. At large scale, ELECTRA achieves state-of-the-art results on the [SQuAD 2.0](https://rajpurkar.github.io/SQuAD-explorer/) dataset.
|
||||
|
||||
For a detailed description and experimental results, please refer the paper [ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators](https://openreview.net/pdf?id=r1xMH1BtvB).
|
||||
|
||||
|
||||
## Model details ⚙
|
||||
|
||||
|Name| # Value|
|
||||
|-----|--------|
|
||||
|Layers| 12 |
|
||||
|Hidden |768 |
|
||||
|Params| 110M|
|
||||
|
||||
## Evaluation metrics (for discriminator) 🧾
|
||||
|
||||
|Metric | # Score |
|
||||
|-------|---------|
|
||||
|Accuracy| 0.985|
|
||||
|Precision| 0.726|
|
||||
|AUC | 0.922|
|
||||
|
||||
|
||||
|
||||
## Fast example of usage 🚀
|
||||
|
||||
```python
|
||||
from transformers import ElectraForPreTraining, ElectraTokenizerFast
|
||||
import torch
|
||||
|
||||
discriminator = ElectraForPreTraining.from_pretrained("/content/electricidad-base-discriminator")
|
||||
tokenizer = ElectraTokenizerFast.from_pretrained("/content/electricidad-base-discriminator")
|
||||
|
||||
sentence = "El rápido zorro marrón salta sobre el perro perezoso"
|
||||
fake_sentence = "El rápido zorro marrón amar sobre el perro perezoso"
|
||||
|
||||
fake_tokens = tokenizer.tokenize(fake_sentence)
|
||||
fake_inputs = tokenizer.encode(fake_sentence, return_tensors="pt")
|
||||
discriminator_outputs = discriminator(fake_inputs)
|
||||
predictions = torch.round((torch.sign(discriminator_outputs[0]) + 1) / 2)
|
||||
|
||||
[print("%7s" % token, end="") for token in fake_tokens]
|
||||
|
||||
[print("%7s" % prediction, end="") for prediction in predictions.tolist()]
|
||||
|
||||
# Output:
|
||||
'''
|
||||
el rapido zorro marro ##n amar sobre el perro pere ##zoso 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0[None, None, None, None, None, None, None, None, None, None, None, None, None
|
||||
'''
|
||||
```
|
||||
|
||||
As you can see there are **1s** in the places where the model detected a fake token. So, it works! 🎉
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
I thank [🤗/transformers team](https://github.com/huggingface/transformers) for allowing me to train the model (specially to [Julien Chaumond](https://twitter.com/julien_c)).
|
||||
|
||||
|
||||
|
||||
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488)
|
||||
|
||||
> Made with <span style="color: #e25555;">♥</span> in Spain
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
language: es
|
||||
thumbnail: https://i.imgur.com/uxAvBfh.png
|
||||
|
||||
|
||||
---
|
||||
|
||||
## ELECTRICIDAD: The Spanish Electra [Imgur](https://imgur.com/uxAvBfh)
|
||||
|
||||
**Electricidad-base-generator** (uncased) is a ```base``` Electra like model (generator in this case) trained on a + 20 GB of the [OSCAR](https://oscar-corpus.com/) Spanish corpus.
|
||||
|
||||
As mentioned in the original [paper](https://openreview.net/pdf?id=r1xMH1BtvB):
|
||||
**ELECTRA** is a new method for self-supervised language representation learning. It can be used to pre-train transformer networks using relatively little compute. ELECTRA models are trained to distinguish "real" input tokens vs "fake" input tokens generated by another neural network, similar to the discriminator of a [GAN](https://arxiv.org/pdf/1406.2661.pdf). At small scale, ELECTRA achieves strong results even when trained on a single GPU. At large scale, ELECTRA achieves state-of-the-art results on the [SQuAD 2.0](https://rajpurkar.github.io/SQuAD-explorer/) dataset.
|
||||
|
||||
For a detailed description and experimental results, please refer the paper [ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators](https://openreview.net/pdf?id=r1xMH1BtvB).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Fast example of usage 🚀
|
||||
|
||||
```python
|
||||
from transformers import pipeline
|
||||
|
||||
fill_mask = pipeline(
|
||||
"fill-mask",
|
||||
model="mrm8488/electricidad-base-generator",
|
||||
tokenizer="mrm8488/electricidad-base-generator"
|
||||
)
|
||||
|
||||
print(
|
||||
fill_mask(f"HuggingFace está creando {fill_mask.tokenizer.mask_token} que la comunidad usa para resolver tareas de NLP.")
|
||||
)
|
||||
|
||||
# Output: [{'sequence': '[CLS] huggingface esta creando herramientas que la comunidad usa para resolver tareas de nlp. [SEP]', 'score': 0.0896105170249939, 'token': 8760, 'token_str': 'herramientas'}, ...]
|
||||
|
||||
```
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
I thank [🤗/transformers team](https://github.com/huggingface/transformers) for allowing me to train the model (specially to [Julien Chaumond](https://twitter.com/julien_c)).
|
||||
|
||||
|
||||
|
||||
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488)
|
||||
|
||||
> Made with <span style="color: #e25555;">♥</span> in Spain
|
||||
@@ -1,70 +0,0 @@
|
||||
---
|
||||
language: en
|
||||
datasets:
|
||||
- break_data
|
||||
---
|
||||
|
||||
# T5-base fine-tuned on break_data / QDMR-high-level 📋➡️❓
|
||||
|
||||
[Google's T5](https://ai.googleblog.com/2020/02/exploring-transfer-learning-with-t5.html) fine-tuned on [break_data](https://huggingface.co/nlp/viewer/?dataset=break_data&config=QDMR-high-level) dataset for **Question Retrieval from its decomposition**.
|
||||
The inverse process of [this model](https://huggingface.co/mrm8488/t5-base-finetuned-break_data).
|
||||
|
||||
## Details of T5 📜 ➡️ 📜
|
||||
|
||||
The **T5** model was presented in [Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer](https://arxiv.org/pdf/1910.10683.pdf) by *Colin Raffel, Noam Shazeer, Adam Roberts, Katherine Lee, Sharan Narang, Michael Matena, Yanqi Zhou, Wei Li, Peter J. Liu* in Here the abstract:
|
||||
|
||||
Transfer learning, where a model is first pre-trained on a data-rich task before being fine-tuned on a downstream task, has emerged as a powerful technique in natural language processing (NLP). The effectiveness of transfer learning has given rise to a diversity of approaches, methodology, and practice. In this paper, we explore the landscape of transfer learning techniques for NLP by introducing a unified framework that converts every language problem into a text-to-text format. Our systematic study compares pre-training objectives, architectures, unlabeled datasets, transfer approaches, and other factors on dozens of language understanding tasks. By combining the insights from our exploration with scale and our new “Colossal Clean Crawled Corpus”, we achieve state-of-the-art results on many benchmarks covering summarization, question answering, text classification, and more. To facilitate future work on transfer learning for NLP, we release our dataset, pre-trained models, and code.
|
||||
|
||||

|
||||
|
||||
|
||||
## Details of the downstream task (Question Retrieval from its decomposition) - Dataset 📚
|
||||
|
||||
Break is a human annotated dataset of natural language questions and their Question Decomposition Meaning Representations (QDMRs). Break consists of 83,978 examples sampled from 10 question answering datasets over text, images and databases. This repository contains the Break dataset along with information on the exact data format.
|
||||
|
||||
| Dataset | Split | # samples |
|
||||
| -------- | ----- | --------- |
|
||||
| break_data | train | 17503 |
|
||||
| break_data | valid | 3130 |
|
||||
|
||||
Check out more about this dataset and others in [NLP Viewer](https://huggingface.co/nlp/viewer/)
|
||||
|
||||
|
||||
## Model fine-tuning 🏋️
|
||||
The training script is a slightly modified version of [this awesome one](https://colab.research.google.com/github/patil-suraj/exploring-T5/blob/master/T5_on_TPU.ipynb) by [Suraj Patil](https://twitter.com/psuraj28). The main change is at preprocessing ```inputs``` and ```targets``` we feed to the model. We do it as a *paraphrasing task*.
|
||||
|
||||
|
||||
## Model in Action 🚀
|
||||
|
||||
```python
|
||||
# Tip: By now, install transformers from source
|
||||
|
||||
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("mrm8488/t5-base-finetuned-break_data-question-retrieval")
|
||||
model = AutoModelForSeq2SeqLM.from_pretrained("mrm8488/t5-base-finetuned-break_data-question-retrieval")
|
||||
|
||||
|
||||
def get_nautural_question(decomposition):
|
||||
input_text = 'translate QDMRs to Natural Language %s </s>' % decomposition
|
||||
features = tokenizer([input_text], return_tensors='pt')
|
||||
|
||||
output = model.generate(input_ids=features['input_ids'],
|
||||
attention_mask=features['attention_mask'],
|
||||
max_length=64)
|
||||
|
||||
return tokenizer.decode(output[0])
|
||||
|
||||
|
||||
|
||||
decomposition = "return the city that was the birthplace of Bernard Berrian ;return the city that was the home of Pablo Picasso ;return the city of both #1 and #2"
|
||||
|
||||
# Ground Truth: What city was the birthplace of Bernard Berrianand the home of Pablo Picasso?
|
||||
|
||||
get_nautural_question(decomposition)
|
||||
|
||||
# output: 'What city was the birthplace of Bernard Berrian and the home of Pablo Picasso?'
|
||||
```
|
||||
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488) | [LinkedIn](https://www.linkedin.com/in/manuel-romero-cs/)
|
||||
|
||||
> Made with <span style="color: #e25555;">♥</span> in Spain
|
||||
@@ -1,64 +0,0 @@
|
||||
---
|
||||
language: en
|
||||
datasets:
|
||||
- break_data
|
||||
---
|
||||
|
||||
# T5-base fine-tuned on break_data / QDMR-high-level ❓➡️📋
|
||||
|
||||
[Google's T5](https://ai.googleblog.com/2020/02/exploring-transfer-learning-with-t5.html) fine-tuned on [break_data](https://huggingface.co/nlp/viewer/?dataset=break_data&config=QDMR-high-level) dataset for **QDMRs**.
|
||||
|
||||
## Details of T5 📜 ➡️ 📜
|
||||
|
||||
The **T5** model was presented in [Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer](https://arxiv.org/pdf/1910.10683.pdf) by *Colin Raffel, Noam Shazeer, Adam Roberts, Katherine Lee, Sharan Narang, Michael Matena, Yanqi Zhou, Wei Li, Peter J. Liu* in Here the abstract:
|
||||
|
||||
Transfer learning, where a model is first pre-trained on a data-rich task before being fine-tuned on a downstream task, has emerged as a powerful technique in natural language processing (NLP). The effectiveness of transfer learning has given rise to a diversity of approaches, methodology, and practice. In this paper, we explore the landscape of transfer learning techniques for NLP by introducing a unified framework that converts every language problem into a text-to-text format. Our systematic study compares pre-training objectives, architectures, unlabeled datasets, transfer approaches, and other factors on dozens of language understanding tasks. By combining the insights from our exploration with scale and our new “Colossal Clean Crawled Corpus”, we achieve state-of-the-art results on many benchmarks covering summarization, question answering, text classification, and more. To facilitate future work on transfer learning for NLP, we release our dataset, pre-trained models, and code.
|
||||
|
||||

|
||||
|
||||
|
||||
## Details of the downstream task (QDMRs) - Dataset 📚
|
||||
|
||||
Break is a human annotated dataset of natural language questions and their Question Decomposition Meaning Representations (QDMRs). Break consists of 83,978 examples sampled from 10 question answering datasets over text, images and databases. This repository contains the Break dataset along with information on the exact data format.
|
||||
|
||||
| Dataset | Split | # samples |
|
||||
| -------- | ----- | --------- |
|
||||
| break_data | train | 17503 |
|
||||
| break_data | valid | 3130 |
|
||||
|
||||
Check out more about this dataset and others in [NLP Viewer](https://huggingface.co/nlp/viewer/)
|
||||
|
||||
|
||||
## Model fine-tuning 🏋️
|
||||
The training script is a slightly modified version of [this awesome one](https://colab.research.google.com/github/patil-suraj/exploring-T5/blob/master/T5_on_TPU.ipynb) by [Suraj Patil](https://twitter.com/psuraj28). The main change is at preprocessing ```inputs``` and ```targets``` we feed to the model. We do it as a *paraphrasing task*.
|
||||
|
||||
|
||||
## Model in Action 🚀
|
||||
|
||||
```python
|
||||
# Tip: By now, install transformers from source
|
||||
|
||||
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("mrm8488/t5-base-finetuned-break_data")
|
||||
model = AutoModelForSeq2SeqLM.from_pretrained("mrm8488/t5-base-finetuned-break_data")
|
||||
|
||||
def get_decomposition(question):
|
||||
input_text = "paraphrase: %s </s>" % question
|
||||
features = tokenizer([input_text], return_tensors='pt')
|
||||
|
||||
output = model.generate(input_ids=features['input_ids'],
|
||||
attention_mask=features['attention_mask'],
|
||||
max_length=32)
|
||||
|
||||
return tokenizer.decode(output[0])
|
||||
|
||||
question = "The composer of Sands Theme plays what type of guitar?"
|
||||
|
||||
get_decomposition(question)
|
||||
|
||||
# output: 'return Sands Theme ;return composer of #1 ;return guitar that #2 plays'
|
||||
```
|
||||
> Created by [Manuel Romero/@mrm8488](https://twitter.com/mrm8488) | [LinkedIn](https://www.linkedin.com/in/manuel-romero-cs/)
|
||||
|
||||
> Made with <span style="color: #e25555;">♥</span> in Spain
|
||||
@@ -1,105 +1,5 @@
|
||||
---
|
||||
language: pt
|
||||
license: mit
|
||||
tags:
|
||||
- bert
|
||||
- pytorch
|
||||
datasets:
|
||||
- brWaC
|
||||
---
|
||||
|
||||
# BERTimbau Base (aka "bert-base-portuguese-cased")
|
||||
|
||||

|
||||
|
||||
## Introduction
|
||||
|
||||
BERTimbau Base is a pretrained BERT model for Brazilian Portuguese that achieves state-of-the-art performances on three downstream NLP tasks: Named Entity Recognition, Sentence Textual Similarity and Recognizing Textual Entailment. It is available in two sizes: Base and Large.
|
||||
|
||||
For further information or requests, please go to [BERTimbau repository](https://github.com/neuralmind-ai/portuguese-bert/).
|
||||
|
||||
## Available models
|
||||
|
||||
| Model | Arch. | #Layers | #Params |
|
||||
| ---------------------------------------- | ---------- | ------- | ------- |
|
||||
| `neuralmind/bert-base-portuguese-cased` | BERT-Base | 12 | 110M |
|
||||
| `neuralmind/bert-large-portuguese-cased` | BERT-Large | 24 | 335M |
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
from transformers import AutoTokenizer # Or BertTokenizer
|
||||
from transformers import AutoModelForPretraining # Or BertForPreTraining for loading pretraining heads
|
||||
from transformers import AutoModel # or BertModel, for BERT without pretraining heads
|
||||
|
||||
model = AutoModelForPreTraining.from_pretrained('neuralmind/bert-base-portuguese-cased')
|
||||
tokenizer = AutoTokenizer.from_pretrained('neuralmind/bert-base-portuguese-cased', do_lower_case=False)
|
||||
```
|
||||
|
||||
### Masked language modeling prediction example
|
||||
|
||||
```python
|
||||
from transformers import pipeline
|
||||
|
||||
pipe = pipeline('fill-mask', model=model, tokenizer=tokenizer)
|
||||
|
||||
pipe('Tinha uma [MASK] no meio do caminho.')
|
||||
# [{'score': 0.14287759363651276,
|
||||
# 'sequence': '[CLS] Tinha uma pedra no meio do caminho. [SEP]',
|
||||
# 'token': 5028,
|
||||
# 'token_str': 'pedra'},
|
||||
# {'score': 0.06213393807411194,
|
||||
# 'sequence': '[CLS] Tinha uma árvore no meio do caminho. [SEP]',
|
||||
# 'token': 7411,
|
||||
# 'token_str': 'árvore'},
|
||||
# {'score': 0.05515013635158539,
|
||||
# 'sequence': '[CLS] Tinha uma estrada no meio do caminho. [SEP]',
|
||||
# 'token': 5675,
|
||||
# 'token_str': 'estrada'},
|
||||
# {'score': 0.0299188531935215,
|
||||
# 'sequence': '[CLS] Tinha uma casa no meio do caminho. [SEP]',
|
||||
# 'token': 1105,
|
||||
# 'token_str': 'casa'},
|
||||
# {'score': 0.025660505518317223,
|
||||
# 'sequence': '[CLS] Tinha uma cruz no meio do caminho. [SEP]',
|
||||
# 'token': 3466,
|
||||
# 'token_str': 'cruz'}]
|
||||
|
||||
```
|
||||
|
||||
### For BERT embeddings
|
||||
|
||||
```python
|
||||
import torch
|
||||
|
||||
model = AutoModel.from_pretrained('neuralmind/bert-base-portuguese-cased')
|
||||
input_ids = tokenizer.encode('Tinha uma pedra no meio do caminho.', return_tensors='pt')
|
||||
|
||||
with torch.no_grad():
|
||||
outs = model(input_ids)
|
||||
encoded = outs[0][0, 1:-1] # Ignore [CLS] and [SEP] special tokens
|
||||
|
||||
# encoded.shape: (8, 768)
|
||||
# tensor([[-0.0398, -0.3057, 0.2431, ..., -0.5420, 0.1857, -0.5775],
|
||||
# [-0.2926, -0.1957, 0.7020, ..., -0.2843, 0.0530, -0.4304],
|
||||
# [ 0.2463, -0.1467, 0.5496, ..., 0.3781, -0.2325, -0.5469],
|
||||
# ...,
|
||||
# [ 0.0662, 0.7817, 0.3486, ..., -0.4131, -0.2852, -0.2819],
|
||||
# [ 0.0662, 0.2845, 0.1871, ..., -0.2542, -0.2933, -0.0661],
|
||||
# [ 0.2761, -0.1657, 0.3288, ..., -0.2102, 0.0029, -0.2009]])
|
||||
```
|
||||
|
||||
## Citation
|
||||
|
||||
If you use our work, please cite:
|
||||
|
||||
```bibtex
|
||||
@inproceedings{souza2020bertimbau,
|
||||
author = {F{\'a}bio Souza and
|
||||
Rodrigo Nogueira and
|
||||
Roberto Lotufo},
|
||||
title = {{BERT}imbau: pretrained {BERT} models for {B}razilian {P}ortuguese},
|
||||
booktitle = {9th Brazilian Conference on Intelligent Systems, {BRACIS}, Rio Grande do Sul, Brazil, October 20-23 (to appear)},
|
||||
year = {2020}
|
||||
}
|
||||
```
|
||||
## bert-base-portuguese-cased
|
||||
@@ -1,106 +1,5 @@
|
||||
---
|
||||
language: pt
|
||||
license: mit
|
||||
tags:
|
||||
- bert
|
||||
- pytorch
|
||||
datasets:
|
||||
- brWaC
|
||||
---
|
||||
|
||||
# BERTimbau Large (aka "bert-large-portuguese-cased")
|
||||
|
||||

|
||||
|
||||
## Introduction
|
||||
|
||||
BERTimbau Large is a pretrained BERT model for Brazilian Portuguese that achieves state-of-the-art performances on three downstream NLP tasks: Named Entity Recognition, Sentence Textual Similarity and Recognizing Textual Entailment. It is available in two sizes: Base and Large.
|
||||
|
||||
For further information or requests, please go to [BERTimbau repository](https://github.com/neuralmind-ai/portuguese-bert/).
|
||||
|
||||
## Available models
|
||||
|
||||
| Model | Arch. | #Layers | #Params |
|
||||
| ---------------------------------------- | ---------- | ------- | ------- |
|
||||
| `neuralmind/bert-base-portuguese-cased` | BERT-Base | 12 | 110M |
|
||||
| `neuralmind/bert-large-portuguese-cased` | BERT-Large | 24 | 335M |
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
from transformers import AutoTokenizer # Or BertTokenizer
|
||||
from transformers import AutoModelForPreTraining # Or BertForPreTraining for loading pretraining heads
|
||||
from transformers import AutoModel # or BertModel, for BERT without pretraining heads
|
||||
|
||||
model = AutoModelForPreTraining.from_pretrained('neuralmind/bert-large-portuguese-cased')
|
||||
tokenizer = AutoTokenizer.from_pretrained('neuralmind/bert-large-portuguese-cased', do_lower_case=False)
|
||||
```
|
||||
|
||||
### Masked language modeling prediction example
|
||||
|
||||
```python
|
||||
from transformers import pipeline
|
||||
|
||||
pipe = pipeline('fill-mask', model=model, tokenizer=tokenizer)
|
||||
|
||||
pipe('Tinha uma [MASK] no meio do caminho.')
|
||||
# [{'score': 0.5054386258125305,
|
||||
# 'sequence': '[CLS] Tinha uma pedra no meio do caminho. [SEP]',
|
||||
# 'token': 5028,
|
||||
# 'token_str': 'pedra'},
|
||||
# {'score': 0.05616172030568123,
|
||||
# 'sequence': '[CLS] Tinha uma curva no meio do caminho. [SEP]',
|
||||
# 'token': 9562,
|
||||
# 'token_str': 'curva'},
|
||||
# {'score': 0.02348282001912594,
|
||||
# 'sequence': '[CLS] Tinha uma parada no meio do caminho. [SEP]',
|
||||
# 'token': 6655,
|
||||
# 'token_str': 'parada'},
|
||||
# {'score': 0.01795753836631775,
|
||||
# 'sequence': '[CLS] Tinha uma mulher no meio do caminho. [SEP]',
|
||||
# 'token': 2606,
|
||||
# 'token_str': 'mulher'},
|
||||
# {'score': 0.015246033668518066,
|
||||
# 'sequence': '[CLS] Tinha uma luz no meio do caminho. [SEP]',
|
||||
# 'token': 3377,
|
||||
# 'token_str': 'luz'}]
|
||||
|
||||
```
|
||||
|
||||
### For BERT embeddings
|
||||
|
||||
```python
|
||||
|
||||
import torch
|
||||
|
||||
model = AutoModel.from_pretrained('neuralmind/bert-large-portuguese-cased')
|
||||
input_ids = tokenizer.encode('Tinha uma pedra no meio do caminho.', return_tensors='pt')
|
||||
|
||||
with torch.no_grad():
|
||||
outs = model(input_ids)
|
||||
encoded = outs[0][0, 1:-1] # Ignore [CLS] and [SEP] special tokens
|
||||
|
||||
# encoded.shape: (8, 1024)
|
||||
# tensor([[ 1.1872, 0.5606, -0.2264, ..., 0.0117, -0.1618, -0.2286],
|
||||
# [ 1.3562, 0.1026, 0.1732, ..., -0.3855, -0.0832, -0.1052],
|
||||
# [ 0.2988, 0.2528, 0.4431, ..., 0.2684, -0.5584, 0.6524],
|
||||
# ...,
|
||||
# [ 0.3405, -0.0140, -0.0748, ..., 0.6649, -0.8983, 0.5802],
|
||||
# [ 0.1011, 0.8782, 0.1545, ..., -0.1768, -0.8880, -0.1095],
|
||||
# [ 0.7912, 0.9637, -0.3859, ..., 0.2050, -0.1350, 0.0432]])
|
||||
```
|
||||
|
||||
## Citation
|
||||
|
||||
If you use our work, please cite:
|
||||
|
||||
```bibtex
|
||||
@inproceedings{souza2020bertimbau,
|
||||
author = {F{\'a}bio Souza and
|
||||
Rodrigo Nogueira and
|
||||
Roberto Lotufo},
|
||||
title = {{BERT}imbau: pretrained {BERT} models for {B}razilian {P}ortuguese},
|
||||
booktitle = {9th Brazilian Conference on Intelligent Systems, {BRACIS}, Rio Grande do Sul, Brazil, October 20-23 (to appear)},
|
||||
year = {2020}
|
||||
}
|
||||
```
|
||||
## bert-large-portuguese-cased
|
||||
@@ -47,8 +47,8 @@ output_ids = model.generate(input_ids)
|
||||
|
||||
print(tokenizer.decode(output_ids[0], skip_special_tokens=True))
|
||||
# should produce
|
||||
# sae was founded in 1856, five years before the civil war. the fraternity has had to work hard to change recently. the university of oklahoma president says the university's affiliation with the fraternity is permanently done. the sae has had a string of members in recent mon
|
||||
ths.
|
||||
# SAE's national chapter suspended the students from campus activities. The fraternity is under fire for a video showing the students singing a racist chant. SAE has had fewer than 400 members of the
|
||||
# fraternity. The group had fewer alcohol consumption, along with about 15, 000 undergraduates populating 219 chapters.
|
||||
```
|
||||
|
||||
## Training script:
|
||||
@@ -69,7 +69,7 @@ from transformers import BertTokenizer, EncoderDecoderModel, Trainer, TrainingAr
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
model = EncoderDecoderModel.from_encoder_decoder_pretrained("bert-base-uncased", "bert-base-uncased")
|
||||
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
|
||||
tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
|
||||
|
||||
# CLS token will work as BOS token
|
||||
tokenizer.bos_token = tokenizer.cls_token
|
||||
@@ -226,4 +226,4 @@ The obtained results should be:
|
||||
|
||||
| - | Rouge2 - mid -precision | Rouge2 - mid - recall | Rouge2 - mid - fmeasure |
|
||||
|----------|:-------------:|:------:|:------:|
|
||||
| **CNN/Daily Mail** | 16.12 | 17.07 | **16.1** |
|
||||
| **CNN/Daily Mail** | 14.12 | 14.37 | **13.8** |
|
||||
Loaded 100 of 354 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user