第 15 章 基于GRPO后训练的智能医疗问诊实战
王晓华DeepSeek开发AI应用入门书《DeepSeek原生应用与智能体开发实践》全文分享~持续更新-CSDN博客
目录
在前一章中,我们深入剖析了GRPO(梯度正则化策略优化算法)的基本算法原理与程序实现细节。GRPO作为一种创新性的优化策略,其核心作用在于高效解决复杂系统中的优化难题,尤其是在面对高维度、非线性且约束条件复杂的优化场景时,展现出卓越的性能与稳定性。
具体而言,GRPO的作用不仅体现在提升优化效率上,更在于其能够智能地平衡探索与利用之间的关系。在算法运行过程中,GRPO通过引入梯度正则化机制,有效避免了传统优化算法易陷入局部最优解的困境,从而引导搜索过程向全局最优解逼近。这种机制使得GRPO在处理大规模数据集或复杂模型参数调优时,能够显著减少计算资源消耗,同时提高优化结果的准确性和可靠性。
此外,GRPO还具备良好的鲁棒性和适应性,能够灵活应对不同领域的优化需求。无论是机器学习中的模型训练、信号处理中的参数估计,还是控制系统中的最优控制策略设计,GRPO都能凭借其独特的算法优势,为各类优化问题提供高效、精准的解决方案。
15.1 模型的后训练与逻辑能力
在人工智能与机器学习领域,模型的后训练阶段不仅是技术流程中的关键环节,更是提升模型性能,尤其是数学逻辑能力的“黄金时期”。这一阶段,通过对已初步训练好的模型进行精细化调优,能够显著增强其处理复杂数学逻辑任务的能力,使模型在诸如数学推理、数据分析、决策优化等场景中展现出更高的智能水平。
模型的后训练,本质上是对模型参数进行二次优化,旨在消除初次训练中的偏差与不足,提升模型的泛化能力和逻辑推断精度。特别是在数学逻辑能力方面,后训练通过引入更高级的数学概念、逻辑规则以及问题求解策略,引导模型学习并掌握更深层次的数学逻辑结构。这一过程不仅要求模型能够准确理解数学符号与表达式的含义,更需具备运用逻辑规则进行复杂推理和解决问题的能力。大模型后训练全景图如图15-1所示。
![]()
图15-1 大模型后训练全景图
为了有效提升模型的数学逻辑能力,后训练阶段可采用多种策略。一方面,可以设计专门的数学逻辑任务集,如数学证明题、逻辑推理题等,作为模型训练的数据源,通过大量实践让模型在“做中学”,逐步积累数学逻辑经验。另一方面,可借鉴人类解决数学问题的思维方式,如归纳推理、演绎推理等,将这些思维方法融入模型的后训练过程中,使模型能够模拟人类的逻辑思考过程,提高解题效率和准确性。
15.1.1 大模型的后训练概念与核心目标
大模型的后训练是在预训练阶段之后,对模型进行进一步调整与优化的关键过程。预训练通常利用海量无标注数据,让模型学习到语言的通用模式、结构以及丰富的语义信息,使模型具备基础的“语言能力”。
然而,预训练模型就像是一个拥有广泛知识但缺乏特定专业技能的“通才”,它虽然对语言有普遍的理解,但无法直接精准地处理各种具体的任务。后训练的目的就是把这个“通才”培养成在特定领域或任务上表现出色的“专才”。
例如,在科学领域,预训练模型可能知道很多通用的词汇和句子结构,但对于数学术语、物理定理等专业内容理解有限。通过后训练,使用大量科学领域的数据对模型进行微调,模型就能更好地理解和处理与逻辑计算相关的文本,比如准确解读论文等。后训练的核心目标就是提升模型在特定任务上的性能,使其能够更精准、高效地完成任务,满足实际应用的需求。
大模型后训练有多种方法和策略,其中监督微调(Supervised Fine-Tuning,SFT)和强化学习等微调手段是比较常用和有效的方法。微调就像是在已经建好的房子基础上进行局部装修。预训练模型就好比是建好的房子主体结构,而微调则是根据具体需求,对房子的内部布局、装饰等进行调整。微调的方法如图15-2所示。
在微调过程中,使用有标注的任务特定数据,对预训练模型的参数进行轻微调整。比如,要将一个预训练的语言模型用于情感分析任务,就会收集大量带有情感标签(积极、消极、中立)的文本数据,然后让模型在这些数据上进行训练,调整模型的参数,使其能够准确判断文本的情感倾向。

图15-2 微调的方法
除了微调,提示学习也是一种重要的后训练方法。提示学习就像是给模型一个“提示语”,引导模型按照特定的方式生成输出。例如,对于GLM系列模型,可以通过设计“请总结以下文章的主要内容”这样的提示,让模型对给定的文章进行摘要。这种方法不需要对模型进行大量的参数调整,只需要设计合适的提示,就能让模型适应新的任务。此外,还有参数高效微调方法,它只微调模型中的部分参数,而不是全部参数,这样可以在保证模型性能的同时,大大减少计算资源和时间成本。
大模型后训练面临着一些挑战。数据稀缺是一个常见问题,特定任务的数据可能非常有限,这就像是要做一道美味的菜肴,但食材却不够。为了解决这个问题,研究人员会使用数据增强技术,比如对文本进行回译、同义词替换等,增加训练数据的多样性。计算资源限制也是一个挑战,微调大型模型需要大量的计算资源,就像要建造一座大型建筑需要大量的人力和物力。
参数高效微调方法和模型压缩技术可以在一定程度上缓解这个问题。
未来,大模型后训练有着广阔的发展前景。一方面,研究人员会不断探索更高效的后训练方法,进一步减少计算资源和时间成本,提高模型的训练效率。另一方面,跨领域和跨任务学习将成为研究热点,让模型能够更好地适应不同的领域和任务,实现更广泛的应用。同时,提高模型的可解释性和安全性也是未来的重要方向,让模型不仅能够做出准确的预测,还能让用户理解其决策过程,并且防止模型被恶意攻击或滥用。
15.1.2 结果奖励与过程奖励:奖励建模详解
在上一节中,我们深入探讨了大模型后训练的多种方法与策略,其中最基础的两种便是监督微调(SFT)与强化学习。监督微调(SFT)我们已在前文(12.5节)有所阐述,它主要是通过标注好的数据对模型进行微调,使模型能够初步适应特定的任务需求。而强化学习,尤其是以梯度正则化策略优化(GRPO)为代表的算法,则为大模型的后训练提供了另一种高效的途径。
在强化学习的框架下,奖励建模扮演着至关重要的角色。奖励建模的核心在于构建一个能够准确反映人类偏好的奖励函数,以此引导模型在训练过程中不断优化其行为策略。其中,结果奖励与过程奖励是奖励建模中的两个关键维度。结果奖励关注的是模型最终输出的质量,即模型生成的答案或决策是否符合人类的期望;而过程奖励则侧重于模型在生成过程中的行为表现,如是否遵循了合理的逻辑、是否展现了创造性等。
在训练奖励模型时,我们通常采用最小化负对数似然函数的方法,其目标函数可以表示为:

这个公式表明,我们希望奖励模型给出的奖励值能够尽可能地接近真实(SFT),或者符合人类的偏好(GRPO)。例如,如果人类更喜欢yi
而不是yj
,那么我们希望模型的输出尽可能地满足R(x,yi)
输出的概率大于(x,yj)
的输出概率。
奖励函数的设计在强化学习领域中占据着举足轻重的地位。它就像一位精准的导航员,为模型在不同状态下明确应得的奖励,进而巧妙地引导模型逐步学习到我们所期望的行为模式。一个精心设计的奖励函数,能够如同明灯照亮模型前行的道路,使其在复杂多变的环境中迅速找到最优的行为策略。在强化学习的宏大框架里,奖励函数的设计绝非可有可无的环节,而是决定模型训练成败与效果优劣的关键因素。
奖励根据来源进行划分,可以清晰地分为过程奖励和结果奖励两大类别。
1. 过程奖励(Process Reward)
过程奖励,顾名思义,是在模型执行任务的每一个具体步骤中,依据其当下的行为表现所给予的奖励。这种奖励机制就像是一位时刻陪伴在模型身边的严格导师,对模型每一步的操作都进行细致入微的评估与反馈。其显著优势在于能够提供极为密集的反馈信号,模型无须等待漫长的任务结束,就能在每一个小步骤中及时知晓自己的行为是否正确、是否符合预期。这种即时反馈的特性,极大地加速了模型的学习进程,使其能够更快地调整策略、优化行为。
下面我们用伪代码模拟了一个过程奖励,代码如下所示:
def calculate_step_reward(response):
# 1. 语法正确性检查
syntax = check_syntax(response)
# 2. 逻辑连贯性评估
coherence = model.predict_coherence(response)
# 3. 事实一致性验证
fact_check = retrieve_evidence(response)
return 0.3*syntax + 0.5*coherence + 0.2*fact_check
在这个例子中,奖励函数考虑了三个方面:
- 语法正确性检查:检查模型生成的文本是否符合语法规则。例如,可以使用语法分析器来判断文本是否存在语法错误。
- 逻辑连贯性评估:评估模型生成的文本是否逻辑连贯。例如,可以使用语言模型来预测文本的连贯性。
- 事实一致性验证:验证模型生成的文本是否与事实相符。例如,可以使用知识库来检索相关信息,然后判断模型生成的文本是否与知识库中的信息一致。
对这三个方面进行加权求和,得到最终的奖励值。权重的选择需要根据实际情况进行调整。一般来说,更重要的方面应该分配更高的权重。
然而,过程奖励并非完美无缺。其最大的挑战在于设计难度极高,这要求设计者必须对任务有极为深入、透彻的理解。不同的任务具有独特的规则、目标和约束条件,要设计出能够精准反映模型在每个步骤中行为优劣的过程奖励函数,需要综合考虑诸多因素。例如,在一个复杂的机器人控制任务中,机器人的每一个动作都可能受到多种环境因素的影响,设计者需要精确衡量这些动作在不同情境下的合理性,才能制定出合适的过程奖励规则。一旦过程奖励设计不当,可能会误导模型,使其学习到并非最优甚至错误的行为模式。
2. 结果奖励(Outcome Reward)
与过程奖励不同,结果奖励关注的是模型在完成整个任务后所达成的最终成果。它更像是一位在终点等待的评判者,根据模型最终呈现的结果给予相应的奖励或惩罚。结果奖励的设计相对比较直观,通常可以根据任务的明确目标来制定。比如,在一场棋类游戏中,赢得比赛即可获得正奖励,输掉比赛则得到负奖励。这种简洁明了的奖励方式,使得模型能够清晰地了解最终需要追求的目标。
结果奖励是指在任务完成后,根据模型的最终结果给出的奖励。结果奖励的设计比较简单,只需要关注最终结果即可。但可能提供较稀疏的反馈信号,导致模型学习困难。典型应用场景包括:
- 数学问题:最终答案正确性。例如,如果模型生成的答案与正确答案一致,则给出正奖励,否则给出负奖励。
- 代码生成:通过单元测试的比例。例如,如果模型生成的代码能够通过所有的单元测试,则给出正奖励,否则给出负奖励。
- 对话系统:用户满意度评分。例如,如果用户对模型的回复感到满意,则给出正奖励,否则给出负奖励。
在实际应用中,为了充分发挥强化学习的优势,往往需要综合考虑过程奖励和结果奖励,将它们巧妙地结合起来。通过合理设计两者的权重和交互方式,使模型既能在每个步骤中得到及时的反馈和指导,又能明确最终的目标方向,从而实现更高效、更优质的学习效果。
但结果奖励也存在一定的局限性。由于它仅关注最终结果,模型在训练过程中可能会缺乏足够的指导,就像在黑暗中摸索前行,只能凭借最终的结果反馈来调整方向。这可能导致模型在探索过程中走很多弯路,学习效率相对较低。而且,对于一些复杂任务,单一的结果奖励可能无法全面反映模型在整个过程中的表现,容易忽略一些重要的中间环节和行为细节。
最后需要提醒大家,结果奖励与过程奖励并不是孤立的,而是相互关联、相互影响的。一个优秀的模型不仅需要在最终结果上符合人类的期望,还需要在生成过程中展现出合理的逻辑和创造性。因此,在构建奖励模型时,我们需要综合考虑结果奖励和过程奖励,以实现模型性能的全面提升。
15.2 带推理的智能医疗问诊实战
在人工智能的发展进程中,智能医疗问诊一直是人们翘首以盼的重要突破领域。然而,长期以来,由于大型模型如同一个“黑箱”,其内部复杂的运算逻辑和决策过程难以被直观解读,人们在使用智能医疗问诊系统时,往往只能被动地接受最终的输出结果,而对于得出该结果的推理过程却一无所知,这无疑在一定程度上限制了智能医疗问诊的进一步应用和信任度的提升。
在本节中,我们将聚焦于一个具备推理能力的智能医疗问诊项目。通过巧妙结合GRPO,致力于构建一个完善且可解释的推理模型,旨在打破“黑箱”限制,让智能医疗问诊的推理过程更加透明、可信。
15.2.1 推理医疗数据集的准备与处理
首先是医疗数据集的获取与准备,在这里我们准备了一套带有推理的医疗数据集,如下所示:
"Question": "在'高血压预防控制'社区健康促进项目中,社区卫生服务站向社区居民提供定期测量血压的服务,属于哪一种健康促进策略?",
"Complex_CoT": "在考虑社区卫生服务站提供的定期测量血压服务时,我首先想到了这是一种常见的健康促进活动。那么,它具体属于哪种健康促进策略呢?我首先想到的,是这些策略包括了健康教育、社区参与、政策发展、个人技能发展和卫生服务调整。于是,我开始仔细分析。社区卫生服务站提供定期的血压测量,从某种程度上来说,这明显是一项与卫生服务有关的活动。通过这种服务,居民可以更好地检测和跟踪自己的健康状况,获得重要的健康数据。\n\n不过等一下,这不仅仅是卫生成分的调整吧!我在想,每次测量血压的时候,那些居民是不是获得了关乎自身健康的即时信息和反馈呢?这会让他们更加警觉,更加主动去管理自己的健康。啊,这不就是个人技能的发展吗?他们的健康管理技能可能正在随着每次测量逐步提高。\n\n尽管这么说,是否还有可能涉及其他策略呢?比如说,社区参与似乎在这种服务中不太突出,因为这主要是卫生站主动提供的,居民主要是接受服务的一方。政策发展也稍显遥远,因为没有大的政策变化而影响到这样的服务。\n\n那么,回到卫生服务的调整,这项服务显然体现了一种定期的、系统化的安排,是关于怎样更好地为居民提供便捷健康服务的提升措施。然而,我隐隐觉得这种便捷的服务本身是不是也在构建一个促进健康的外部环境呢?如果通过这种节奏性的监测,居民可以更随时了解到自己的健康状况,那不正帮助他们营造了一个更健康的生活环境吗?\n\n所以,这样想下来,定期的血压测量服务不仅仅是一种卫生服务的调整,它可能更是关于如何改善居民整体健康外部环境的环境支持策略。是的,就是这种通过改变周边条件来促进健康的方式,让我意识到这种服务实际上是在塑造一个支持居民健康管理的环境。所以,最后我觉得这种服务正好体现了环境支持策略的意图。",
"Response": "在“高血压预防控制”社区健康促进项目中,社区卫生服务站为社区居民提供的定期测量血压的服务,主要属于“环境支持策略”。这种服务通过为居民提供便捷的健康监测条件,从而营造了一个有利于健康管理的外部环境。通过定期测量血压,居民不仅能及时了解自身健康状况,还能在这一过程中逐步提升自我健康管理的意识和能力。因此,这种服务既是对卫生服务的调整,也是通过改变周边环境来支持和促进居民健康的策略。"
与经典的数据集不同,在本数据集中,针对文本的问题“Question”和对应的回复“Response”,额外提供了一套复杂的中间推理流程“Complex_CoT”。这一独特设计的作用可不容小觑,它旨在深度增加模型的推理过程,使模型不再仅仅局限于简单地从问题直接映射到答案,而是能够像人类思考一样,经历一系列严谨且富有逻辑的推理步骤。
通过“Complex_CoT”,模型得以在推理过程中构建更丰富和细致的语义理解框架。它促使模型深入挖掘问题背后的潜在语义信息,分析各个概念之间的关联和逻辑层次,进而形成更全面和更准确的推理路径。
下面是我们实现的数据读取代码,如下所示:
import re
from datasets import load_dataset, Dataset
# Load and prep dataset
SYSTEM_PROMPT = """
Respond in the following format:
<reasoning>
...
</reasoning>
<answer>
...
</answer>
"""
def get_medical_questions(dataset_path = "./dataset/",split="train",mini_datast = True) -> Dataset:
"""加载medical-o1-reasoning-SFT 数据集并格式化"""
data = load_dataset(dataset_path)[split]
def format_example(x):
xml_answer = f"""\
<reasoning>
{x['Complex_CoT'].strip()}
</reasoning>
<answer>
{x['Response'].strip()}
</answer>"""
return {
'prompt': [
{'role': 'system', 'content': SYSTEM_PROMPT},
{'role': 'user', 'content': x['Question']}
],
'answer': (xml_answer) # 确保解析正确答案
}
data = data.map(format_example)
if mini_datast:
data = data.select(range(128))
return data
在上面代码中,数据的处理环节相对简便,我们采用直接的文本解析手段来提取其中的关键内容,随后按照特定的需求对这些内容进行精心整理。不过,在实际操作过程中,有一个关键要点需要格外留意。那就是针对经过文本处理和解析所得到的内容,必须确保它们与大模型的Prompt实现精准对齐。
具体而言,我们需要将处理后的内容按照如下特定的格式进行组织:
<reasoning>
...(此处填充经过解析和整理后的推理相关内容)
</reasoning>
<answer>
...(此处填充基于推理得出的最终答案内容)
</answer>
采用这种格式进行内容组织具有显著的优势。它明确要求输出结果严格遵循模型的生成定义,使得模型在生成响应时能够有清晰的结构和逻辑依据。从模型的角度来看,这种格式化的输入就像是一份详细的“任务说明书”,它清晰地告知模型哪些部分是需要进行推理分析的,哪些部分是用于呈现最终答案的。
从实际应用的角度而言,这种对齐方式有助于提升模型输出的质量和一致性。一方面,它确保了模型在生成结果时能够聚焦于关键信息,避免产生无关或冗余的内容。另一方面,当多个模型或系统需要协同工作时,统一的格式规范能够大大提高数据交互和处理的效率,使得整个流程更加流畅和稳定。而且,这种结构化的输出也为后续的结果评估和分析提供了便利,我们可以更方便地提取和比较不同模型或不同场景下的推理过程和答案,从而进一步优化模型性能和应用效果。
15.2.2 奖励函数的完整实现
在GRPO中,奖励函数是模型完成构建后进行训练的核心要素。我们精心设计了多个相互协同的奖励函数,以此对模型进行精准指导。具体说明如下:
(1)correctness_reward_func(正确性奖励函数):当模型所提取的答案与真实答案完全匹配时,会给予2.0分的奖励。这一奖励机制是确保模型学习事实正确性的主要信号,激励模型朝着准确的方向进行优化。
(2)int_reward_func(整数奖励函数):若答案为数字形式,模型将获得0.5分的奖励。此奖励函数特别适用于数学问题场景,能够有效引导模型生成数值类型的响应,提升模型在数值处理方面的能力。
(3)soft_format_reward_func和strict_format_reward_func(宽松格式与严格格式奖励函数):当模型输出正确的XML格式时,会获得0.5分的奖励。这两个函数旨在教导模型运用正确的标签结构进行响应,确保输出结果的格式规范。
(4)xmlcount_reward_func(XML标签计数奖励函数):该函数会为每个正确使用的XML标签提供部分奖励,每个标签奖励0.125分。这种奖励方式能够形成平滑的学习梯度,有助于模型逐步掌握XML标签的正确使用方法。
上述奖励函数主要聚焦于对模型输出结果的处理进行模拟奖励。这样使得在GRPO中我们可以依据不同的判定要求,为模型输出结果提供相应的奖励。下面是我们实现的奖励函数:
import re
def extract_xml_answer(text: str) -> str:
"""提取 <answer> 标签内的内容"""
match = re.search(r"<answer>(.*?)</answer>", text, re.DOTALL)
return match.group(1).strip() if match else text.strip()
# 奖励函数
def correctness_reward_func(prompts, completions, answer, **kwargs) -> list[float]:
"""
检查提取的答案是否与真实答案匹配的奖励函数。
正确答案返回2.0,否则返回0.0。
"""
responses = [completion[0]['content'] for completion in completions]
extracted_responses = [extract_xml_answer(r) for r in responses]
return [2.0 if r == a else 0.0 for r, a in zip(extracted_responses, answer)]
def int_reward_func(completions, **kwargs) -> list[float]:
"""检查答案是否为整数"""
responses = [completion[0]['content'] for completion in completions]
extracted_responses = [extract_xml_answer(r) for r in responses]
return [0.5 if r.isdigit() else 0.0 for r in extracted_responses]
def strict_format_reward_func(completions, **kwargs) -> list[float]:
"""严格格式检查:必须有换行符
检查补全内容是否完全符合格式的奖励函数。
匹配格式返回0.5,否则返回0.0。
"""
pattern = r"^<reasoning>\n.*?\n</reasoning>\n<answer>\n.*?\n</answer>\n$"
responses = [completion[0]["content"] for completion in completions]
return [0.5 if re.match(pattern, r) else 0.0 for r in responses]
def soft_format_reward_func(completions, **kwargs) -> list[float]:
"""宽松格式检查:允许不严格换行
宽松的格式检查奖励函数。
匹配格式返回0.5,否则返回0.0。
"""
pattern = r"<reasoning>.*?</reasoning>\s*<answer>.*?</answer>"
responses = [completion[0]["content"] for completion in completions]
return [0.5 if re.match(pattern, r) else 0.0 for r in responses]
def count_xml(text) -> float:
"""
统计XML标签并为每个正确放置的标签提供部分奖励。
"""
count = 0.0
if text.count("<reasoning>\n") == 1:
count += 0.125
if text.count("\n</reasoning>\n") == 1:
count += 0.125
if text.count("\n<answer>\n") == 1:
count += 0.125
count -= len(text.split("\n</answer>\n")[-1]) * 0.001
if text.count("\n</answer>") == 1:
count += 0.125
count -= (len(text.split("\n</answer>")[-1]) - 1) * 0.001
return count
def xmlcount_reward_func(completions, **kwargs) -> list[float]:
"""计算 XML 结构完整性分数
基于响应中XML标签计数的奖励函数。
"""
contents = [completion[0]["content"] for completion in completions]
return [count_xml(c) for c in contents]
从上面代码可以看到,奖励函数主要围绕从文本中提取特定内容以及基于不同规则设计奖励函数展开。核心目标是处理包含XML格式信息的文本数据,通过多种奖励函数对模型输出进行评估和反馈。
上面代码首先定义了一个用于提取<answer>标签内容的函数extract_xml_answer,该函数利用正则表达式在给定文本中搜索<answer>标签及其包裹的内容,并返回提取后的结果。若未找到匹配内容,则返回原文本去除首尾空白后的字符串。
在此基础上,后续定义了多个奖励函数,这些函数分别从不同角度对模型输出进行评判,包括答案的正确性、答案是否为整数、输出格式是否符合要求,以及XML标签的使用情况等。
在GRPO的训练过程中,若模型的回答需要遵循特定的XML格式,这些奖励函数可以帮助模型学习到正确的格式规范,提高答案的准确性和规范性。同时,对于答案正确性和格式的奖励设置,有助于模型在追求答案正确的同时,也注重输出格式的美观和一致性,从而提升模型的整体性能和用户 体验。
15.2.3 基于GRPO后训练的智能医疗问诊实战
在对数据做好准备并完成了奖励函数的编写后,接下来我们需要完成基于GRPO的后训练(注意:这里使用的transformers版本要求为4.47.0,版本不符的读者可重新安装以完成训练),完整代码如下所示:
#1. 模型与训练配置
# 设置输出目录和运行名称
output_dir ="outputs/GRPO"
run_name ="medical_o1_sft_Chinese"
from trl import GRPOConfig, GRPOTrainer # 导入 GRPO 训练配置和训练器
from peft import LoraConfig
training_args = GRPOConfig(
output_dir=output_dir,
run_name=run_name,
learning_rate=5e-5,
adam_beta1=0.9,
adam_beta2=0.99,
weight_decay=0.1,
warmup_ratio=0.1,
lr_scheduler_type='cosine',
logging_steps=4,
bf16=True, # 设置为False
fp16=False, # 使用fp16以提高兼容性
per_device_train_batch_size=8, # 增加以兼容GRPO
gradient_accumulation_steps=1,
num_generations=4, # 必须是per_device_train_batch_size的除数
max_prompt_length=128,
max_completion_length=312,
num_train_epochs=1,
save_steps=50,
max_grad_norm=0.1,
report_to="none",
log_on_each_node=False,
)
peft_config = LoraConfig(
r=8, # 从16减少以适应Colab内存
lora_alpha=16,
target_modules=["q_proj", "v_proj"], # 简化目标模块
task_type="CAUSAL_LM",
lora_dropout=0.05,
)
#2. 模型与分词器加载
from transformers import AutoModelForCausalLM
from deepseek_vl2.models import DeepseekVLV2Processor, DeepseekVLV2ForCausalLM
# specify the path to the model
model_path = "deepseek-ai/deepseek-vl2-tiny"
# 加载分词器并设置 chat_template
vl_chat_processor = DeepseekVLV2Processor.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).cuda()
tokenizer = vl_chat_processor.tokenizer
# 手动设置 chat_template(示例模板)
tokenizer.chat_template = [
{"name": "user", "content": "<|begin▁of▁sentence|>User: {{input}}"},
{"name": "assistant", "content": "Assistant: {{response}}"}
]
#3.数据集与奖励函数
# 数据集预处理
def add_prompt_column(example):
example["prompt"] = f"患者:{example['Question']}\n医生:"
return example
print("加载数据集...")
import get_dataset
dataset = get_dataset.get_medical_questions(mini_datast=True)
dataset = dataset.map(add_prompt_column)
print(f"数据集加载完成,共{len(dataset)}个示例")
print("初始化GRPO训练器...")
import grpo_reward_fun
trainer = GRPOTrainer(
model=model,
processing_class=tokenizer,
reward_funcs=[
grpo_reward_fun.xmlcount_reward_func,
grpo_reward_fun.soft_format_reward_func,
grpo_reward_fun.int_reward_func,
grpo_reward_fun.correctness_reward_func
],
args=training_args,
train_dataset=dataset,
peft_config=peft_config,
)
#4. 训练与保存
# 开始训练
print("开始GRPO训练...")
trainer.train()
# 保存最终模型
print("训练完成。保存模型...")
trainer.save_model()
在上面代码中,我们使用DeepSeek-VL2-Tiny模型作为微调的对象,并直接使用trl库中的GRPO训练器对模型进行训练。这个示例实现了一个基于DeepSeek-VL2-Tiny模型的GRPO(Guided Reward Policy Optimization)训练流程,结合LoRA(Low-Rank Adaptation)进行参数高效微调,适用于中文医疗领域的生成任务。
1. 模型与训练配置
示例代码首先定义了模型名称、输出目录和运行名称,然后导入了GRPO训练框架和LoRA配置模块。在GRPOConfig中,设置了训练参数,包括学习率、优化器超参数(如adam_beta1和adam_beta2)、权重衰减、学习率调度策略(余弦退火)、混合精度选项(fp16和bf16),以及批量大小和梯度累积步数等。特别地,num_generations指定了每次生成的样本数量,必须与批量大小整除。LoraConfig则定义了LoRA的秩(r=8)、目标模块(如q_proj和v_proj)以及任务类型(因果语言建模)。这些配置旨在平衡训练效率和内存使用,同时适配医疗领域任务的特性。
2. 模型与分词器加载
示例代码通过加载预训练的DeepSeek-VL2-Tiny模型,并指定使用float16精度来优化内存和计算资源。而分词器通过vl_chat_processor.tokenizer加载。在这里,我们本地化加载了模型,启用了trust_remote_code,允许从远程加载自定义代码,这一步骤确保了模型和分词器能够正确初始化,并为后续的数据处理和训练做好准备。
3. 数据集与奖励函数
示例代码加载使用了我们准备的带有推理数据的医疗数据集,并打印了数据集大小。为了引导生成过程,定义了多个奖励函数(如xmlcount_reward_func、soft_format_reward_func等),这些函数可能分别关注生成内容的结构完整性、格式规范性、信息准确性和逻辑正确性。奖励函数被传递给GRPOTrainer,作为训练过程中的指导信号,帮助模型生成更符合医疗领域需求的文本。
4. 训练与保存
最后,示例代码初始化了GRPOTrainer,将模型、分词器、奖励函数、训练参数和数据集整合到训练流程中。通过调用trainer.train()启动训练,模型在奖励函数的引导下优化生成策略。训练完成后,调用trainer.save_model()保存微调后的模型,确保训练成果可以被后续任务复用。整个过程通过GRPO框架实现了策略优化与高效微调的结合,适用于资源受限环境下的模型训练。
15.2.4 智能医疗问诊模型的推理展示
接下来就到验收结果的时刻。在前面我们通过后训练GRPO算法完成了模型的训练,在这个过程中我们通过设置系统提示system_prompt的方式引导大模型对内容进行思考,并获取带有推理过程的模型回复,此时我们需要完成GRPO训练的最后一步,即模型的推理,代码如下所示:
import torch
from deepseek_vl2.models import DeepseekVLV2ForCausalLM, DeepseekVLV2Processor
# 设置模型路径
model_path = "outputs/GRPO"
print(f"加载模型:{model_path}")
# 使用自定义模型类加载
model = DeepseekVLV2ForCausalLM.from_pretrained(
model_path,
trust_remote_code=True
).cuda()
processor = DeepseekVLV2Processor.from_pretrained("deepseek-ai/deepseek-vl2-tiny")
tokenizer = processor.tokenizer
# 如果 pad_token 不存在,设为 eos_token
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
def extract_xml_answer(text: str) -> str:
"""提取 <answer> 标签内的内容"""
import re
match = re.search(r"<answer>(.*?)</answer>", text, re.DOTALL)
return match.group(1).strip() if match else text.strip()
def generate_prediction(question: str, max_length=512) -> str:
# 手动构建 prompt 字符串,避开 chat_template 的问题
system_prompt = (
"Respond in the following format:\n"
"<reasoning>\n...\n</reasoning>\n"
"<answer>\n...\n</answer>"
)
formatted_prompt = (
f"<|begin▁of▁sentence|>System: {system_prompt}\n"
f"User: {question}\n"
"Assistant:"
)
# 编码输入
inputs = tokenizer(formatted_prompt, return_tensors="pt").to(model.device)
# 生成响应
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=max_length,
temperature=0.7,
top_p=0.9,
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id
)
# 解码并返回结果
response = tokenizer.decode(outputs[0][inputs.input_ids.size(1):], skip_special_tokens=True)
return response
# 测试样例
question = "瓷层的颜色缺乏层次感。造成这种现象的最常见原因是什么?"
print(f"问题:{question}")
response = generate_prediction(question)
answer = extract_xml_answer(response)
print(f"\n解析后的答案:{answer}")
print("-" * 50)
对于问题的回复,读者可以自行尝试,从结果上也可以看到,此时我们可以成功地引导出模型按要求进行回复,即完成了带有推理过程的智能医疗问答系统的开发过程。
15.3 本 章 小 结
本章我们顺利完成了大模型开发流程中至关重要的最后一个阶段——GRPO(基于策略梯度优化的后训练方法)的训练工作。在这一阶段,我们采用了精细化的人工比对策略,对模型的输出格式、推理逻辑以及最终结果进行了全方位、深层次的校验与调整。这一过程不仅显著提升了模型对复杂任务的理解能力,而且使其能够精准捕捉人类用户的需求与偏好,从而生成契合以人为本思想的高质量输出内容。
在实践操作层面,我们系统展示了GRPO的完整训练流程,从数据准备、模型初始化到多阶段分步训练,每一步都力求精确无误。通过这一系列精心设计的后训练步骤,我们成功引导模型逐步逼近预期的输出标准,不仅验证了GRPO方法的有效性,更为后续利用该框架进行模型的深度强化学习奠定了坚实的基础。
值得一提的是,在GRPO训练过程中,我们创新性地引入了多样化的奖励函数机制,以量化模型输出与理想分布之间的差异。这种综合优化策略极大地促进了模型性能的提升,使得最终训练出的模型在保持高效性的同时,也展现出了卓越的泛化能力和适应性。
GRPO的讲解到此为止,有兴趣的读者可以继续深化对GRPO方法的研究与应用,不断探索其在不同领域、不同任务中的潜力与价值。同时,我们也将积极寻求与其他先进技术的融合创新,共同推动人工智能技术的蓬勃发展,为人类社会创造更多的价值。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐




所有评论(0)