PEFT documentation
Ajuste de prefijo
Ajuste de prefijo

Prefix tuning antepone una serie de vectores específicos de la tarea a la secuencia de entrada, que pueden aprenderse manteniendo el modelo preentrenado congelado. Los parámetros del prefijo se insertan en todas las capas del modelo.
El resumen del artículo es:
El fine-tuning es la forma de facto de aprovechar los grandes modelos de lenguaje preentrenados para realizar tareas de nivel inferior. Sin embargo, modifica todos los parámetros del modelo de lenguaje y, por lo tanto, requiere almacenar una copia completa para cada tarea. En este artículo, proponemos prefix-tuning, una alternativa ligera al fine-tuning para tareas de generación de lenguaje natural, que mantiene los parámetros del modelo de lenguaje congelados, pero optimiza un pequeño vector continuo específico de la tarea (llamado prefix). El prefix-tuning se inspira en el prompting, permitiendo que los tokens posteriores presten atención a este prefix como si fueran “tokens virtuales”. Aplicamos prefix-tuning a GPT-2 para la generación de texto a partir de tablas y a BART para la resumición. Descubrimos que, al aprender solo el 0,1\% de los parámetros, prefix-tuning obtiene un rendimiento comparable en el escenario de datos completos, supera al fine-tuning en escenarios con pocos datos y se extrapola mejor a ejemplos con temas no vistos durante el entrenamiento.
Nota En los modelos encoder-decoder (seq2seq), el prefijo solo se aplica al decodificador, lo cual no corresponde a la especificación del artículo (véase, por ejemplo, la Figura 2). El prefix tuning aún puede ajustarse en estas arquitecturas de modelo, pero el rendimiento podría ser inferior; considere utilizar otros métodos PEFT para los modelos encoder-decoder.
El prefix tuning es muy similar al prompt tuning. La principal diferencia es que los parámetros de prefijo se insertan en todas las capas del modelo, mientras que el prompt tuning solo añade los parámetros del prompt a las incrustaciones de entrada del modelo. Los parámetros de prefijo también se optimizan mediante una red feed-forward (FFN) separada en lugar de entrenar directamente sobre los soft prompts, ya que esto causa inestabilidad y perjudica el rendimiento. La FFN se descarta después de actualizar los soft prompts.
Como resultado, los autores encontraron que el prefix tuning demuestra un rendimiento comparable al de un ajuste completo de un modelo, a pesar de tener 1000 veces menos parámetros, y su rendimiento es aún mejor en escenarios con pocos datos.
Uso básico
Cree un PrefixTuningConfig con el tipo de tarea y el número de tokens virtuales a añadir y aprender.
from peft import PrefixTuningConfig, get_peft_model
peft_config = PrefixTuningConfig(task_type="CAUSAL_LM", num_virtual_tokens=20)
model = get_peft_model(model, peft_config)
model.print_healthcheck()Inicializaciones posibles
Por defecto, el prefix tuning utiliza tokens virtuales inicializados aleatoriamente. También existe la opción de inicializar los vectores para que sean cercanos a una operación sin efecto (si se inicializan a cero, aún desplazarán ligeramente la masa de probabilidad). Esto significa que los prefijos inyectados en la KV-cache tienen menos impacto desde el principio y reducen la varianza en el rendimiento del entrenamiento.
PEFT también proporciona utilidades para inicializar un adaptador de prefix-tuning a partir de un prefijo de caché KV existente (por ejemplo, a partir de los primeros p tokens de un prompt/corpus). Esto solo se admite cuando prefix_projection=False (el valor predeterminado), porque en ese caso los parámetros aprendidos son el propio prefijo KV.
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PrefixTuningConfig, get_peft_model, initialize_kv_prefix_from_text
base = AutoModelForCausalLM.from_pretrained("gpt2")
tok = AutoTokenizer.from_pretrained("gpt2")
peft_cfg = PrefixTuningConfig(task_type="CAUSAL_LM", num_virtual_tokens=20, prefix_projection=False)
model = get_peft_model(base, peft_cfg)
initialize_kv_prefix_from_text(
model,
tok,
text="...a long context with at least num_virtual_tokens tokens...",
use_chat_template=False,
)m peft import PrefixTuningConfig, get_peft_model, initialize_kv_prefix_from_text
base = AutoModelForCausalLM.from_pretrained("gpt2")
tok = AutoTokenizer.from_pretrained("gpt2")
peft_cfg = PrefixTuningConfig(task_type="CAUSAL_LM", num_virtual_tokens=20, prefix_projection=False)
model = get_peft_model(base, peft_cfg)
initialize_kv_prefix_from_text(
model,
tok,
text="...a long context with at least num_virtual_tokens tokens...",
use_chat_template=False,
)
Asegúrate de que el texto sea lo suficientemente largo para generar al menos num_virtual_tokens tokens; de lo contrario, la inicialización fallará.
Como orientación:
- comience con una secuencia inicial neutra usando
initialize_kv_prefix_from_text, puede ser una cadena muy corta como “Question: ” - si eso no ayuda, use una secuencia más larga con relevancia para la tarea (es decir, un prompt diseñado), lo que le dará más tokens virtuales para ajustar, pero también más control sobre el modelo
- si no es posible usar un texto de inicialización o se desea verificar rápidamente si el prefix tuning es viable en absoluto, use una inicialización cero sin proyección
Resumen de las pruebas de rendimiento
API
PrefixTuningConfig
clase peft.PrefixTuningConfig
< source >( task_type: Optional[Union[str, TaskType]] = Nonepeft_type: Optional[Union[str, PeftType]] = Noneauto_mapping: Optional[dict] = Nonepeft_version: Optional[str] = Nonebase_model_name_or_path: Optional[str] = Nonerevision: Optional[str] = Noneinference_mode: bool = Falsenum_virtual_tokens: int = Nonetoken_dim: int = Nonenum_transformer_submodules: Optional[int] = Nonenum_attention_heads: Optional[int] = Nonenum_layers: Optional[int] = Nonemodules_to_save: Optional[list[str]] = Noneinit_weights: typing.Literal['zero'] | None = Noneencoder_hidden_size: int = Noneprefix_projection: bool = False )
Parámetros
- init_weights (
Optional[str]) — Si no se establece, los pesos se inicializan de forma aleatoria; si se establece en “zero”, los pesos se inicializan de modo que las activaciones sean una operación sin efecto (cero). - encoder_hidden_size (
int) — El tamaño oculto del codificador de prompts. - prefix_projection (
bool) — Si se deben proyectar las incrustaciones del prefijo.
Esta es la clase de configuración para almacenar la configuración de un PrefixEncoder.
PrefixEncoder
clase peft.PrefixEncoder
< source >( config )
Parámetros
- config (PrefixTuningConfig) — La configuración del codificador de prefijo.
El modelo torch.nn para codificar el prefijo.
Ejemplo:
>>> from peft import PrefixEncoder, PrefixTuningConfig
>>> config = PrefixTuningConfig(
... peft_type="PREFIX_TUNING",
... task_type="SEQ_2_SEQ_LM",
... num_virtual_tokens=20,
... token_dim=768,
... num_transformer_submodules=1,
... num_attention_heads=12,
... num_layers=12,
... encoder_hidden_size=768,
... )
>>> prefix_encoder = PrefixEncoder(config)Atributos:
- embedding (
torch.nn.Embedding) — La capa de embedding del codificador de prefijo. - transform (
torch.nn.Sequential) — El MLP de dos capas para transformar los embeddings del prefijo siprefix_projectionesTrue. - prefix_projection (
bool) — Si se deben proyectar las incrustaciones del prefijo.
Forma de entrada: (batch_size, num_virtual_tokens)
Forma de salida: (batch_size, num_virtual_tokens, 2*layers*hidden)
Cargue los embeddings de prompt aplanados guardados por PEFT (prompt_embeddings).
Para el ajuste de prefijo, esto solo se admite cuando prefix_projection=False, porque en ese caso los parámetros aprendidos son el propio prefijo KV (embedding.weight tiene forma [num_virtual_tokens, num_layers*2*token_dim]).
Si prefix_projection=True, los parámetros son (embeddings de tokens virtuales + un MLP) y no existe una forma general de invertir la proyección para recuperar esos parámetros a partir de un prefijo KV aplanado.