# レイヤーごとの設定

一部のチェックポイントは非均質（レイヤー間で均一でない）です。あるレイヤーでMLPが小さく、別のレイヤーでキーバリューヘッド数が少なく、特定のレイヤーでレイアウトが異なる場合、単一のグローバルな設定ではスタックを正確に記述できません。

設定の作成や確認、およびモデルコードがそれらを消費する場面では、[PreTrainedConfig](/docs/transformers/main/ja/main_classes/configuration#transformers.PreTrainedConfig) の `per_layer_config` を使用して、これらの差分を記録します。各エントリは、グローバルな設定と異なる部分のみを保存し、それ以外は継承されます。

> [!NOTE]
> Heterogeneous configurations は強力な機能です。Heterogeneous なレイアウトが一般的かつ主要なアーキテクチャとなった場合、`per_layer_config` に依存するのではなく、アーキテクチャの実装内で明示的にモデル化するように努めます。明示的なアーキテクチャが存在する場合は、そちらを優先してください。

以下のモデルは、ヘテロジニアスなチェックポイントです。スタック全体でレイヤーが均一ではありません。標準アーキテクチャの`per_layer_config`ではなく、`block_configs`と独自の`model_type`を持つ専用アーキテクチャを使用しています。

| モデル | 派生元 |
|---|---|
| [nvidia/Llama-3_3-Nemotron-Super-49B-v1_5](https://huggingface.co/nvidia/Llama-3_3-Nemotron-Super-49B-v1_5) | [meta-llama/Llama-3.3-70B-Instruct](https://huggingface.co/meta-llama/Llama-3.3-70B-Instruct) |
| [nvidia/Llama-3_1-Nemotron-Ultra-253B-v1](https://huggingface.co/nvidia/Llama-3_1-Nemotron-Ultra-253B-v1) | [meta-llama/Llama-3.1-405B-Instruct](https://huggingface.co/meta-llama/Llama-3.1-405B-Instruct) |
| [nvidia/gpt-oss-puzzle-88B](https://huggingface.co/nvidia/gpt-oss-puzzle-88B) | [openai/gpt-oss-120b](https://huggingface.co/openai/gpt-oss-120b) |
| [nvidia/NVIDIA-Nemotron-Labs-3-Puzzle-75B-A9B-BF16](https://huggingface.co/nvidia/NVIDIA-Nemotron-Labs-3-Puzzle-75B-A9B-BF16) | [nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-BF16](https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-BF16) |

## レイヤーごとのオーバーライドを定義する

`per_layer_config` を [LlamaConfig](/docs/transformers/main/ja/model_doc/llama2#transformers.LlamaConfig) に、レイヤーインデックスから属性の上書きへのマッピングとして渡します。レイヤーインデックスはゼロベースです。グローバルな設定と異なる属性のみを指定すれば十分です。

`per_layer_config` は設定値を記録し、解決します。それ自体では、モデルが生成するモジュールや、それらのモジュールの実行方法を変更しません。サイズの上書きや `skip` を適用するには、各レイヤーを構築または実行する際に、解決済みのレイヤー別設定を読み取るモデルコードが必要です。現在の `LlamaModel` はすべての `LlamaDecoderLayer` をグローバル設定で構築するため、以下の `skip` エントリは設定値のままとなり、`from_pretrained` 後にモジュールを削除するものではありません。

次の例では、4つの層のオーバーライドを記録します。層5ではより小さいMLPを使用し、層11ではより少ないキーバリューヘッドを使用します。また、層23と層27では、それらをサポートするアーキテクチャに対して`skip`値を記録します。

```py
from transformers import LlamaConfig

config = LlamaConfig(
    hidden_size=4096,
    intermediate_size=14336,
    num_hidden_layers=32,
    num_attention_heads=32,
    num_key_value_heads=8,
    per_layer_config={
        # Use a smaller MLP in one layer.
        5: {"intermediate_size": 8192},

        # Use fewer key-value heads in another layer.
        11: {"num_key_value_heads": 4},

        # Record a request to skip the MLP in architectures that support it.
        23: {"skip": ["mlp"]},

        # Record a request to skip attention in architectures that support it.
        27: {"skip": ["attention"]},
    },
)
```

アーキテクチャがスキップできるサブモジュール（例: `"mlp"` や `"attention"`）は、アーキテクチャごとに定義されています。`skip` はリストを受け取るため、1つのレイヤーで複数のサブモジュールのオーバーライドを記録できます。

`config.per_layer_config[layer_idx]` にアクセスすると、解決済みのレイヤー設定が返されます。解決済みの設定は、グローバル設定と、そのレイヤーに対するオーバーライドを組み合わせものです。

```py
# Layer 0 does not define overrides, so it inherits the global values.
config.per_layer_config[0].intermediate_size
# 14336

config.per_layer_config[0].num_key_value_heads
# 8

# Layer 5 overrides the MLP intermediate size.
config.per_layer_config[5].intermediate_size
# 8192

# Layer 11 overrides the number of key-value heads.
config.per_layer_config[11].num_key_value_heads
# 4

# Layer 23 records an MLP skip.
config.per_layer_config[23].skip
# ["mlp"]

# Layer 27 records an attention skip.
config.per_layer_config[27].skip
# ["attention"]
```

`per_layer_config` を使用した設定は、他の設定と同様に、[save_pretrained()](/docs/transformers/main/ja/main_classes/configuration#transformers.PreTrainedConfig.save_pretrained) と [from_pretrained()](/docs/transformers/main/ja/main_classes/configuration#transformers.PreTrainedConfig.from_pretrained) による往復（保存と読み込み）をサポートしています。

各アーキテクチャは、そのコード内でレイヤーレベルで消費する属性を定義しています。`per_layer_config` は、これらのレイヤーレベルの差分を記録し、グローバルな設定に対して解決するための仕組みを提供します。

## グローバル属性へのアクセス

レイヤーごとのオーバーライドを持つ属性には、モデル全体に適用される単一の値がありません。`num_key_value_heads`は、ほとんどのレイヤーでは`8`であり、特定のレイヤーでは`4`である可能性があります。レイヤーのコンテキスト外で`config.num_key_value_heads`を読み取ると、意味が曖昧になります。

デフォルトでは、そのアクセスは`AmbiguousGlobalPerLayerAttributeError`を発生させ、`config.per_layer_config[layer_idx]`への参照を促します。グローバルなconfigにはその属性がまだ存在するため、これは`AttributeError`ではありません。レイヤーインデックスを指定せずにそのグローバルな値を読み取ることは、依然として誤りです。グローバルな`num_key_value_heads`からキーバリューキャッシュを構築するコードは、誤ったレイヤーのサイズを正しく設定できません。

`allow_global_per_layer_attribute_access=True` は、意図的にグローバルフォールバックを必要とし、非一様な設定を処理できる場合にのみ設定してください。この設定により、グローバルアクセスが許可されます。警告は一度だけ出力されます。

```py
config = LlamaConfig(
    hidden_size=4096,
    intermediate_size=14336,
    num_hidden_layers=32,
    num_attention_heads=32,
    num_key_value_heads=8,
    allow_global_per_layer_attribute_access=True,
    per_layer_config={
        11: {"num_key_value_heads": 4},
    },
)

config.num_key_value_heads
# 8
# Emits a one-time warning because num_key_value_heads has a per-layer override.
```

## シリアライズ

`per_layer_config` はデフォルトでスパースにシリアライズされ、オーバーライドがないレイヤーは省略されます。グローバルの値と一致するオーバーライドされた属性も省略されます。

```py
from transformers import LlamaConfig

config = LlamaConfig(
    hidden_size=4096,
    intermediate_size=14336,
    num_hidden_layers=4,
    num_attention_heads=32,
    num_key_value_heads=8,
    per_layer_config={
        0: {"num_key_value_heads": 8},
        2: {"num_key_value_heads": 4},
    },
)

config.to_dict()["per_layer_config"]
# {"2": {"num_key_value_heads": 4}}
```

`serialize_explicit_per_layer_config=True` を設定すると、`per_layer_config` で表される属性のすべてのレイヤーが含まれます。これにより、一部の値がグローバル設定と一致している場合でも、レイヤーの構成をより容易に確認できるようになります。

```py
explicit_config = LlamaConfig(
    hidden_size=4096,
    intermediate_size=14336,
    num_hidden_layers=4,
    num_attention_heads=32,
    num_key_value_heads=8,
    serialize_explicit_per_layer_config=True,
    per_layer_config={
        0: {"num_key_value_heads": 8},
        2: {"num_key_value_heads": 4},
    },
)

serialized_per_layer_config = explicit_config.to_dict()["per_layer_config"]

serialized_per_layer_config
# {
#     "0": {"num_key_value_heads": 8},
#     "1": {"num_key_value_heads": 8},
#     "2": {"num_key_value_heads": 4},
#     "3": {"num_key_value_heads": 8},
# }
```

コンパクトな設定にはスパースシリアライズを使用し、可読性やツール利用のためにレイヤーごとの完全なレイアウトが必要な場合は、明示的なシリアライズを使用してください。

