大模型微调技术

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
微调的两种方式:1.权重W的微调(强化原始模型参数中的某些值,使得模型在特定任务上表现的更好) 2.输入参数X的微调(使得输入能够更加符合模型的要求)

理解篇

  1. prompt tuning方式
    在这里插入图片描述
    注:改变X输入

固定预训练参数,为每一个任务额外添加一个或多个embedding,之后拼接query正常输入LLM,并只训练这些embedding。左图为单任务全参数微调,右图为prompt tuning。

代码样例:

from peft import PromptTuningConfig, get_peft_model
peft_config = PromptTuningConfig(task_type="SEQ_CLS", num_virtual_tokens=10)
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, return_dict=True)
model = get_peft_model(model, peft_config)
  1. prefix tuning 方式

在这里插入图片描述

prefix tuning依然是固定预训练参数,但除为每一个任务额外添加一个或多个embedding之外,利用多层感知编码prefix,注意多层感知机就是prefix的编码器,不再像prompt tuning继续输入LLM,采用小的神经网络模型对输入数据进行编码,并将编码后的向量进行拼接。

embedding = torch.nn.Embedding(num_virtual_tokens, token_dim)
transform = torch.nn.Sequential(
    torch.nn.Linear(token_dim, encoder_hidden_size),
    torch.nn.Tanh(),
    torch.nn.Linear(encoder_hidden_size, num_layers * 2 * token_dim),
)

代码样例:

peft_config = PrefixTuningConfig(task_type="CAUSAL_LM", num_virtual_tokens=20)
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, return_dict=True)
model = get_peft_model(model, peft_config)
  1. LoRA方式
    在这里插入图片描述

LoRA冻结了预训练模型的参数,并在每一层decoder中加入dropout+Linear+Conv1d额外的参数(加外挂,以并联的形式在一侧加入AB两个矩阵,注:初始化时B矩阵采用全0矩阵)

代码样例:

peft_config = LoraConfig(task_type="SEQ_CLS", inference_mode=False, r=8, lora_alpha=16, lora_dropout=0.1)
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, return_dict=True)
model = get_peft_model(model, peft_config)

4.p-tuning方式

在这里插入图片描述

手动尝试最优的提示无异于大海捞针,于是便有了自动离散提示搜索的方法(作图),但提示是离散的,神经网络是连续的,所以寻找的最优提示可能是次优的。p-tuning依然是固定LLM参数,利用多层感知机和LSTM对prompt进行编码,编码之后与其他向量进行拼接之后正常输入LLM。注意,训练之后只保留prompt编码之后的向量即可,无需保留编码器。

self.lstm_head = torch.nn.LSTM(
                    input_size=self.input_size,
                    hidden_size=self.hidden_size,
                    num_layers=num_layers,
                    dropout=lstm_dropout,
                    bidirectional=True,
                    batch_first=True,
  )

self.mlp_head = torch.nn.Sequential(
    torch.nn.Linear(self.hidden_size * 2, self.hidden_size * 2),
    torch.nn.ReLU(),
    torch.nn.Linear(self.hidden_size * 2, self.output_size),
)
self.mlp_head(self.lstm_head(input_embeds)[0])

以上代码可清晰展示出prompt编码器的结构。

  1. p-tuning v2方式

p-tuning的问题是在小参数量模型上表现差,于是有了V2版本,类似于LoRA每层都嵌入了新的参数(称之为Deep FT)。p-tuning v2 在多种任务上下进行微调,之后对于不同的任务如token classification与sentence classification添加了随机初始化的任务头(AutoModelForTokenClassification、AutoModelForSequenceClassification),而非使用自然语言的方式,可以说V2是集大成者。

在这里插入图片描述

v1到v2的可视化:蓝色部分为参数冻结,橙色部分为可训练部分

代码样例:

peft_config = PrefixTuningConfig(task_type="SEQ_CLS", num_virtual_tokens=20)
model = AutoModelForSequenceClassification.from_pretrained(model_name_or_path, return_dict=True)
model = get_peft_model(model, peft_config)

代码篇

注:以下代码在pytorch 1.12.1版本下运行,其他包都是最新版本

按照官方文档搭建环境:

pip install deepspeed>=0.9.0

git clone https://github.com/microsoft/DeepSpeedExamples.git
cd DeepSpeedExamples/applications/DeepSpeed-Chat/
pip install -r requirements.txt

全参数微调,会爆OOM

deepspeed --num_gpus 1 main.py
–data_path Dahoas/rm-static
–data_split 2,4,4
–model_name_or_path facebook/opt-6.5b
–gradient_accumulation_steps 2
–lora_dim 128
–zero_stage 0
–deepspeed
–output_dir $OUTPUT
&> $OUTPUT/training.log

修改为deepspeed ,便能愉快的run起来

deepspeed main.py
–data_path Dahoas/rm-static
–data_split 2,4,4
–model_name_or_path facebook/opt-6.7b
–per_device_train_batch_size 4
–per_device_eval_batch_size 4
–max_seq_len 512
–learning_rate 9.65e-6
–weight_decay 0.1
–num_train_epochs 2
–gradient_accumulation_steps 1
–lr_scheduler_type cosine
–num_warmup_steps 0
–seed 1234
–lora_dim 128
–gradient_checkpointing
–zero_stage 3
–deepspeed
–output_dir $OUTPUT_PATH
&> $OUTPUT_PATH/training.log

可以加上LoRA

deepspeed --num_gpus 1 main.py
–data_path Dahoas/rm-static
–data_split 2,4,4
–model_name_or_path facebook/opt-6.7b
–per_device_train_batch_size 8
–per_device_eval_batch_size 8
–max_seq_len 512
–learning_rate 1e-3
–weight_decay 0.1
–num_train_epochs 2
–gradient_accumulation_steps 16
–lr_scheduler_type cosine
–num_warmup_steps 0
–seed 1234
–gradient_checkpointing
–zero_stage 0
–lora_dim 128
–lora_module_name decoder.layers.
–deepspeed
–output_dir $OUTPUT_PATH
&> $OUTPUT_PATH/training.log

peft代码实战,以下代码省略了数据处理

from datasets import load_dataset,load_from_disk
import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer,default_data_collator
from peft import prepare_model_for_int8_training, LoraConfig, get_peft_model

MICRO_BATCH_SIZE = 1  
BATCH_SIZE = 1
GRADIENT_ACCUMULATION_STEPS = BATCH_SIZE // MICRO_BATCH_SIZE
EPOCHS = 3  
LEARNING_RATE = 3e-6  
CUTOFF_LEN = 256  
LORA_R = 16
LORA_ALPHA = 32
LORA_DROPOUT = 0.05

模型加载,并使用int8进行训练

model_path = "facebook/opt-6.7b"
output_dir = "model"
model = AutoModelForCausalLM.from_pretrained(model_path)
tokenizer = AutoTokenizer.from_pretrained(model_path, add_eos_token=True)
model = prepare_model_for_int8_training(model)  
config = LoraConfig(
    r=LORA_R,
    lora_alpha=LORA_ALPHA,
    target_modules=None,
    lora_dropout=LORA_DROPOUT,
    bias="none",
    task_type="CAUSAL_LM",
)
model = get_peft_model(model, config)
tokenizer.pad_token_id = 0  
data = load_from_disk("data")

训练与保存

trainer = transformers.Trainer(
    model=model,
    train_dataset=data["train"],
    eval_dataset=data["validation"],
    args=transformers.TrainingArguments(
        per_device_train_batch_size=MICRO_BATCH_SIZE,
        per_device_eval_batch_size=MICRO_BATCH_SIZE,
        gradient_accumulation_steps=GRADIENT_ACCUMULATION_STEPS,
        warmup_steps=1000,
        num_train_epochs=EPOCHS,
        learning_rate=LEARNING_RATE,
        # bf16=True,  
        fp16=True,  
        logging_steps=1,
        output_dir=output_dir,
        save_total_limit=4,
    ),
    data_collator=default_data_collator,
)
model.config.use_cache = False
trainer.train(resume_from_checkpoint=False)
model.save_pretrained(output_dir)

直接运行依然会OOM
编写accelerate配置文件accelerate.yaml

compute_environment: LOCAL_MACHINE
deepspeed_config:
gradient_accumulation_steps: 1
gradient_clipping: 1.0
offload_optimizer_device: none
offload_param_device: none
zero3_init_flag: true
zero3_save_16bit_model: true
zero_stage: 3
distributed_type: DEEPSPEED
downcast_bf16: ‘yes’
dynamo_backend: ‘yes’
fsdp_config: {}
machine_rank: 0
main_training_function: main
megatron_lm_config: {}
mixed_precision: fp16
num_machines: 1
num_processes: 2
rdzv_backend: static
same_network: true
use_cpu: true

deepspeed配置文件:ds.json

{
“fp16”: {
“enabled”: true,
“loss_scale”: 0,
“loss_scale_window”: 500,
“initial_scale_power”: 16,
“hysteresis”: 2,
“min_loss_scale”: 1
},

"optimizer": {
    "type": "AdamW",
    "params": {
        "lr": "auto",
        "betas": "auto",
        "eps": 1e-8,
        "weight_decay": "auto"
    }
},

"scheduler": {
    "type": "WarmupLR",
    "params": {
        "warmup_min_lr": 0,
        "warmup_max_lr": 2e-05,
        "warmup_num_steps": 0
    }
},

"zero_optimization": {
    "stage": 2,
    "offload_optimizer": {
        "device": "cpu",
        "pin_memory": false
    },
    "allgather_partitions": true,
    "allgather_bucket_size": 2e8,
    "overlap_comm": true,
    "reduce_scatter": true,
    "reduce_bucket_size": 2e8,
    "contiguous_gradients": true
},

"gradient_accumulation_steps":2,
"gradient_clipping": "auto",
"steps_per_print": 2000,
"train_batch_size": 4,
"train_micro_batch_size_per_gpu": 1,
"wall_clock_breakdown": false
}

启动

accelerate launch --dynamo_backend=nvfuser --config_file accelearte.yaml finetune.py
注:其他方法与Lora使用方法差距不大,不再赘述,在peft项目中均有代码样例。

(1) Fine-Tuning(标准微调)
优点:

    简单易用:直接在预训练模型上进行微调。
    适应性强:可以针对特定任务调整整个模型的参数。
    效果显著:通常能显著提高模型在特定任务上的表现。

缺点:

    计算成本高:需要调整模型的大量参数。
    数据需求较高:为了有效微调,通常需要较多的标注数据。

适用场景:当有足够的标注数据和计算资源时,适用于大多数NLP任务。

(2)Parameter-Efficient Fine-Tuning(PEFT)
优点:

    参数高效:只修改或优化模型的一小部分参数。
    节省计算资源:比完全微调需要的资源少。

缺点:

    可能效果有限:对于某些复杂任务,仅优化少量参数可能不足以达到最佳效果。

适用场景:资源受限的情况,或者需要快速适应新任务时。

(3) Prompt-Tuning
优点:

    无需改变模型架构:通过设计任务相关的提示(prompt),引导模型生成所需的输出。
    资源消耗少:不需要改变模型参数。

缺点:

    需要精心设计prompt:有效的prompt设计可能需要丰富的经验和实验。

适用场景:快速适应新任务,尤其适用于资源有限的场景。

(4) LoRA(Low-Rank Adaptation)
优点:

    参数高效:通过引入低秩矩阵来调整模型,减少需要优化的参数数量。
    节省内存和计算资源。

缺点:

    效果可能有限:对于某些复杂任务可能无法达到完全微调的效果。
    需要一定的技术知识来实现和调试。

适用场景:需要参数高效调整的场景,特别是在资源有限的情况下。

(5) P-Tuning
优点:

    可解释性强:通过可训练的prompt向量进行微调。
    资源消耗相对较少。

缺点:

    需要适当的调整和实验来找到最佳配置。
    可能不适用于所有类型的任务。

适用场景:适用于需要提高模型解释性的任务,以及资源有限的情况。

  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值