SWIFT (Scalable lightWeight Infrastructure for Fine-Tuning)

发布于:2025-02-13 ⋅ 阅读:(12) ⋅ 点赞:(0)

SWIFT (Scalable lightWeight Infrastructure for Fine-Tuning)

flyfish

ms-swift是魔搭社区提供的大模型与多模态大模型训练部署框架。
https://github.com/modelscope/ms-swift

可扩展轻量级微调基础设施

依赖

  1. PEFT (Parameter-Efficient Fine-Tuning): PEFT是一种针对大规模预训练模型进行高效微调的方法。它旨在通过调整少量参数而不是整个模型的参数来实现对特定任务的优化,从而节省计算资源和时间。

  2. TRL (Transformers Reinforcement Learning): TRL是一个专注于将强化学习应用于基于Transformer架构的模型中的库。它提供了一系列工具和算法,使得研究人员和开发者能够更容易地在自己的项目中集成强化学习技术,尤其是在NLP领域。

  3. vLLM: vLLM 是一个高效的生成式语言模型推理库,专门设计用来加速大模型的推理速度,同时保持较低的资源消耗。这个库特别适合需要快速响应的应用场景,如实时对话系统等。

  4. lmdeploy: LMDeploy 是大语言模型(LLM)压缩、部署和服务的工具包。LMDeploy 通过引入持久批处理(即连续批处理)、分块键值缓存(blocked KV cache)、动态拆分与融合(dynamic split&fuse)、张量并行、高性能 CUDA 内核等关键特性,其请求吞吐量比 vLLM 最高可提升 1.8 倍。LMDeploy 支持仅权重量化和键值(k/v)量化,4 位推理性能比 FP16 高 2.4 倍。量化质量已通过 OpenCompass 评估得到验证。借助请求分发服务,LMDeploy 便于在多台机器和多个计算卡上轻松高效地部署多模型服务。在多轮对话过程中,该引擎通过缓存注意力机制的键值(k/v)来记住对话历史,从而避免对历史会话进行重复处理。LMDeploy 支持同时使用键值缓存量化(KV Cache Quant)、激活感知权重量化(AWQ)和自动前缀缓存。。

  5. DeepSpeed: DeepSpeed是由微软开发的一个深度学习优化库,旨在使分布式训练更加高效和可扩展。它支持大规模模型训练,并提供了诸如ZeRO(Zero Redundancy Optimizer)等技术来减少内存占用和提高训练效率。DeepSpeed对于那些希望训练非常大的模型但受限于硬件资源的研究人员和工程师来说是非常有价值的。

使用swift工具对Qwen2.5-7B-Instruct模型进行微调(Specific Fine-Tuning, SFT),采用了LoRA(Low-Rank Adaptation)技术

# 22GB
CUDA_VISIBLE_DEVICES=0 \
swift sft \
    --model Qwen/Qwen2.5-7B-Instruct \
    --train_type lora \
    --dataset 'AI-ModelScope/alpaca-gpt4-data-zh#500' \
              'AI-ModelScope/alpaca-gpt4-data-en#500' \
              'swift/self-cognition#500' \
    --torch_dtype bfloat16 \
    --num_train_epochs 1 \
    --per_device_train_batch_size 1 \
    --per_device_eval_batch_size 1 \
    --learning_rate 1e-4 \
    --lora_rank 8 \
    --lora_alpha 32 \
    --target_modules all-linear \
    --gradient_accumulation_steps 16 \
    --eval_steps 50 \
    --save_steps 50 \
    --save_total_limit 5 \
    --logging_steps 5 \
    --max_length 2048 \
    --output_dir output \
    --system 'You are a helpful assistant.' \
    --warmup_ratio 0.05 \
    --dataloader_num_workers 4 \
    --model_author swift \
    --model_name swift-robot
  • CUDA_VISIBLE_DEVICES=0: 指定使用的GPU设备ID为0,意味着将使用系统中的第一块GPU进行训练。
  • --model Qwen/Qwen2.5-7B-Instruct: 指定了要微调的基础模型是Qwen2.5-7B-Instruct。
  • --train_type lora: 表示采用LoRA方式进行微调,这是一种高效调整大规模预训练模型的方法。
  • --dataset: 列出了用于微调的数据集,这里包括了三个数据集,每个数据集取500条记录。
  • --torch_dtype bfloat16: 设置PyTorch在训练过程中使用的数据类型为bfloat16,这是一种减少内存占用同时保持较高数值精度的方式。
  • --num_train_epochs 1: 设置训练周期数为1,即整个数据集将被遍历一次。
  • --per_device_train_batch_size 1: 每个设备上的训练批次大小设置为1。
  • --learning_rate 1e-4: 设置学习率为0.0001。
  • --lora_rank 8--lora_alpha 32: 定义了LoRA配置参数,其中rank指定了低秩矩阵的维度,alpha是一个缩放因子。
  • --target_modules all-linear: 指定哪些模块将应用LoRA技术,这里是所有线性层。
  • --gradient_accumulation_steps 16: 梯度累积步骤设置为16,有助于在小批次大小的情况下模拟较大的批次大小效果。
  • --eval_steps 50, --save_steps 50: 分别设置了每50步进行一次评估和保存模型。
  • --save_total_limit 5: 限制最多保存5个检查点。
  • --logging_steps 5: 每5步记录一次日志。
  • --max_length 2048: 设置输入的最大长度为2048。
  • --output_dir output: 训练结果将保存到名为"output"的目录下。
  • --system 'You are a helpful assistant.': 设置系统的提示信息或角色描述。
  • --warmup_ratio 0.05: 学习率预热的比例设置为5%。
  • --dataloader_num_workers 4: 数据加载器的工作线程数设置为4。
  • --model_author swift--model_name swift-robot: 分别指定了模型作者和模型名称。

运行过程

Generating train split: 108 examples [00:00, 2678.70 examples/s]
Map: 100%|██████████████████████████████████████████████| 108/108 [00:00<00:00, 6555.59 examples/s]
[WARNING:swift] dataset_sample:499 is greater than len(dataset):107, repeated sampling will be performed.
[INFO:swift] train_dataset: Dataset({
    features: ['messages'],
    num_rows: 1489
})
[INFO:swift] val_dataset: Dataset({
    features: ['messages'],
    num_rows: 11
})
Map: 100%|█████████████████████████████████████████████| 1489/1489 [00:01<00:00, 949.29 examples/s]
Map: 100%|█████████████████████████████████████████████████| 11/11 [00:00<00:00, 633.16 examples/s]
[INFO:swift] [INPUT_IDS] [151644, 8948, 198, 2610, 525, 264, 10950, 17847, 13, 151645, 198, 151644, 872, 198, 101042, 87752, 20074, 62926, 101987, 103929, 106073, 8997, 32664, 16, 15, 99605, 103993, 101923, 3837, 56007, 99650, 100399, 104602, 99998, 100019, 1773, 22, 99605, 36587, 100399, 104602, 3837, 18, 99605, 36587, 116889, 1773, 151645, 198, 151644, 77091, 198, 106073, 5122, 100345, 101923, 59151, 3837, 16, 15, 99605, 105656, 22, 15, 4, 100623, 99729, 100399, 104602, 3837, 118233, 102250, 101043, 18, 15, 4, 100623, 99729, 116889, 1773, 43288, 102406, 104596, 101923, 110241, 15946, 3837, 100399, 104602, 100623, 56006, 116889, 100623, 42140, 1773, 100169, 17447, 3837, 104602, 33108, 100019, 99250, 102212, 100140, 20412, 101441, 100218, 106099, 3837, 102527, 73670, 83751, 63789, 96050, 99487, 101923, 110241, 15946, 3837, 104602, 9370, 103215, 100069, 105688, 100019, 1773, 151645]
[INFO:swift] [INPUT] <|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
分析以下数据并展示你的结论。
对10个人进行了调查,问他们喝咖啡还是茶。7个人说喝咖啡,3个人说喝茶。<|im_end|>
<|im_start|>assistant
结论:根据调查结果,10个人中有70%的人喜欢喝咖啡,相较之下只有30%的人喜欢喝茶。这表明在这个调查样本中,喝咖啡的人比喝茶的人多。传统上,咖啡和茶被普遍认为是两种竞争饮料,由此可以推断,在这个调查样本中,咖啡的受欢迎程度高于茶。<|im_end|>
[INFO:swift] [LABELS_IDS] [-100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, -100, 106073, 5122, 100345, 101923, 59151, 3837, 16, 15, 99605, 105656, 22, 15, 4, 100623, 99729, 100399, 104602, 3837, 118233, 102250, 101043, 18, 15, 4, 100623, 99729, 116889, 1773, 43288, 102406, 104596, 101923, 110241, 15946, 3837, 100399, 104602, 100623, 56006, 116889, 100623, 42140, 1773, 100169, 17447, 3837, 104602, 33108, 100019, 99250, 102212, 100140, 20412, 101441, 100218, 106099, 3837, 102527, 73670, 83751, 63789, 96050, 99487, 101923, 110241, 15946, 3837, 104602, 9370, 103215, 100069, 105688, 100019, 1773, 151645]
[INFO:swift] [LABELS] [-100 * 52]结论:根据调查结果,10个人中有70%的人喜欢喝咖啡,相较之下只有30%的人喜欢喝茶。这表明在这个调查样本中,喝咖啡的人比喝茶的人多。传统上,咖啡和茶被普遍认为是两种竞争饮料,由此可以推断,在这个调查样本中,咖啡的受欢迎程度高于茶。<|im_end|>
Map: 100%|███████████████████████████████████████████| 1489/1489 [00:00<00:00, 10891.12 examples/s]
[INFO:swift] Dataset Token Length: 133.057757±110.177715, min=28.000000, max=608.000000, size=1489
Map: 100%|████████████████████████████████████████████████| 11/11 [00:00<00:00, 3253.92 examples/s]
[INFO:swift] Dataset Token Length: 147.363636±107.492302, min=43.000000, max=336.000000, size=11
[INFO:swift] lora_config: LoraConfig(task_type='CAUSAL_LM', peft_type=<PeftType.LORA: 'LORA'>, auto_mapping=None, base_model_name_or_path='/home/sss/.cache/modelscope/hub/Qwen/Qwen2___5-7B-Instruct', revision=None, inference_mode=False, r=8, target_modules={'v_proj', 'up_proj', 'q_proj', 'down_proj', 'o_proj', 'k_proj', 'gate_proj'}, exclude_modules=None, lora_alpha=32, lora_dropout=0.05, fan_in_fan_out=False, bias='none', use_rslora=False, modules_to_save=[], init_lora_weights=True, layers_to_transform=None, layers_pattern=None, rank_pattern={}, alpha_pattern={}, megatron_config=None, megatron_core='megatron.core', loftq_config={}, eva_config=None, use_dora=False, layer_replication=None, runtime_config=LoraRuntimeConfig(ephemeral_gpu_offload=False), lora_bias=False, lora_dtype=None, lorap_lr_ratio=None, lorap_emb_lr=1e-06)
[INFO:swift] model: PeftModelForCausalLM(
  (base_model): LoraModel(
    (model): Qwen2ForCausalLM(
      (model): Qwen2Model(
        (embed_tokens): Embedding(152064, 3584)
        (layers): ModuleList(
          (0-27): 28 x Qwen2DecoderLayer(
            (self_attn): Qwen2Attention(
              (q_proj): lora.Linear(
                (base_layer): Linear(in_features=3584, out_features=3584, bias=True)
                (lora_dropout): ModuleDict(
                  (default): Dropout(p=0.05, inplace=False)
                )
                (lora_A): ModuleDict(
                  (default): Linear(in_features=3584, out_features=8, bias=False)
                )
                (lora_B): ModuleDict(
                  (default): Linear(in_features=8, out_features=3584, bias=False)
                )
                (lora_embedding_A): ParameterDict()
                (lora_embedding_B): ParameterDict()
                (lora_magnitude_vector): ModuleDict()
              )
              (k_proj): lora.Linear(
                (base_layer): Linear(in_features=3584, out_features=512, bias=True)
                (lora_dropout): ModuleDict(
                  (default): Dropout(p=0.05, inplace=False)
                )
                (lora_A): ModuleDict(
                  (default): Linear(in_features=3584, out_features=8, bias=False)
                )
                (lora_B): ModuleDict(
                  (default): Linear(in_features=8, out_features=512, bias=False)
                )
                (lora_embedding_A): ParameterDict()
                (lora_embedding_B): ParameterDict()
                (lora_magnitude_vector): ModuleDict()
              )
              (v_proj): lora.Linear(
                (base_layer): Linear(in_features=3584, out_features=512, bias=True)
                (lora_dropout): ModuleDict(
                  (default): Dropout(p=0.05, inplace=False)
                )
                (lora_A): ModuleDict(
                  (default): Linear(in_features=3584, out_features=8, bias=False)
                )
                (lora_B): ModuleDict(
                  (default): Linear(in_features=8, out_features=512, bias=False)
                )
                (lora_embedding_A): ParameterDict()
                (lora_embedding_B): ParameterDict()
                (lora_magnitude_vector): ModuleDict()
              )
              (o_proj): lora.Linear(
                (base_layer): Linear(in_features=3584, out_features=3584, bias=False)
                (lora_dropout): ModuleDict(
                  (default): Dropout(p=0.05, inplace=False)
                )
                (lora_A): ModuleDict(
                  (default): Linear(in_features=3584, out_features=8, bias=False)
                )
                (lora_B): ModuleDict(
                  (default): Linear(in_features=8, out_features=3584, bias=False)
                )
                (lora_embedding_A): ParameterDict()
                (lora_embedding_B): ParameterDict()
                (lora_magnitude_vector): ModuleDict()
              )
            )
            (mlp): Qwen2MLP(
              (gate_proj): lora.Linear(
                (base_layer): Linear(in_features=3584, out_features=18944, bias=False)
                (lora_dropout): ModuleDict(
                  (default): Dropout(p=0.05, inplace=False)
                )
                (lora_A): ModuleDict(
                  (default): Linear(in_features=3584, out_features=8, bias=False)
                )
                (lora_B): ModuleDict(
                  (default): Linear(in_features=8, out_features=18944, bias=False)
                )
                (lora_embedding_A): ParameterDict()
                (lora_embedding_B): ParameterDict()
                (lora_magnitude_vector): ModuleDict()
              )
              (up_proj): lora.Linear(
                (base_layer): Linear(in_features=3584, out_features=18944, bias=False)
                (lora_dropout): ModuleDict(
                  (default): Dropout(p=0.05, inplace=False)
                )
                (lora_A): ModuleDict(
                  (default): Linear(in_features=3584, out_features=8, bias=False)
                )
                (lora_B): ModuleDict(
                  (default): Linear(in_features=8, out_features=18944, bias=False)
                )
                (lora_embedding_A): ParameterDict()
                (lora_embedding_B): ParameterDict()
                (lora_magnitude_vector): ModuleDict()
              )
              (down_proj): lora.Linear(
                (base_layer): Linear(in_features=18944, out_features=3584, bias=False)
                (lora_dropout): ModuleDict(
                  (default): Dropout(p=0.05, inplace=False)
                )
                (lora_A): ModuleDict(
                  (default): Linear(in_features=18944, out_features=8, bias=False)
                )
                (lora_B): ModuleDict(
                  (default): Linear(in_features=8, out_features=3584, bias=False)
                )
                (lora_embedding_A): ParameterDict()
                (lora_embedding_B): ParameterDict()
                (lora_magnitude_vector): ModuleDict()
              )
              (act_fn): SiLU()
            )
            (input_layernorm): Qwen2RMSNorm((3584,), eps=1e-06)
            (post_attention_layernorm): Qwen2RMSNorm((3584,), eps=1e-06)
          )
        )
        (norm): Qwen2RMSNorm((3584,), eps=1e-06)
        (rotary_emb): Qwen2RotaryEmbedding()
      )
      (lm_head): Linear(in_features=3584, out_features=152064, bias=False)
    )
  )
)
[INFO:swift] model_parameter_info: PeftModelForCausalLM: 7635.8016M Params (20.1851M Trainable [0.2643%]), 0.0001M Buffers.

使用swift工具进行推理

第一个脚本:使用交互式命令行进行推理

专注于简单的推理任务,使用了基本的流式输出和固定的采样温度。

# Using an interactive command line for inference.
CUDA_VISIBLE_DEVICES=0 \
swift infer \
    --adapters output/vx-xxx/checkpoint-xxx \
    --stream true \
    --temperature 0 \
    --max_new_tokens 2048
  • CUDA_VISIBLE_DEVICES=0: 指定使用的GPU设备ID为0。
  • swift infer: 使用swift工具进行推理。
  • --adapters output/vx-xxx/checkpoint-xxx: 指定加载的适配器(通常是经过微调后的模型检查点)路径。
  • --stream true: 启用流式输出,即逐步返回生成的文本而不是一次性返回全部内容。
  • --temperature 0: 设置采样温度为0,这意味着在生成文本时将选择概率最高的单词,不引入随机性。
  • --max_new_tokens 2048: 设置生成的最大新标记数为2048个。

第二个脚本:合并LoRA权重并使用vLLM加速推理

进一步优化了推理过程,通过合并LoRA权重减少了计算负担,并利用vLLM加速了推理速度,同时支持更长的序列处理。

# merge-lora and use vLLM for inference acceleration
CUDA_VISIBLE_DEVICES=0 \
swift infer \
    --adapters output/vx-xxx/checkpoint-xxx \
    --stream true \
    --merge_lora true \
    --infer_backend vllm \
    --max_model_len 8192 \
    --temperature 0 \
    --max_new_tokens 2048
  • CUDA_VISIBLE_DEVICES=0: 同样指定使用的GPU设备ID为0。
  • swift infer: 使用swift工具进行推理。
  • --adapters output/vx-xxx/checkpoint-xxx: 指定加载的适配器路径。
  • --stream true: 启用流式输出。
  • --merge_lora true: 合并LoRA权重到基础模型中,这可以减少推理时的计算复杂度和内存占用。
  • --infer_backend vllm: 使用vLLM作为推理后端,这是一个专门用于加速大规模语言模型推理的库。
  • --max_model_len 8192: 设置模型能够处理的最大序列长度为8192,比第一个脚本中的2048要大得多,适合处理更长的输入或生成更长的输出。
  • --temperature 0: 同样设置采样温度为0。
  • --max_new_tokens 2048: 设置生成的最大新标记数为2048个。