# 学習可能なトークン

Trainable Tokensメソッドは、埋め込み行列全体を学習したり、埋め込み行列にアダプターを適用したりすることなく、特定のトークン埋め込みをファインチューニングの対象とする方法を提供します。この手法は、[こちら](https://github.com/huggingface/peft/pull/1541)の初期実装に基づいています。

このメソッドは特定のトークンにのみ対象を絞り、指定したトークンインデックスを選択的に学習します。その結果、必要なRAMは低くなり、完全なファインチューニング済み埋め込み行列を保存する場合と比べてディスクメモリも大幅に少なくなります。

`gemma-2-2b`（埋め込み行列が比較的大きい）では、[このスクリプト](https://github.com/huggingface/peft/blob/main/scripts/train_memory.py)で取得した予備的なベンチマークの結果から、埋め込み行列の完全なファインチューニングと比較して、Trainable Tokens を使用することで約 4 GiB の VRAM を節約できることが示唆されています。LoRA も同程度の VRAM を使用しますが、変更したくないトークンも対象となる可能性があります。なお、これらはあくまで目安であり、埋め込み行列のサイズによってこれらの数値が多少変動する可能性があります。

このメソッドはトークンを追加しません。トークナーにトークンを追加し、モデルの埋め込み行列をそれに応じてリサイズする必要があります。このメソッドは、指定したトークンの埋め込みのみを再学習します。このメソッドはLoRAレイヤーと併用することもできます。[LoRAのドキュメント](lora#efficiently-train-tokens-alongside-lora)を参照してください。

> [!TIP]
> 新しいトークンを追加する場合、[save_pretrained()](/docs/peft/main/ja/package_reference/peft_model#peft.PeftModel.save_pretrained) でモデルを保存したり、[get_peft_model_state_dict()](/docs/peft/main/ja/package_reference/peft_model#peft.get_peft_model_state_dict) で状態辞列を取得したりすると、埋め込み行列がリサイズされたため、差分のみではなく、埋め込み行列全体を保存する可能性があります。これは予防措置です。容量を節約するには、`save_pretrained` を呼び出す際に `save_embedding_layers=False` を設定して、この動作を無効にできます。埋め込み行列を他の方法で変更しない限り、この変更は学習可能なトークンによって追跡されないため、安全に実行できます。

## ベンチマーク概要

<iframe src="https://peft-internal-testing-peft-method-comparison-embed.hf.space/?highlight[type]=TRAINABLE_TOKENS" frameborder="0" width="850" height="1000"
>

# API

## TrainableTokensConfig[[peft.TrainableTokensConfig]]

#### peft.TrainableTokensConfig[[peft.TrainableTokensConfig]]

```python
peft.TrainableTokensConfig(task_type: Optional[Union[str, TaskType]] = None, peft_type: Optional[Union[str, PeftType]] = None, auto_mapping: Optional[dict] = None, peft_version: Optional[str] = None, base_model_name_or_path: Optional[str] = None, revision: Optional[str] = None, inference_mode: bool = False, token_indices: list[int] = <factory>, target_modules: Optional[Union[list[str], str]] = None, init_weights: bool = True)
```

[ソース](https://github.com/huggingface/peft/blob/main/src/peft/tuners/trainable_tokens/config.py#L25)

**パラメータ:**

token_indices (`list[int]`) : 学習可能なトークンのインデックスを示す整数のリストです。トークナイザーでトークンのインデックスを調べるには、文字列をトークン化して返される`input_ids`を確認できます。インデックスの数がトークンの総数に近づくほど、この方法の効率は低下します。

target_modules (`Optional[Union[list[str], str]]`) : `TrainableTokensLayer`に置き換えるモジュール名のリスト、またはモジュール名の正規表現です。定義されていない場合、モデルに`get_input_embeddings`メソッドがある場合（transformerモデルには通常あります）、モデルの入力埋め込み層を取得しようとします。それが失敗した場合、デフォルトは'embed_tokens'です。その他のターゲットの例としては、`embedding`、`encoder.embeddings`、または`decoder.embeddings`があります。

init_weights (`bool`) : デフォルトでは、新しいトークンの重みは、対応するトークン埋め込みと同じ値で初期化されます。これにより、学習を行わない場合、TrainableTokensは何もしない（no-op）状態になります。`False`に設定すると、重みはランダムな値になります。正確に意図していることが明確でない限り、この設定を変更しないでください。

`TrainableTokens`メソッドの設定。

新しいトークンの学習（および既存トークンの再学習）を、埋め込み行列全体を学習せずに実行できます。一部の選択したトークン（インデックスで識別）を学習可能にし、残りは変更しないことで、この手法はメモリを節約しながら新しいトークンを追加したり、既存トークンの埋め込みを変更したりするために使用できます。埋め込み行列を完全に学習する場合と比べて、ストレージおよびワーキングメモリの使用量が削減されます。

FSDP/DeepSpeedでのトレーニングがまだ完全にサポートされていない可能性があることに注意してください。

## TrainableTokensModel[[peft.TrainableTokensModel]]

#### peft.TrainableTokensModel[[peft.TrainableTokensModel]]

```python
peft.TrainableTokensModel(model, peft_config: Union[PeftConfig, dict[str, PeftConfig]], adapter_name: str, low_cpu_mem_usage: bool = False, state_dict: Optional[dict[str, torch.Tensor]] = None)
```

[ソース](https://github.com/huggingface/peft/blob/main/src/peft/tuners/trainable_tokens/model.py#L26)

