huggingface / huggingface/transformers

Unexpected/wrong handling of added special tokens in special_tokens_mask (GPT1, BERT, possibly others)

Open
#7,951 6 comments 1 reaction 0 assignees View on GitHub
WIP
Dominant language
Python
Stars
166k
Forks
34.6k
Avg merge
3d 8h
Merged PRs (30d)
276

Description

## Environment info


- `transformers` version: 3.1.0
- Platform: Linux-5.4.0-52-generic-x86_64-with-glibc2.29
- Python version: 3.8.5
- PyTorch version (GPU?): 1.6.0+cpu (False)
- Tensorflow version (GPU?): not installed (NA)
- Using GPU in script?: **No**
- Using distributed or parallel set-up in script?: **No**

### Who can help

Most appropriate seems @mfuntowicz (tokenization), blame says @thomwolf.
## Information

Model I am using (Bert, XLNet ...): OpenAI GPT (also BERT)

The problem arises when using:
* [ ] the official example scripts: (give details below)
* [X] my own modified scripts: (give details below)

The tasks I am working on is:
* [ ] an official GLUE/SQUaD task: (give the name)
* [X] my own task or dataset: (give details below)

I am adding special tokens (`BOS`, `SEP` and `EOS`) to GPT1 tokenizer in order to format and fine-tune a GPT model a bit differently. I am also making use of the convenient `return_special_tokens_mask` argument in `encode_plus()`, though it does not seem to mark the added custom special tokens as special in the returned mask.

The same is also true when adding custom special tokens to BERT tokenizer. I did not check beyond these two.
The problem for GPT seems to be that `get_special_tokens_mask()` in `tokenization_utils.py` does not seem to take into account any special tokens.
```python
def get_special_tokens_mask(
self, token_ids_0: List, token_ids_1: Optional[List] = None, already_has_special_tokens: bool = False
) -> List[int]:
return [0] * ((len(token_ids_1) if token_ids_1 else 0) + len(token_ids_0))
```

For BERT, it only seems to take into account `[CLS]` and `[SEP]`.

## To reproduce

```python
from transformers import OpenAIGPTTokenizer

tokenizer = OpenAIGPTTokenizer.from_pretrained("openai-gpt")
tokenizer.add_special_tokens({
"bos_token": "",
"sep_token": "",
"eos_token": ""
})

# Does not work this way either
# tokenizer.add_special_tokens({
# "additional_special_tokens": ["", "", ""]
# })

encoded = tokenizer.encode_plus(" State your name, rank and intention The Doctor, doctor, fun. ",
return_special_tokens_mask=True)
print(encoded["input_ids"])
print(encoded["special_tokens_mask"]) # This returns all zeros
```

## Expected behavior
I would expect that the additional special tokens also get marked as special, i.e. that the `special_tokens_mask` in above snippet returns `[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1]`

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.