From 836e770d46c70effc18de03dca9b8456006f9ead Mon Sep 17 00:00:00 2001 From: JavaZero <2487163254@qq.com> Date: Fri, 13 Jun 2025 17:50:26 +0800 Subject: [PATCH] add configuration files for Qwen2.5 model fine-tuning --- .../finetune_qwen2_5_7b_8k.yaml | 252 ++++++++++++++++++ .../finetune_qwen2_5_7b_8k_1p.yaml | 247 +++++++++++++++++ .../guide/supervised_fine_tuning.md | 247 +++++++---------- 3 files changed, 601 insertions(+), 145 deletions(-) create mode 100644 docs/mindformers/docs/source_zh_cn/example/supervised_fine_tuning/finetune_qwen2_5_7b_8k.yaml create mode 100644 docs/mindformers/docs/source_zh_cn/example/supervised_fine_tuning/finetune_qwen2_5_7b_8k_1p.yaml diff --git a/docs/mindformers/docs/source_zh_cn/example/supervised_fine_tuning/finetune_qwen2_5_7b_8k.yaml b/docs/mindformers/docs/source_zh_cn/example/supervised_fine_tuning/finetune_qwen2_5_7b_8k.yaml new file mode 100644 index 0000000000..3988973264 --- /dev/null +++ b/docs/mindformers/docs/source_zh_cn/example/supervised_fine_tuning/finetune_qwen2_5_7b_8k.yaml @@ -0,0 +1,252 @@ +seed: 42 +output_dir: './output' +load_checkpoint: '/path/to/Qwen2.5-7B/' +load_ckpt_format: 'safetensors' +auto_trans_ckpt: True # If true, auto transform load_checkpoint to load in distributed model +only_save_strategy: False +resume_training: False +run_mode: 'finetune' + +# trainer config +trainer: + type: CausalLanguageModelingTrainer + model_name: 'qwen2_5_7b' +# if True, do evaluate during the training process. if false, do nothing. +# note that the task trainer should support _evaluate_in_training function. +do_eval: False +eval_step_interval: -1 # num of step intervals between each eval, -1 means no step end eval. +eval_epoch_interval: 50 # num of epoch intervals between each eval, 1 means eval on every epoch end. + +# runner config +runner_config: + epochs: 2 + batch_size: 1 + sink_mode: True + sink_size: 1 + +# wrapper cell config +runner_wrapper: + type: MFTrainOneStepCell + scale_sense: + type: DynamicLossScaleUpdateCell + loss_scale_value: 4096 + scale_factor: 1 + scale_window: 100000 + use_clip_grad: True + max_grad_norm: 1.0 + +# optimizer +optimizer: + type: AdamW + betas: [0.9, 0.95] + eps: 1.e-8 + learning_rate: 1.e-6 + weight_decay: 0.01 + +# lr schedule +lr_schedule: + type: CosineWithWarmUpLR + learning_rate: 1.e-6 + lr_end: 1.e-6 + warmup_ratio: 0 + total_steps: -1 # -1 means it will load the total steps of the dataset + +# dataset +train_dataset: &train_dataset + input_columns: &input_columns ["input_ids", "labels", "loss_mask", "position_ids", "attention_mask"] + construct_args_key: *input_columns + data_loader: + type: CommonDataLoader + load_func: 'load_dataset' + shuffle: False + path: "llm-wizard/alpaca-gpt4-data" + packing: pack + handler: + - type: AlpacaInstructDataHandler + tokenizer: + vocab_file: "/path/to/Qwen2.5-7B/vocab.json" + merges_file: "/path/to/Qwen2.5-7B/merges.txt" + unk_token: null + pad_token: "<|endoftext|>" + eos_token: "<|im_end|>" + bos_token: null + type: Qwen2Tokenizer + auto_register: qwen2_5_tokenizer.Qwen2Tokenizer + seq_length: &seq_length 8192 + prompt_key: "conversations" + output_columns: ["input_ids", "labels"] + is_dynamic: False + - type: PackingHandler + seq_length: *seq_length + output_columns: ["input_ids", "labels", "actual_seq_len"] + adaptor_config: + compress_mask: False + column_names: *input_columns + python_multiprocessing: False + drop_remainder: True + numa_enable: False + prefetch_size: 1 +train_dataset_task: + type: CausalLanguageModelDataset + dataset_config: *train_dataset + +# eval dataset +eval_dataset: &eval_dataset + data_loader: + type: MindDataset + dataset_dir: "" + shuffle: False + input_columns: ["input_ids", "target_ids", "attention_mask"] + num_parallel_workers: 8 + python_multiprocessing: False + drop_remainder: False + repeat: 1 + numa_enable: False + prefetch_size: 1 +eval_dataset_task: + type: CausalLanguageModelDataset + dataset_config: *eval_dataset + +use_parallel: True +# parallel context config +parallel: + parallel_mode: 1 # 0-data parallel, 1-semi-auto parallel, 2-auto parallel, 3-hybrid parallel + gradients_mean: False + enable_alltoall: False + full_batch: True + search_mode: "sharding_propagation" + strategy_ckpt_save_file: "./ckpt_strategy.ckpt" + enable_parallel_optimizer: True + parallel_optimizer_config: + gradient_accumulation_shard: False + parallel_optimizer_threshold: 64 + +# default parallel of device num = 8 +parallel_config: + data_parallel: 4 + model_parallel: 1 + pipeline_stage: 2 + context_parallel: 1 + use_seq_parallel: True + micro_batch_num: 16 + vocab_emb_dp: False + gradient_aggregation_group: 4 +# when model parallel is greater than 1, we can set micro_batch_interleave_num=2, that may accelerate the train process. +micro_batch_interleave_num: 1 + +# recompute config +recompute_config: + recompute: [7, 7] + select_recompute: + 'feed_forward\.mul': [14, 14] + 'feed_forward\.w1\.activation\.silu': [14, 14] + 'feed_forward\.w1\.reshape': [14, 14] + 'feed_forward\.w2\.reshape': [14, 14] + parallel_optimizer_comm_recompute: False + mp_comm_recompute: False + recompute_slice_activation: False + +# callbacks +callbacks: + - type: MFLossMonitor + - type: CheckpointMonitor + prefix: "qwen2_5" + save_checkpoint_steps: 5000 + keep_checkpoint_max: 1 + integrated_save: False + async_save: False + checkpoint_format: "safetensors" + +# mindspore context init config +context: + mode: 0 #0--Graph Mode; 1--Pynative Mode + device_target: "Ascend" + max_call_depth: 10000 + max_device_memory: "58GB" + save_graphs: False + save_graphs_path: "./graph" + device_id: 0 + memory_optimize_level: "O1" + jit_config: + jit_level: "O1" + ascend_config: + precision_mode: "must_keep_origin_dtype" + +# model config +model: + model_config: + type: LlamaConfig + batch_size: 1 + seq_length: *seq_length + hidden_size: 3584 + num_layers: 28 + num_heads: 28 + n_kv_heads: 4 + vocab_size: 152064 + intermediate_size: 18944 + qkv_has_bias: True + rms_norm_eps: 1.0e-6 + theta: 1000000.0 + max_position_embedding: 131072 + emb_dropout_prob: 0.0 + eos_token_id: 151643 + pad_token_id: 151643 + bos_token_id: 151643 + compute_dtype: "bfloat16" + layernorm_compute_type: "float32" + softmax_compute_type: "float32" + rotary_dtype: "float32" + param_init_type: "float32" + use_past: False + use_flash_attention: True + use_past_shard: False + offset: 0 + checkpoint_name_or_path: "" + repetition_penalty: 1.05 + max_decode_length: 1024 + top_k: 0 + top_p: 0.8 + do_sample: False + extend_method: "None" # support "None", "PI", "NTK" + fine_grain_interleave: 1 + qkv_concat: false + # configuration items copied from Qwen + rotary_pct: 1.0 + rotary_emb_base: 1000000 + input_sliced_sig: True + arch: + type: LlamaForCausalLM + +processor: + return_tensors: ms + tokenizer: + model_max_length: 131072 + vocab_file: "path/vocab.json" + merges_file: "path/merges.txt" + unk_token: None + pad_token: "<|endoftext|>" + eos_token: "<|endoftext|>" + type: Qwen2Tokenizer + type: Qwen2Processor + +# metric +metric: + type: PerplexityMetric + + +auto_tune: False +filepath_prefix: './autotune' +autotune_per_step: 10 + +profile: False +profile_start_step: 1 +profile_stop_step: 10 +init_start_profile: False +profile_communication: False +profile_memory: True +layer_scale: False +layer_decay: 0.65 +lr_scale_factor: 256 + +# aicc +remote_save_url: "Please input obs url on AICC platform." \ No newline at end of file diff --git a/docs/mindformers/docs/source_zh_cn/example/supervised_fine_tuning/finetune_qwen2_5_7b_8k_1p.yaml b/docs/mindformers/docs/source_zh_cn/example/supervised_fine_tuning/finetune_qwen2_5_7b_8k_1p.yaml new file mode 100644 index 0000000000..afa279eae7 --- /dev/null +++ b/docs/mindformers/docs/source_zh_cn/example/supervised_fine_tuning/finetune_qwen2_5_7b_8k_1p.yaml @@ -0,0 +1,247 @@ +seed: 42 +output_dir: './output' +load_checkpoint: '/path/to/Qwen2.5-7B/' +load_ckpt_format: 'safetensors' +auto_trans_ckpt: True # If true, auto transform load_checkpoint to load in distributed model +only_save_strategy: False +resume_training: False +run_mode: 'finetune' + +# trainer config +trainer: + type: CausalLanguageModelingTrainer + model_name: 'qwen2_5_7b' +# if True, do evaluate during the training process. if false, do nothing. +# note that the task trainer should support _evaluate_in_training function. +do_eval: False +eval_step_interval: -1 # num of step intervals between each eval, -1 means no step end eval. +eval_epoch_interval: 50 # num of epoch intervals between each eval, 1 means eval on every epoch end. + +# runner config +runner_config: + epochs: 2 + batch_size: 1 + sink_mode: True + sink_size: 1 + +# wrapper cell config +runner_wrapper: + type: MFTrainOneStepCell + scale_sense: + type: DynamicLossScaleUpdateCell + loss_scale_value: 4096 + scale_factor: 1 + scale_window: 100000 + use_clip_grad: True + max_grad_norm: 1.0 + +# optimizer +optimizer: + type: AdamW + betas: [0.9, 0.95] + eps: 1.e-8 + learning_rate: 1.e-6 + weight_decay: 0.01 + +# lr schedule +lr_schedule: + type: CosineWithWarmUpLR + learning_rate: 1.e-6 + lr_end: 1.e-6 + warmup_ratio: 0 + total_steps: -1 # -1 means it will load the total steps of the dataset + +# dataset +train_dataset: &train_dataset + input_columns: &input_columns ["input_ids", "labels", "loss_mask", "position_ids", "attention_mask"] + construct_args_key: *input_columns + data_loader: + type: CommonDataLoader + load_func: 'load_dataset' + shuffle: False + path: "llm-wizard/alpaca-gpt4-data" + packing: pack + handler: + - type: AlpacaInstructDataHandler + tokenizer: + vocab_file: "/path/to/Qwen2.5-7B/vocab.json" + merges_file: "/path/to/Qwen2.5-7B/merges.txt" + unk_token: null + pad_token: "<|endoftext|>" + eos_token: "<|im_end|>" + bos_token: null + type: Qwen2Tokenizer + auto_register: qwen2_5_tokenizer.Qwen2Tokenizer + seq_length: &seq_length 8192 + prompt_key: "conversations" + output_columns: ["input_ids", "labels"] + is_dynamic: False + - type: PackingHandler + seq_length: *seq_length + output_columns: ["input_ids", "labels", "actual_seq_len"] + adaptor_config: + compress_mask: False + column_names: *input_columns + python_multiprocessing: False + drop_remainder: True + numa_enable: False + prefetch_size: 1 +train_dataset_task: + type: CausalLanguageModelDataset + dataset_config: *train_dataset + +# eval dataset +eval_dataset: &eval_dataset + data_loader: + type: MindDataset + dataset_dir: "" + shuffle: False + input_columns: ["input_ids", "target_ids", "attention_mask"] + num_parallel_workers: 8 + python_multiprocessing: False + drop_remainder: False + repeat: 1 + numa_enable: False + prefetch_size: 1 +eval_dataset_task: + type: CausalLanguageModelDataset + dataset_config: *eval_dataset + +use_parallel: True +# parallel context config +parallel: + parallel_mode: 1 # 0-data parallel, 1-semi-auto parallel, 2-auto parallel, 3-hybrid parallel + gradients_mean: False + enable_alltoall: False + full_batch: True + search_mode: "sharding_propagation" + strategy_ckpt_save_file: "./ckpt_strategy.ckpt" + enable_parallel_optimizer: True + parallel_optimizer_config: + gradient_accumulation_shard: False + parallel_optimizer_threshold: 64 + +# default parallel of device num = 8 +parallel_config: + data_parallel: 4 + model_parallel: 1 + pipeline_stage: 2 + context_parallel: 1 + use_seq_parallel: True + micro_batch_num: 16 + vocab_emb_dp: False + gradient_aggregation_group: 4 +# when model parallel is greater than 1, we can set micro_batch_interleave_num=2, that may accelerate the train process. +micro_batch_interleave_num: 1 + +# recompute config +recompute_config: + recompute: False + parallel_optimizer_comm_recompute: False + mp_comm_recompute: False + recompute_slice_activation: False + +# callbacks +callbacks: + - type: MFLossMonitor + - type: CheckpointMonitor + prefix: "qwen2_5" + save_checkpoint_steps: 5000 + keep_checkpoint_max: 1 + integrated_save: False + async_save: False + checkpoint_format: "safetensors" + +# mindspore context init config +context: + mode: 0 #0--Graph Mode; 1--Pynative Mode + device_target: "Ascend" + max_call_depth: 10000 + max_device_memory: "58GB" + save_graphs: False + save_graphs_path: "./graph" + device_id: 0 + memory_optimize_level: "O1" + jit_config: + jit_level: "O1" + ascend_config: + precision_mode: "must_keep_origin_dtype" + +# model config +model: + model_config: + type: LlamaConfig + batch_size: 1 + seq_length: *seq_length + hidden_size: 3584 + num_layers: 4 + num_heads: 28 + n_kv_heads: 4 + vocab_size: 152064 + intermediate_size: 18944 + qkv_has_bias: True + rms_norm_eps: 1.0e-6 + theta: 1000000.0 + max_position_embedding: 131072 + emb_dropout_prob: 0.0 + eos_token_id: 151643 + pad_token_id: 151643 + bos_token_id: 151643 + compute_dtype: "bfloat16" + layernorm_compute_type: "float32" + softmax_compute_type: "float32" + rotary_dtype: "float32" + param_init_type: "float32" + use_past: False + use_flash_attention: True + use_past_shard: False + offset: 0 + checkpoint_name_or_path: "" + repetition_penalty: 1.05 + max_decode_length: 1024 + top_k: 0 + top_p: 0.8 + do_sample: False + extend_method: "None" # support "None", "PI", "NTK" + fine_grain_interleave: 1 + qkv_concat: false + # configuration items copied from Qwen + rotary_pct: 1.0 + rotary_emb_base: 1000000 + input_sliced_sig: True + arch: + type: LlamaForCausalLM + +processor: + return_tensors: ms + tokenizer: + model_max_length: 131072 + vocab_file: "path/vocab.json" + merges_file: "path/merges.txt" + unk_token: None + pad_token: "<|endoftext|>" + eos_token: "<|endoftext|>" + type: Qwen2Tokenizer + type: Qwen2Processor + +# metric +metric: + type: PerplexityMetric + + +auto_tune: False +filepath_prefix: './autotune' +autotune_per_step: 10 + +profile: False +profile_start_step: 1 +profile_stop_step: 10 +init_start_profile: False +profile_communication: False +profile_memory: True +layer_scale: False +layer_decay: 0.65 +lr_scale_factor: 256 + +# aicc +remote_save_url: "Please input obs url on AICC platform." \ No newline at end of file diff --git a/docs/mindformers/docs/source_zh_cn/guide/supervised_fine_tuning.md b/docs/mindformers/docs/source_zh_cn/guide/supervised_fine_tuning.md index 4ba7b69452..0ae8d23dc8 100644 --- a/docs/mindformers/docs/source_zh_cn/guide/supervised_fine_tuning.md +++ b/docs/mindformers/docs/source_zh_cn/guide/supervised_fine_tuning.md @@ -1,166 +1,138 @@ -# SFT微调 +# 微调 [![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindformers/docs/source_zh_cn/guide/supervised_fine_tuning.md) ## 概述 -SFT(Supervised Fine-Tuning,监督微调)采用有监督学习思想,是指在预训练模型的基础上,通过调整部分或全部参数,使其更适应特定任务或数据集的过程。 +SFT(Supervised Fine-Tuning,监督微调)采用有监督学习思想,是指在预训练模型的基础上,通过调整部分或全部参数,使模型更适应特定任务或数据集的过程。 ## SFT微调的基本流程 -SFT微调整体包含以下几个部分: - -- **预训练:** - 首先需要在一个较大规模的数据集上训练一个神经网络模型,比如针对大语言模型,通常是在大量未标记的文本数据上进行,预训练阶段的目标是使模型获取通用的知识和理解能力。 -- **微调:** - 结合目标任务,用新的训练数据集对已经得到的预训练模型进行微调。在微调过程中,通过反向传播可以对原始模型的全部参数或者部分参数进行优化,使模型在目标任务上取得更好的效果。 -- **评估:** - 经过微调之后会得到一个新的模型,可以用目标任务的评测数据集对微调模型进行评估,从而得到微调模型在目标任务上的性能指标。 - 结合实际操作,可以将SFT微调分解为以下步骤: -1. **选择预训练模型:** - 选择一个预训练的语言模型,如GPT-2、Llama2等。预训练模型通常是在大型文本语料库上进行过训练,以学习语言的通用表示。 -2. **下载模型权重:** - 针对选择的预训练模型,可以从HuggingFace模型库中下载预训练的权重。 -3. **模型权重转换:** - 结合自己所要使用的框架,对已经下载的HuggingFace权重进行权重转换,比如转换为MindSpore框架所支持的ckpt权重。 -4. **数据集准备:** - 结合微调的目标,选择用于微调任务的数据集,针对大语言模型,微调数据集一般是包含文本和标签的数据,比如alpaca数据集。同时在使用数据集时,需要对数据做相应的预处理,比如使用MindSpore框架时,需要将数据集转换为MindRecord格式。 -5. **执行微调任务:** - 使用微调任务的数据集对预训练模型进行训练,更新模型参数,如果是全参微调则会对所有参数进行更新,微调任务完成后,便可以得到新的模型。 +### 1. 权重准备 -## SFT微调方式 +在微调之前,需要准备好预训练模型的权重文件。MindSpore Transformers 提供加载 [safetensors权重](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/safetensors.html)的能力,支持直接加载从 HuggingFace 模型库中下载的模型权重。 -MindSpore Transformers当前支持全参微调和LoRA低参微调两种SFT微调方式。全参微调是指在训练过程中对所有参数进行更新,适用于大规模数据精调,能获得最优的任务适应能力,但需要的计算资源较大。LoRA低参微调在训练过程中仅更新部分参数,相比全参微调显存占用更少、训练速度更快,但在某些任务中的效果不如全参微调。 +### 2. 数据集准备 -### LoRA 原理简介 +MindSpore Transformers 微调阶段当前已支持[MindRecord格式](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/dataset.html#mindrecord%E6%95%B0%E6%8D%AE%E9%9B%86)以及[HuggingFace格式](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/dataset.html#huggingface%E6%95%B0%E6%8D%AE%E9%9B%86)的数据集。用户可根据任务需求完成数据准备。 -LoRA通过将原始模型的权重矩阵分解为两个低秩矩阵来实现参数量的显著减少。例如,假设一个权重矩阵W的大小为m x n,通过LoRA,该矩阵被分解为两个低秩矩阵A和B,其中A的大小为m x r,B的大小为r x n(r远小于m和n)。在微调过程中,仅对这两个低秩矩阵进行更新,而不改变原始模型的其他部分。 +### 3. 配置文件准备 -这种方法不仅大幅度降低了微调的计算开销,还保留了模型的原始性能,特别适用于数据量有限、计算资源受限的环境中进行模型优化,详细原理可以查看论文 [LoRA: Low-Rank Adaptation of Large Language Models](https://arxiv.org/abs/2106.09685) 。 +微调任务通过[配置文件](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/configuration.html)统一控制,用户可灵活调整[模型训练超参数](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/training_hyperparameters.html)。另外可以通过[分布式并行训练](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/parallel_training.html)、[内存优化特性](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/memory_optimization.html)以及[其它训练特性](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/other_training_features.html)对微调性能进行调优。 -## 使用MindSpore Transformers进行全参微调 +### 4. 启动训练任务 -### 选择预训练模型 +MindSpore Transformers 提供[一键启动脚本](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/start_tasks.html)启动微调任务。训练过程中可结合[日志](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/logging.html)与[可视化工具](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/monitor.html)监控训练情况。 -MindSpore Transformers目前已经支持业界主流大模型,该实践流程选择Llama2-7B模型SFT微调为例。 +### 5. 模型保存 -### 下载模型权重 +训练过程中保存检查点或完成后,模型权重将保存至指定路径。当前支持保存为[Ckpt 格式](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/ckpt.html)或[Safetensors 格式](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/safetensors.html),后续可以使用保存的权重进行续训或微调等。 -MindSpore Transformers提供已经转换完成的预训练权重、词表文件用于预训练、微调和推理,用户也可以下载HuggingFace官方权重经过模型权重转换后进行使用。 +### 6. 故障恢复 -词表下载链接:[tokenizer.model](https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/MindFormers/llama2/tokenizer.model) +为应对训练中断等异常情况,MindSpore Transformers 具备临终保存、自动恢复等[高可用特性](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/high_availability.html),并支持[断点续训](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/resume_training.html),提升训练稳定性。 -| 模型名称 | MindSpore权重 | HuggingFace权重 | -|:----------|:------------------------------------------------------------------------------------------------------------:| :---------------------------------------------------------------------------------------------: | -| Llama2-7B | [Link](https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/MindFormers/llama2/llama2_7b.ckpt) | [Link](https://huggingface.co/meta-llama/Llama-2-7b-hf) | +## SFT微调方式 -> Llama2的所有权重都需要通过向Meta[提交申请](https://ai.meta.com/resources/models-and-libraries/llama-downloads)来获取,如有需要请自行申请。 +MindSpore Transformers 支持全参微调和LoRA低参微调两种SFT微调方式。全参微调是指在训练过程中对所有参数进行更新,适用于大规模数据精调,能获得最优的任务适应能力,但需要的计算资源较大。LoRA低参微调在训练过程中仅更新部分参数,相比全参微调显存占用更少、训练速度更快,但在某些任务中的效果不如全参微调。 -### 模型权重转换 +> **LoRA 原理简介** +> LoRA通过将原始模型的权重矩阵分解为两个低秩矩阵来实现参数量的显著减少。例如,假设一个权重矩阵W的大小为$m \times n$,通过LoRA,该矩阵被分解为两个低秩矩阵A和B,其中A的大小为$m \times r$,B的大小为$r \times n$($r$远小于$m$和$n$)。在微调过程中,仅对这两个低秩矩阵进行更新,而不改变原始模型的其他部分。 +> 这种方法不仅大幅度降低了微调的计算开销,还保留了模型的原始性能,特别适用于数据量有限、计算资源受限的环境中进行模型优化,详细原理可以查看论文 [LoRA: Low-Rank Adaptation of Large Language Models](https://arxiv.org/abs/2106.09685) 。 -以[Llama2-7B模型](https://huggingface.co/meta-llama/Llama-2-7b-hf/tree/main)为例,原始的HuggingFace权重文件主要包含:
+## 使用MindSpore Transformers进行全参微调 -- `config.json`:模型架构的主要配置信息
-- `generation_config.json`:文本生成相关的配置信息
-- `safetensors文件`:模型权重文件
-- `model.safetensors.index.json`:safetensors模型参数文件索引和描述模型切片的json文件
-- `bin文件`:pytorch的模型权重文件
-- `pytorch_model.bin.index.json`:pytorch索引和描述模型切片的json文件
-- `tokenizer.json`:分词器的词汇配置文件
-- `tokenizer.model`:模型的分词器
+### 选择预训练模型 -MindSpore Transformers提供权重转换脚本,通过执行[convert_weight.py转换脚本](https://gitee.com/mindspore/mindformers/blob/dev/convert_weight.py),可以将HuggingFace的权重转换为完整的ckpt权重。 +MindSpore Transformers目前已经支持业界主流大模型,该实践流程选择Qwen2.5-7B模型为例。 -```bash -python convert_weight.py --model llama --input_path TORCH_CKPT_DIR --output_path {path}/MS_CKPT_NAME -``` +### 下载模型权重 -参数说明: +MindSpore Transformers提供加载HuggingFace模型权重的能力,支持直接加载从HuggingFace模型库中下载的模型权重。详细信息可以参考[MindSpore Transformers-Safetensors权重](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/safetensors.html)。 -```commandline -model: 模型名称(其他模型请参考模型说明文档) -input_path: 下载HuggingFace权重的文件夹路径 -output_path: 转换后的MindSpore权重文件保存路径 -``` +| 模型名称 | HuggingFace权重 | +| :--------- | :--------------------------------------------: | +| Qwen2.5-7B | [Link](https://huggingface.co/Qwen/Qwen2.5-7B) | ### 数据集准备 -MindSpore Transformers提供**WikiText2**作为预训练数据集,**alpaca**作为微调数据集。 - -| 数据集名称 | 适用模型 | 适用阶段 | 下载链接 | -|:----------|:-------------------------------------:|:---------:| :--------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| alpaca | Llama2-7B
Llama2-13B
Llama2-70B | 微调 | [Link](https://github.com/tatsu-lab/stanford_alpaca/blob/main/alpaca_data.json) | - -以alpaca数据集为例,下载数据集后需要对数据集进行预处理。预处理中所用的`tokenizer.model`可以参考模型权重下载进行下载。 - -**alpaca 数据预处理** - -1. 执行MindSpore Transformers中的[alpaca_converter.py脚本](https://gitee.com/mindspore/mindformers/blob/dev/mindformers/tools/dataset_preprocess/llama/alpaca_converter.py),将数据集转换为多轮对话格式。 - - ```bash - python alpaca_converter.py \ - --data_path /{path}/alpaca_data.json \ - --output_path /{path}/alpaca-data-conversation.json - ``` - - 参数说明: +MindSpore Transformers提供在线加载huggingface数据集的能力,详细信息可以参考[MindSpore Transformers-数据集-HuggingFace数据集](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/dataset.html#huggingface%E6%95%B0%E6%8D%AE%E9%9B%86)。 +本实践流程以[llm-wizard/alpaca-gpt4-data](https://huggingface.co/datasets/llm-wizard/alpaca-gpt4-data)作为微调数据集为例。 - ```commandline - data_path: 输入下载的文件路径 - output_path: 输出文件的保存路径 - ``` +| 数据集名称 | 适用阶段 | 下载链接 | +| :-------------------------: | :------: | :-----------------------------------------------------------------: | +| llm-wizard/alpaca-gpt4-data | 微调 | [Link](https://huggingface.co/datasets/llm-wizard/alpaca-gpt4-data) | -2. 执行MindSpore Transformers中的[llama_preprocess.py脚本](https://gitee.com/mindspore/mindformers/blob/dev/mindformers/tools/dataset_preprocess/llama/llama_preprocess.py),将数据转换为MindRecord格式。该操作依赖fastchat工具包解析prompt模板, 请提前安装fastchat >= 0.2.13。 +### 执行微调任务 - ```bash - python llama_preprocess.py \ - --dataset_type qa \ - --input_glob /{path}/alpaca-data-conversation.json \ - --model_file /{path}/tokenizer.model \ - --seq_length 4096 \ - --output_file /{path}/alpaca-fastchat4096.mindrecord - ``` +#### 单卡训练 - 参数说明: +首先准备配置,本实践流程以Qwen2.5-7B模型为例,提供了一个微调配置文件`finetune_qwen2_5_7b_8k_1p.yaml`,可以在[gitee仓库](https://gitee.com/mindspore/docs/tree/master/docs/mindformers/docs/source_zh_cn/guide/supervised_fine_tuning/finetune_qwen2_5_7b_8k_1p.yaml)下载。 - ```commandline - dataset_type: 预处理数据类型 - input_glob: 转换后的alpaca的文件路径 - model_file: 模型tokenizer.model文件路径 - seq_length: 输出数据的序列长度 - output_file: 输出文件的保存路径 - ``` +> 注意:由于单卡显存有限,配置文件中的`num_layers`被设置为了4,仅作为示例使用。 -### 执行微调任务 +然后根据实际情况修改配置文件中的参数,主要包括: -#### 单卡训练 +```yaml +load_checkpoint: '/path/to/Qwen2.5-7B/' # 预训练模型权重文件夹路径 +... +train_dataset: &train_dataset + ... + data_loader: + ... + handler: + - type: AlpacaInstructDataHandler + tokenizer: + vocab_file: "/path/to/Qwen2.5-7B/vocab.json" # 词表文件路径 + merges_file: "/path/to/Qwen2.5-7B/merges.txt" # merges文件路径 +``` 执行`run_mindformer.py`启动单卡的微调任务,下面提供了一个使用示例: -以Llama2模型单卡微调为例,由于单卡显存有限,无法运行完整的Llama2-7B模型,所以缩层进行示例,修改`finetune_llama2_7b.yaml`,将其中`num_layers`设置为2。 - 启动命令如下: ```shell python run_mindformer.py \ - --config configs/llama2/finetune_llama2_7b.yaml \ - --train_dataset_dir /{path}/alpaca-fastchat4096.mindrecord \ - --load_checkpoint /{path}/llama2_7b.ckpt \ + --config /path/to/finetune_qwen2_5_7b_8k_1p.yaml \ --use_parallel False \ --run_mode finetune ``` +参数说明: + +```commandline +config: 模型的配置文件 +use_parallel: 是否开启并行 +run_mode: 运行模式,train:训练,finetune:微调,predict:推理 +``` + #### 单机训练 -以Llama2-7B为例,执行msrun启动脚本,进行8卡分布式训练,启动命令如下: +首先准备配置,本实践流程以Qwen2.5-7B模型为例,提供了一个微调配置文件`finetune_qwen2_5_7b_8k.yaml`,可以在[gitee仓库](https://gitee.com/mindspore/docs/tree/master/docs/mindformers/docs/source_zh_cn/guide/supervised_fine_tuning/finetune_qwen2_5_7b_8k.yaml)下载。 + +然后根据实际情况修改配置文件中的参数,主要包括: + +```yaml +load_checkpoint: '/path/to/Qwen2.5-7B/' # 预训练模型权重文件夹路径 +... +train_dataset: &train_dataset + ... + data_loader: + ... + handler: + - type: AlpacaInstructDataHandler + tokenizer: + vocab_file: "/path/to/Qwen2.5-7B/vocab.json" # 词表文件路径 + merges_file: "/path/to/Qwen2.5-7B/merges.txt" # merges文件路径 +``` + +执行以下msrun启动脚本,进行8卡分布式训练: ```bash bash scripts/msrun_launcher.sh "run_mindformer.py \ - --config configs/llama2/finetune_llama2_7b.yaml \ - --load_checkpoint /{path}/llama2_7b.ckpt \ - --train_dataset_dir /{path}/alpaca-fastchat4096.mindrecord \ + --config /path/to/finetune_qwen2_5_7b_8k.yaml \ --use_parallel True \ --run_mode finetune" 8 ``` @@ -168,9 +140,7 @@ bash scripts/msrun_launcher.sh "run_mindformer.py \ 参数说明: ```commandline -config: 模型的配置文件,文件在MindSpore Transformers代码仓中config目录下 -load_checkpoint: checkpoint文件的路径 -train_dataset_dir: 训练数据集路径 +config: 模型的配置文件 use_parallel: 是否开启并行 run_mode: 运行模式,train:训练,finetune:微调,predict:推理 ``` @@ -179,11 +149,22 @@ run_mode: 运行模式,train:训练,finetune:微调,predict #### 多机训练 -多机多卡微调任务与启动预训练类似,可参考[多机多卡的预训练命令](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/guide/pre_training.html#%E5%A4%9A%E6%9C%BA%E8%AE%AD%E7%BB%83),并对命令进行如下修改: +多机多卡微调任务与启动预训练类似,可参考[多机多卡的预训练命令](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/guide/pre_training.html#%E5%A4%9A%E6%9C%BA%E8%AE%AD%E7%BB%83)。 -1. 增加启动脚本入参`--load_checkpoint /{path}/llama2_7b.ckpt`加载预训练权重。 -2. 设置启动脚本中的`--train_dataset_dir /{path}/alpaca-fastchat4096.mindrecord`加载微调数据集。 -3. 设置启动脚本中的`--run_mode finetune`,run_mode表示运行模式,train:训练,finetune:微调,predict:推理。 +首先对配置文件进行修改,这里需要针对不同的机器数量进行设置: + +```yaml +parallel_config: + data_parallel: ... + model_parallel: ... + pipeline_stage: ... + context_parallel: ... +``` + +并对命令进行如下修改: + +1. 增加启动脚本入参`--config /path/to/finetune_qwen2_5_7b_8k.yaml`加载预训练权重。 +2. 设置启动脚本中的`--run_mode finetune`,run_mode表示运行模式,train:训练,finetune:微调,predict:推理。 任务执行完成后,在mindformers/output目录下,会生成checkpoint文件夹,同时模型文件会保存在该文件夹下。 @@ -191,30 +172,21 @@ run_mode: 运行模式,train:训练,finetune:微调,predict MindSpore Transformers支持配置化使能LoRA微调,无需对每个模型进行代码适配,而仅需修改全参微调的YAML配置文件中的模型配置,添加 `pet_config` 低参微调配置,即可使用其进行LoRA低参微调任务。以下展示了Llama2模型LoRA微调的YAML配置文件中的模型配置部分,并对 `pet_config` 参数进行了详细说明。 -### 示例配置文件(YAML) +### 修改配置文件 -完整的YAML配置文件可以通过以下链接访问:[Llama2 LoRA微调 YAML 文件](https://gitee.com/mindspore/mindformers/blob/dev/configs/llama2/lora_llama2_7b.yaml)。 +基于全参微调的配置文件,我们需要在模型配置中添加LoRA相关的参数,并将其重命名为`fine_tune_qwen2_5_7b_8k_lora.yaml`。以下是一个示例配置片段,展示了如何在Qwen2.5-7B模型的配置文件中添加LoRA微调的相关参数: ```yaml # model config model: model_config: - type: LlamaConfig - batch_size: 1 - seq_length: 4096 - hidden_size: 4096 - num_layers: 32 - num_heads: 32 - vocab_size: 32000 - compute_dtype: "float16" + ... pet_config: pet_type: lora lora_rank: 16 lora_alpha: 16 lora_dropout: 0.05 target_modules: '.*wq|.*wk|.*wv|.*wo' - arch: - type: LlamaForCausalLM ``` ### pet_config 参数详解 @@ -227,30 +199,15 @@ model: - **lora_dropout:** 设置LoRA模块中的dropout概率。Dropout是一种正则化技术,用于减少过拟合风险。设置为0.05表示在训练过程中有5%的概率会随机“关闭”某些神经元连接,这在数据量有限的情况下尤为重要。 - **target_modules:** 通过正则表达式指定LoRA将应用于模型中的哪些权重矩阵。在Llama中,这里的配置将LoRA应用于模型的自注意力机制中的Query(wq)、Key(wk)、Value(wv)和Output(wo)矩阵。这些矩阵在Transformer结构中扮演关键角色,插入LoRA后可以在减少参数量的同时保持模型性能。 -### Llama2-7B 的 LoRA 微调示例 - -MindSpore Transformers 提供了 Llama2-7B 的 [LoRA 微调示例](https://gitee.com/mindspore/mindformers/blob/dev/docs/model_cards/llama2.md#lora%E5%BE%AE%E8%B0%83)。微调过程中使用的数据集可以参考[数据集下载](https://github.com/tatsu-lab/stanford_alpaca/blob/main/alpaca_data.json)获得。 +### Qwen2.5-7B 的 LoRA 微调示例 -以 Llama2-7B 为例,可以执行以下 msrun 启动脚本,进行 8 卡分布式微调。 - -```shell -bash scripts/msrun_launcher.sh "run_mindformer.py \ - --config configs/llama2/lora_llama2_7b.yaml \ - --train_dataset_dir /{path}/alpaca-fastchat4096.mindrecord \ - --load_checkpoint /{path}/llama2_7b.ckpt \ - --auto_trans_ckpt False \ - --use_parallel True \ - --run_mode finetune" 8 -``` +LoRA微调过程中使用的数据集可以参考全参微调部分的[数据集准备](#数据集准备)章节。 -当权重的分布式策略和模型的分布式策略不一致时,需要对权重进行切分转换。加载权重路径应设置为以 `rank_0` 命名的目录的上一层路径,同时开启权重自动切分转换功能 `--auto_trans_ckpt True` 。关于分布式权重切分转换的场景和使用方式的更多说明请参考[分布式权重切分与合并](https://www.mindspore.cn/mindformers/docs/zh-CN/dev/feature/ckpt.html#%E6%9D%83%E9%87%8D%E5%88%87%E5%88%86%E4%B8%8E%E5%90%88%E5%B9%B6)。 +以 Qwen2.5-7B 为例,可以执行以下 msrun 启动脚本,进行 8 卡分布式微调。 ```shell bash scripts/msrun_launcher.sh "run_mindformer.py \ - --config configs/llama2/lora_llama2_7b.yaml \ - --train_dataset_dir /{path}/alpaca-fastchat4096.mindrecord \ - --load_checkpoint /{path}/checkpoint/ \ - --auto_trans_ckpt True \ + --config /path/to/finetune_qwen2_5_7b_8k_lora.yaml \ --use_parallel True \ --run_mode finetune" 8 ``` -- Gitee