昇思MindSpore大模型迁移与调优实践
利用MindSpore Transformers(MindFormers)进行模型的迁移与调优
我们首先来看一下MindSpore的整体框架

- 1.MindSpore的定位:MindSpore是一个AI框架(@或者说深度学习框架),在昇腾软硬件全栈中,向上对接如 MindIE的应用使能,向下对接CANN计算架构。
- 2.MindSpore和CANN的关系:CANN面向算子开发,MindSpore对接/调用CANN这一层开发出的算子。
- 3.MindSpore和MindSpore Transformers的关系:MindSpore Transformers是基于MindSpore构建的大模型使能套件,承载了MindSpore?如分布式并行能 力的同时,覆盖预训练、微调、推理、部署全流程,预置多种预训练大模型,微调算法及下游应用,低代码实现原生大模型原生全流程开发。
- 4.MindSporel的能力:MindSpores分布式并行依托于图编译和对整图的切分,这种方式降低了大模型的开发门槛,又保证了多种并行策略的灵活组合使用。 同时在内存管理上,训练时构造整图,可以获取所有Tensor的生命周期,设计最优内存复用策略。
为何需要做模型迁移:
为适配业界生态,我们经常会遇到将其他框架实现的大模型迁移到MindSpore Transformers的情况,目前常遇到的模型迁移场景主要分为两类: 1.在MindSpore Transformerst中目前已支特的基座模型(如LLāMA)上进行改动,变成适配相应业务场景的模型,工作量及难度较小 2.基于MindSpore Transformers/从头自主完成模型迁移,工作量及难度较大
模型精度调优:
- 1.精度调优分为有标杆和无标杆的场景,以有标杆场景为例,目标是将基于MindSpore Transformerss实现的模型精度和原框架对齐
- 2.精度调优常见的对t比项:loss、local norm、global norm
- 3.精度调优的思路:训练前准备、基础问题排查、长稳问题观察
- 4.训川练前准备重点关注数据集对济、权重对齐、训练参数对齐,在后续的问题排查中,可重点关注数据类型是否保持一致
- 5.精度调优工具:MindSpore Dump、Torch Dump、TroubleShooter
开启实战:

由于计算卡显存的限制,我选择了 Qwen2.5-3B 模型以及 alpaca_data 数据集
数据集预处理(我们首先需要把数据集变为标准的Alpaca 数据集格式)
数据集链接:https://modelscope.cn/datasets/YorickHe/alpaca_data

下载数据及后我们用如下脚本将数据集转换为标准格式的Alpaca 数据集格式:
然后再将json文件转换成标准的Alpaca 数据集格式:

最终需要的数据集格式:


- 然后再进行数据预处理和Mindrecord数据生成
注意,在运行这一步时可能会报错:

然后进入到:mindformers下运行脚本:

- 然后就是进行torch权重转mindspore权重

但是yaml文件中的对应配置文件需要你自己写入:


- 下面是我的完整yaml配置文件(路径需要改为自己的)
思考:在这个过程中,用mindformers微调的过程还是与其他主流框架有不小的异同的,我认为mindformers适合的群体是专业的开发者,对性能要求有着严格追求的群体,说白了就是上手难度不小,如果要是让我去选择的话我会选择mindnlp来进行微调。但是其优化的效果确实不错,与mindnlp对比,能够减小一部分显存的占用率。
建议:如果可以的话,我觉得可以做一个webui来进行微调,这样更加方便也更加直观。mindnlp也是一样的。
昇思MindSpore大模型迁移与调优实践
利用MindSpore Transformers(MindFormers)进行模型的迁移与调优
我们首先来看一下MindSpore的整体框架
为何需要做模型迁移:
为适配业界生态,我们经常会遇到将其他框架实现的大模型迁移到MindSpore Transformers的情况,目前常遇到的模型迁移场景主要分为两类: 1.在MindSpore Transformerst中目前已支特的基座模型(如LLāMA)上进行改动,变成适配相应业务场景的模型,工作量及难度较小 2.基于MindSpore Transformers/从头自主完成模型迁移,工作量及难度较大
模型精度调优:
开启实战:
由于计算卡显存的限制,我选择了 Qwen2.5-3B 模型以及 alpaca_data 数据集
数据集预处理(我们首先需要把数据集变为标准的Alpaca 数据集格式)
数据集链接:https://modelscope.cn/datasets/YorickHe/alpaca_data
下载数据及后我们用如下脚本将数据集转换为标准格式的Alpaca 数据集格式:
import csv import json # 输入和输出文件路径 input_csv_path = 'alpaca_data.csv' output_json_path = 'json_data.json' # 读取 CSV 并写入标准 Alpaca 格式 JSON with open(input_csv_path, 'r', encoding='utf-8') as csv_file, open(output_json_path, 'w', encoding='utf-8') as json_file: reader = csv.DictReader(csv_file) for row in reader: # 假设列名是 instruction, input, output alpaca_entry = { "instruction": row.get("instruction", "").strip(), "input": row.get("input", "").strip(), "output": row.get("output", "").strip() } json_file.write(json.dumps(alpaca_entry, ensure_ascii=False) + '\n') print("转换完成,输出文件:", output_json_path)然后再将json文件转换成标准的Alpaca 数据集格式:
import json # 输入:jsonl 文件路径 input_file = 'json_data.json' # 输出:json 数组格式文件路径 output_file = 'converted_output.json' data = [] with open(input_file, 'r', encoding='utf-8') as f: for line in f: if line.strip(): # 忽略空行 data.append(json.loads(line)) with open(output_file, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=4) print(f"转换完成,共转换 {len(data)} 条记录,输出文件:{output_file}")最终需要的数据集格式:
注意,在运行这一步时可能会报错:
解决办法:
在终端输入:
然后进入到:mindformers下运行脚本:
但是yaml文件中的对应配置文件需要你自己写入:
# dataset train_dataset: &train_dataset data_loader: type: MindDataset dataset_dir: "/home/ma-user/work/dataset/alpaca_data/alpaca-messages.mindrecord" shuffle: False num_samples: 64 input_columns: ["input_ids"] num_parallel_workers: 8 python_multiprocessing: False drop_remainder: True batch_size: 1 repeat: 1 numa_enable: False prefetch_size: 1 train_dataset_task: type: CausalLanguageModelDataset dataset_config: *train_dataset checkpoint_name_or_path: "/home/ma-user/work/model/Qwen2.5-3B/qwen2_5_3b.ckpt"seed: 42 output_dir: './output' run_mode: 'train' use_parallel: True resume_training: False only_save_strategy: False load_checkpoint: '' auto_trans_ckpt: False # If true, auto transform load_checkpoint to load in distributed model # trainer config trainer: type: CausalLanguageModelingTrainer model_name: 'qwen2_5_3b' # runner config runner_config: epochs: 3 batch_size: 4 sink_mode: True sink_size: 1 gradient_accumulation_steps: 1 runner_wrapper: type: MFTrainOneStepCell scale_sense: type: DynamicLossScaleUpdateCell loss_scale_value: 1 scale_factor: 1 scale_window: 1000 use_clip_grad: True max_grad_norm: 1.0 # optimizer optimizer: type: AdamW betas: [0.9, 0.95] eps: 1.e-8 weight_decay: 0.1 lr_schedule: type: WarmUpStableDecayLR learning_rate: 3.e-4 lr_end: 0 warmup_ratio: 0.1 decay_start_ratio: 0.9 total_steps: -1 # -1 means it will load the total steps of the dataset # dataset train_dataset: &train_dataset data_loader: type: MindDataset dataset_dir: "/home/ma-user/work/dataset/alpaca_data/alpaca-messages.mindrecord" shuffle: False num_samples: 64 input_columns: ["input_ids"] num_parallel_workers: 8 python_multiprocessing: False drop_remainder: True batch_size: 1 repeat: 1 numa_enable: False prefetch_size: 1 train_dataset_task: type: CausalLanguageModelDataset dataset_config: *train_dataset # parallel context config parallel: full_batch: True enable_parallel_optimizer: True parallel_optimizer_config: gradient_accumulation_shard: False parallel_optimizer_threshold: 64 # default parallel of device num = 32 910B parallel_config: data_parallel: 1 model_parallel: 1 pipeline_stage: 1 context_parallel: 1 use_seq_parallel: True micro_batch_num: 1 vocab_emb_dp: False # when model parallel is greater than 1, we can set micro_batch_interleave_num=2, that may accelerate the train process. # recompute config recompute_config: recompute: True select_recompute: False # select_recompute: # 'feed_forward\.mul': [3] # 'feed_forward\.w1\.activation\.silu': [3] # 'feed_forward\.w1\.reshape': [3] # 'feed_forward\.w2\.reshape': [3] parallel_optimizer_comm_recompute: False mp_comm_recompute: True recompute_slice_activation: False # callbacks callbacks: - type: CheckpointMonitor prefix: "qwen2_5" save_checkpoint_steps: 2000 keep_checkpoint_max: 1 save_ckpt_with_optim_param: True async_save: False # mindspore context init config context: jit_config: jit_level: "O1" memory_optimize_level: "O1" mode: 0 #0--Graph Mode; 1--Pynative Mode graph_kernel_flags: "--enable_cluster_ops=MatMul --online_tuning=1" max_device_memory: "59GB" device_id: 0 # model config model: model_config: #use_attn_mask_compression: True type: LlamaConfig batch_size: 1 seq_length: 4096 hidden_size: 2048 num_layers: 36 num_heads: 16 n_kv_heads: 2 vocab_size: 151936 initializer_range: 0.02 intermediate_size: 11008 qkv_has_bias: True rms_norm_eps: 1.0e-6 theta: 1000000.0 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: "/home/ma-user/work/model/Qwen2.5-3B/qwen2_5_3b.ckpt" 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 tie_word_embeddings: True arch: type: LlamaForCausalLM # metric metric: type: PerplexityMetric思考:在这个过程中,用mindformers微调的过程还是与其他主流框架有不小的异同的,我认为mindformers适合的群体是专业的开发者,对性能要求有着严格追求的群体,说白了就是上手难度不小,如果要是让我去选择的话我会选择mindnlp来进行微调。但是其优化的效果确实不错,与mindnlp对比,能够减小一部分显存的占用率。
建议:如果可以的话,我觉得可以做一个webui来进行微调,这样更加方便也更加直观。mindnlp也是一样的。