目录

基于llamafactory微调

微调操作指南

微调参数介绍

  • llamafactory涉及的微调参数一般包括以下这些,保存在yaml文件中
  1. bf16: 是否使用半精度浮点数bf16进行训练。bf16 是一种低精度浮点数类型,好处是,可以减少内存使用并可能加速训练,但可能会降低模型性能,。

    在深度学习中,我们可以选择不同的数值精度来进行模型的训练和计算。不同的精度会影响计算资源的使用、训练速度和模型的精确度。下面我用更通俗的语言解释一下这些术语:
    FP16 (Half Precision,半精度):
    这种方式使用16位的浮点数来保存和计算数据。想象一下,如果你有一个非常精细的秤,但现在只用这个秤的一半精度来称重,这就是FP16。它不如32位精度精确,但计算速度更快,占用的内存也更少。
    BF16 (BFloat16):
    BF16也是16位的,但它在表示数的方式上和FP16不同,特别是它用更多的位来表示数的大小(指数部分),这让它在处理大范围数值时更加稳定。你可以把它想象成一个专为机器学习优化的“半精度”秤,尤其是在使用特殊的硬件加速器时。
    FP32 (Single Precision,单精度):
    这是使用32位浮点数进行计算的方式,可以想象为一个标准的、全功能的精细秤。它在深度学习中非常常见,因为它提供了足够的精确度,适合大多数任务。
    Pure BF16:
    在表示数的方式上和FP16不同,特别是它用更多的位来表示数的大小(指数部分),这让它在处理大范围数值时更加稳定。你可以把它想象成一个专为机器学习优化的“半精度”秤,尤其是在使用特殊的硬件加速器时。
    FP32 (Single Precision,单精度):
    这是使用32位浮点数进行计算的方式,可以想象为一个标准的、全功能的精细秤。它在深度学习中非常常见,因为它提供了足够的精确度,适合大多数任务。
    Pure BF16:
    这种模式下,所有计算都仅使用BF16格式。这意味着整个模型训练过程中,从输入到输出,都在使用为机器学习优化的半精度计算。
    
  2. cutoff_len: 训练数据集的长度截断,也可以看作是训练数据的最大长度。超过这个长度的样本将被裁剪。

  3. dataset: 训练数据集的文件列表。这些文件包含模型所需的训练数据。使用的数据集列表,所有字段都需要按上文在data_info.json里注册,多个数据集用","分隔

  4. dataset_dir: 训练数据集文件的目录。 数据集所在目录,可以直接使用项目自带的data目录

  5. do_train: 是否进行训练。如果设置为 false,则模型将进入评估模式。

  6. eval_steps: 模型在每次训练后评估的步数。如果设置为 10,模型将在每 10 个训练步后进行一次评估。

  7. eval_strategy: 评估策略。可以设置为 “steps”(每次训练后评估)或 “epochs”(每个epoch后评估)。

  8. finetuning_type: 微调训练的类型,枚举值,有"lora",“full”,"freeze"等,比如设置为 “lora”,表示使用 LoRA(Low-Rank Adaptation)进行微调。

    ​ Full:这种方式就是从头到尾完全训练一个模型。想象一下,你有一块白纸,你要在上面画出一幅完整的画作,这就是Full Training。你从零开始,逐步训练模型,直到它能够完成你想要的任务。
    ​ Freeze:这种方式有点像是在一幅半完成的画上继续作画。在模型中,有些部分(通常是模型的初级部分,如输入层或底层特征提取部分)是已经训练好的,这部分会被“冻结”,不再在训练过程中更新。你只更新模型的其他部分,这样可以节省训练时间和资源。
    ​ LoRA:这是一种比较新的技术,全称是“Low-Rank Adaptation”。可以理解为一种轻量级的模型调整方式。它主要是在模型的某些核心部分插入小的、低秩的矩阵,通过调整这些小矩阵来实现对整个模型的微调。这种方法不需要对原始模型的大部分参数进行重训练,从而可以在不牺牲太多性能的情况下,快速适应新的任务或数据。
    ​ QLoRA:这是在LoRA的基础上进一步发展的一种方法。它使用量化技术(也就是用更少的比特来表示每个数字),来进一步减少模型调整过程中需要的计
    
  9. gradient_accumulation_steps: 梯度累积步数,用于在更新模型前累积更多的梯度,有助于使用较小的批次大小训练大模型。比如设置为2,代表累积的梯度将在每 2 个训练步后更新模型参数。

    梯度累积的工作原理:
    在每个批次的前向和反向传播过程中,不是立即更新模型权重,而是将梯度累积多个批次。当累积到一定数量的步骤后,再统一更新模型权重。这样可以模拟更大批量大小的效果。
    选择梯度累积步数:
    选择多少步骤进行梯度累积取决于你的具体需求和硬件限制。一般来说,步数越多,模拟的批量大小就越大,但同时每次更新权重的间隔也更长,可能会影响训练速度和效率。
    低资源环境:可以选择较高的累积步数,以减少硬件压力。
    高资源环境:如果内存允许,可以减少累积步数,使训练更加频繁地更新,可能会加速收敛。
    
  10. learning_rate: 模型的学习率。

    学习率是机器学习和深度学习中控制模型学习速度的一个参数。你可以把它想象成你调节自行车踏板力度的旋钮:旋钮转得越多,踏板动得越快,自行车就跑得越快;但如果转得太快,可能会导致自行车失控。同理,学习率太高,模型学习过快,可能会导致学习过程不稳定;学习率太低,模型学习缓慢,训练时间长,效率低。
    常见的学习率参数包括但不限于:
    1e-1(0.1):相对较大的学习率,用于初期快速探索。
    1e-2(0.01):中等大小的学习率,常用于许多标准模型的初始学习率。
    1e-3(0.001):较小的学习率,适用于接近优化目标时的细致调整。
    1e-4(0.0001):更小的学习率,用于当模型接近收敛时的微调。
    5e-5(0.00005):非常小的学习率,常见于预训练模型的微调阶段,例如在自然语言处理中微调BERT模型。
    
  11. logging_steps: 日志记录步数。比如设置为10,代表模型将每 10 个训练步记录一次日志。

  12. lora_alpha: LoRA 的α值。可以调节 LoRA 更新的步长。

  13. lora_dropout: LoRA 的丢弃率。比如,设置为 0,表示不使用丢弃。

  14. lora_rank: LoRA 的秩。调节 LoRA 的参数量。

  15. lora_target: LoRA 的目标层。在使用LoRA(Low-Rank Adaptation,低秩适应)技术进行模型微调时,我们通常会选择模型中的特定层(或部分)进行调整。这些层被称为“目标层”。

一般可以设置为q_proj和v_proj。
q_proj:通常指的是在自注意力机制中,用于生成查询(Query)向量的投影层。
v_proj:指的是在自注意力机制中,用于生成值(Value)向量的投影层。
​ 自注意力机制是很多现代深度学习模型,特别是Transformer模型的核心组成部分。在这种机制中,输入数据会被转换成三种类型的向量:查询(Query)、键(Key)、值(Value)。这些转换通常通过线性投影实现,即通过乘以一个权重矩阵。
​ 在使用LoRA进行微调时,我们不直接修改这些投影层的权重矩阵,而是在这些层插入低秩矩阵。通过优化这些低秩矩阵,我们可以在不显著改变原始模型结构的情况下,有效地调整模型的行为,使其更好地适应新的任务或数据。
​ 这种方法的优点是,它可以在保持大部分预训练模型权重不变的情况下,通过调整相对较少的参数来实现快速有效的微调。这样不仅可以节省计算资源,还可以减少过拟合的风险,特别是在数据较少的情况下。

16.lr_scheduler_type: 学习率调度器的类型。比如,设置为 “cosine”,表示使用余弦调度器。

其他学习率调度器类型:
linear(线性):学习率从一个较高的初始值开始,然后随着时间线性地减少到一个较低的值。
使用场景:当你想要让模型在训练早期快速学习,然后逐渐减慢学习速度以稳定收敛时使用。

cosine(余弦): 学习率按照余弦曲线的形状进行周期性调整,这种周期性的起伏有助于模型在不同的训练阶段探索参数空间。
使用场景:在需要模型在训练过程中不断找到新解的复杂任务中使用,比如大规模的图像或文本处理。

cosine_with_restarts(带重启的余弦):这是余弦调整的一种变体,每当学习率达到一个周期的最低点时,会突然重置到最高点,然后再次减少。
使用场景:适用于需要模型从局部最优解中跳出来,尝试寻找更好全局解的情况。

polynomial(多项式):学习率按照一个多项式函数减少,通常是一个幂次递减的形式。
使用场景:当你需要更精细控制学习率减少速度时使用,适用于任务比较复杂,需要精细调优的模型。

constant(常数):学习率保持不变。
使用场景:简单任务或者小数据集,模型容易训练到足够好的性能时使用。

constant_with_warmup(带预热的常数):开始时使用较低的学习率“预热”模型,然后切换到一个固定的较高学习率。
使用场景:在训练大型模型或复杂任务时,帮助模型稳定地开始学习,避免一开始就进行大的权重调整。

inverse_sqrt(逆平方根):学习率随训练步数的增加按逆平方根递减。
使用场景:常用于自然语言处理中,特别是在训练Transformer模型时,帮助模型在训练后期进行细微的调整。

reduce_lr_on_plateau(在平台期降低学习率):当模型的验证性能不再提升时,自动减少学习率。
使用场景:适用于几乎所有类型的任务,特别是当模型很难进一步提高性能时,可以帮助模型继续优化和提升。

17.max_samples: 每个数据集采样多少数据/训练数据集的最大样本数。如果样本数超过这个值,将被随机采样。

18.model_name_or_path: 模型的路径或名称。如果设置为路径,将从该路径加载模型;如果设置为名称,将从模型库下载模型。

19.num_train_epochs:训练的 epoch 数量。

20.output_dir: 训练结果保存的位置。

21.overwrite_cache: 是否覆盖缓存。如果设置为 true,将覆盖缓存文件。

22.overwrite_output_dir: 是否覆盖输出目录。如果设置为 true,将覆盖输出目录。

23.per_device_eval_batch_size: 评估批次大小。

24.per_device_train_batch_size: 训练批次大小。

25.plot_loss: 是否绘制损失图。如果设置为 true,将保存损失图。

26.preprocessing_num_workers: 预处理工作线程数。

27.save_steps: 模型保存步数。如果设置为 50,将每 50 个训练步保存一次模型。

28.stage: 训练阶段。设置为 “sft”,表示模型处于微调阶段。

29.template: 模型模板。模型问答时所使用的prompt模板,不同模型不同,可以参考https://github.com/hiyouga/LLaMA-Factory?tab=readme-ov-file#supported-models获取不同模型的模板定义,否则会回答结果会很奇怪或导致重复生成等现象的出现。chat 版本的模型基本都需要指定,比如Meta-Llama-3-8B-Instruct的template 就是 llama3

30.val_size: 验证集的随机抽取比例。如果设置为 0.1,将使用 10% 的数据作为验证集。

31.warmup_ratio: warmup 比例。如果设置为 0.03,将 warmup 3% 的训练数据

怎么控制总训练步数?

  • llamafactory 中,总微调时间长短可以体现在Total optimization steps,它的计算公式如下:
    优化步数Total optimization steps可以通过以下公式计算:
    Total optimization steps = (样本数量 × Epoch) / (total batch size × gradient_accumulation_steps)
    总批次大小 =per_device_train_batch_size × device num(使用卡数) × gradient_accumulation_steps

  • 根据上面的公式便可以知道,如果想要缩短微调时间,减少总训练部署,可以通过以下几种方式:

    减少Epoch
    增加gradient_accumulation_steps
    增加per_device_train_batch_size
    增大device num
    减少样本数量/或者可以通过设置max_samples,控制最大的样本数量
    
  • 以下面真实的微调日志为例, 对上面公式做个解释,
    在这里插入图片描述

  • 在上述日志图片中可以看到,该微调样本总数是43684条数据,epoch设置的是10gradient_accumulation_steps2,用了4张卡,per batch size设置的是8,所以总的批次大小是2*4*8=64, 它的最终Total optimization steps6830,详细计算公式见下图手稿:

怎么控制显存占用?

微调经验分享

微调数据构建

  • 数据很重要!!数据是模型的养料,在数据还可以优化的前提下,建议可以先优化数据,喂给模型微调的数据,可能对于整个微调任务的影响可能会更大,收益也会更明显。在数据优化地差不多的情况下,可以进一步优化微调参数,进行消融实验等等

SFT语料构建

  • 梳理出业务的逻辑,最好能定义成比较规则的格式,输出的output,推荐使用json格式输出,方便对于结果进行解析
  • 生成的语料,在于质量不在于数量,要保持多样性

微调常见参数推荐

  • 微调其实说白了就是控制各种参数,可以根据自己的任务选择合适的参数,根据上面的介绍也可以知道,微调的参数有很多,但是一般情况下,我们真正会去改动的几个参数可能也就那几个。以下一些常见值,仅供参考,具体也还是要结合自己的业务数据以及实验结果进行调整。
微调参数 常见值 备注
学习率 2e-5 通常来说,学习率是最关键的超参数之一。 在模型训练初期或者当你不确定最佳参数时,可以使用较大的学习率(例如1e-1或1e-2),快速找到一个合理的解。当你发现模型的性能开始稳定,但还需要进一步优化时,可以减小学习率(例如1e-3或1e-4),帮助模型更精确地找到最优解。微调预训练模型:当使用已经预训练好的模型(如在特定任务上微调BERT)时,通常使用非常小的学习率(例如5e-5或更小),这是因为预训练模型已经非常接近优化目标,我们只需要做一些轻微的调整。或者也可以从较小的学习率开始(如 1e-5 或 2e-5)可以通过监控任务的训练损失和验证指标来决定最佳值
epoch 2,3,5,10 微调的轮数取决于数据集的大小和复杂性。可以从 2-5 轮开始,可以观测loss曲线是否收敛,或者看验证集的性能是否有改善,进行调控,也可以先设置大一点,后面考虑提前停止,注意避免过拟合
Batch Size 8,16,32 批大小会影响训练过程中的稳定性和速度。较小的批大小(如 16 或 32)可以让模型获得更好的泛化能力,但训练速度会慢;较大的批大小可以加快训练速度,但可能导致过拟合。
lr_scheduler_type cosine
finetuning_type LoRA 当下最新最火的一种微调方式,详细可以见下一小结,lora简介或者直接看论文
cutoff_len 512 有的微调中也叫seq_len,模型微调支持的最大截断长度,可以根据自己微调任务数据长短进行设置,在资源足够的情况下,如果数据比较长,可以设长一点,如果数据比较短,可以设置短一点。PS: 较大的seq_len会占用更多的显存。在选择 seq_len 时,也要考虑到计算资源,尤其是在使用大模型时。也可以进行实验找到显存的瓶颈

自动化微调代码实现推荐

  • 现在基于llamafactory的微调,涉及到很多手动的操作,比如要通过vim进到文件中修改文件,还要各种ctrl v ,ctrl c操作,但是微调其实本质上就是调各种参数,并且一般情况下,我们调的参数也不是很多,同时微调之后的合并权重,起服务,评测等,本质上也是可以通过控制参数的方式进行,甚至这几个模块中,参数也是可以共享的,所以可以将各个流程之间一步组合起来,可以直接用过参数控制的方式,可以借助python中的 import argparse包,将一些默认使用的参数使用default赋默认值,通过共享参数+定制化参数,一步命令完成微调任务,也可以大大提高微调效率,而且通过--help的方式也可以知道参数的含义

  • 最后微调命令行pipeline启动方式如下:

    python pipeline.py --dataset="0929_flow_rule_sft_1239_v1_train.json" --max_samples=20000 --task_name="flow_rule" --version="v1" --base_model="qwen25_code_7b" --num_train_epochs=5 --port=8080 --npu=0,5,6,7 --model_name_or_path="/data1/model/Qwen/Qwen2.5-Coder-7B-Instruct"
    

参考网址

Logo

更多推荐