PEFT documentation

Lily: Adaptación de bajo rango interconectada entre capas

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.21.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Lily: Adaptación de bajo rango interconectada entre capas

Lily es una técnica de ajuste fino eficiente en parámetros que introduce el intercambio de pesos entre capas para las matrices de adaptador. En lugar de aprender un par AB independiente por capa, como en LoRA, Lily utiliza adaptadores A compartidos localmente (cada A se comparte entre un bloque de stride_A capas consecutivas) y expertos B compartidos globalmente (un pequeño conjunto de num_B adaptadores B se comparte entre todas las capas). En cada pasada hacia adelante, un enrutador ligero dependiente de los datos calcula una combinación ponderada con softmax de los expertos B para producir el B efectivo para esa capa y entrada.

Este intercambio puede reducir el número total de matrices de adaptador de 2N (LoRA estándar) a N / stride_A + num_B, liberando el presupuesto de parámetros para usar un rango r mucho mayor —típicamente 2×–4× lo que se usaría en LoRA. Un rango más alto y una mejor interconectividad aumentan el rango efectivo de la actualización de pesos ΔW = A × combined_B, lo que conduce a un mejor rendimiento de adaptación.

Dado que la combinación B es dependiente de los datos (los pesos del router dependen de las activaciones de entrada en tiempo de ejecución), merge y unmerge no están soportados. Si se requiere la fusión de pesos para su despliegue, considere otros métodos, como LoRA.

Lily tiene actualmente las siguientes restricciones adicionales:

  • Solo se admiten capas nn.Linear.
  • No se admiten capas cuantizadas.

Si estas restricciones no se ajustan a su caso de uso, considere otros métodos.

El resumen del artículo es:

La adaptación de bajo rango (LoRA) es un método de ajuste fino eficiente en parámetros (PEFT) ampliamente utilizado que aprende actualizaciones de pesos ΔW = AB para los pesos preentrenados W a través de adaptadores de bajo rango A y B. Si bien LoRA garantiza la eficiencia de hardware, sus actualizaciones de pesos de bajo rango limitan el rendimiento de la adaptación. En este artículo, proponemos la adaptación interconectada de bajo rango entre capas (Lily), un nuevo método PEFT que introduce un marco interconectado con expertos A compartidos localmente y expertos B compartidos globalmente. Esta estructura elimina las pares AB redundantes por capa, lo que permite un ΔW de rango superior con igual o menor número de parámetros. Para mejorar la expresividad, utilizamos enrutadores dependientes de los datos para determinar las interconexiones A-B, evitando que los expertos B converjan al mismo comportamiento y mejorando el poder representativo entre dominios. Los experimentos en diferentes modalidades, arquitecturas y tamaños de modelo demuestran el rendimiento y la eficiencia superiores de Lily.

Resumen de las pruebas de rendimiento

API

LilyConfig

clase peft.LilyConfig

< >

( 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 = Falser: int = 32stride_A: int = 1num_B: int = 2scaling: float = 1.0target_modules: Optional[Union[list[str], str]] = Noneexclude_modules: Optional[Union[list[str], str]] = Nonemodules_to_save: Optional[list[str]] = Nonelayers_to_transform: Optional[Union[list[int], int]] = Nonelayers_pattern: Optional[Union[list[str], str]] = Noneinit_weights: bool = True )

Parámetros

  • r (int) — Rango de Lily. Determina la dimensión oculta interna de cada adaptador y el rango de la actualización de pesos A @ B. En Lily, dado que el número de adaptadores suele ser menor que en LoRA, cada adaptador necesita tener más capacidad, por lo que se recomienda usar un r mayor que en LoRA, típicamente 2x, 3x o 4x el rango de LoRA que se usaría normalmente. El número total de parámetros entrenables escala con r * (total_layers / stride_A + num_B), por lo que aumentar r manteniendo stride_A grande y num_B pequeño es el compromiso recomendado.
  • stride_A (int) — El número de capas consecutivas que comparten un adaptador A. Por ejemplo, si stride_A=4, cada 4 capas adyacentes comparten el mismo adaptador A, lo que resulta en total_layers / stride_A adaptadores A distintos en total. El adaptador A comprime la entrada en una representación de bajo rango de tamaño r. stride_A no debe ser menor que
    1. Valores sugeridos: 2, 3 o 4 (es decir, compartir cada 2, 3 o 4 capas). Mantener stride_A grande (menos adaptadores A distintos) y aumentar r en su lugar conduce a un mejor rendimiento que el compromiso opuesto (pequeño stride_A, pequeño r). Establecer stride_A=1 significa que cada capa tiene su propio adaptador A. NOTA: el compartimiento de A ocurre dentro de cada objetivo (capas con el mismo sufijo de objetivo). Por ejemplo, si sus target_modules son ['q_proj', 'v_proj'] y establece stride_A=2, entonces cada 2 capas q_proj adyacentes compartirán un adaptador A, y cada 2 capas v_proj adyacentes compartirán otro adaptador A, pero las capas q_proj y v_proj no compartirán adaptadores A entre sí ya que tienen sufijos diferentes.
  • num_B (int) — El número de adaptadores B compartidos. A diferencia de los adaptadores A (que se agrupan por capa), todos los adaptadores B se comparten globalmente entre todas las capas. En cada pasada hacia adelante, un router calcula una combinación ponderada de todos los num_B adaptadores B (usando pesos normalizados con softmax) para producir un único adaptador B combinado, que luego proyecta la representación de bajo rango de vuelta a la dimensión original. Se recomienda establecer num_B en un orden similar al de total_layers / stride_A. Valores sugeridos: total_layers / 2, total_layers / 3 o total_layers / 4. Al igual que con stride_A, se prefiere un num_B más pequeño con un r más grande que un num_B más grande con un r más pequeño. NOTA: para entrenar el router, se necesitan al menos 2 adaptadores B (es decir, num_B >= 2), ya que el router aprende a calcular una combinación ponderada de los adaptadores B. NOTA: el compartimiento de B ocurre dentro de cada objetivo (capas con el mismo sufijo de objetivo). Por ejemplo, si tus target_modules son ['q_proj', 'v_proj'] y estableces num_B=4, entonces habrá 4 adaptadores B compartidos entre todas las capas q_proj, y otros 4 adaptadores B compartidos entre todas las capas v_proj, pero las capas q_proj y v_proj no compartirán adaptadores B entre sí, ya que tienen sufijos diferentes.
  • target_modules (Union[List[str], str], opcional) — Los nombres de los módulos a los que se aplicará Lily. Puede ser una lista de cadenas de nombres de módulos (p. ej. ['q_proj', 'v_proj']) o un patrón de expresión regular (p. ej. '.*decoder.*(SelfAttention|EncDecAttention).*(q|v)$'). Si no se especifica, Lily se aplicará a todas las capas lineales compatibles.
  • scaling (float) — Un multiplicador escalar aplicado a la salida combinada del adaptador (scaling * A @ combined_B) antes de sumarla a la paso de adelante del peso congelado. A diferencia de LoRA, Lily no utiliza una formulación de alpha / r; en su lugar, scaling es un multiplicador directo. Este diseño facilita realizar barridos de valores en una escala logarítmica (p. ej. 0.01, 0.1, 1.0, 10.0). El valor óptimo depende de la tarea y debe tratarse como un hiperparámetro. Recomendamos comenzar con 1.0.
  • modules_to_save (List[str], opcional) — Lista de módulos, aparte de las capas de Lily, que se configurarán como entrenables y se guardarán en el checkpoint final. Por ejemplo, en tareas de clasificación de secuencias o clasificación de tokens, la capa final classifier/score se inicializa aleatoriamente y, por lo tanto, debe ser entrenable y guardada.
  • exclude_modules (Union[List[str], str], opcional) — Los nombres de los módulos a los que no se aplicará el adaptador. Al pasar una cadena de caracteres, se realizará una coincidencia con una expresión regular. Al pasar una lista de cadenas de caracteres, se realizará una coincidencia exacta o se comprobará si el nombre del módulo termina con alguna de las cadenas de caracteres pasadas.
  • layers_to_transform (Union[list[int], int], opcional) — Los índices de las capas a transformar. Si se especifica este argumento, PEFT transformará únicamente los índices de las capas especificados en esta lista. Si se pasa un solo entero, PEFT transformará únicamente la capa en ese índice.
  • layers_pattern (Optional[Union[List[str], str]], opcional) — El nombre del patrón de capas, utilizado solo si layers_to_transform es diferente de None y si el patrón de capas no está en el patrón de capas común. Esto debe apuntar al nn.ModuleList del modelo, que a menudo se llama 'layers' o 'h'.
  • init_weights (bool) — Si se deben inicializar los pesos del adaptador Lily usando el esquema de inicialización predeterminado: las matrices A se inicializan con Kaiming uniform y las matrices B se inicializan a cero, lo que garantiza que la salida del adaptador sea cero al inicio del entrenamiento y no altere el modelo preentrenado. Se recomienda encarecidamente mantenerlo como True a menos que se tenga una razón específica para cambiarlo.

Esta es la clase de configuración para almacenar la configuración de un LilyModel.

LilyModel

clase peft.LilyModel

< >

( modelpeft_config: Union[PeftConfig, dict[str, PeftConfig]]adapter_name: strlow_cpu_mem_usage: bool = Falsestate_dict: Optional[dict[str, torch.Tensor]] = None ) → torch.nn.Module

Parámetros

  • model (torch.nn.Module) — El modelo que se va a adaptar.
  • config (LilyConfig) — La configuración del modelo Lily.
  • adapter_name (str) — El nombre del adaptador, por defecto es "default".

Devuelve

torch.nn.Module

El modelo PEFT de Lily.

Crea un modelo Low-Rank Interconnected Adaptation Across Layers (Lily) a partir de un modelo de transformers preentrenado.

El método se describe en detalle en https://arxiv.org/abs/2407.09946.

Atributos:

Update on GitHub