7B大模型微调实战:GRPO与Qwen2.5的强强联合!

图片

又有两位训练营同学斩获大模型offer!一个是40k某军实验室offer,另一个是第四范式~恭喜两位同学成功上岸!

这是国外技术大佬介绍如何训练领域特定模型的文章,作者使用 GRPO 微调 qwen2.5-coder-7B,实现了一个生成日程表的大模型。

他分享了教程、代码、模型以及实践中的收获,感兴趣的同学可以参考以下内容详细阅读:

  • 教程:https://huggingface.co/blog/anakin87/qwen-scheduler-grpo

  • 代码:https://github.com/anakin87/qwen-scheduler-grpo

  • 模型:https://huggingface.co/anakin87

01

问题定义

给模型提供一份事件列表(包含开始和结束时间),并告知它哪些事件是高优先级的。目标是创建一个日程安排,使所选事件的总加权时长达到最大化。

在这种设定下,高优先级事件的权重为 2,普通事件的权重为 1。

02

示例输入

这是 prompt 的一个精简版本(你可以在后面的内容找到完整的 prompt)。

Task: create an optimized schedule based on the given events.Rules: ...You must use this format:  <think>...</think><schedule><event><name>...</name><start>...</start><end>...</end></event>...</schedule>---Events:- Event A (01:27 - 01:42)- Event B (01:15 - 02:30)- Event C (15:43 - 17:43)Priorities:- Event B

03

示例输出​​​​​​​

<think>A detailed reasoning</think><schedule><event><name>Event B</name><start>01:15</start><end>02:30</end></event><event><name>Event C</name><start>15:43</start><end>17:43</end></event></schedule>

经过一番研究,作者发现这类问题属于区间调度问题。这个特定的问题是加权区间调度问题的变体,使用动态规划可以高效地解决它。

这使我们能够轻松计算出任何给定输入的最佳得分,而这个得分就是模型在训练过程中要努力达到的目标。

04

数据集生成

既然问题已经被清晰地定义好了,下面就可以开始构建用于训练和评估模型的数据集了。

数据集中每一行的核心内容只是一条提示信息,其中包含了供模型进行日程安排的事件列表以及优先级信息。

与监督微调(SFT)不同的是,这里无需提供模型应该遵循的参考生成内容。这就是为什么在像数学这类可验证的领域中,为 GRPO 构建数据集往往更容易的原因之一。

我们还在每一行数据中加入了最优得分(即最大可能的加权时长)。模型在训练过程中不会看到这个得分,但我们会用它来计算奖励,从而引导模型朝着正确的方向学习。

鉴于这些要求,编写数据集生成脚本相对容易:

  • 使用来自不同类别的活动名称(音乐节、大学相关活动、科技会议等等)。

  • 每个示例包含数量随机(在 4 到 8 个之间)、时长各异的活动。

  • 确保一些活动存在时间上的重叠。

  • 随机将某些活动标记为优先活动。

我们生成了 500 个示例用于训练集,100 个示例用于测试集。

你可以在这里找到数据集生成脚本:

https://github.com/anakin87/qwen-scheduler-grpo/blob/main/dataset_generation/generate.py

生成的数据集可在 Hugging Face 平台上获得:

https://huggingface.co/datasets/anakin87/events-scheduling

05

训练

完整的训练 notebook 在这里:

https://github.com/anakin87/qwen-scheduler-grpo/blob/main/train_grpo.ipynb

现在有几个训练库支持 GRPO。Hugging Face TRL 是一个很好的选择,它也支持使用 vLLM 在训练期间更快地生成样本。

https://huggingface.co/docs/trl/index

在这个例子中,我们决定使用 Unsloth:

https://docs.unsloth.ai/

它是一个对 TRL 进行修补以大幅减少 GPU 内存使用的库。此处使用 NVIDIA A6000 GPU(48GB VRAM),但经过小的调整,你可以在免费的 Colab/Kaggle 实例上用 16GB VRAM 复制同样的实验。

如果你的 GPU 很差,Unsloth 可以很好地进行实验,但是会有一些令人沮丧的错误,我们稍后会看到。

(1)选择并加载要训练的模型

这里决定训练 Qwen2.5-Coder-7B-Instruct,这是 Qwen 系列中一款专门针对代码的语言模型。

这个选择有点基于经验,但主要有两个考虑因素:

  • 作者首先尝试了较小的模型(0.5B 和 1.5B),但这些非常小的模型产生的推理几乎毫无意义。这是第一个经验教训:如果基础模型的预训练或规模使其能力与期望相差甚远,GRPO 也无法创造奇迹。

  • 使用了代码模型而非通用模型,部分原因是这在数学任务中很常见,另一部分原因是这个模型在遵循所需格式(<think>, <schedule>等)方面已经相当出色。

现在使用 Unsloth 加载模型,用 QLoRA 对其进行训练以节省 GPU 资源。​​​​​​

from unsloth import FastLanguageModelmax_seq_length = 2048lora_rank = 32model, tokenizer = FastLanguageModel.from_pretrained(    model_name = "Qwen/Qwen2.5-Coder-7B-Instruct",    max_seq_length = max_seq_length,    load_in_4bit = True,    fast_inference = True,    max_lora_rank = lora_rank,    gpu_memory_utilization = 0.85, # Reduce if out of memory)model = FastLanguageModel.get_peft_model(    model,    r = lora_rank,    target_modules = [        "q_proj", "k_proj", "v_proj", "o_proj",        "gate_proj", "up_proj", "down_proj",    ], # Remove QKVO if out of memory    lora_alpha = lora_rank,    use_gradient_checkpointing = "unsloth", # Enable long context finetuning    random_state = 3407,)

如果你的显存小于 48GB,可以调整几个参数:gpu_memory_utilizationlora_rank 和 target_modules;后两个参数会影响模型的学习能力。

(2)数据集准备

数据集中的每个示例都包含事件和优先级。

我们对数据集进行预处理,以系统消息和用户消息的形式添加一般任务描述和说明。​​​​​​​

import datasetsSYSTEM_PROMPT = """You are a precise event scheduler.1. First, reason through the problem inside <think> and </think> tags. Here you can create drafts, compare alternatives, and check for mistakes.2. When confident, output the final schedule inside <schedule> and </schedule> tags. Your schedule must strictly follow the rules provided by the user."""USER_PROMPT ="""Task: create an optimized schedule based on the given events.Rules:- The schedule MUST be in strict chronological order.   Do NOT place priority events earlier unless their actual start time is earlier.- Event start and end times are ABSOLUTE. NEVER change, shorten, adjust, or split them.- Priority events (weight = 2) carry more weight than normal events (weight = 1),   but they MUST still respect chronological order.- Maximize the sum of weighted event durations.- No overlaps allowed. In conflicts, include the event with the higher weighted time.- Some events may be excluded if needed to meet these rules.You must use this format:  <think>...</think><schedule><event><name>...</name><start>...</start><end>...</end></event>...</schedule>---"""ds = datasets.load_dataset("anakin87/events-scheduling", split="train")ds = ds.map(    lambda x: {        "prompt": [            {"role": "system", "content": SYSTEM_PROMPT},            {"role": "user", "content": USER_PROMPT + x["prompt"]},        ]    })

(3)奖励函数

GRPO 是一种强化学习算法,在该算法中,对于每个提示,会从模型中生成多个样本(在我们的例子中是 8 个)。在训练过程中,模型的参数会被更新,以生成具有高奖励的回复。

因此,虽然在数据集中不需要生成的文本,但奖励函数的设计至关重要。

在像从 GSM8K 中学习这样较为简单的问题中,一种常见的选择是定义多个奖励函数并将它们相加:

  • 一种方法是检查输出格式是否正确。

  • 另一种方法是检查最终答案是否与已知解决方案相符。

在我们的实验中,可以很容易地为格式设计一个奖励函数。​​​​​​​

import reoverall_pattern = (r"<think>.+</think>.*<schedule>.*(<event>.*<name>.+</name>.*<start>\d{2}:\d{2}</start>.*"                   r"<end>\d{2}:\d{2}</end>.*</event>)+.*</schedule>")overall_regex = re.compile(overall_pattern, re.DOTALL)def format_reward(prompts, completions, **kwargs):    responses = [completion[0]['content'] for completion in completions]    return [0.0 if not overall_regex.match(response) else 10.0 for response in responses]

现在,要评判日程安排本身的质量更难。

一个有效的日程安排具有以下特点:

  • 活动源自原始提示(不存在臆造的活动或更改的时间)。

  • 活动按时间顺序排列。

  • 不存在活动重叠。

  • 活动至少有两项。

我们还希望鼓励模型生成一个能使总加权时长最大化的时间表。

在确定下面所示的解决方案之前,作者对不同数量的奖励函数进行了试验,得出了一些观察结果。

  • 作者尝试对分数使用单一奖励函数,如果日程安排有效(满足上述所有标准),则奖励为日程安排分数/最优分数,否则为 0。结果发现这是个糟糕的主意,因为它太不连续,而且大多数时候返回 0,无法为模型的学习提供足够的信号。

  • 另一方面,作者尝试使用了几种奖励函数,分别对应上述每个要求:已有事件、时间顺序、无重叠等。在这种情况下,他发现即使模型在学习某些东西,但训练在生成良好的日程安排方面并不有效。使用过多的奖励函数也可能会有弊端。

在“奖励过多”阶段,作者遇到了一个经典的强化学习问题:奖励作弊。起初作者忘了舍弃活动少于两个的日程安排。

突然间,奖励看起来很不错!模型在格式、时间顺序、无重叠等方面都获得了高分……

查看了实际输出,发现它找到了一个漏洞:它只是生成只有一个活动的日程安排(通常是高优先级的活动)。

这完美地满足了大多数单个奖励函数。这并非模型聪明,而是奖励设置可被利用。

最终作者采用了一个奖励函数,该函数鼓励生成按时间顺序排列的日程安排,另一个奖励函数则用于最大化得分。

如下所示,他试图在这两个奖励函数中纳入并因此优先考虑其他要求。​​​​​​​

def sorted_events_reward(completions, **kwargs):    scores = []    responses = [completion[0]['content'] for completion in completions]    for response in responses:        scheduled_events = get_events(response)        # not a valid schedule: should be discarded        if len(scheduled_events) < 2:            scores.append(0.0)            continue        scheduled_events_minutes = [(ev[0], time_to_minutes(ev[1]), time_to_minutes(ev[2]))                                   for ev in scheduled_events]        if all(scheduled_events_minutes[i][1] < scheduled_events_minutes[i+1][1]                   for i in range(len(scheduled_events_minutes)-1)):            scores.append(20.0)        else:            scores.append(0)    return scoresdef score_reward(prompts, completions, events, priority_events, optimal_score, **kwargs):    scores = []    responses = [completion[0]['content'] for completion in completions]    for content, valid_events, priorities, opt_score in zip(responses, events, priority_events, optimal_score):        scheduled_events = get_events(content)        # Get valid scheduled events        existing_events = {ev for ev in scheduled_events if [ev[0], ev[1], ev[2]] in valid_events}        # penalize choosing nonexistent events or less than 2 events (not a valid schedule)        if len(existing_events)<len(scheduled_events) or len(existing_events) < 2:            scores.append(0.0)            continue        # Convert to minutes        existing_events_minutes = [(ev[0], time_to_minutes(ev[1]), time_to_minutes(ev[2]))                                   for ev in existing_events]        # remove overlapping events and remove both events - to penalize overlaps        overlapping_events = set()        for j in range(len(existing_events_minutes)):            for k in range(j + 1, len(existing_events_minutes)):                if (existing_events_minutes[j][1] <= existing_events_minutes[k][2] and                     existing_events_minutes[j][2] >= existing_events_minutes[k][1]):                    overlapping_events.add(existing_events_minutes[j])                    overlapping_events.add(existing_events_minutes[k])        existing_events_minutes = [ev for ev in existing_events_minutes                                   if ev not in overlapping_events]        # Calculate score        score = sum(2 * (ev[2] - ev[1]) if ev[0] in priorities                    else ev[2] - ev[1] for ev in existing_events_minutes)        scores.append((score/opt_score) * 70)    return scores

简而言之,在实验中使用了以下奖励函数:

  • 格式(0 - 10)

  • 排序后的事件(0 - 20)

  • 分数(0 - 70)。

累积奖励的范围可以在 0 到 100 之间。

作者在这一步上反复尝试了很多次。正如将看到的,它仍然不完美,但它让模型开始学习了。

(4)设置训练配置并进行训练​​​​​​​

from trl import GRPOConfig, GRPOTrainertokenized_prompts = [tokenizer.apply_chat_template(prompt, tokenize=True, add_generation_prompt=True)                       for prompt in ds['prompt']]exact_max_prompt_length = max([len(tokenized_prompt) for tokenized_prompt in tokenized_prompts])max_prompt_length = 448  # manually adjustednew_model_id="anakin87/qwen-scheduler-7b-grpo"training_args = GRPOConfig(    learning_rate = 8e-6,    adam_beta1 = 0.9,    adam_beta2 = 0.99,    weight_decay = 0.1,    warmup_ratio = 0.01,    lr_scheduler_type = "cosine",    optim = "paged_adamw_8bit",    logging_steps = 1,    per_device_train_batch_size = 8,    gradient_accumulation_steps = 1,    num_generations = 8, # Decrease if out of memory    max_prompt_length = max_prompt_length,    max_completion_length = max_seq_length - max_prompt_length,    max_grad_norm = 0.1,    output_dir = "outputs",    overwrite_output_dir = True,    push_to_hub = True,    hub_model_id=new_model_id,    hub_strategy="every_save",    save_strategy="steps",    save_steps=50,    save_total_limit=1,    num_train_epochs=3,)trainer = GRPOTrainer(    model = model,    processing_class = tokenizer,    reward_funcs=[        format_reward,        sorted_events_reward,        score_reward,    ],    args = training_args,    train_dataset = ds,)trainer.train()

max_prompt_length 是提示的最大长度。过长的提示将被截断。我们可以轻松计算出这个值,然后手动调整。

num_generations 是 GRPO 的一个关键参数,表示为每个提示生成的样本数量。

该算法通过比较不同的样本进行学习,并引导模型生成具有更高奖励的样本。

更多的样本为其提供了更多的学习信息,有可能带来更好的结果,但生成这些样本需要更多的时间和内存。

06

结果

让我们看看训练曲线:

我们可以看到模型在训练过程中奖励有所提升。从一开始,样本在格式一致性方面就获得了不错的分数。

随着时间的推移,在遵循时间顺序以及日程安排方面获得良好分数的情况有所改善,这表明模型实际上学习到了奖励函数中规定的行为。

其他记录的指标,如 reward_std(奖励组内的平均标准差)和 KL 散度(模型与参考模型之间的平均 KL 散度),显示出可接受的值。

07

检查样本

在训练过程中,我们记录生成样本的一个随机子集。你可以在此处浏览完整日志。

https://huggingface.co/anakin87/qwen-scheduler-7b-grpo/raw/main/completion_samples.txt

查看这些生成情况既有趣又有启发性。正是通过这种方式,作者意识到较小的模型就是无法掌握:随着时间推移,它们的推理能力并没有显著提升。

以下是在不同训练阶段针对相同输入提示的一个示例:​​​​​​​

Events:- Analyzing product performance (04:33 - 06:03)- One-on-one with manager (08:41 - 08:56)- Client call with Acme Corp (09:13 - 10:58)- Meeting with Lisa at café (10:14 - 11:14)- Updating website content (12:21 - 13:36)- Preparing PTO handover (16:07 - 17:37)- Marketing standup on Zoom (17:58 - 19:43)- Brainstorming with Luke and Patrick (19:11 - 19:56)Priorities:- Analyzing product performance- Meeting with Lisa at café

Step 473/1500​​​​​​​

<think>At first glance, the events overlap in the time slot from 10:14 to 11:14. The priority event "Meeting with Lisa at café" is higher in weight compared to "Client call with Acme Corp", so we must include it. However, this will exclude the client call if we want to prioritize "Meeting with Lisa at café". To resolve this, we need to decide whether to exclude the client call or the brainstormingsession (19:11 - 19:56) which is a normal event.Since "Meeting with Lisa at café" is a priority event and it overlaps with the client call, we should include "Meeting with Lisa at café" and exclude the client call. This will give us more time for "Updating website content" (12:21 - 13:36) and "Preparing PTO handover" (16:07 - 17:37), which are also normal events.Here is the adjusted schedule:[...]This schedule maximizes the sum of weighted event durations while respecting all the rules provided.</think><schedule><event><name>Analyzing product performance</name><start>04:33</start><end>06:03</end></event><event><name>One-on-one with manager</name><start>08:41</start><end>08:56</end></event><event><name>Client call with Acme Corp</name><start>09:13</start><end>10:14</end></event><event><name>Meeting with Lisa at café</name><start>10:14</start><end>11:14</end></event><event><name>Updating website content</name><start>12:21</start><end>13:36</end></event><event><name>Preparing PTO handover</name><start>16:07</start><end>17:37</end></event><event><name>Marketing standup on Zoom</name><start>17:58</start><end>19:43</end></event><event><name>Brainstorming with Luke and Patrick</name><start>19:11</start><end>19:56</end></event></schedule>

在这个阶段,该模型在思考给定的限制条件方面展现出了令人期待的能力,但它错误地更改了一些事件的时间,以实现时间利用的最大化。

Step 973/1500​​​​​​​

<think>To create an optimized schedule, I need to prioritize events based on provided weights and ensure no overlaps. The priority events are "Analyzing product performance" and "Meeting with Lisa at café". Let\'s evaluate the schedule step-by-step.1. **Analyzing product performance (04:33 - 06:03)** - This is a priority event (weight = 2).2. **One-on-one with manager (08:41 - 08:56)** - This is a normal event (weight = 1).3. **Client call with Acme Corp (09:13 - 10:58)** - This is a normal event (weight = 1). It conflicts with "Meeting with Lisa at café", which is also a priority event. Since "Meeting with Lisa at café" has higher priority, we exclude this event.4. **Meeting with Lisa at café (10:14 - 11:14)** - This is a priority event (weight = 2). However, it conflicts with "Client call with Acme Corp" as discussed. We need to decide whether to exclude this event or find another slot.5. **Updating website content (12:21 - 13:36)** - This is a normal event (weight = 1).6. **Preparing PTO handover (16:07 - 17:37)** - This is a normal event (weight = 1).7. **Marketing standup on Zoom (17:58 - 19:43)** - This is a normal event (weight = 1). It conflictswith "Preparing PTO handover" as they overlap. We need to decide whether to exclude one of them.8. **Brainstorming with Luke and Patrick (19:11 - 19:56)** - This is a normal event (weight = 1). It conflicts with "Marketing standup on Zoom" as they overlap. We need to decide whether to exclude one of them.To maximize the sum of weighted event durations, we should exclude conflicts with the highest priorityevents first.- Exclude "Client call with Acme Corp" since it conflicts with "Meeting with Lisa at café"  (higher priority).- Exclude "Marketing standup on Zoom" since it conflicts with "Preparing PTO handover" and does not   interfere with any higher priority events.Thus, the optimized schedule is as follows:</think><schedule><event><name>Analyzing product performance</name><start>04:33</start><end>06:03</end></event><event><name>One-on-one with manager</name><start>08:41</start><end>08:56</end></event><event><name>Updating website content</name><start>12:21</start><end>13:36</end></event><event><name>Preparing PTO handover</name><start>16:07</start><end>17:37</end></event><event><name>Brainstorming with Luke and Patrick</name><start>19:11</start><end>19:56</end></event></schedule>

好多了!在这里,该模型明确考虑了权重,并生成了一个有效的时间表。

Step 1470/1500​​​​​​​

<think>The goal is to create a schedule that maximizes the sum of weighted event durations while respecting the chronological order, priorities, and non-overlapping constraints. Let\'s analyze the events and prioritize them:1. **Analyzing product performance**: Start time: 04:33, End time: 06:03, Priority: 22. **One-on-one with manager**: Start time: 08:41, End time: 08:56, Priority: 13. **Client call with Acme Corp**: Start time: 09:13, End time: 10:58, Priority: 14. **Meeting with Lisa at café**: Start time: 10:14, End time: 11:14, Priority: 25. **Updating website content**: Start time: 12:21, End time: 13:36, Priority: 16. **Preparing PTO handover**: Start time: 16:07, End time: 17:37, Priority: 17. **Marketing standup on Zoom**: Start time: 17:58, End time: 19:43, Priority: 18. **Brainstorming with Luke and Patrick**: Start time: 19:11, End time: 19:56, Priority: 1Given the priorities, we must ensure that "Analyzing product performance" and "Meeting with Lisa at café" are included. Let\'s try to fit the rest while avoiding overlaps:1. **Analyzing product performance**: 04:33 - 06:03 (Priority 2)2. **One-on-one with manager**: 08:41 - 08:56 (Priority 1)3. **Client call with Acme Corp**: 09:13 - 10:58 (Priority 1)4. **Meeting with Lisa at café**: 10:14 - 11:14 (Priority 2)5. **Updating website content**: 12:21 - 13:36 (Priority 1)6. **Preparing PTO handover**: 16:07 - 17:37 (Priority 1)The next event, "Marketing standup on Zoom", starts at 17:58, but the availability is only until 19:43. We can fit "Brainstorming with Luke and Patrick" from 19:11 to 19:56 before the standup.1. **Analyzing product performance**: 04:33 - 06:03 (Priority 2)2. **One-on-one with manager**: 08:41 - 08:56 (Priority 1)3. **Client call with Acme Corp**: 09:13 - 10:58 (Priority 1)4. **Meeting with Lisa at café**: 10:14 - 11:14 (Priority 2)5. **Updating website content**: 12:21 - 13:36 (Priority 1)6. **Preparing PTO handover**: 16:07 - 17:37 (Priority 1)7. **Brainstorming with Luke and Patrick**: 19:11 - 19:56 (Priority 1)Final schedule:- Analyzing product performance: 04:33 - 06:03- One-on-one with manager: 08:41 - 08:56- Client call with Acme Corp: 09:13 - 10:58- Meeting with Lisa at café: 10:14 - 11:14- Updating website content: 12:21 - 13:36- Preparing PTO handover: 16:07 - 17:37- Brainstorming with Luke and Patrick: 19:11 - 19:56This schedule respects the chronological order, includes the high-priority events, and avoids any overlaps.</think><schedule><event><name>Analyzing product performance</name><start>04:33</start><end>06:03</end></event><event><name>One-on-one with manager</name><start>08:41</start><end>08:56</end></event><event><name>Client call with Acme Corp</name><start>09:13</start><end>10:58</end></event><event><name>Meeting with Lisa at café</name><start>10:14</start><end>11:14</end></event><event><name>Updating website content</name><start>12:21</start><end>13:36</end></event><event><name>Preparing PTO handover</name><start>16:07</start><end>17:37</end></event><event><name>Brainstorming with Luke and Patrick</name><start>19:11</start><end>19:56</end></event></schedule>

在这个样本中,尽管推理过程很长,但模型在最终的日程安排中放入了两个重叠的事件。查看样本很不错,但我们需要系统的评估。

08

评估

为了进行评估,我们可以使用事件调度数据集的测试集,模型之前从未见过该测试集。

我们将评估阶段分为两个步骤:

  • 推理:为每个测试提示生成一个日程安排。

  • 评分:根据我们的规则(格式正确、至少 2 个事件、仅存在的事件、按时间顺序、无重叠)检查每个生成的日程安排。

    如果违反任何规则,该日程安排在该提示下得分为 0。

    如果有效,其得分是(weighted_duration/optimal_weighted_duration) * 100

你可以在 GitHub 存储库中找到这些脚本:

https://github.com/anakin87/qwen-scheduler-grpo/tree/main/evaluation

在推理过程中出现了 Unsloth 错误。用 Unsloth 训练的模型无法可靠地转换为标准的 Hugging Face Transformers 模型;尝试这样做可能会得到一个不同的模型。

这是一个已知问题:

https://github.com/unslothai/unsloth/issues/2009

如果在生产工作中需要这样做,比如说,用 vLLM 进行服务,这将是一个重大障碍,而且相当令人沮丧。

由于 Unsloth 对 TRL 进行了补丁,因此改编代码并使用 TRL 相当容易,而且 TRL 更稳定。只需注意,你将需要更多的 GPU 显存。

比较 qwen-scheduler-7b-grpo(我们的模型)、Qwen2.5-Coder-7B-Instruct(原始模型)以及 Qwen2.5-Coder-14B-Instruct(同一模型家族中更大的模型)。

由于样本表明模型在第 2 个 epoch 到第 3 个 epoch 之间可能变差了,作者还评估了第 2 个 epoch 结束时的检查点。

从以上对比可以看出:

  • GRPO 肯定起作用了!它在引导模型产生期望行为方面相当有效。

  • 经过调优的模型在这项任务中的表现甚至超过了规模是其两倍的模型。

  • 该模型几乎完美地学会了格式、时间顺序,并且只使用现有事件。

  • 该模型在处理重叠问题上仍有困难,这在测试集中很大一部分样本中都很明显。

09

如何改善

主要问题肯定是重叠现象。我们可以看到,模型并没有有效地学会避免这些重叠。

此外,在第 3 个训练周期中出现的轻微性能下降,可能表明模型正在学习一种并非最优的策略。

奖励函数的思路:

  • 更强的重叠惩罚:在 score_reward 函数中,从分数计算中剔除重叠事件。我们可以实施更严厉的惩罚...

  • 专门的重叠奖励:或者,添加一个仅检查重叠情况的奖励函数。

奖励函数默认是累加的,因此,根据对惩罚的设计方式,这两种不同的方法在数学上可能是等效的。

10

结论与主要收获

在本文中,详细介绍了如何使用 GRPO 在一项新的可验证任务上对语言模型进行后训练:根据一系列事件和优先级创建日程安排。

涵盖了问题定义、数据集生成、基础模型选择、奖励函数设计、使用 Unsloth 进行训练以及评估等方面。通过实际操作,对 GRPO 以及在大语言模型中应用强化学习有了一些认识。

(1)对于可验证任务,GRPO 非常出色

它简化了典型的强化学习设置(例如在 PPO 中使用的设置):无需价值模型;奖励模型通常被确定性奖励函数所取代(具有可验证奖励的强化学习)。

由于数据集只需要提示(无需生成内容),数据收集比监督微调(SFT)要容易得多,成本也低得多。

(2)启发模型行为

使用 GRPO 及类似算法进行启发,更多是从训练好的模型中引出期望的行为,而非向其教授全新的内容。如果你需要从根本上获得新技能,指令微调(以及蒸馏)可能会更有效。

(3)基础模型很重要

如果在采样过程中,基础模型在任务上从未表现出有前景的行为,那么 GRPO 可能对你的问题无效。你可能首先需要一个更大或更好的基础模型。

(4)“顿悟时刻”可能被过度炒作了

在 DeepSeek-R1 论文中,作者表明,在 GRPO 过程中,“模型学会以拟人化的语气进行反思”。这是奇迹吗?最近的研究表明,基础模型也有类似的行为。

(5)奖励函数的设计至关重要

奖励应该体现目标,提供一个可学习的信号(对模型的一种激励),并且要具有稳健性。

如果它们不稳健,你可能会遇到奖励作弊的情况:模型找到捷径来最大化奖励,而实际上并没有解决你心中所想的问题。

(6)Unsloth:对节省 GPU 资源很有用,但要注意

如果你没有太多的 GPU 资源,或者处于实验阶段,Unsloth 可能会有帮助。这些人在 GPU 效率方面做出了令人印象深刻的成果。

然而,目前这个库存在难以解决的漏洞,这使得它不适合用于严肃的应用场景。如果你有足够的显存,TRL 会更稳定。

 一、大模型风口已至:月薪30K+的AI岗正在批量诞生

2025年大模型应用呈现爆发式增长,根据工信部最新数据:

国内大模型相关岗位缺口达47万

初级工程师平均薪资28K

70%企业存在"能用模型不会调优"的痛点

真实案例:某二本机械专业学员,通过4个月系统学习,成功拿到某AI医疗公司大模型优化岗offer,薪资直接翻3倍!

二、如何学习大模型 AI ?


🔥AI取代的不是人类,而是不会用AI的人!麦肯锡最新报告显示:掌握AI工具的从业者生产效率提升47%,薪资溢价达34%!🚀

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

1️⃣ 提示词工程:把ChatGPT从玩具变成生产工具
2️⃣ RAG系统:让大模型精准输出行业知识
3️⃣ 智能体开发:用AutoGPT打造24小时数字员工

📦熬了三个大夜整理的《AI进化工具包》送你:
✔️ 大厂内部LLM落地手册(含58个真实案例)
✔️ 提示词设计模板库(覆盖12大应用场景)
✔️ 私藏学习路径图(0基础到项目实战仅需90天)

 

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

*   大模型 AI 能干什么?
*   大模型是怎样获得「智能」的?
*   用好 AI 的核心心法
*   大模型应用业务架构
*   大模型应用技术架构
*   代码示例:向 GPT-3.5 灌入新知识
*   提示工程的意义和核心思想
*   Prompt 典型构成
*   指令调优方法论
*   思维链和思维树
*   Prompt 攻击和防范
*   …

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

*   为什么要做 RAG
*   搭建一个简单的 ChatPDF
*   检索的基础概念
*   什么是向量表示(Embeddings)
*   向量数据库与向量检索
*   基于向量检索的 RAG
*   搭建 RAG 系统的扩展知识
*   混合检索与 RAG-Fusion 简介
*   向量模型本地部署
*   …

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

*   为什么要做 RAG
*   什么是模型
*   什么是模型训练
*   求解器 & 损失函数简介
*   小实验2:手写一个简单的神经网络并训练它
*   什么是训练/预训练/微调/轻量化微调
*   Transformer结构简介
*   轻量化微调
*   实验数据集的构建
*   …

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

*   硬件选型
*   带你了解全球大模型
*   使用国产大模型服务
*   搭建 OpenAI 代理
*   热身:基于阿里云 PAI 部署 Stable Diffusion
*   在本地计算机运行大模型
*   大模型的私有化部署
*   基于 vLLM 部署大模型
*   案例:如何优雅地在阿里云私有部署开源大模型
*   部署一套开源 LLM 项目
*   内容安全
*   互联网信息服务算法备案
*   …

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值