Datawhale AI夏令营:Baseline与调优

0.遗留问题:什么是LoRA

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

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

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

1.深入理解赛题:

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

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

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

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

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

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

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

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

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

整体的流程如下图所示:

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

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

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

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

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

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

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

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

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

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

3.Baseline的具体实现

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

python 复制代码
import pandas as pd
import requests
import re
import json
from 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




# 简单问题的prompt
prompt = '''你是列车的乘务员,请你基于给定的列车班次信息回答用户的问题。
# 列车班次信息
{}

# 用户问题列表
{}

'''
output_format = '''# 输出格式
按json格式输出,且只需要输出一个json即可
```json
[{
    "q": "用户问题",
    "a": "问题答案"
},
...
]
```'''

train_data_list = []
error_data_list = []
# 提取列
cols = data.columns
# 遍历数据(baseline先10条数据)
i = 1
for 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个阶段

  1. 数据准备阶段
  • 读取Excel格式的列车时刻表数据
  • 自动处理缺失值(填充为"无数据")
  • 转换为字典形式便于处理
  1. 问题生成阶段
  • 我们这次的蒸馏模型是Qwen/Qwen3-235B-A22B-Instruct-2507
  • 提示词覆盖检票口、站台、目的地、时间等关键信息
  • 提示词尽可能覆盖每个字段的多个问法
  • 提示词明确角色设定(专业乘务员)
  • 提示词强调严格基于给定数据回答
  • 包含严格的JSON输出格式要求
  • 实现带重试机制的可靠请求
  • 自动解析模型返回的JSON格式响应
  1. 数据后处理阶段
  • 验证生成问答对的有效性
  • 转换为标准微调格式(instruction-output结构)
  • 错误日志记录与异常处理
  1. 结果输出阶段
  • 保存为single_row.json训练文件

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

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

4.结果展示

相关推荐
广东小61 小时前
昇思学习营-【模型推理和性能优化】学习心得_20250730
学习·性能优化
数据智能老司机3 小时前
基础图谱增强检索生成(GraphRAG)——智能代理式 RAG
langchain·llm·aigc
Hi202402175 小时前
支持OCR和AI解释的Web PDF阅读器:解决大文档阅读难题
pdf·flask·llm·ocr·阅读器
中等生5 小时前
ReAct: 减少 LLM 幻觉,提升准确度
llm·openai·ai编程
智泊AI5 小时前
NLP是什么?一文带你搞懂“自然语言处理(NLP)”看这篇就够了!
llm
顾林海6 小时前
Android 性能优化:提升应用启动速度(GC抑制)
android·面试·性能优化
radient6 小时前
GoLang-pprof-案例实践及解析
后端·面试·性能优化
Generalzy6 小时前
从 Print 到 Debug:用 PyCharm 掌控复杂程序的调试之道
ide·性能优化·pycharm
数据智能老司机6 小时前
使用 Python 进行并行与高性能编程——并行编程导论
python·性能优化·编程语言