Datawhale AI夏令营第四期大模型技术(微调)方向 task02初学者笔记

一、基础概念介绍:
1、大模型技术:

<1>定义:
大模型是指具有数千万甚至数亿参数的深度学习模型。这些模型通常由深度神经网络构建而成,拥有数十亿甚至数千亿个参数,旨在提高模型的表达能力和预测性能,以处理更加复杂的任务和数据。

<2>特点:
参数规模大:大模型包含数十亿甚至千亿级别的参数,能够捕捉到数据中的深层次特征。

训练数据量大:大模型通常在数百GB甚至TB级别的数据上进行预训练,以提高模型的泛化能力。

计算资源需求高:大模型的训练过程需要大量的计算资源,如GPU、TPU等,且训练时间可能长达数周或数月。

泛化能力强:由于在大规模数据集上进行训练,大模型能够在未见过的数据上表现出色,具有较强的泛化能力。

多任务学习:大模型通常会一起学习多种不同的任务,如机器翻译、文本摘要、问答系统等,从而学习到更广泛和泛化的知识。

<3>分类:
自然语言处理(NLP)大模型:
如GPT、BERT等,用于处理文本数据和理解自然语言。

计算机视觉(CV)大模型:如Transformer在计算机视觉领域的应用,用于图像处理和分析。

多模态大模型:能够处理多种不同类型的数据,如文本、图像、音频等,如CLIP、DALL-E等。

2、大语言模型微调:

<1>定义:
大语言模型微调(Fine-tuning)是一种在已经预训练好的大型语言模型基础上,使用特定数据集进行进一步训练的技术,旨在使模型适应特定任务或领域。

<2>优势:
任务特定性能提升:预训练语言模型虽然具备广泛的语言理解和生成能力,但在特定任务上的表现可能并不理想。通过微调,模型可以进一步学习任务相关的特征和模式,从而提高性能。

领域适应性:不同领域的数据具有独特的术语、结构和语义。通过在特定领域的数据集上进行微调,模型可以更好地适应该领域的特殊需求。

数据稀缺性:某些任务可能面临数据稀缺的问题。微调可以利用有限的标签数据来训练模型,从而在数据有限的情况下取得较好的性能。

防止过拟合:在监督微调过程中,通过使用有标签数据进行训练,可以减少模型在特定任务上的过拟合风险。

成本效益:与从头开始训练新模型相比,微调可以节省大量时间和资源,并快速迁移到新任务上。

<3>步骤:
选择合适的基座模型:根据任务需求和资源情况选择合适的预训练模型作为基座模型。

准备高质量数据集:收集并标注与任务相关的数据集,确保数据的质量和多样性。

配置模型训练:设置合适的训练参数和配置,如学习率、批处理大小、训练轮次等。

进行微调训练:在特定任务的数据集上对基座模型进行微调训练。

评估模型性能:使用验证集评估微调后模型的性能,并根据需要进行调整和优化。

3、LoRa:
<1> 定义:
LoRA(Low-Rank Adaptation of Large Language Models)是一种针对大型语言模型(如GPT系列)的微调技术,旨在通过引入低秩(Low-Rank)矩阵来高效地调整预训练模型,以适应特定的任务或数据集,同时保持较低的计算成本和参数增加量。

<2>特点:
高效性:LoRA通过只更新预训练模型中的一小部分参数(即低秩矩阵),而不是全部参数,从而大大减少了计算量和存储需求。这使得在资源受限的环境下也能有效地对大型语言模型进行微调。

灵活性:LoRA允许用户针对不同的任务或数据集快速训练多个不同的低秩矩阵,这些矩阵可以独立存储和切换,从而实现模型的快速适应和多样化。

可迁移性:由于LoRA只修改了模型的一小部分参数,因此这些修改后的参数(即低秩矩阵)可以很容易地迁移到其他预训练模型上,而无需重新训练整个模型。

二、代码分析:
1、环境准备:
相关库的下载与安装:

!pip install pandas openpyxl

数据加载与抽取;

2、数据处理(以语文为例):
<1>数据加载:

# coding~

import pandas as pd
import re

# 读取Excel文件
df = pd.read_excel('训练集-语文.xlsx')
df = df.replace('.', '.', regex=True)
df = df.replace('(', '(', regex=True)

# 读取第二行(即第三行)“选项”列的内容
# 可以使用loc获取某行的数据
second_row_option_content = df.loc[2, '选项']

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

这里我们使用pandas加载xlsx中的数据,这里面我们使用全局匹配,将训练集中的中文点与左侧括号匹配为英文类型。

<2>抽取问题:

这里主要是为了抽取题目及答案,并且过滤简答题。大家可以阅读详细的注释理解问题抽取的函数如何工作。

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

    
    question_pattern = re.compile(r'\d+\..*?(?=\d+\.|$)', re.DOTALL)
    # 这一行作用是匹配一个以数字开头、后面跟着一个点字符的字符串,
    #。直到遇到下一个数字和点字符或字符串结束。
    choice_pattern = re.compile(r'([A-D])\s*(.*?)(?=[A-D]|$|\n)', re.DOTALL)
    # 这一行作用是匹配一个以字母[A到D]开头、后面跟着一个点字符的字符串,
    #直到遇到下一个[A到D]或字符串结束。
    
    
    # 找到所有问题
    questions = question_pattern.findall(text)

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

        # 处理每个问题
    for id,question in enumerate(questions):
        # 这里取到的question,如果是选择题会带着选择题的选项。
        # 检查是否是选择题 因为选择题内有ABCD这样的选项
        if re.search(r'[A-D]', question):
            # 如果有选项,提取出选项的内容
            choices = choice_pattern.findall(question)
            # 这里提取了题目的内容,因为每个题目都会有一个打分的(X分)这样的标记
            # 以左括号为目标,截取选择题选项中的内容
            question_text = re.split(r'\n', question.split('(')[0])[0]
            
            
            pattern_question = re.compile(r'(\d+)\.(.*)')
            # 这里清洗了选择题的编号,重新用循环中的id进行编号。
            # 如果不做这一步可以发现给定的数据中编号是乱序的。
            matches_question = str(id+1)+'.'+ pattern_question.findall(question_text)[0][1] # 取出问题后重排序
            # print(str(id+1)+'.'+matches_question)
            
            # 这里我们实现声明好了存储的列表
            # 将每个问题和选项以字典的形式存入方便我们处理
            multiple_choice_questions.append({
                'question': matches_question,
                'choices': choices
            })
        else:
            # 大家可以想想这里怎么用?
            short_answer_questions.append(question.strip())
    # 最后我们返回抽取后的选择题字典列表
    return multiple_choice_questions

<3>抽取问题的结果:
这里我们抽取刚才我们拿到的选择题的答案部分。

def chinese_multiple_choice_answers(questions_with_answers):
   # 首先清洗输入字段,因为答案字段中的格式不统一,清洗后便于统一处理。
   # 这里删除了所有的换行和空格
    questions_with_answers = questions_with_answers.replace(" ", "").replace("\n", "")
    
    # print(questions_with_answers)
    # 使用正则表达式匹配答案
    # 这里我们主要使用第一个匹配 一个数字+点+字母ABCD之间一个
    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 = []

    # 输出结果
    
    # print("选择题答案:")
    for id in range(len(sorted_choice_answers)):
    # 这里我们也将重新编号号的答案作为返回,返回的是一个列表,方便与问题字典列表匹配~
        answers.append(f"{id+1}. {sorted_choice_answers[id][1]}")
    return answers

<4>prompt设计:

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

<5>中文数据处理主函数:

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)
        # 抽取阅读材料组合成input内容
        data_prompt = get_prompt_cn(data_prompt)
        # print(data_options)
        # print(data_answers)
        # 做数据验证,因为训练数据格式不能确定每组数据都能被正常处理(会有一部分处理失败)
        # 我们验证一下两个列表的长度 如果相同代表数据处理正确
        if(len(data_answers)==len(data_options)):
            # 定义output的数据字符串
            res = ''
            # 处理选择题目中的每个数据,逐个拼入到output字符串
            for id_,question in enumerate(data_options):
            # 首先放入题目
                res += f'''
{question['question']}?
                '''+'\n'
                # 然后找到选择题的每个选项,进行choices列表循环
                for choise in question['choices']:
                # 逐个将选项拼接到字符串
                    res = res+ choise[0] + choise[1]+ '\n'
                #  最后将答案拼接到每个选择题的最后
                # 以 答案:题号.选项的格式
                res = res + '答案:' + str(data_answers[id_].split('.')[-1])  + '\n'
            # 最后将处理得到的input、output数据存入到列表
            res_output.append(res)
            res_input.append(data_prompt)
        # break
    return res_input,res_output
    



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值