# トークナイザーのカスタマイズ

Tokenizer は学習された語彙から分離されています。これにより、学習用の空の Tokenizer を初期化したり、独自の語彙を直接指定して作成したりできます。基盤となるトークナイズ処理パイプライン（正規化器、プレトークナイザー、トークナイズアルゴリズム）は同じままであるため、ゼロから再作成する必要はありません。

このガイドでは、カスタムトークナイザーの学習と作成方法を示します。

## トークナイザーの学習

空の学習可能トークナイザーは、語彙を新しいターゲット語彙に置き換えます。これは、金融のような新しいドメイン、低リソース言語、またはコードへの適応に役立ちます。

空のトークナイザーを作成し、データセットを読み込みます。

```py
from datasets import load_dataset
from transformers import GemmaTokenizer

tokenizer = GemmaTokenizer()
dataset = load_dataset("Josephgflowers/Finance-Instruct-500k", split="train")
```

[TokenizersBackend.train_new_from_iterator()](/docs/transformers/main/ja/main_classes/tokenizer#transformers.TokenizersBackend.train_new_from_iterator) メソッドを使用して、トークナイザーを学習します。このメソッドは、データセット全体を一度にメモリに読み込まずに、ジェネレーター関数を通じてテキストのチャンクを返すことを受け入れます。`vocab_size` 引数は、トークナイザーの語彙サイズを設定します。

```py
def batch_iterator(batch_size=1000):
    for i in range(0, len(dataset), batch_size):
        yield dataset[i : i + batch_size]["assistant"]

trained_tokenizer = tokenizer.train_new_from_iterator(
    batch_iterator(),
    vocab_size=32000,
)
encoded = trained_tokenizer("The stock market rallied today.")
print(encoded["input_ids"])
[5866, 11503, 98, 5885, 8617, 13381, 30]
```

`new_special_tokens` 引数で新しい特殊トークンを追加するか、`special_tokens_map` を使用して古い特殊トークンを新しい特殊トークンにリネームしてください。

新しい finance トークナイザーを [save_pretrained()](/docs/transformers/main/ja/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.save_pretrained) で保存するか、[push_to_hub()](/docs/transformers/main/ja/main_classes/model#transformers.utils.PushToHubMixin.push_to_hub) で保存して Hub にアップロードします。これにより、新しく学習された語彙、マージルール、および完全なパイプライン設定を記録した `tokenizer.json` ファイルが作成されます。

```py
trained_tokenizer.save_pretrained("./finance-gemma-tokenizer")
trained_tokenizer.push_to_hub("finance-gemma-tokenizer")
```

## カスタム語彙

空のtokenizerは、`vocab`と`merges`引数によってカスタム語彙をサポートします。

- `vocab` は、トークナイザーが認識するトークンの完全な集合であり、各エントリはトークンとその入力 ID を対応付けます。
- `merges` は、BPE アルゴリズムが隣接するトークンをどのように結合すべきかを定義します。

```py
from transformers import GemmaTokenizer

vocab={
    "<pad>": 0,
    "</s>": 1,
    "<s>": 2,
    "<unk>": 3,
    "<mask>": 4,
    "▁the": 5,
    "▁stock": 6,
    "▁market": 7,
    "▁": 8,
    "r": 9,
    "a": 10,
    "l": 11,
    "i": 12,
    "e": 13,
    "d": 14,
    "ra": 15,
    "li": 16,
    "lie": 17,
    "lied": 18,
    "ral": 19,
    "ralli": 20,
    "rallie": 21,
    "rallied": 22,
}
merges=[
    ("r", "a"),       # r + a → ra
    ("l", "i"),       # l + i → li
    ("li", "e"),      # li + e → lie
    ("lie", "d"),     # lie + d → lied
    ("ra", "l"),      # ra + l → ral
    ("ral", "li"),    # ral + li → ralli
    ("ralli", "e"),   # ralli + e → rallie
    ("rallie", "d"),  # rallie + d → rallied
]

tokenizer = GemmaTokenizer(vocab=vocab, merges=merges)
encoded = tokenizer("the stock market rallied")
print(encoded["input_ids"])
```

## TokenizersBackend のサブクラス化

Tokenizers は 4 つの異なる [バックエンド](./fast_tokenizers#backends) をサポートしています。一般的には、[TokenizersBackend](/docs/transformers/main/ja/main_classes/tokenizer#transformers.TokenizersBackend) を使用して新しいトークナイザーを定義することをお勧めします。より高速だからです。

> [!TIP]
> [PythonBackend](/docs/transformers/main/ja/main_classes/tokenizer#transformers.PythonBackend) は、Rust、SentencePiece、mistral-common などのバックエンドに依存しない、純粋な Python によるトークナイザーです。[PythonBackend](/docs/transformers/main/ja/main_classes/tokenizer#transformers.PythonBackend) は、Rust バックエンドでは表現できない非常に特殊なトークナイザーを構築する場合にのみ使用してください。

1. クラス属性としてパディング側や使用するトークナイズアルゴリズムなどを指定して、[TokenizersBackend](/docs/transformers/main/ja/main_classes/tokenizer#transformers.TokenizersBackend)をサブクラス化します。
2. `__init__`内でトークナイズパイプラインを定義します。これには、使用するトークナイズアルゴリズム、アルゴリズム適用前に生テキストをどのように分割するか、そしてトークンをどのようにテキストにデコードするかを含みます。

```py
from tokenizers import Tokenizer, decoders, pre_tokenizers
from tokenizers.models import BPE
from transformers import TokenizersBackend

class NewTokenizer(TokenizersBackend):
    padding_side = "left"
    model = BPE

    def __init__(
        self,
        vocab=None,
        merges=None,
        unk_token="<unk>",
        bos_token="<s>",
        eos_token="</s>",
        pad_token="<pad>",
    ):
        self._vocab = vocab or {
            str(unk_token): 0,
            str(bos_token): 1,
            str(eos_token): 2,
            str(pad_token): 3,
        }
        self._merges = merges or []

        self._tokenizer = Tokenizer(
            BPE(vocab=self._vocab, merges=self._merges, fuse_unk=True)
        )
        self._tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
        self._tokenizer.decoder = decoders.ByteLevel()

        super().__init__(
            unk_token=unk_token,
            bos_token=bos_token,
            eos_token=eos_token,
            pad_token=pad_token,
        )
```

新しい空のトークナイザーを学習するか、保存します。

```py
tokenizer = NewTokenizer()

# train on new corpus
corpus = ["The stock market rallied today.", "Bond yields fell sharply."]
trained_tokenizer = tokenizer.train_new_from_iterator(corpus, vocab_size=32000)
# save tokenizer
trained_tokenizer.save_pretrained("./new-tokenizer")
```

