huggingface / transformers

🤗 Transformers: State-of-the-art Machine Learning for Pytorch, TensorFlow, and JAX.
https://huggingface.co/transformers
Apache License 2.0
134.65k stars 26.93k forks source link

fast tokenizer issue on most user uploaded models #8117

Closed pommedeterresautee closed 3 years ago

pommedeterresautee commented 4 years ago

Environment info

Who can help

@mfuntowicz @julien-c

Information

Found the bug on camembert/camembert-base-ccnet but probably common to many models uploaded by users. On camembert base model, it works out of the box (there is no bug).

To reproduce

Since tokenizer 0.9, it's possible to load the many unigram based tokenizers with the fast Rust implementation.
It appears that the file tokenizer_config.json of some of them is not up to date, in particular the information "model_max_length": 512 is missing.

Because of that, the value of model_max_length is a very big integer.

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("camembert/camembert-base-ccnet", use_fast=True)
tokenizer.model_max_length
# Out[4]: 1000000000000000019884624838656

To fix it, the field model_max_length has to be added to the config file.

Expected behavior

I would expect tokenizer.model_max_length to be equal to 512.

julien-c commented 4 years ago

Yes, we need to remove all the hardcoded configuration values of tokenizers in the transformers source code, and upload tokenizer_config.json files for all those models.

Also cc @n1t0

pommedeterresautee commented 4 years ago

Very strange, making some tests, the Rust implem is much slower than the Python one...

Measure done on my Mac (i7)

import time

from transformers import AutoTokenizer

text = """
Il se déduit des arrêts de la Cour de justice de l’Union européenne du 27 avril 2017 (A-Rosa Flussschiff GmbH, n° C-620/15) et du 6 février 2018 (Ömer Altun, n° C-359/16) que le juge, lorsqu’il est saisi de poursuites pénales du chef de travail dissimulé, pour défaut de déclarations aux organismes de protection sociale, et que la personne poursuivie produit des certificats E101, devenus A1, à l’égard des travailleurs concernés, délivrés au titre de l’article 14, paragraphe 2, sous a, du règlement n° 1408/71, ne peut, à l’issue du débat contradictoire, écarter lesdits certificats que si, sur la base de l’examen des éléments concrets recueillis au cours de l’enquête judiciaire ayant permis de constater que ces certificats avaient été obtenus ou invoqués frauduleusement et que l’institution émettrice saisie s’était abstenue de prendre en compte, dans un délai raisonnable, il caractérise une fraude constituée, dans son élément objectif, par l’absence de respect des conditions prévues à la disposition précitée et, dans son élément subjectif, par l’intention de la personne poursuivie de contourner ou d’éluder les conditions de délivrance dudit certificat pour obtenir l’avantage qui y est attaché.
Doit ainsi être cassé l’arrêt de la cour d’appel qui écarte les certificats E101 sans avoir, au préalable, recherché si l’institution émettrice desdits certificats avait été saisie d’une demande de réexamen et de retrait de ceux-ci sur la base des éléments concrets recueillis dans le cadre de l’enquête judiciaire permettant, le cas échéant, de constater que ces certificats avaient été obtenus ou invoqués de manière frauduleuse et que l’institution émettrice s’était abstenue, dans un délai raisonnable, de les prendre en considération aux fins de réexamen du bien-fondé de la délivrance desdits certificats, et dans l’affirmative, sans établir, sur la base de l’examen des éléments concrets et dans le respect des garanties inhérentes au droit à un procès équitable, l’existence d’une fraude de la part de la société poursuivie, constituée, dans son élément matériel, par le défaut, dans les faits de la cause, des conditions prévues à l’article 14, paragraphe 2, sous a, précité aux fins d’obtention ou d’invocation des certificats E101 en cause et, dans son élément moral, par l’intention de ladite société de contourner ou d’éluder les conditions de délivrance dudit certificat pour obtenir l’avantage qui y est attaché (arrêt n° 1, pourvoi 13-88.631, arrêt n° 2, pourvoi 13-88.632 et arrêt n° 3, pourvoi n° 15-80.735).
En revanche, prononce par des motifs conformes à la doctrine de la Cour de l’Union européenne précitée, la cour d’appel qui, pour relaxer les prévenues, sociétés d’aviation civile, énonce que l’enquête n’ a pas permis de constater les éléments de fraude et s’abstient, en conséquence, d’opérer une vérification relative aux certificats E101 produits par elles (arrêt n° 4, pourvoi n° 1581316).
"""

fast = False
repeat = 1000

# use_fast
tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path="camembert/camembert-base-ccnet", use_fast=fast)

_ = tokenizer(text)
start = time.time()
for _ in range(repeat):
    _ = tokenizer(text)
print("ccnet new", time.time() - start)

# CCNET Camembert saved few months ago
tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path="output/model", use_fast=fast)

_ = tokenizer(text)
start = time.time()
for _ in range(repeat):
    _ = tokenizer(text)
print("ccnet old", time.time() - start)

tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path="camembert-base", use_fast=fast)

_ = tokenizer(text)
start = time.time()
for _ in range(repeat):
    _ = tokenizer(text)
print("camembert base", time.time() - start)

fast = False

wandb: WARNING W&B installed but not logged in.  Run `wandb login` or set the WANDB_API_KEY env variable.
ccnet new 2.104267120361328
ccnet old 2.3693552017211914
Token indices sequence length is longer than the specified maximum sequence length for this model (684 > 512). Running this sequence through the model will result in indexing errors
camembert base 2.245959997177124

Process finished with exit code 0

fast = True

wandb: WARNING W&B installed but not logged in.  Run `wandb login` or set the WANDB_API_KEY env variable.
ccnet new 2.7245991230010986
ccnet old 2.7714219093322754
camembert base 2.9007809162139893

It appears that fast tokenizer... is much slower than Python implementation on a Mac (measures not done a Linux machine).

n1t0 commented 4 years ago

Thank you for reporting this @pommedeterresautee.

I think this is expected though: You are comparing a tokenizer that is based on SentencePiece (c++) with one in Rust. Our rust implementation is a bit slower than the SentencePiece when encoding a single sentence, but as soon as you are starting to encode batches with padding and post-processing, it gets faster!

pommedeterresautee commented 4 years ago

Thank you, I didn't understood that batching was a thing during tokenization too!

import time

from transformers import AutoTokenizer

text = """
Il se déduit des arrêts de la Cour de justice de l’Union européenne du 27 avril 2017 (A-Rosa Flussschiff GmbH, n° C-620/15) et du 6 février 2018 (Ömer Altun, n° C-359/16) que le juge, lorsqu’il est saisi de poursuites pénales du chef de travail dissimulé, pour défaut de déclarations aux organismes de protection sociale, et que la personne poursuivie produit des certificats E101, devenus A1, à l’égard des travailleurs concernés, délivrés au titre de l’article 14, paragraphe 2, sous a, du règlement n° 1408/71, ne peut, à l’issue du débat contradictoire, écarter lesdits certificats que si, sur la base de l’examen des éléments concrets recueillis au cours de l’enquête judiciaire ayant permis de constater que ces certificats avaient été obtenus ou invoqués frauduleusement et que l’institution émettrice saisie s’était abstenue de prendre en compte, dans un délai raisonnable, il caractérise une fraude constituée, dans son élément objectif, par l’absence de respect des conditions prévues à la disposition précitée et, dans son élément subjectif, par l’intention de la personne poursuivie de contourner ou d’éluder les conditions de délivrance dudit certificat pour obtenir l’avantage qui y est attaché.
Doit ainsi être cassé l’arrêt de la cour d’appel qui écarte les certificats E101 sans avoir, au préalable, recherché si l’institution émettrice desdits certificats avait été saisie d’une demande de réexamen et de retrait de ceux-ci sur la base des éléments concrets recueillis dans le cadre de l’enquête judiciaire permettant, le cas échéant, de constater que ces certificats avaient été obtenus ou invoqués de manière frauduleuse et que l’institution émettrice s’était abstenue, dans un délai raisonnable, de les prendre en considération aux fins de réexamen du bien-fondé de la délivrance desdits certificats, et dans l’affirmative, sans établir, sur la base de l’examen des éléments concrets et dans le respect des garanties inhérentes au droit à un procès équitable, l’existence d’une fraude de la part de la société poursuivie, constituée, dans son élément matériel, par le défaut, dans les faits de la cause, des conditions prévues à l’article 14, paragraphe 2, sous a, précité aux fins d’obtention ou d’invocation des certificats E101 en cause et, dans son élément moral, par l’intention de ladite société de contourner ou d’éluder les conditions de délivrance dudit certificat pour obtenir l’avantage qui y est attaché (arrêt n° 1, pourvoi 13-88.631, arrêt n° 2, pourvoi 13-88.632 et arrêt n° 3, pourvoi n° 15-80.735).
En revanche, prononce par des motifs conformes à la doctrine de la Cour de l’Union européenne précitée, la cour d’appel qui, pour relaxer les prévenues, sociétés d’aviation civile, énonce que l’enquête n’ a pas permis de constater les éléments de fraude et s’abstient, en conséquence, d’opérer une vérification relative aux certificats E101 produits par elles (arrêt n° 4, pourvoi n° 1581316).
"""

repeat = 1000

# use_fast
tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path="camembert/camembert-base-ccnet", use_fast=True)

_ = tokenizer(text)
start = time.time()
for _ in range(repeat):
    _ = tokenizer([text] * 10)
print("fast", time.time() - start)

tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path="camembert/camembert-base-ccnet", use_fast=False)

_ = tokenizer(text)
start = time.time()
for _ in range(repeat):
    _ = tokenizer([text] * 10)
print("slow", time.time() - start)

Produces

wandb: WARNING W&B installed but not logged in.  Run `wandb login` or set the WANDB_API_KEY env variable.
fast 16.272130966186523
slow 22.52426290512085

... as expected!

Narsil commented 4 years ago

@pommedeterresautee

Hi, I am not sure it's a fast tokenizers bug but maybe more a property that was (maybe unintentionnally) dropped from Tokenizers.

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("camembert/camembert-base-ccnet", use_fast=False)
tokenizer.model_max_length
# Out[4]: 1000000000000000019884624838656

Can you tell us what's the actual bug for you in the end ? Just to make sure the fix I am working on will actually work as generally as possible

pommedeterresautee commented 4 years ago

I think you are right, it's more about a dropped property in the config file or a change in the source code than a bug specific to the fast tokenizer. I discovered the issue because I was comparing the model + tokenizer as exported few months ago with the fast tokenizer of today and thought it was because of the fast tokenizer. My "old" export returns me 512 when I call max_len.

Still it's not returning the correct value, fast tokenizer or not.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Allaoua9 commented 1 year ago

Hi, this issue is still not resolved; i have the same problem with camembert/camembert-large