【LLM】Práctica de ajuste fino de modelo grande de ajuste rápido

nota

  • El ajuste rápido se puede considerar como una versión simplificada del ajuste de prefijo. Agregar tokens rápidos a la capa de entrada no necesita agregar MLP para ajustar para resolver problemas de entrenamiento difíciles. Los experimentos del autor muestran que con el aumento de los parámetros del modelo de entrenamiento previo, el se acerca el efecto de ajuste rápido.

1. Sintonización rápida

1. Sintonización en la biblioteca peft

  • Como se mencionó anteriormente, peftel ajuste fino se puede realizar con la ayuda de la biblioteca (ajuste fino de eficiencia de parámetros), que admite el siguiente ajuste:
    • Adaptación del adaptador (fija los parámetros del modelo original preentrenado y solo afina el nuevo adaptador)
    • Ajuste de prefijo (construya una sección de tokens virtuales relacionados con tareas como un prefijo antes de ingresar el token, y solo actualice los parámetros independientemente del prefijo durante el entrenamiento, mientras que otros parámetros del transformador son fijos, similar a la construcción del aviso, excepto que el la solicitud se construye artificialmente y no se puede actualizar los parámetros durante el entrenamiento del modelo, y el prefijo puede aprender la solicitud <implícita>)
    • Prompt Tuning (versión simplificada de Prefix Tuning, solo agrega tokens de solicitud en la capa de entrada, no necesita agregar MLP)
    • P-tuning (transformar el aviso en una capa de incrustación aprendible, v2 agrega tokens de avisos como entrada)
    • LoRA (adaptación de rango bajo, para resolver el problema de que el adaptador aumenta la profundidad del modelo y aumenta el tiempo de razonamiento del modelo, el mensaje en el ajuste anterior es más difícil de entrenar y reduce la longitud de secuencia disponible del modelo)
      • Este método puede agregar directamente las dos matrices AB entrenadas a los parámetros del modelo de preentrenamiento original durante la inferencia, y reemplazar los parámetros del modelo de preentrenamiento original con el resultado de la suma.
      • Equivale a simular el proceso de sintonización completa con LoRA

2. Cómo hacer una sintonización rápida

  • Dar un buen aviso puede permitir que LLM genere mejores respuestas. A su vez, quiero usar LLM para ayudarnos a encontrar un buen aviso es la idea de ajuste de aviso. El entrenamiento le permite al modelo ver un nuevo ejemplo para generar un aviso, y empalmando el indicador como un prefijo Vaya a nuestro propio indicador, envíelo a LLM para obtener el resultado
    • El prefijo de entrenamiento de afinación rápida es un vector, por lo que la interpretación es un poco peor
  • Comparado con pocos programas: la duración del contexto de LLM es limitada (se dan ejemplos limitados en el mensaje, es difícil que el modelo aprenda suficiente conocimiento cuando el negocio es complejo), el ajuste del mensaje no tiene esta limitación, solo muéstrelo a él al entrenar LLM suficientes ejemplos,Luego haga preguntas con un breve prefijo rápido (generalmente de 8 a 20 fichas)
  • En comparación con el ajuste fino: el ajuste rápido consiste en congelar por completo los parámetros del modelo LLM, solo necesita entrenar un prefijo rápido de varios tokens; pero el ajuste fino requiere muchos recursos para ajustar un modelo
  • Agregue una o más incrustaciones para cada tarea y luego empalme la consulta en LLM normalmente, y solo entrene estas incrustaciones. Como se muestra en la figura a continuación, la imagen de la izquierda muestra el ajuste fino de parámetros completos de una sola tarea, y la imagen de la derecha muestra el ajuste rápido.
    • El ajuste rápido convierte las tareas de ajuste fino en tareas de mlm. Plantillas de aprendizaje automático: las discretas incluyen principalmente Minería de avisos, Paráfrasis de avisos, Búsqueda basada en gradientes, Generación de avisos y Puntuación de avisos; las continuas incluyen principalmente Ajuste de prefijo, Ajuste inicializado con avisos discretos y Ajuste híbrido de avisos duro-soft.
    • Ejemplo de ajuste fino normal: [cls] El sol está en el cielo hoy, y el sol brilla intensamente. [SEP]
      Ejemplo de entrada de solicitud: [cls] El clima de hoy es [MASK]. [SEP] El sol está en el cielo hoy, y el sol brilla intensamente. [SEP]

inserte la descripción de la imagen aquí

3. Cómo elegir los parámetros

ajuste rápido论文:El poder de la escala para el ajuste rápido de parámetros eficientes

inserte la descripción de la imagen aquí

  • El experimento comparativo del autor es el siguiente. Con el aumento de los parámetros del modelo de preentrenamiento, la configuración de parámetros muy simples también puede lograr buenos resultados:
    • La longitud de solicitud es el parámetro en el siguiente código num_virtual_tokens: cuando los parámetros del modelo alcanzan un cierto nivel, una longitud de solicitud de 1 también puede lograr buenos resultados, y una longitud de solicitud de 20 puede lograr excelentes resultados.
    • El método de inicialización rápido, es decir, en el siguiente código prompt_tuning_init: el método aleatorio en el método de inicialización es ligeramente peor que el otro
    • TaskTypeTipo de tarea: Similar a otras afinaciones de peft, también tiene este parámetro
class TaskType(str, enum.Enum):
    SEQ_CLS = "SEQ_CLS"   常规分类任务
    SEQ_2_SEQ_LM = "SEQ_2_SEQ_LM" seq2seq任务
    CAUSAL_LM = "CAUSAL_LM"  LM任务
    TOKEN_CLS = "TOKEN_CLS"  token的分类任务:序列标注之类的

Dos, código de ajuste rápido combate real

1. entrenamiento de afinación

  • Datos: twitter_quejas
  • Modelo: modelo bigscience/bloomz-560m
  • PromptTuningConfignum_virtual_tokensEstablezca la configuración de ajuste de solicitud y establezca la cantidad de tokens prefijados con el mensaje a continuación , porque es mejor usar texto relacionado con la tarea para la inicialización del token, así que use Classify if the tweet is a complaint or not:la inicialización a continuación,
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Author : andy
@Date   : 2023/7/10 20:37
@Contact: [email protected] 
@File   : prompt_tuning.py 
"""
from transformers import AutoModelForCausalLM, AutoTokenizer, default_data_collator, get_linear_schedule_with_warmup
from peft import get_peft_config, get_peft_model, PromptTuningInit, PromptTuningConfig, TaskType, PeftType
import torch
from datasets import load_dataset
import os
from torch.utils.data import DataLoader
from tqdm import tqdm

device = "mps"
# device = "cuda"
model_name_or_path = "bigscience/bloomz-560m"
tokenizer_name_or_path = "bigscience/bloomz-560m"
peft_config = PromptTuningConfig(
    task_type=TaskType.CAUSAL_LM,
    prompt_tuning_init=PromptTuningInit.TEXT,
    num_virtual_tokens=8,
    prompt_tuning_init_text="Classify if the tweet is a complaint or not:",
    tokenizer_name_or_path=tokenizer_name_or_path,
)

dataset_name = "twitter_complaints"
text_column = "Tweet text"
label_column = "text_label"
max_length = 64
learning_rate = 3e-2
num_epochs = 20
batch_size = 8
output_dir = './output'

# 1. load a subset of the RAFT dataset at https://huggingface.co/datasets/ought/raft
dataset = load_dataset("ought/raft", dataset_name)

# get lable's possible values
label_values = [name.replace("_", "") for name in dataset["train"].features["Label"].names]
# append label value to the dataset to make it more readable
dataset = dataset.map(
    lambda x: {
    
    label_column: [label_values[label] for label in x["Label"]]},
    batched=True,
    num_proc=1
)
# have a look at the data structure
dataset["train"][0]

inserte la descripción de la imagen aquí

# 2. dataset
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)
if tokenizer.pad_token_id is None:
    tokenizer.pad_token_id = tokenizer.eos_token_id

def preprocess_fn(examples):
    tweets = examples[text_column]
    # pad labels with a pad token at the end
    labels = [str(x) + tokenizer.pad_token for x in examples[label_column]]
    # concatenate the tweet with it label
    inputs = [f"{
      
      text_column} : {
      
      tweet}\nLabel :{
      
      label}"
              for tweet, label in zip(tweets, labels)]
    # tokenize input
    model_inputs = tokenizer(inputs,
                           padding='max_length',
                           max_length=max_length,
                           truncation=True,)
    # tokenize label, as -100 not a valid token id, do the padding manually here
    labels_input_ids = []
    for i in range(len(labels)):
        ids = tokenizer(labels[i])["input_ids"]
        padding = [-100] * (max_length - len(ids))
        labels_input_ids.append(padding + ids)
        model_inputs["labels"] = labels_input_ids
        # make model inputs tensor
        model_inputs["input_ids"] = [torch.tensor(ids) for ids in model_inputs["input_ids"]]
        model_inputs["attention_mask"] = [torch.tensor(ids) for ids in model_inputs["attention_mask"]]
        model_inputs["labels"] = [torch.tensor(ids) for ids in model_inputs["labels"]]

    return model_inputs

# have a look at the preprocessing result
# print(preprocess_fn(dataset["train"][:2]))

processed_datasets = dataset.map(
    preprocess_fn,
    batched=True,
    num_proc=1,
    remove_columns=dataset["train"].column_names, #remove unprocessed column for training
    load_from_cache_file=False,
    desc="Running tokenizer on datasset"
)

test_size = round(len(processed_datasets["train"]) * 0.2)
train_val = processed_datasets["train"].train_test_split(
    test_size=test_size, shuffle=True, seed=42)
train_data = train_val["train"]
val_data = train_val["test"]


# 3. model
model = AutoModelForCausalLM.from_pretrained(model_name_or_path)
model = get_peft_model(model, peft_config)
print(model.print_trainable_parameters())
trainable params: 8192 || all params: 559222784 || trainable%: 0.0014648902430985358

De los resultados impresos anteriores, se puede ver que los parámetros del modelo son alrededor de 560 millones, pero los parámetros que necesitan ser entrenados representan solo el 0.001%, solo 8192.

# 4. trainer
from transformers import Trainer, TrainingArguments
trainer = Trainer(
    model=model,
    train_dataset=train_data,
    eval_dataset=val_data,
    data_collator=default_data_collator,
    args=TrainingArguments(
      output_dir='./output',
      per_device_train_batch_size=batch_size,
      num_train_epochs=num_epochs,
      learning_rate=learning_rate,
      load_best_model_at_end=True,
      logging_strategy='steps',
      logging_steps=10,
      evaluation_strategy='steps',
      eval_steps=10,
      save_strategy='steps',
      save_steps=10,
    )
  )
trainer.train()

inserte la descripción de la imagen aquí

2. Comparación de inferencia de modelos

# 5. inference
def  inference():
    def generate(inputs, infer_model):
        with torch.no_grad():
            inputs = {
    
    k: v.to(device) for k, v in inputs.items()}
            outputs = infer_model.generate(
                input_ids=inputs["input_ids"],
                attention_mask=inputs["attention_mask"],
                max_new_tokens=20,
                eos_token_id=3
            )
            print(tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True)[0])

    # (1) base model_inference
    base_model = AutoModelForCausalLM.from_pretrained(model_name_or_path)
    base_model.to(device)
    inputs = tokenizer(
        f'{
      
      text_column} : {
      
      "@denny the grocery price is soaring, even milk is becoming unaffordable, could you do something?"}\nLabel :',
        return_tensors="pt",  # Return PyTorch torch.Tensor objects.
    )
    generate(inputs, base_model)
    print("----------------------------------------")
    shot1 = f'{
      
      text_column} : {
      
      "@nationalgridus I have no water and the bill is current and paid. Can you do something about this?"}\nLabel :complaint\n'
    shot2 = f'{
      
      text_column} : {
      
      "@HMRCcustomers No this is my first job"}\nLabel :no complaint\n'
    input = f'{
      
      text_column} : {
      
      "@denny the grocery price is soaring, even milk is becoming unaffordable, could you do something?"}\nLabel :'
    inputs_few_shot = tokenizer(
        shot1 + shot2 + input,
        return_tensors="pt",
    )
    generate(inputs_few_shot, base_model)

    # (2) prompt-tuned model_inference
    from peft import PeftModel, PeftConfig
    path = "/content/drive/MyDrive/prompt_tuning"
    config = PeftConfig.from_pretrained(path)
    pretrained_model = AutoModelForCausalLM.from_pretrained(config.base_model_name_or_path)
    prompt_tuned_model = PeftModel.from_pretrained(pretrained_model, path)
    prompt_tuned_model.to(device)
    inputs = tokenizer(
        f'{
      
      text_column} : {
      
      "@denny the grocery price is soaring, even milk is becoming unaffordable, could you do something?"}\nLabel :',
        return_tensors="pt",  # Return PyTorch torch.Tensor objects.
    )
    generate(inputs, prompt_tuned_model)

inference()
  • El razonamiento del modelo base anterior da como resultado:
Tweet text : @denny the grocery price is soaring, even milk is becoming unaffordable, could you do something?
Label : @denny the grocery<?php
/**
 * Copyright © 2016 Google Inc.

----------------------------------------
Tweet text : @nationalgridus I have no water and the bill is current and paid. Can you do something about this?
Label :complaint
Tweet text : @HMRCcustomers No this is my first job
Label :no complaint
Tweet text : @denny the grocery price is soaring, even milk is becoming unaffordable, could you do something?
Label :complaint<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
  • Resultados de razonamiento del modelo ajustado rápidamente:
Tweet text : @denny the grocery price is soaring, even milk is becoming unaffordable, could you do something?
Label :complaint

3. Otras técnicas de afinación

inserte la descripción de la imagen aquí

  • Tanto el ajuste de prefijo como el ajuste de solicitud no necesitan cambiar los parámetros del modelo LLM en sí mismos, pero el ajuste de prefijo no encuentra un prefijo en la capa de entrada del usuario, sino que también encuentra un prefijo en cada capa de LLM y lo agrega, el costo de entrenamiento es significativamente más alto
  • p-tuning no solo puede agregar información adicional al comienzo de la entrada del usuario, sino también agregar información adicional en el medio o al final
  • El ajuste de Lora se muestra en la imagen a continuación, como se mencionó en el blog anterior.

inserte la descripción de la imagen aquí

Referencia

[1] https://github.com/jxhe/unify-parameter-ficient-tuning
[2] Optimización continua: desde el ajuste de prefijos hasta el más potente P-Tuning V2
[3] ¡Resumen de 50 000 palabras! Ajuste rápido: interpretación en profundidad de un nuevo paradigma de ajuste fino
[4] ¿Todavía en el modelo de preentrenamiento a gran escala de ajuste fino? Más información sobre el ajuste rápido
[5] Que el mundo no tenga dificultades Ajuste de modelo grande: Introducción a la tecnología PEFT Ali-Feng Yang
[6] Documento de ajuste rápido: El poder de la escala para el ajuste rápido de parámetros eficientes
[6] Todavía no ¿No conoce xxxForCausalLM y xxxForConditionalGeneration?

Supongo que te gusta

Origin blog.csdn.net/qq_35812205/article/details/131647749
Recomendado
Clasificación