Transformers documentation
Urmărirea output-urilor intermediare ale modelului
Urmărirea output-urilor intermediare ale modelului
Metoda forward() a fiecărui model obișnuia să rezolve manual flag-uri de tip None precum output_attentions din valorile implicite din config, să acumuleze attention weights și hidden states per layer în tuples și să convertească dataclasses ModelOutput în tuple-uri plain când return_dict=False. Doi decoratori înlocuiesc tot acel cod boilerplate.
@capture_outputsrezolvă flag-urile de ieșire, colectează valorile intermediare și gestionează conversiareturn_dict.@merge_with_config_defaultsrezolvăuse_cachedin config. Omite-l pentru modelele care nu fac cache, precumCLIPModel.
Vei întâlni acești decoratori mai ales când integrezi un model nou. Vezi adăugarea unui model în 🤗 Transformers pentru un ghid pas cu pas.
Declară ce submodule să captezi
Aplică @capture_outputs pe metoda forward() a modelului de bază. Atașează forward hooks care:
- Interceptează ieșirile din clasele de submodule specificate în timpul forward pass-ului, fără ca acele submodule să știe că sunt observate.
- Colectează attention weights și hidden states per layer în tuple-uri.
- Injectează valorile colectate în dataclass-ul
ModelOutputreturnat. - Convertesc dataclass-ul într-un tuple plain când
return_dict=False. - Rezolvă
output_attentionsșioutput_hidden_statesdin kwargs sauself.configcând suntNone.
Mapează câmpurile de ieșire la submodule
@capture_outputs trebuie să știe ce submodul produce ce ieșire. Declară un dicționar _can_record_outputs la nivel de clasă pe subclasa ta PreTrainedModel. Fiecare cheie este un nume de câmp de ieșire ("hidden_states", "attentions", "cross_attentions"), iar fiecare valoare este o clasă de modul sau o instanță OutputRecorder.
Control detaliat cu OutputRecorder
OutputRecorder acceptă un target_class (o subclasă nn.Module ale cărei output-uri să le colectezi) și un index opțional pentru a selecta ce element din tuple-ul de ieșire al modulului să ia. Pasează layer_name ca să atașezi hook-uri doar la modulele cu un nume de atribut specific. Folosește layer_name când două layers partajează aceeași clasă, de exemplu self-attention vs. cross-attention.
Exemplul de mai jos arată ambii decoratori în practică cu diferite niveluri de control al ieșirii. Vezi LlamaModel pentru o referință din lumea reală.
from ...processing_utils import Unpack
from ...utils import TransformersKwargs
from ...utils.generic import merge_with_config_defaults
from ...utils.output_capturing import capture_outputs, OutputRecorder
class MyPreTrainedModel(PreTrainedModel):
_can_record_outputs = {
# Capturează hidden_states: hook-ul se declanșează după fiecare forward MyDecoderBlock,
# luând prima ieșire (index 0 implicit).
"hidden_states": MyDecoderBlock,
# Capturează self-attention weights: hook-ul se declanșează după fiecare forward MyAttention,
# luând a doua ieșire (index=1 implicit).
"attentions": MyAttention,
# Capturează cross-attention weights: aceeași clasă, submodul diferit.
# layer_name țintește atributul `self.crossattention` din interiorul block-ului.
# Capturează a doua ieșire cum s-a cerut (index=1)
"cross_attentions": OutputRecorder(
MyAttention, layer_name="crossattention", index=1
),
}
# Acum în forward-ul modelului de bază avem nevoie de decoratori și `Unpack` `kwargs`
class MyModel(MyPreTrainedModel):
@merge_with_config_defaults # ← rezolvă use_cache
@capture_outputs # ← gestionează colectarea ieșirilor + return_dict
def forward(
self,
input_ids: torch.LongTensor | None = None,
past_key_values: Cache = None,
**kwargs: Unpack[TransformersKwargs],
) -> BaseModelOutputWithPast:
# Nu e nevoie de colectare manuală. Rulează layers normal.
hidden_states = self.embed_tokens(input_ids)
for layer in self.layers:
hidden_states = layer(hidden_states, **kwargs)
# Returnează ieșirile primare. Decoratorul va completa automat
# hidden_states/attentions/cross_attentions.
return BaseModelOutputWithPast(
last_hidden_state=hidden_states,
past_key_values=past_key_values
)Patch-uiește clasele de layers
Urmărirea output-urilor depinde de _can_record_outputs care pointează la clasele exacte pe care layer-urile modelului le instanțiază. Dacă înlocuiești o implementare de layer cu un kernel de attention personalizat, un layer de expert quantized sau o variantă arhitecturală, acei pointeri trebuie să rămână sincronizați. API-ul de patching oferă un registru global curat pentru a menține _can_record_outputs consistent.
register_patch_mapping mapează numele originale ale claselor la subclase nn.Module de înlocuire. Cheile pot fi nume exacte de clase sau pattern-uri regex. Potrivirile exacte au prioritate. Pattern-urile sunt testate cu re.search(), deci pattern-urile neancorate se potrivesc oriunde în numele clasei. Înregistrarea aceleiași chei de două ori ridică ValueError dacă nu pasezi overwrite=True.
Elimină intrările cu unregister_patch_mapping.
from transformers.monkey_patching import register_patch_mapping, unregister_patch_mapping
# Nume exact – înlocuiește doar Qwen2MoeExperts
register_patch_mapping({"Qwen2MoeExperts": SequentialExperts})
# Regex – înlocuiește orice clasă al cărei nume se termină cu "Attention"
register_patch_mapping({".*Attention$": FusedAttention})
# Versiunea ancorată – se potrivește doar cu Llama2Attention, Llama3Attention, …
register_patch_mapping({"^Llama\\d+Attention$": CustomLlamaAttention})
# La fel, cheile personalizate pot fi eliminate din registru pasând numele care a fost înregistrat
unregister_patch_mapping(["Qwen2MoeExperts", ".*Attention$"])Odată ce mapările sunt înregistrate, patch_output_recorders parcurge fiecare submodul și actualizează fiecare OutputRecorder.target_class la înlocuitorul înregistrat.
Metoda
from_pretrained()apeleazăpatch_output_recordersautomat. Trebuie să o apelezi tu doar când construiești un model direct.
from transformers.monkey_patching import patch_output_recorders
# Construit manual, în afara from_pretrained
model = Qwen2MoeModel(config)
# Fără asta, _can_record_outputs tot pointează la clasa originală Qwen2MoeExperts
# și hook-urile nu se vor declanșa niciodată pe instanțele CustomExperts.
patch_output_recorders(model)