Datawhale AI夏令营-大模型技术(微调)Task1打卡

一、赛题解读

1.1 赛事任务

基于大模型微调技术,微调适用于高考语文现代文阅读和英语阅读的QAG的大模型,完成输入文章输出问题与答案的任务。

1.2 任务开发过程

数据集管理(上传数据)——数据集管理(去训练,可用赠送的抵用券进行训练)——模型管理(发布为服务)——我的模型服务(查看serviceId和resourceId)

1.3 数据说明

比赛为参赛选手提供了近几年的高考语文现代阅读和英语阅读的数据集(包含原文,题目,答案)用于训练和测试,数据可在AI大赛参赛页面下载,此外,我们鼓励参赛选手自行拓展数据以优化Q&A的生成效果

【数据处理要求】

在数据处理方面,需要参赛者对所给数据进行清洗、整理,以达到能够上传到讯飞大模型定制训练平台上的数据集要求(包括格式、prompt优化等)。

大模型训练的数据格式要求是input/target,其中input为阅读文章本体以及完成QAG所需的prompt(例如:假如你是高考出题专家,请你根据以下阅读文本出4道选择题以及答案),target为题目选项以及答案

1.4 模型说明

本次大赛要求使用的模型为spark-13b。微调基本要求是:输入阅读文本,返回4组Q&A(单项选择)输出格式见“输出样例数据”。

参赛团队可以利用该开源工具( GitHub - iflytek/spark-ai-python: 星火大模型 python sdk库 )来测试微调后模型的输出效果。

1.5 评估指标

大赛依据提交的resourceId进行测试产生定量的Q&A进行评估,采用自动化评估和人工评估两种方式综合评审成绩。

第一阶段,通过自动化评估筛选出【前五支且得分高于65分】的团队入围第二阶段。

第二阶段,入围团队作品进入人工评估。最终作品成绩构成为:40%*(第一阶段自动化得分)+ 60%*(第二阶段人工评估得分)。经评审此阶段TOP3团队进入决赛答辩。

【自动化评估】

1)准确度评估(50%)

我们利用星火大模型最新的版本,围绕测评文本构建QAG系统,来测评选手模型生成Q&A的QA配对准确率。

2)考纲维度评估(50%)

我们构建了基于星火3.5的考纲评估系统来评估Q&A在考纲维度的得分,求取平均得总分,具体考纲要求参见2019年普通高等学校招生全国统一考试大纲 ( 2019年普通高等学校招生全国统一考试大纲(英语) - 中国教育考试网 )。

【人工评估】

1)教育专家评审 (50%)

邀请教育专家对生成的Q&A进行评审,评估其教育价值和是否符合教学大纲要求,对所有的Q&A综合评分。

2)教师评审 (50%)

教师从教学实践的角度出发,评估Q&A的实用性和对学生学习的帮助,对所有的Q&A综合评分

1.6 作品提交要求

1、提交的作品如下:微调好的大模型的resourceId、以及对应prompt。

2、文件大小:无要求

3、提交次数限制:每支团队每周最多4次

4、文件详细说明:编码为UTF-8,提交格式见样例

5、其他文件说明:建议一并提供数据处理及微调流程方法文件

  1. 对模型微调数据的理解

  2. 对教育业务的理解

  3. 数据处理方法

二、baseline代码解读

2.1 数据

2.1.1 数据集样本分析

①测试集

语文(共9道),包括以下类型:

①散文的艺术特色鉴赏

②散文的相关内容理解与分析

③⑨科技科普文章的相关内容理解与分析

④⑤经典文学作品的相关内容理解与分析

⑥⑦⑧传统文化焕新散文

英语(共9道),包括以下类型:

①②⑤⑥内容信息的正确提取

③⑦⑧⑨内容的正确理解

④内容的比较

②训练集-语文(64道,以前20道为例)

①②④⑤⑦⑨、11、12、14、15、17、19科普文章的内容理解

③⑥⑧13、16散文的艺术特色赏析

⑩散文的内容理解与写作方法

18、20小说的内容理解与艺术特色赏析

③训练集-英语(64道,以前10道为例)

①⑤⑨实用型文本-信息提取与选择

②③④⑥⑦⑧⑩叙述型文本-信息理解

④输出样例数据

input-材料

output-选项

2.1.2 数据类型分析
高考语文现代文阅读题型特点
  1. 理解题:这类题目要求考生理解文章的主旨大意、段落大意以及作者的观点和态度。例如,题目可能会问:“文章主要讨论了什么?”或“作者对某事物的态度是什么?”

  2. 分析题:考生需要分析文章的结构、语言特点、修辞手法等。例如,可能会要求考生分析某段文字的论证结构或者某个词语的表达效果。

  3. 综合题:这类题目要求考生综合全文信息,进行推理和总结。例如,可能会要求考生根据文章内容推断作者的写作背景或目的。

  4. 评价题:考生需要对文章的观点、论据、论证方法等进行评价。例如,可能会问:“你认为作者的论证是否充分?”或“文章的哪些方面给你留下了深刻印象?”

  5. 开放性题目:这类题目没有固定答案,鼓励考生发挥自己的思考和见解。例如,可能会要求考生就文章中提出的问题给出自己的看法。

高考英语阅读题型特点
  1. 细节理解题:这类题目考察考生对文章中具体信息的把握。例如,可能会问:“根据第一段,作者提到了什么?”或“文章中提到的某个数据是多少?”

  2. 推理判断题:考生需要根据文章内容进行逻辑推理,判断作者的隐含意义或文章的深层含义。例如,可能会问:“根据文章,我们可以推断出什么?”

  3. 主旨大意题:这类题目要求考生概括文章的中心思想或主题。例如,可能会问:“文章的主要论点是什么?”

  4. 词义猜测题:考生需要根据上下文猜测生词或短语的含义。例如,可能会问:“在文章中,'innovative'这个词是什么意思?”

  5. 观点态度题:考生需要识别作者或文中人物的观点、态度和情感色彩。例如,可能会问:“作者对某事物持什么态度?”

  6. 篇章结构题:这类题目考察考生对文章结构的把握,如段落之间的逻辑关系。例如,可能会问:“文章的结构是如何组织的?”

2.1.3 数据选择与处理
  1. 数据收集:可以收集大量的高考语文和英语阅读真题,包括问题和标准答案。确保数据覆盖不同年份和不同地区的高考试卷,以增加多样性。

  2. 数据预处理:对收集到的数据进行清洗,去除无关信息,如试卷编号、考生信息等,清理文本中的噪声,比如多余的空格、特殊字符、HTML标签等;将问题和答案进行格式化,确保数据的一致性和可读性,对于中文数据,使用分词工具将文本分割成单独的词汇或短语,因为中文文本不像英文那样有明显的单词分隔符;对于英文数据,可以使用空格和标点符号作为分词的依据。

  3. 数据标注:对问题进行分类,如理解题、分析题、综合题、评价题等。对答案进行标注,明确每类问题的答题要点和评分标准。

  4. 训练集和测试集的划分:使用时间序列划分法,将较早年份的试卷作为训练集,较晚年份的试卷作为测试集,以模拟模型在实际应用中的预测能力;考虑使用交叉验证,特别是在数据量有限的情况下,以评估模型的稳定性和泛化能力;在划分训练集、验证集和测试集时,确保每个集合中各类别的比例与整个数据集的比例相同。

  5. 数据增强:通过同义词替换、句子重组等方式增加训练数据的多样性,提高模型的鲁棒性。

  6. 任务特定调整:对于语文现代文阅读,模型需要能够处理复杂的语言结构和文化背景,因此训练集应包含丰富的文学和文化元素;对于英语阅读,模型需要能够理解和生成符合英语习惯的表达,训练集应包含多样化的英语表达和句式。

  7. 模型微调:在预训练的QAG大模型基础上,使用训练集进行微调,优化模型对特定任务的适应性。

  8. 性能评估:使用测试集评估模型的性能,关注准确率、召回率和F1分数等指标。进行错误分析,了解模型在哪些类型的题目上表现不佳,并针对性地调整训练策略。

2.2 代码理解

2.2.1 语文问答数据制作

#pip install pandas openpyxl

#导入pandas库,并将其别名设置为pd
import pandas as pd

#导入Python的正则表达式模块re,允许进行复杂的字符串匹配和替换
import re

# 读取Excel文件,df是一个DataFrame对象,它是pandas中用于存储表格数据的主要数据结构。
df = pd.read_excel('训练集-语文.xlsx')

#使用DataFrame的replace方法替换DataFrame中的所有.(全角句号)为.(半角句号)。参数regex=True表示将替换逻辑视为正则表达式
df = df.replace('.', '.', regex=True)

#使用replace方法将所有的((全角括号)替换为((半角括号)。同样,regex=True参数确保替换逻辑按照正则表达式处理
df = df.replace('(', '(', regex=True)

'''
使用loc属性通过行索引和列名来访问DataFrame中的特定数据。这里,2是行索引,表示第三行(因为索引从0开始),'选项'是列名。这数据被赋值给变量second_row_option_content。
'''
# 读取第二行(即第三行)“选项”列的内容
second_row_option_content = df.loc[2, '选项']

# 显示第二行“选项”列的内容
print(second_row_option_content)

输出结果:

def chinese_multiple_choice_questions(questions_with_answers):
    # 输入的题目文本
    text = questions_with_answers

    # 正则表达式模式

    # 编译一个正则表达式模式,用于匹配问题文本。
    # \d+ 匹配一个或多个数字(问题编号)。
    # .*? 非贪婪匹配任意字符直到遇到下一个模式。
    # (?=\d+\.|$) 正向前瞻断言,匹配后面是数字和点或文本结尾的位置。
    # re.DOTALL 使得 '.' 匹配包括换行符在内的任意字符。

    question_pattern = re.compile(r'\d+\..*?(?=\d+\.|$)', re.DOTALL)

    # 编译一个正则表达式模式,用于匹配选择题的选项。
    # ([A-D]) 匹配一个A到D之间的字母(选项前缀)。
    # \s* 匹配任意数量的空白字符。
    # (.*?) 非贪婪匹配任意字符直到遇到下一个模式。
    # (?=[A-D]|$|\n) 正向前瞻断言,匹配后面是选项前缀或文本结尾或换行符的位置。

    choice_pattern = re.compile(r'([A-D])\s*(.*?)(?=[A-D]|$|\n)', re.DOTALL)

    # 使用question_pattern.findall方法找到所有匹配的问题文本
    questions = question_pattern.findall(text)

    # 初始化选择题和简答题列表
    multiple_choice_questions = []
    short_answer_questions = []

        # 处理每个问题,enumerate函数用于获取每个问题及其索引
    for id,question in enumerate(questions):
        # 使用search方法检查问题文本中是否包含A到D的字符,以判断是否为选择题
        if re.search(r'[A-D]', question):
             # 使用choice_pattern.findall方法找到所有匹配的选项
            choices = choice_pattern.findall(question)

            # 从问题文本中提取问题部分,这里假设问题文本在第一个'('之前
            question_text = re.split(r'\n', question.split('(')[0])[0]
            
            # 重新编译一个正则表达式模式,用于匹配问题编号和问题文本
            pattern_question = re.compile(r'(\d+)\.(.*)')

            # 使用pattern_question.findall方法提取问题编号和问题文本,并重新构建问题字符串
            matches_question = str(id+1)+'.'+ pattern_question.findall(question_text)[0][1]
            # print(str(id+1)+'.'+matches_question)
            
            # 将问题和选项作为字典添加到multiple_choice_questions列表中
            multiple_choice_questions.append({
                'question': matches_question,
                'choices': choices
            })
        else:
            # 如果问题不是选择题,则认为是简答题,将其添加到short_answer_questions列表中
            # strip方法用于移除字符串两端的空白字符
            short_answer_questions.append(question.strip())

    # 函数返回包含所有选择题的列表
    return multiple_choice_questions

正则表达式:

代码作用:定义一个函数 chinese_multiple_choice_questions,处理一个包含题目和答案的字符串,并从中提取选择题。

questions_list = []

#for循环data_id 从0开始,到df[:3]的长度(即3),df[:3]表示选取DataFrame df的前3行

for data_id in range(len(df[:3])):
    second_row_option_content = df.loc[data_id, '选项']


#预期会返回一个包含选择题信息的列表,添加到 questions_list 中
    questions_list.append(chinese_multiple_choice_questions(second_row_option_content))
def chinese_multiple_choice_answers(questions_with_answers):

#将输入的字符串 questions_with_answers 中的所有空格和换行符删除,以便进行正则表达式匹配

    questions_with_answers = questions_with_answers.replace(" ", "").replace("\n", "")
    

    # 使用正则表达式匹配答案:一个数字后面跟着一个点和一串大写字母
    choice_pattern = re.compile(r'(\d+)\.([A-Z]+)')

    # 使用正则表达式匹配答案:一个数字后面跟着一个点和非大写字母的任意字符序列
    short_pattern = re.compile(r'(\d+)\.([^A-Z]+)')

    # 找到所有匹配的答案
    choice_matches = choice_pattern.findall(questions_with_answers)
    short_matches = short_pattern.findall(questions_with_answers)

    # 将匹配结果转换为字典
    choice_answers = {int(index): answer for index, answer in choice_matches}
    short_answers = {int(index): answer for index, answer in short_matches}

    # 按序号重新排序
    sorted_choice_answers = sorted(choice_answers.items())
    sorted_short_answers = sorted(short_answers.items())
    
    answers = []

    # 输出结果,返回一个包含所有排序后的选择题答案的列表
    
    for id in range(len(sorted_choice_answers)):
        answers.append(f"{id+1}. {sorted_choice_answers[id][1]}")
    return answers
# 读取第二行(即第三行)“选项”列的内容
second_row_option_content = df.loc[60, '答案']

# 显示第二行“选项”列的内容
print(second_row_option_content)


chinese_multiple_choice_answers(second_row_option_content)

df['答案_processed'] = df['答案'].map(chinese_multiple_choice_answers)
def get_prompt_cn(text):
    prompt = f'''
    你是⼀个⾼考选择题出题专家,你出的题有⼀定深度,你将根据阅读文本,出4道单项选择题,包含题目选项,以及对应的答案,注意:不⽤给出原文,每道题由1个问题和4个选项组成,仅存在1个正确答案,请严格按照要求执行。 阅读文本主要是中文,你出的题目需要满足以下要点,紧扣文章内容且题干和答案为中文:
    
    ### 回答要求
    (1)理解文中重要概念的含义
    (2)理解文中重要句子的含意
    (3)分析论点、论据和论证方法
    
    
    ### 阅读文本
    {text}
    '''
    
    return prompt   

def process_cn(df): 
    res_input = []
    res_output = []
    for id in range(len(df)):
        data_options = df.loc[id, '选项']
        data_answers = df.loc[id,'答案']
        data_prompt = df.loc[id,'阅读文本']
        data_options = chinese_multiple_choice_questions(data_options)
        data_answers = chinese_multiple_choice_answers(data_answers)
        data_prompt = get_prompt_cn(data_prompt)
        
        if(len(data_answers)==len(data_options)):
            res = ''
            for id_,question in enumerate(data_options):
                res += f'''
{question['question']}?
                '''+'\n'
                for choise in question['choices']:
                    res = res+ choise[0] + choise[1]+ '\n'
                res = res + '答案:' + str(data_answers[id_].split('.')[-1])  + '\n'

            # 将构建好的题目和答案字符串添加到 res_output 列表
            res_output.append(res)

            # 将格式化的题目提示添加到 res_input 列表
            res_input.append(data_prompt)
        # break
    return res_input,res_output

函数 process_cn 的目的是处理一个DataFrame df,其中包含有关选择题的数据,并生成格式化的题目和答案字符串。

cn_input,cn_output = process_cn(df)

len(cn_input)

2.2.2 英语问答制作

import pandas as pd

# 读取Excel文件
df = pd.read_excel('训练集-英语.xlsx')
df = df.replace('.', '.', regex=True).replace('А.', 'A.', regex=True).replace('В.', 'B.', regex=True).replace('С.', 'C.', regex=True).replace('D.', 'D.', regex=True)
# df = df.replace('(', '(', regex=True)

# 读取第二行(即第三行)“选项”列的内容
second_row_option_content = df.loc[0, '选项']

# 显示第二行“选项”列的内容
print(second_row_option_content)

def remove_whitespace_and_newlines(input_string):
    # 使用str.replace()方法删除空格和换行符
    result = input_string.replace(" ", "").replace("\n", "").replace(".", "")
    return result
import re

# 示例文本
text = """
32. B. The underlying logic of the effect.                                                   33.D. estimates were not fully independent.
34.C. The discussion process.            35.D. Approving.
"""
def get_answers(text):
    text = remove_whitespace_and_newlines(text)
    # 正则表达式模式
    pattern = re.compile(r'(\d)\s*([A-D])')

    # 查找所有匹配项

    # 编译一个正则表达式模式,用于匹配问题编号和答案选项
    # \d 匹配数字,代表问题编号
    # \s* 匹配任意数量的空白字符
    # [A-D] 匹配大写字母A、B、C或D,代表答案选项

    matches = pattern.findall(text)
    res = []
    # 打印结果
    for match in matches:
        number_dot, first_letter = match
        res.append(first_letter)
    return res

import re

# 示例文本
text = second_row_option_content

def get_questions(text):
    text = text.replace('\n', '  ')+'  '
    # print(text)
    # 正则表达式模式
    pattern = re.compile(r'(\d+\..*?)(A\..*?\s{2})([B-D]\..*?\s{2})([B-D]\..*?\s{2})(D\..*?\s{2})', re.DOTALL)

    # 查找所有匹配项
    matches = pattern.findall(text)

    # 存储结果的字典列表
    questions_dict_list = []

    # 打印结果
    for match in matches:
        question, option1, option2, option3, option4 = match
        pattern_question = re.compile(r'(\d+)\.(.*)')
        question_text = pattern_question.findall(question.strip())[0][1]
        
        # 提取选项字母和内容
        options = {option1[0]: option1, option2[0]: option2, option3[0]: option3, option4[0]: option4}
        
        question_dict = {
            'question': question_text,
            'options': {
                'A': options.get('A', '').strip(),
                'B': options.get('B', '').strip(),
                'C': options.get('C', '').strip(),
                'D': options.get('D', '').strip()
            }
        }
        questions_dict_list.append(question_dict)
    return questions_dict_list

# 调用函数并打印结果
questions = get_questions(text)
for q in questions:
    print(q)

def get_prompt_en(text):
    prompt = f'''
    你是⼀个⾼考选择题出题专家,你出的题有⼀定深度,你将根据阅读文本,出4道单项选择题,包含题目选项,以及对应的答案,注意:不⽤给出原文,每道题由1个问题和4个选项组成,仅存在1个正确答案,请严格按照要求执行。
The reading text is mainly in English. The questions and answers you raised need to be completed in English for at least the following points:
    
    ### 回答要求
    (1)Understanding the main idea of the main idea.
    (2)Understand the specific information in the text.
    (3)infering the meaning of words and phrases from the context
    
    
    ### 阅读文本
    {text}
    '''
    
    return prompt  
def process_en(df): 
    res_input = []
    res_output = []
    for id in range(len(df)):
        data_options = df.loc[id, '选项']
        data_answers = df.loc[id,'答案']
        data_prompt = df.loc[id,'阅读文本']
        data_options = get_questions(data_options)
        data_answers = get_answers(data_answers)
        data_prompt = get_prompt_en(data_prompt)
        # print(data_options)
        # print(data_answers)

        if(len(data_answers)==len(data_options)):
            res = ''
            for id,question in enumerate(data_options):
                res += f'''
                {id+1}.{question['question']}
                {question['options']['A']}
                {question['options']['B']}
                {question['options']['C']}
                {question['options']['D']}
                answer:{data_answers[id]}
                '''+'\n'
            res_output.append(res)
            res_input.append(data_prompt)
    return res_input,res_output
    # break
en_input,en_output = process_en(df)
# 将两个列表转换为DataFrame
df_new = pd.DataFrame({'input': cn_input+cn_input[:30]+en_input+en_input[:20], 'output': cn_output+cn_output[:30]+en_output+en_output[:20]})

df_new

import json

'''
使用 with 语句打开一个名为 'output.jsonl' 的文件用于写入('w' 模式),
并指定文件编码为 utf-8

with 语句可以确保文件在使用后正确关闭
'''

# 打开一个文件用于写入 JSONL,并设置编码为 UTF-8
with open('output.jsonl', 'w', encoding='utf-8') as f:
    # 遍历每一行并将其转换为 JSON
    for index, row in df_new.iterrows():
        row_dict = row.to_dict()

'''
使用 json.dumps() 函数将字典 row_dict 转换为JSON格式的字符串。
ensure_ascii=False 参数指示 json.dumps() 允许非ASCII字符输出,
这样能够保持原始的Unicode字符
'''
        row_json = json.dumps(row_dict, ensure_ascii=False,)
        # 将 JSON 字符串写入文件,并添加换行符
        f.write(row_json + '\n')

# 打印确认信息
print("JSONL 文件已生成")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值