掘金 人工智能 前天 11:23
Datawhale AI夏令营:Baseline与调优
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了LoRA(Low-Rank Adaptation)技术在参数高效微调(PEFT)中的应用,特别是在讯飞星火平台上用于优化列车时刻问答模型。文章首先解释了LoRA的核心原理,即通过低秩分解来学习模型参数的变化量,从而在降低微调数据量的同时,确保模型能给出符合预期的回答。随后,文章详细介绍了赛题目标——让模型准确回答列车时刻相关问题,并分析了模型需具备的数据解析与自然语言问答能力。在此基础上,文章提出了一种基于模型蒸馏的Baseline调优方案,旨在解决直接生成问答对时可能出现的“问题合理性”和“答案保真度”问题,通过“老师-学生”模型训练,让学生模型学习推理过程。最后,文章展示了具体的代码实现,包括数据准备、问题生成、模型调用、结果后处理及保存为训练文件等关键步骤,并概述了整个Baseline的结构和实现流程。

🔹 LoRA技术的核心优势在于参数高效微调,它利用低秩分解来捕捉预训练大语言模型(LLM)在微调过程中参数的变化量,目标是在显著降低数据量的同时,保证模型能够生成准确且符合预期的回答,是提升大模型定制化能力(如风格迁移、纠错)的重要手段之一,并与其他PEFT方法如Adapter、Prefix tuning并行存在。

🔸 本次赛题的核心任务是训练一个能够准确回答关于列车时刻问题的模型,这要求模型不仅要掌握表格数据的解析与表示能力,还要能理解并回应自然语言形式的用户查询,特别是针对包含数值、文本描述及推理步骤的结构化回答要求。

🔹 Baseline调优方案采用了模型蒸馏技术,通过引入一个能力更强的“老师模型”来指导“学生模型”进行推理学习,而非简单的答案复制。这一过程旨在让学生模型在学习如何得出正确答案的同时,也理解其背后的推理逻辑,从而以更小的模型体积和更快的速度达到高质量的问答表现。

🔸 代码实现涵盖了数据预处理(读取Excel、填充缺失值)、问题生成(结合数据生成多维度问题)、模型调用(使用Qwen/Qwen3-235B-A22B-Instruct-2507,并处理JSON输出)、数据后处理(验证问答对有效性、转为标准微调格式)以及结果保存等阶段,确保了整个调优流程的完整性和鲁棒性。

🔹 针对结构化数据问答的初期尝试,直接让大模型端到端生成问答对存在潜在缺陷,可能导致生成的问题与数据无关或逻辑错误,以及答案与原始数据不符或计算错误,模型蒸馏方案的引入正是为了规避这些问题,提升生成问答对的质量和可靠性。

0.遗留问题:什么是LoRA

在本次的Baseline调优中,我们使用了LoRA技术来对讯飞星火平台上的模型进行微调,那么什么是LoRA技术呢?

LoRA技术的核心思想,是针对预训练大语言模型(LLM)的参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)而提出的一种创新方法。其核心在于利用低秩分解(Low-Rank Decomposition)来建模模型微调过程中所需的参数变化量。或者更加直接明了一些来说,LoRA技术就是希望通过在降低数据量的同时,保证大模型可以做出符合我们预期的回答。我们这里采用的LoRA技术属于大模型微调的技术中的一种,微调本身可以提升大模型的表现,比如定制化风格,纠正提示工程和上下文学习中难以修正的错误等。

如我们之前几篇博客中所提到的,LoRA本身并非大模型调优的唯一选择,实际上也还有其他的模型调优选择,另外两种比较知名的大模型微调的方法分别为AdapterPrefix tuning,下图来自LoRA的论文本身,对比了LoRA和另外两种方案的,可以用户可以根据自己的需求选择特定的模型来完成对模型的微调

1.深入理解赛题:

本次的赛题其实目标非常简单:

我们需要对模型进行调优,使其可以尽可能准确地回答用户有关于列车时刻的问题

这里实际上涉及到模型两个方面的能力:

    让模型学习如何解析和表示表格数据。回答与表格数据对应的自然语言问题。

模型一般会面对以下7类问题:

而我们需要给出包含数值结果、文本描述及必要推理步骤的结构化回答,能够直接展示提取的指标和相关信息。

我们打开官方给的数据文件,先浏览我们手中的数据

这个文件包括一些车次的信息,包括“序号”、“车次”、“始发站”、“终到站”、“到点”、“开点”、“候车厅”、“检票口”、“站台”等信息。

但是值得留意的是并不是所有数据的所有字段的信息都是完整的,我们可以针对数据缺失进行补全

整体的流程如下图所示:

2.基于模型蒸馏的baseline的调优方案:

在应对结构化数据问答任务初期,我们采用了最直接的方法:利用大语言模型(LLM)端到端地生成训练所需的“问题-答案”对

具体而言,策略是向大模型输入单行表格数据,并指令其严格依据预设的输出模板生成相应的、包含问题和答案的JSON结构

这种“大模型同时生成问题与答案”的策略存在一个根本性缺陷:无法有效保证生成结果的准确性。

核心问题主要在于在于以下两点:

    问题的合理性:模型可能生成与表格数据无关、语义不清或逻辑错误的无效问题。答案的保真度:生成的答案可能存在与输入表格信息不一致、计算错误或捏造信息的情况。

这个时候我们选择引入模型蒸馏的方案来对模型进行

简单来说,我们会选取一个能力更强的模型作为老师模型,老师模型会教会学生模型如何推理出正确的答案(注意此处不是简单的教会学生模型如何输出正确答案,同时还会保证学生模型理解这推理个过程)

我们结合这个比赛的案例来了解一下模型蒸馏

模型蒸馏如同让新调度员(小模型)学习资深专家(大模型)的经验。新调度员重点学习这种思维模式,而非简单结论,最终能以更小的模型体积和更快的速度,做出正确的判断

3.Baseline的具体实现

我们这里采用了Datawhale所提供的代码

import pandas as pdimport requestsimport reimport jsonfrom tqdm import tqdm# 读取数据data = pd.read_excel('data/info_table(训练+验证集).xlsx')data = data.fillna('无数据')def call_llm(content: str):    """    调用大模型        Args:        content: 模型对话文本        Returns:        list: 问答对列表    """    # 调用大模型(硅基流动免费模型,推荐学习者自己申请)    url = "https://api.siliconflow.cn/v1/chat/completions"    payload = {        "model": "Qwen/Qwen3-8B",        "messages": [            {                "role": "user",                "content": content  # 最终提示词,"/no_think"是关闭了qwen3的思考            }        ]    }    headers = {        "Authorization": "", # 替换自己的api token        "Content-Type": "application/json"    }    resp = requests.request("POST", url, json=payload, headers=headers).json()    # 使用正则提取大模型返回的json    content = resp['choices'][0]['message']['content'].split('</think>')[-1]    pattern = re.compile(r'^```json\s*([\s\S]*?)```$', re.IGNORECASE)  # 匹配 ```json 开头和 ``` 结尾之间的内容(忽略大小写)    match = pattern.match(content.strip())  # 去除首尾空白后匹配    if match:        json_str = match.group(1).strip()  # 提取JSON字符串并去除首尾空白        data = json.loads(json_str)        return data    else:        return content    return response['choices'][0]['message']['content']def create_question_list(row: dict):    """    根据一行数创建问题列表        Args:        row: 一行数据的字典形式        Returns:        list: 问题列表    """    question_list = []    # ----------- 添加问题列表数据 begin ----------- #    # 检票口    question_list.append(f'{row["车次"]}号车次应该从哪个检票口检票?')    # 站台    question_list.append(f'{row["车次"]}号车次应该从哪个站台上车?')    # 目的地    question_list.append(f'{row["车次"]}次列车的终到站是哪里?')        # ----------- 添加问题列表数据 end ----------- #    return question_list# 简单问题的promptprompt = '''你是列车的乘务员,请你基于给定的列车班次信息回答用户的问题。# 列车班次信息{}# 用户问题列表{}'''output_format = '''# 输出格式按json格式输出,且只需要输出一个json即可```json[{    "q": "用户问题",    "a": "问题答案"},...]```'''train_data_list = []error_data_list = []# 提取列cols = data.columns# 遍历数据(baseline先10条数据)i = 1for idx, row in tqdm(data.iterrows(), desc='遍历生成答案', total=len(data)):    try:        # 组装数据        row = dict(row)        row['到点'] = str(row['到点'])        row['开点'] = str(row['开点'])        # 创建问题对        question_list = create_question_list(row)        # 大模型生成答案        llm_result = call_llm(prompt.format(row, question_list) + output_format)        # 总结结果        train_data_list += llm_result    except:        error_data_list.append(row)        continue# 转换训练集data_list = []for data in tqdm(train_data_list, total=len(train_data_list)):    if isinstance(data, str):        continue    data_list.append({'instruction': data['q'], 'output': data['a']})json.dump(data_list, open('train_data/single_row.json', 'w', encoding='utf-8'), ensure_ascii=False)

本次的代码大约可以分为4个阶段

    数据准备阶段
    问题生成阶段
    数据后处理阶段
    结果输出阶段

整个代码的流程大约如下图所示

整体的baseline的整体的结构如下图所示:

4.结果展示

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

LoRA 模型微调 参数高效微调 模型蒸馏 自然语言处理 列车时刻问答
相关文章