Transformers documentation
レイヤーごとの設定
レイヤーごとの設定
一部のチェックポイントは非均質(レイヤー間で均一でない)です。あるレイヤーでMLPが小さく、別のレイヤーでキーバリューヘッド数が少ない、あるいは特定のレイヤーでレイアウトが異なる場合、単一のグローバルな設定ではスタックを正確に記述できません。
設定の作成や確認を行う際、およびモデルコードがそれらを消費する際には、PreTrainedConfig の per_layer_config を使用して、これらの差分を記録します。各エントリは、グローバルな設定と異なる部分のみを保存し、残りは継承されます。
ヘテロジニアスな構成は強力な機能です。ヘテロジニアスなレイアウトが一般的かつ目立つアーキテクチャとなった場合、
per_layer_configに依存するのではなく、アーキテクチャの実装内で明示的にモデル化するように努めます。明示的なアーキテクチャが存在する場合は、そちらを優先してください。
以下のモデルは、ヘテロジニアスなチェックポイントです。スタック全体でレイヤーが均一ではありません。標準アーキテクチャのper_layer_configではなく、block_configsと独自のmodel_typeを持つ専用アーキテクチャを使用しています。
レイヤーごとのオーバーライドを定義する
per_layer_config を LlamaConfig に、レイヤーインデックスから属性の上書きへのマッピングとして渡します。レイヤーインデックスはゼロベースです。グローバルな設定と異なる属性のみを指定すれば十分です。
per_layer_config は設定値を記録し、解決します。それ自体では、モデルが生成するモジュールや、それらのモジュールの実行方法を変更しません。サイズの上書きや skip を適用するには、各レイヤーを構築または実行する際に、解決済みのレイヤー別設定を読み取るモデルコードが必要です。現在の LlamaModel はすべての LlamaDecoderLayer をグローバル設定で構築するため、以下の skip エントリは設定値のままとなり、from_pretrained 後にモジュールを削除することにはなりません。
次の例では、4つの層のオーバーライドを記録します。層5はより小さいMLPを使用し、層11はより少ないキーバリューヘッドを使用します。また、層23と層27は、それらをサポートするアーキテクチャに対してskip値を記録します。
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] にアクセスすると、解決済みのレイヤー設定が返されます。解決済みの設定は、グローバル設定と、そのレイヤーに対するオーバーライドを組み合わせます。
# 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() と 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 は、意図的にグローバルフォールバックを必要とし、非一様な設定を処理できる場合にのみ設定してください。この設定により、グローバルアクセスが許可されます。警告は一度だけ出力されます。
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 はデフォルトでスパースにシリアライズされ、オーバーライドがないレイヤーは省略されます。グローバルの値と一致するオーバーライドされた属性も省略されます。
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 で表される属性のすべてのレイヤーが含まれます。これにより、一部の値がグローバル設定と一致している場合でも、レイヤーの構成をより容易に確認できるようになります。
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},
# }コンパクトな設定にはスパースシリアライズを使用し、可読性やツール利用のためにレイヤーごとの完全なレイアウトが必要な場合は、明示的なシリアライズを使用してください。
Update on GitHub