# Training sentencePiece from scratch?

**URL:** </static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%3E%5C
**Category:** 🤗Tokenizers\
**Created:** [February 2, 2021, 4:07pm UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477 "2021-02-02T16:07:40Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Johncwok](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@Johncwok](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2FJohncwok)%5C
**Post date:** [February 2, 2021, 4:07pm UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F1 "2021-02-02T16:07:40Z")

</div>

Hi! I would like to train a sentencePiece tokenizer from scratch but I’m a bit lost from the documentation and don’t know where to start. There are already examples on how to train a BPE tokenizer on the huggingface website but I don’t know if I can simply transfer it 1 to 1. Also I don’t even know where to find the trainable class for sentencePiece.  
Have you already trained a sentencePiece tokenizer?

---

<div class="post-metadata">

**Author:** ![finiteautomata](https://sea2.discourse-cdn.com/hellohellohello/user_avatar/discuss.huggingface.co/finiteautomata/32/47620_2.png) [@finiteautomata](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2Ffiniteautomata)%5C
**Post date:** [July 27, 2021, 2:45pm UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F2 "2021-07-27T14:45:35Z")

</div>

@Johncwok check this page: [Using tokenizers from 🤗 Tokenizers — transformers 4.7.0 documentation](https://huggingface.co/transformers/fast_tokenizers.html)

You can train a SentencePiece tokenizer

```python
from tokenizers import SentencePieceBPETokenizer

tokenizer = SentencePieceBPETokenizer()
tokenizer.train_from_iterator(
    text,
    vocab_size=30_000,
    min_frequency=5,
    show_progress=True,
    limit_alphabet=500,
)

```

and then just wrap it with a `PreTrainedTokenizerFast`

```python
from transformers import PreTrainedTokenizerFast

transformer_tokenizer = PreTrainedTokenizerFast(
    tokenizer_object=tokenizer
)

```

Documentation is not quite clear about this

---

<div class="post-metadata">

**Author:** ![jbmaxwell](https://avatars.discourse-cdn.com/v4/letter/j/5daacb/32.png) [@jbmaxwell](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2Fjbmaxwell)%5C
**Post date:** [May 16, 2022, 6:24pm UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F3 "2022-05-16T18:24:35Z")

</div>

Sorry to jump on this old question, but I’m wondering how to _properly_ get a tokenizer that I’ve trained this way loaded from file? I’ve been using the same approach you indicate here, but saving it with `tokenizer.save('/path/to/tokenizer.json')`, then loading it with the `tokenizer_file` option. It loads, but I’m noticing that it loads with all the special tokens set to `None`.

Also, although using `from transformers import PreTrainedTokenizerFast` does seem to actually _work_, the compiler indicates that it’s supposed to be from `transformers.utils.dummy_tokenizers_objects` instead… but that doesn’t actually seem to work.

It’s all a bit muddy. Any help appreciated.

---

<div class="post-metadata">

**Author:** ![jbmaxwell](https://avatars.discourse-cdn.com/v4/letter/j/5daacb/32.png) [@jbmaxwell](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2Fjbmaxwell)%5C
**Post date:** [May 16, 2022, 7:49pm UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F4 "2022-05-16T19:49:50Z")

</div>

Okay, what seems to give me a fully configured, functioning Transformers tokenizer is:

```auto
special_tokens = ["<s>", "<pad>", "</s>", "<unk>", "<cls>", "<sep>", "<mask>"]
tk_tokenizer = SentencePieceBPETokenizer()
tk_tokenizer.train_from_iterator(
    text,
    vocab_size=4000,
    min_frequency=2,
    show_progress=True,
    special_tokens=special_tokens
)
tk_tokenizer.save(tokenizer_path)
# convert
tokenizer = transformers.PreTrainedTokenizerFast(tokenizer_object=tk_tokenizer, model_max_length=model_length, special_tokens=special_tokens)
tokenizer.bos_token = "<s>"
tokenizer.bos_token_id = tk_tokenizer.token_to_id("<s>")
tokenizer.pad_token = "<pad>"
tokenizer.pad_token_id = tk_tokenizer.token_to_id("<pad>")
tokenizer.eos_token = "</s>"
tokenizer.eos_token_id = tk_tokenizer.token_to_id("</s>")
tokenizer.unk_token = "<unk>"
tokenizer.unk_token_id = tk_tokenizer.token_to_id("<unk>")
tokenizer.cls_token = "<cls>"
tokenizer.cls_token_id = tk_tokenizer.token_to_id("<cls>")
tokenizer.sep_token = "<sep>"
tokenizer.sep_token_id = tk_tokenizer.token_to_id("<sep>")
tokenizer.mask_token = "<mask>"
tokenizer.mask_token_id = tk_tokenizer.token_to_id("<mask>")
# and save for later!
tokenizer.save_pretrained("./path/to/transformers/version/")

```

This seems to load properly using `AutoTokenizer.from_pretrained()` which should make life a lot easier.

---

<div class="post-metadata">

**Author:** ![appledora](https://sea2.discourse-cdn.com/hellohellohello/user_avatar/discuss.huggingface.co/appledora/32/13640_2.png) [@appledora](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2Fappledora)%5C
**Post date:** [January 16, 2023, 8:56pm UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F5 "2023-01-16T20:56:16Z")

</div>

Thanks for this code snippet! How did you format the dataset (`text`) here? One sentence per line? I was also wondering whether I could train it iteratively for multiple chunks of text input?

---

<div class="post-metadata">

**Author:** ![jbmaxwell](https://avatars.discourse-cdn.com/v4/letter/j/5daacb/32.png) [@jbmaxwell](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2Fjbmaxwell)%5C
**Post date:** [January 16, 2023, 9:24pm UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F6 "2023-01-16T21:24:23Z")

</div>

You’re welcome! I know it always helps to see code.

In my case it was just one line per sentence in a single flat text file.

---

<div class="post-metadata">

**Author:** ![derVokler](https://avatars.discourse-cdn.com/v4/letter/d/ee7513/32.png) [@derVokler](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2FderVokler)%5C
**Post date:** [February 1, 2023, 2:23pm UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F8 "2023-02-01T14:23:47Z")

</div>

Hi everyone,

I found this thread when I was looking for information how to best use a custom Sentencepiece model with the huggingface models / tokenizers. I found a different solution that works for me:

1. Train a Sentencepiece model with the Sentencepiece library
2. Load it one time into the tokenizer that I want
3. Save that tokenizer with .save\_pretrained()

After that it can be loaded with .from\_pretrained(). Here are the steps with a little more detail.

First, training the Sentencepiece model:

```auto
import sentencepiece as spm

spm.SentencePieceTrainer.Train(
    input=<FILE_NAME>,
    model_prefix='spModel',
    vocab_size=1000,
    pad_id=0,                
    unk_id=1,
    bos_id=2,
    eos_id=3,
    pad_piece='[PAD]',
    unk_piece='[UNK]',
    bos_piece='[CLS]',
    eos_piece='[SEP]',
    user_defined_symbols='[MASK]',
    model_type='unigram'
)

```

Now load it into a tokenizer, here a DebertaV2Tokenizer (why this needs to be the vocab file, I am not sure, but it works; I also specify the maximum length here):

```auto
from transformers import DebertaV2Tokenizer

tokenizer_deberta = DebertaV2Tokenizer(
    vocab_file = "spModel.model",
    max_len = 512,
)

```

Now save as a pretrained tokenizer:

```auto
tokenizer_deberta.save_pretrained( PATH )

```

And from that point on you can load it as any pretrained tokenizer:

```auto
tokenizer_loaded = DebertaV2Tokenizer.from_pretrained(
    PATH
)

```

When I print that guy, it looks to me like all special tokens and the sequence length are correct:

> DebertaV2Tokenizer(name\_or\_path=PATH, vocab\_size=1000, model\_max\_length=512, is\_fast=False, padding\_side=‘right’, truncation\_side=‘right’, special\_tokens={‘bos\_token’: ‘[CLS]’, ‘eos\_token’: ‘[SEP]’, ‘unk\_token’: ‘[UNK]’, ‘sep\_token’: ‘[SEP]’, ‘pad\_token’: ‘[PAD]’, ‘cls\_token’: ‘[CLS]’, ‘mask\_token’: ‘[MASK]’})

Maybe this still helps. I think the nice thing about this approach is that you can get a custom _unigram_ tokenizer.

---

<div class="post-metadata">

**Author:** ![VS9205](https://avatars.discourse-cdn.com/v4/letter/v/bc79bd/32.png) [@VS9205](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2FVS9205)%5C
**Post date:** [November 5, 2023, 11:05am UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F9 "2023-11-05T11:05:31Z")

</div>

How did you format the dataset (`text` ) here?

---

<div class="post-metadata">

**Author:** ![jubueche](https://sea2.discourse-cdn.com/hellohellohello/user_avatar/discuss.huggingface.co/jubueche/32/20460_2.png) [@jubueche](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Fu%2Fjubueche)%5C
**Post date:** [December 19, 2023, 10:23am UTC](/static-proxy?url=https%3A%2F%2Fdiscuss.huggingface.co%2Ft%2Ftraining-sentencepiece-from-scratch%2F3477%2F10 "2023-12-19T10:23:53Z")

</div>

I couldn’t figure out how to pass an iterator to this function. Do you know how to do that? Otherwise one always has to create a file first.
