readme for custom tokenizers
This commit is contained in:
@@ -142,6 +142,47 @@ Which gives the same results. More detailed testing will be done in `test_all.py
|
|||||||
$ pytest
|
$ pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## custom tokenizers
|
||||||
|
|
||||||
|
In everything above, we've assumed the custom Lllama 2 tokenizer with 32,000 tokens. However, in many boutique LLMs, using vocabulary this big might be an overkill. If you have a small application you have in mind, you might be much better off training your own tokenizers. This can make everything nicer - with smaller vocabs your model has fewer parameters (because the token embedding table is a lot smaller), the inference is faster (because there are fewer tokens to predict), and your average sequence length per example could also get smaller (because the compression is a lot more efficient on your data). So let's see how we train a custom tokenizer.
|
||||||
|
|
||||||
|
By default, to pretokenize the tinystories dataset we had to run, in order:
|
||||||
|
|
||||||
|
```
|
||||||
|
python tinystories.py download
|
||||||
|
python tinystories.py pretokenize
|
||||||
|
```
|
||||||
|
|
||||||
|
The `pretokenize` stage here loads the Llama 2 tokenizer (vocab size 32,000) and uses it to convert the downloaded text into integers, and saves that to file. We now change this as follows, to train an example 4096-token tokenizer:
|
||||||
|
|
||||||
|
```
|
||||||
|
python tinystories.py download
|
||||||
|
python tinystories.py train_vocab --vocab_size=4096
|
||||||
|
python tinystories.py pretokenize --vocab_size=4096
|
||||||
|
```
|
||||||
|
|
||||||
|
The `train_vocab` stage will call the `train_vocab.sh` script, which calls the `sentencepiece` library to train the tokenizer, storing it in a new file `data/tok4096.model`. I tried to reproduce as well as I could the settings that (I think) Meta used to train their vocabulary. This uses the Byte Pair Encoding algorithm that starts out with raw utf8 byte sequences of the text data and then iteratively merges the most common consecutive pairs of tokens to form the vocabulary. Inspect the `tinystories.py` file - the custom tokenizers are stored in a special directory structure indexed by the vocab size.
|
||||||
|
|
||||||
|
Now that we have pretokenized the dataset with our custom tokenizer, we can train the model. The training script `train.py` doesn't care about the exact tokens, it only cares about the vocabulary size so it can correctly initialize the model. So when training your model, make sure to pass in
|
||||||
|
|
||||||
|
```
|
||||||
|
python train.py --vocab_source=custom --vocab_size=4096
|
||||||
|
```
|
||||||
|
|
||||||
|
(The defaults are `llama2` and `32000` respectively, which indicates the default Llama 2 tokenizer). This trains the model. Finally we are ready to run inference with our `run.c` script. For that we need two things. Number one, we have to export our tokenizer in the `.bin` format, do that with:
|
||||||
|
|
||||||
|
```
|
||||||
|
python tokenizer.py --tokenizer-model=data/tok4096.model
|
||||||
|
```
|
||||||
|
|
||||||
|
This writes the tokenizer to `data/tok4096.bin`. Now we can run inference, pointing it to this tokenizer using the `-z` flag:
|
||||||
|
|
||||||
|
```
|
||||||
|
./run out/model.bin -z data/tok4096.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
This should print the samples. If you leave out the `-z` flag, it will use the default Llama 2 tokenizer, which would generate a good sequence of integers, but they would get translated using a different vocabulary to text, so it would look like gibberish.
|
||||||
|
|
||||||
## performance
|
## performance
|
||||||
|
|
||||||
There are many ways to potentially speed up this code depending on your system. Have a look at the [Makefile](Makefile), which contains a lot of notes. The `make run` command currently uses the `-O3` optimization by default, i.e.:
|
There are many ways to potentially speed up this code depending on your system. Have a look at the [Makefile](Makefile), which contains a lot of notes. The `make run` command currently uses the `-O3` optimization by default, i.e.:
|
||||||
|
|||||||
Reference in New Issue
Block a user