大模型微调训练实战|Qwen2.5思维链微调代码实操 + 多卡Lora微调完整代码

最近对于Scaling Law的讨论异常火热。包括ilya大神自己都下场演讲关于大模型数据规模碰壁的问题(参考:机器之心官网发文)。直觉上,现在大模型思维的过程更像是人对一件事情直觉的反应,而不是多步思考和迭代思考的过程。正如下图ilya的PPT中的一张图,10层神经网络可以干人在0.1秒干的事情。而现在大模型上十亿的参数也可能只是解决人经过一分钟思考的回答。像OpenAI o1或者强化对齐可能是通往AGI的方法之一。刚好趁这个机会尝试一下一直没有进行的思维链微调。

  • Scaling Law:

    https://baike.baidu.com/item/Scaling%20Law/65144136?fr=ge_ala

  • 机器之心官网发文:

    https://www.jiqizhixin.com/articles/2024-12-14-3

下面简单介绍一下思维链技术,并且使用通义千问[1]进行CoT数据微调并且简单测试一下。

img

网上关于思维链微调的实操比较少,甚至对于Qwen的指令微调高质量的文章都不多,许多细节都描述的不清楚,希望这篇文章能够进一步帮助到读者微调Qwen时能够关注到一些细节。

这里感谢魔乐社区赞助了华为昇腾910卡进行微调。尝试了下国产卡做微调的效果还是非常不错!本篇教程专门做了openMind Library的适配,兼容华为昇腾910卡。

友情链接:

  • 魔乐社区:https://modelers.cn/models
  • Qwen2.5模型:https://github.com/QwenLM/Qwen2.5
  • SwanLab训练跟踪工具:https://swanlab.cn

1 思维链技术介绍

思维链技术(Chain of Thought,也简称为CoT),最早由Json Wei等人在《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》[2]文章提出。简单来说就是通过提示词让模型能够将一个复杂的问题分步思考。比如举个文章中提到的例子(见下图),一个数学问题是:

食堂有 23 个苹果。如果他们用掉了 20 个来做午餐,又买了 6 个,现在他们有多少个苹果?

对于一个人类,他的思考步骤是:

  • 食堂有23个苹果,用了20个,所以是23-20=3
  • 又买了6个,所以是3+6=9
  • 共有9个苹果

当然这个思维过程还能猜得更碎。

比如上面的过程中第一个实际上蕴涵了“因为食堂有23个苹果,用了20个”、“所以是23-20=3”两个步骤。对于进行了“指令微调”的模型来说,更倾向于简短的回答入,比如直接回答“他现在有XX个苹果”,而且对于一个需要多步计算的数学题往往是错误的。CoT技术的主要目标就是通过提示词让模型一步一步来,像上面的思考步骤那样要求模型不仅回答问题,同时还将问题的生成过程写出来。

img

Json Wei的这篇文章的工作是在提示词上做的(文中分了few-shot和zero-shot两种方式,简单来说就是给样例和不给样例),用学术些的话来说就是“上下文学习”。这篇文章的实验部分证明了CoT确实能有效提升LLM的推理能力,尤其是数学任务。当然很多人一下就想到了,我能否用微调的方式直接将这种“一步步思考”的能力直接微调到模型中呢?实际上Json Wei大神也很快想到了,所以在紧接着下一篇《Scaling Instruction-Finetuned Language Models》[3]、Google的FLAN[4]数据集改进版FLAN PaLM中直接引入了CoT数据集,这篇Json Wei虽然不是一作,但也是参与者之一。

下图展示了FLAN PaLM所使用微调数据集,和对CoT部分的消融实验,很明显CoT使得模型能够具备更强的zero-shot能力。

(建议读一下原文,CoT部分在第四章节,我个人觉得文章中的消融实验不足以直接证明CoT数据对于模型的性能提升,但是目前看来大家在构建finetune数据时还是倾向于将CoT数据构建进去,起码能够显著提升模型使用CoT提示词的能力)。

img

img

2 Qwen2.5思维链微调实操

2.1 CoT数据集准备

本文使用的是早年收集的一个CoT英文数据集,从质量判断是利用GPT4+提示词生成的,因为时间太久了实在是忘了出处无法附上链接,在这里跟原作者抱歉了orz。现在网上已经有许多高质量的CoT数据集,包括一些数据集专门区分了思考中间过程与返回结果,以及一些将思维步骤使用Special Token进行分隔的。

本文考虑到仅仅是练手项目,选用了最基础的数据集,并且使用经过指令微调的Qwen2.5-7B将英文数据集进一步翻译成了中文+整理成了标准的Instruction-Input-Output样式,以方便对Qwen模型的微调和练手学习。

注意这个数据集仅仅是练手,LLM翻译的质量并不高,很容易被要翻译的内容带偏了。下图展示了部分数据集和样式:

可以使用如下链接直接下载测试数据集

  • 数据集已经同步至魔乐社区:

    https://modelers.cn/datasets/chenshaohon/alpaca_cot_zh

  • 数据集下载链接:https://modelers.cn/coderepo/web/v1/file/chenshaohon/alpaca_cot_zh/main/media/cot_train_cn.jsonl

2.2 环境安装

2.2.1 昇腾NPU + openMind Library环境安装

使用昇腾NPU的话推荐在魔乐社区中找模型,里面能找到完成NPU适配的模型。魔乐社区使用的是openMind Library工具包,这个包支持在Nvidia GPU和Ascend NPU上运行,使用起来和transfomers接口一致。如果说做昇腾NPU迁移的话非常推荐使用。

魔乐社区的模型分为MindSpore支持和Pytorch-NPU支持,这里主要看本地装什么环境,考虑到新手学习的话推荐使用Pytorch-NPU,和Pytorch逻辑基本一致。

img

2.2.2 驱动安装&验证

首先得确定有NPU卡和NPU相关驱动,驱动是8.0.RC3.beta1,具体可以参考软件安装-CANN商用版8.0.RC3开发文档-昇腾社区[5]。

安装好后的验证方法是运行下面的命令,该命令作用与nvidia-smi类似,这里是查看NPU的状态和性能:

npu-smi info

可以看到如下信息的话就表示驱动已经安装完成了,左侧是安装成功后运行代码后的结果,右侧是每一部分的含义。

img

2.2.3 openMind环境搭建

openMind环境安装比较简单,这边列出所需用到的全部安装命令:

# 下载PyTorch安装包
wget https://download.pytorch.org/whl/cpu/torch-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
# 下载torch_npu插件包
wget https://gitee.com/ascend/pytorch/releases/download/v6.0.rc3-pytorch2.4.0/torch_npu-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
# 安装命令
pip3 install torch-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
pip3 install torch_npu-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
# 安装openMind Library
pip install openmind[pt]
pip install transformers accelerate datasets peft   # 部分场景会用到hf几个包,干脆全装了
# 安装SwanLab
pip install swanlab

2.2.4 Nvidia GPU + Transformers环境安装

这个流程比较简单,首先也是得确保Nvidia驱动存在,验证命令:

nvida-smi

如果没显示同样需要先安装cuda环境,这里贴上CUDA官方安装链接[6]

网上有大量cuda安装安装教程,这里笔者就不赘述了。同样放出transformers环境安装的全部命令:

pip install torch
pip install transformers accelerate datasets peft
# 安装SwanLab
pip install swanlab

2.2.5 关于提示词模版构建(大坑)

这里需要强调一下,在使用Qwen2.5的Instruct模型微调时,为了保障效果建议严格按照模型自身的Instruct的提示词模版构建。

HF Transformers在4.3几的版本开始支持Chat Templates[7]。Qwen2.5关于Instruct和Chat的提示词模版被直接写到了tokenziers的设置保存中,这导致了很多人在原始代码中找不到instruct提示词格式的构造。很多教程在教微调的时候用的还是Qwen1的老提示词模版或者自己构建的提示词模版,这会严重影响使用已经微调的模型做进一步微调时的效果。

因此,建议针对模型微调时一定要仔细检查提示词模版的实现部分。尽量使用模型已经定义好的格式和结构。

可以在Qwen的HF项目中找到提示词模版,点击HF Qwen[8]查看chat_template设置。chat_template默认使用的是一种前端模版语言jinja,并不好看懂,笔者把Qwen2.5的提示词模版格式化后粘贴在下文:

{%- if tools %}
    {{- '<|im_start|>system\n' }}    
    {%- if messages[0]['role'] == 'system' %}    
        {{- messages[0]['content'] }}    
    {%- else %}     
        {{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }}   
    {%- endif %}    
    {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}    
    {%- for tool in tools %}    
        {{- "\n" }}        
        {{- tool | tojson }}    
    {%- endfor %}    
    {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
{%- else %}
    {%- if messages[0]['role'] == 'system' %}    
        {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}   
    {%- else %}    
        {{- '<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\n' }}    
    {%- endif %}
{%- endif %}
{%- for message in messages %}
    {%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %}    
        {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}    
    {%- elif message.role == "assistant" %}    
        {{- '<|im_start|>' + message.role }}        
        {%- if message.content %}       
            {{- '\n' + message.content }}        
        {%- endif %}        
        {%- for tool_call in message.tool_calls %}      
            {%- if tool_call.function is defined %}             
                {%- set tool_call = tool_call.function %}            
            {%- endif %}            
            {{- '\n<tool_call>\n{"name": "' }}            
            {{- tool_call.name }}            
            {{- '", "arguments": ' }}            
            {{- tool_call.arguments | tojson }}            
            {{- '}\n</tool_call>' }}        
        {%- endfor %}        
        {{- '<|im_end|>\n' }}    
    {%- elif message.role == "tool" %}    
        {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}        
            {{- '<|im_start|>user' }}        
        {%- endif %}        
        {{- '\n<tool_response>\n' }}        
        {{- message.content }}        
        {{- '\n</tool_response>' }}        
        {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}        
            {{- '<|im_end|>\n' }}       
        {%- endif %}   
    {%- endif %}
{%- endfor %}
{%- if add_generation_prompt %}
    {{- '<|im_start|>assistant\n' }}
{%- endif %}

可以看到超级长,因为定义了好几种情况,包括是否有system prompt。以及针对function tools怎么处理等等等等。

如果读不懂(我感觉大多数搞deep learning的除了做LLM Finetune也很小有机会去学一个前端语言),建议用大模型给你逐行解释下,这里附上jinja的官方文档[9]

这里笔者简单提供我所使用的Qwen2.5简化版python模版(下脚本),去除了Function Calling和多轮对话的部分。并且只包含对Instruct和Inputs的处理部分,以及Assitants的生成头。这分为带inputs的版本和不带inputs的版本。

我自己专门测试了使用此模版构造的提示词长度上和使用Qwen带chat_template的tokenziers完全一致。你只需要将outputs部分增加一个 \n<|im_end|>\n 即可直接拼接成finetune LLM模型的targets部分。

PROMPT_DICT = {
    "prompt_no_input": """<|im_start|>system\n{instruction}<|im_end|>\n<|im_start|>user\n<|im_end|>\n<|im_start|>assistant\n""",    
    "prompt_input": """<|im_start|>system\n{instruction}<|im_end|>\n<|im_start|>user\n{input}<|im_end|>\n<|im_start|>assistant\n""",
}

如果你直接偷懒使用chat_template来tokenizer仅带outputs部分的数据。**你会发现由于Qwen的chat template处理机制,实际上生成的outputs部分会默认带上system prompts。**导致最后训练阶段会出现奇怪的内容。Qwen的tokenizers针对未增加system角色的对话输入会自动加上如下提示词:

system:You are Qwen, created by Alibaba Cloud. You are a helpful assistant.

更神奇的是,这个system prompt居然是个英文的。Qwen可是个中文模型。。。这个system prompt的出现会影响后续的模型微调效果。

2.3 可视化工具配置(SwanLab使用教程)

img

SwanLab可以将微调的许多关键参数自动记录下来并且能够再现可视化查看训练。能够在线或者离线保存+查看训练日志。

SwanLab(有可能是唯一的)同时支持记录NVIDIA GPU和华为昇腾NPU设备的日志记录工具。最新版本已经支持对NPU的内存使用、功率、温度等进行记录。甚至还有黑夜模式,方便苦逼研究生大晚上搞科研。😃

img

关于SwanLab的使用方法可以参考SwanLab官方文档-快速开始[10]

对于Huggingface Transformers或者支持华为昇腾NPU的openMind Library[11],可以使用SwanLab Integration轻松完成实验数据记录:

...
from swanlab.integration.huggingface import SwanLabCallback
swanlab_call = SwanLabCallback( #
    "Ascend_finetune_v2",    
    experiment_name=os.path.basename(os.path.normpath(training_args.output_dir)),    
    config=asdict(data_args)    
    | asdict(model_args)    
    | asdict(training_args)    
    | asdict(lora_config),    
    public=True,
)
trainer = openmind.Trainer( # 使用hf transformers的话则是把openmind替换为transformers
    model=model,    
    tokenizer=tokenizer,    
    args=training_args,    
    callbacks=[swanlab_call],   # callback加入进去即可    
    **data_module,
)
...

使用后不仅能进行多图表对比,更重要的是把一大堆的huggingface transformers的训练超参数全部记录下来了,简直调参党福音。

img

2.4 微调代码(多卡,支持华为Ascend卡)

下面附上完整的微调代码。在项目目录下创建 finetune.py文件,并将如下代码粘贴进文件中:

import copy
import os
import io
import json
import logging
from dataclasses import dataclass, field, asdict
from typing import Dict, Optional, Sequence
import torch
from torch.utils.data import Dataset
try:
    import openmind as tf_module
except:
    import transformers as tf_module
import transformers
from peft import LoraConfig, get_peft_model
from swanlab.integration.huggingface import SwanLabCallback
IGNORE_INDEX = -100
PROMPT_DICT = {
    "prompt_no_input": """<|im_start|>system\n{instruction}<|im_end|>\n<|im_start|>user\n<|im_end|>\n<|im_start|>assistant\n""",    
    "prompt_input": """<|im_start|>system\n{instruction}<|im_end|>\n<|im_start|>user\n{input}<|im_end|>\n<|im_start|>assistant\n""",
}
@dataclass
class ModelArguments:
    model_name_or_path: Optional[str] = field(     
        default="./weights/Qwen/Qwen2.5-7B-Instruct"    
    )
@dataclass
class DataArguments:
    data_path: str = field(    
        default="./data/cot_train_cn.jsonl",        
        metadata={"help": "Path to the training data."},    
    )
@dataclass
class TrainingArguments(transformers.TrainingArguments):
    cache_dir: Optional[str] = field(default=None)    
    optim: str = field(default="adamw_torch")    
    model_max_length: int = field(    
        default=512,        
        metadata={      
            "help": "Maximum sequence length. Sequences will be right padded (and possibly truncated)."        
        },    
    )
def _tokenize_fn(strings: Sequence[str], tokenizer) -> Dict:
    """Tokenize a list of strings."""    
    tokenized_list = [    
        tokenizer(        
            text,            
            return_tensors="pt",            
            padding="longest",            
            max_length=tokenizer.model_max_length,            
            truncation=True,        
        )        
        for text in strings    
    ]    
    input_ids = labels = [tokenized.input_ids[0] for tokenized in tokenized_list]    
    input_ids_lens = labels_lens = [    
        tokenized.input_ids.ne(tokenizer.pad_token_id).sum().item()        
        for tokenized in tokenized_list    
    ]    
    return dict(    
        input_ids=input_ids,        
        labels=labels,        
        input_ids_lens=input_ids_lens,        
        labels_lens=labels_lens,    
    )
def jload(f, mode="r", jsonl=True):
    if not isinstance(f, io.IOBase):     
        with open(f, mode=mode, encoding="utf-8") as f:        
            if jsonl:            
                # Parse JSON Lines                
                return [json.loads(line) for line in f if line.strip()]            
            else:             
                # Parse standard JSON                
                return json.load(f)    
    else:    
        if jsonl:       
            return [json.loads(line) for line in f if line.strip()]        
        else:        
            return json.load(f)
def preprocess(
    sources: Sequence[str],    
    targets: Sequence[str],    
    tokenizer,
) -> Dict:
    """Preprocess the data by tokenizing."""    
    examples = [s + t for s, t in zip(sources, targets)]    
    examples_tokenized, sources_tokenized = [   
        _tokenize_fn(strings, tokenizer) for strings in (examples, sources)    
    ]    
    input_ids = examples_tokenized["input_ids"]    
    labels = copy.deepcopy(input_ids)    
    for label, source_len in zip(labels, sources_tokenized["input_ids_lens"]):    
        label[:source_len] = IGNORE_INDEX    
    return dict(input_ids=input_ids, labels=labels)
class SupervisedDataset(Dataset):
    """Dataset for supervised fine-tuning."""    
    def __init__(self, data_path: str, tokenizer):    
        super(SupervisedDataset, self).__init__()        
        logging.warning("Loading data...")        
        list_data_dict = jload(data_path)        
        logging.warning("Formatting inputs...")        
        prompt_input, prompt_no_input = (      
            PROMPT_DICT["prompt_input"],            
            PROMPT_DICT["prompt_no_input"],        
        )        
        sources = [      
            (           
                prompt_input.format_map(example)                
                if example.get("input", "") != ""                
                else prompt_no_input.format_map(example)            
            )            
            for example in list_data_dict        
        ]       
        targets = [       
            f"{example['output']}\n{tokenizer.eos_token}\n"            
            for example in list_data_dict        
        ]        
        logging.warning("Tokenizing inputs... This may take some time...")        
        data_dict = preprocess(sources, targets, tokenizer)        
        try:        
            self.input_ids = data_dict["input_ids"]        
        except KeyError as e:        
            raise KeyError("input_ids is invalid") from e        
        try:        
            self.labels = data_dict["labels"]        
        except KeyError as e:        
            raise KeyError("labels is invalid") from e    
    def __len__(self):     
        return len(self.input_ids)    
    def __getitem__(self, i) -> Dict[str, torch.Tensor]:     
        return dict(input_ids=self.input_ids[i], labels=self.labels[i])
@dataclass
class DataCollatorForSupervisedDataset(object):
    """Collate examples for supervised fine-tuning."""    
    tokenizer: object    
    def __call__(self, instances: Sequence[Dict]) -> Dict[str, torch.Tensor]:    
        input_ids, labels = tuple(        
            [instance[key] for instance in instances] for key in ("input_ids", "labels")        
        )        
        input_ids = torch.nn.utils.rnn.pad_sequence(        
            input_ids, batch_first=True, padding_value=self.tokenizer.pad_token_id        
        )        
        labels = torch.nn.utils.rnn.pad_sequence(         
            labels, batch_first=True, padding_value=IGNORE_INDEX        
        )        
        return dict(        
            input_ids=input_ids,            
            labels=labels,            
            attention_mask=input_ids.ne(self.tokenizer.pad_token_id),        
        )
def make_supervised_data_module(tokenizer, data_args) -> Dict:
    """Make dataset and collator for supervised fine-tuning."""    
    train_dataset = SupervisedDataset(    
        tokenizer=tokenizer, data_path=data_args.data_path    
    )    
    data_collator = DataCollatorForSupervisedDataset(tokenizer=tokenizer)    
    return dict(     
        train_dataset=train_dataset, eval_dataset=None, data_collator=data_collator    
    )
def train():
    parser = transformers.HfArgumentParser(    
        (ModelArguments, DataArguments, TrainingArguments)   
    )    
    model_args, data_args, training_args = parser.parse_args_into_dataclasses()    
    model = tf_module.AutoModelForCausalLM.from_pretrained(    
        model_args.model_name_or_path,        
        cache_dir=training_args.cache_dir,        
        trust_remote_code=True,    
    )    
    # 定义LoRA配置    
    lora_config = LoraConfig(    
        r=16,        
        lora_alpha=16,        
        target_modules=["q_proj", "v_proj"],        
        lora_dropout=0.1,        
        bias="none",    
    )    
    model = get_peft_model(model, lora_config)    
    model.print_trainable_parameters()    
    tokenizer = tf_module.AutoTokenizer.from_pretrained(    
        model_args.model_name_or_path,        
        cache_dir=training_args.cache_dir,        
        model_max_length=training_args.model_max_length,        
        padding_side="right",        
        use_fast=False,        
        trust_remote_code=True,    
    )    
    data_module = make_supervised_data_module(tokenizer=tokenizer, data_args=data_args)    
    swanlab_call = SwanLabCallback(     
        "Ascend_finetune_v2",        
        experiment_name=os.path.basename(os.path.normpath(training_args.output_dir)),        
        config=asdict(data_args)        
        | asdict(model_args)        
        | asdict(training_args)       
        | asdict(lora_config),        
        public=True,    
    )    
    trainer = tf_module.Trainer(    
        model=model,        
        tokenizer=tokenizer,        
        args=training_args,        
        callbacks=[swanlab_call],        
        **data_module,    
    )    
    trainer.train()    
    trainer.save_state()    
    trainer.save_model(output_dir=training_args.output_dir)
if __name__ == "__main__":
    train()

多卡训练的话可以使用torchrun,这里附上一个启动多卡的bash脚本,在当前目录下创建 finetune.sh,并且粘贴如下脚本:

NPU_NUM=${1:-8}

EXP_NAME=$(basename "$0" .sh)
if [ -d ./output ];then
    rm -rf ./output/$EXP_NAME    
    mkdir -p ./output/$EXP_NAME
else
    mkdir -p ./output/$EXP_NAME
fi

# master_port参数需用户根据实际情况进行配置
torchrun --nproc_per_node=$NPU_NUM --master_port=20248 finetune.py \
    --model_name_or_path "./weights/Qwen/Qwen2.5-7B-Instruct" \   
    --data_path data/cot_train_cn.jsonl \    
    --bf16 True \   
    --output_dir ./output/$EXP_NAME \    
    --max_steps 2000 \    
    --per_device_train_batch_size 2 \    
    --eval_strategy "no" \    
    --save_strategy "steps" \    
    --save_steps 3000 \    
    --save_total_limit 1 \    
    --learning_rate 2e-5 \    
    --weight_decay 0. \    
    --warmup_ratio 0.03 \    
    --lr_scheduler_type "cosine" \    
    --seed 42 \    
    --logging_steps 10

开启多卡训练的方式如下:

bash finetune.sh <使用的GPU/NPU数量>

如果提示登录swanlab,可以在官网完成注册(https://swanlab.cn)后,使用获取API KEY(https://swanlab.cn/settings)找到对应的登陆密钥并粘贴,这样将能够使用云上看版随时查看训练过程与结果。

2.5 微调效果(附上Gradio代码)

本来准备了Ceval的测试结果,结果不知道为什么Ascend服务器连不上了,等过段时间更新下教程文档。

img

这里放出使用CoT数据微调qwen-7b-instruct、qwen-0.5b-instruct和使用qwen-7b-instruct(8NPU)的loss结果。可以看到使用8个NPU能带来更好的训练loss表现和稳定性,哪怕在使用同样迭代数据量的情况下,8个NPU依然能带来更好的loss结果。可能更大的loss有助于模型稳定下降。

最后展现下使用gradio完成的官方Qwen2.5-7B-Instruct、基于Qwen2.5-7B在中文alpaca数据集上指令微调、以及cot微调后的模型回复对比。可以看到CoT微调后模型确实具备了“step by step”的回复模式。

img

当然许多读者注意到了官方模型也展现出了“step by step”的回答模式,这主要是因为现在较新的模型在finetune数据集甚至pretrain数据集中就会预先加入CoT数据,所以模型在进行问答、尤其是数学题问答时,会展现出“步骤分解”的现象。笔者后续会尝试在较早期的demo中更新微调的。

附上启用gradio的demo测试代码:

使用 pip install gradio 安装依赖包

# 下载PyTorch安装包
wget https://download.pytorch.org/whl/cpu/torch-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
# 下载torch_npu插件包
wget https://gitee.com/ascend/pytorch/releases/download/v6.0.rc3-pytorch2.4.0/torch_npu-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
# 安装命令
pip3 install torch-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
pip3 install torch_npu-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
# 安装openMind Library
pip install openmind[pt]
pip install transformers accelerate datasets peft   # 部分场景会用到hf几个包,干脆全装了
# 安装SwanLab
pip install swanlab

如何学习AI大模型?

大模型时代,火爆出圈的LLM大模型让程序员们开始重新评估自己的本领。 “AI会取代那些行业?”“谁的饭碗又将不保了?”等问题热议不断。

不如成为「掌握AI工具的技术人」,毕竟AI时代,谁先尝试,谁就能占得先机!

想正式转到一些新兴的 AI 行业,不仅需要系统的学习AI大模型。同时也要跟已有的技能结合,辅助编程提效,或上手实操应用,增加自己的职场竞争力。

但是LLM相关的内容很多,现在网上的老课程老教材关于LLM又太少。所以现在小白入门就只能靠自学,学习成本和门槛很高

那么我作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,希望可以帮助到更多学习大模型的人!至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费

👉 福利来袭优快云大礼包:《2025最全AI大模型学习资源包》免费分享,安全可点 👈

全套AGI大模型学习大纲+路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

👉学会后的收获:👈
基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

👉 福利来袭优快云大礼包:《2025最全AI大模型学习资源包》免费分享,安全可点 👈

img

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

### Qwen 模型训练参数设置及说明 对于 Qwen 模型的训练,参数的选择至关重要。这些参数不仅影响到模型性能还涉及到计算资源的有效利用。 加载预训练模型时采用如下方式: ```python from transformers import AutoModelForCausalLM, GenerationConfig model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen-7B", device_map="auto", # 自动分配设备并选择最优精度[^1] trust_remote_code=True # 加载来自远程仓库自定义代码 ).eval() # 切换至评估模式以禁用dropout等训练特有作 ``` 针对生成配置,则需初始化 `GenerationConfig` 对象来指定解码策略和其他超参: ```python generation_config = GenerationConfig.from_pretrained( "Qwen/Qwen-7B", trust_remote_code=True # 支持动态加载额外编码逻辑 ) model.generation_config = generation_config ``` 在微调过程中,官方文档提供了更指导,在路径 `Qwen2.5-main/examples/llama-factory/finetune-zh.md` 中可以找到有关中文场景下如何调整模型的具体指南[^2]。然而需要注意的是,某些地方可能缺乏足够的解释,因此建议结合社区反馈和个人验来进行更深入的理解和优化。 为了更好地适应特定应用场景,还可以考虑修改默认的学习率、批次大小以及其他与优化器相关的选项;同时也要关注数据集准备阶段的数据清洗、分词处理等方面的工作,这些都是成功训练高质量对话系统的基石。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值