大模型基础:PT预训练,SFT有监督微调 基础知识

发布时间:2024年01月18日

大模型基础:PT预训练,SFT有监督微调 基础知识

关系如图:

在这里插入图片描述

一、入门概念

基础概念:

  • Token:在NLP中,一个“token”可以是一个词、一个字或一个标点符号。例如,句子“我爱北京”被切分成三个tokens: “我”, “爱” 和 “北京”。

  • Prediction:预测是指根据模型的当前输入,猜测接下来应该出现的token是什么。

训练:

  • 在训练过程中,模型通过大量的文本数据来学习文本之间的模式和结构。

  • 例如,模型会看到成千上万次的“我爱X”这样的模式,其中X可以是各种不同的词。通过这样的训练,模型会学会哪些词最有可能出现在“我爱”之后。

二、PT预训练

????????要理解清楚这一训练过程,最主要的就是搞清楚预训练的数据怎么构造数据怎么喂给模型模型输出的是什么,以及如何计算loss

????????这里通过一个完整的例子来介绍一下这个过程,假设现在有一个用来预训练的数据集

你知道什么是微调吗?

假设经过分词后

你:3
知道:5
什么:7
是:2
微调:9
吗:4
?:1

????????原来的数据变为如下序列,后面补了三个0(假设我们希望最大序列长度是10)

3 5 7 2 9 4 1 0 0 0 

????????预测下一个token就类似于3预测5,35预测7,以此类推,但是如果这样拆成很多个数据段其实比较低效,因此就可以考虑移位来构造数据,即

  • 模型输入X为:3 5 7 2 9 4 1 0 0 0
  • 模型输出targets为:5 7 2 9 4 1 0 0 0 0

???????? 这样就可以一次性把整条序列喂给模型,计算一次就包含了6个预测下一个token的损失了。注意这里模型的设计是有讲究的,我们不能让输入看到后面的词(如果看得到的话就没必要进行预测了),也就是“你”在模型内看不到“知道”,“你 知道”在模型内看不到“什么”,这个可以通过注意力机制实现,不是本文的关注点,这里就不展开了。

???????? 现在模型的输入的维度为(1,10),第一维为batch_size,然后经过embedding层后变为(1,10,768),这里假设embedding的维度为768。

???????? 记住进入transfomer前后数据的维度不会发生变化,把transfomer当作一个黑盒,也就是transformer(X)的维度还是(1,10,768),接下来就是基于它来进行预测了,因为要预测哪个词,词的可能情况就是词表的大小,所以做的就是一个分类任务,预测下一个token是词表中的哪一个(词表中的每一个词当作一个类别)。

???????? 为了完成分类任务,需要对transformer的输出做一个映射,映射到跟词表一样大,也就需要定义这样一个线性变换

output_layer = nn.Linear(768, vocab_size, bias=False)

然后logits=output_layer(transformer(X))的维度就是(1,10,vocab_size),接下来就可以计算loss了,具体来说就是计算logits(模型预测)与targets(真实标签)之间的交叉熵损失,同时忽略了填充值对应的损失。

loss = F.cross_entropy(logits.view(-1, logits.size(-1)), targets.view(-1), ignore_index=0)

三、有监督微调Supervised fine-tuning (SFT)

?????? “有监督微调”意味着使用有标签的数据来调整一个已预训练好的语言模型(LLM),使其更适应某一特定任务
??????通常LLM的预训练是无监督的,但微调过程往往是有监督的

?????? 当进行有监督微调时,模型权重会根据与真实标签的差异进行调整。通过这个微调过程,模型能够捕捉到标签数据中特定于某一任务的模式和特点。使得模型更加精确,更好地适应某一特定任务。

???????? 以一个简单的例子来说,你有一个已经预训练好的LLM。当输入“我不能登录我的账号,我该怎么办?”时,它可能简单地回答:“尝试使用‘忘记密码’功能来重置你的密码。”
在这里插入图片描述
???????? 这个回答很直接,适用于一般问题,但如果是客服场景,可能就不太合适了。一个好的客服回答应该更有同情心,并且可能不会这么直接,甚至可能包含联系信息或其他细节。这时候,有监督微调就显得非常重要了。

在这里插入图片描述
????????经过有监督微调后,你的模型可以提供更加符合特定指导原则的答案。例如,经过一系列专业的培训示例后,你的模型可以更有同情心地回答客服问题。


????????接下来我们还是从数据到模型输出,计算loss的步骤来看看SFT的实现原理。

????????首先还是来看看数据怎么构造,SFT的每一条样本一般由两部分组成,也就是prompt(instruction)+ answer,比如:

prompt: 翻译以下句子: What is pretrain
answer: 什么是预训练

????????也就是我们要给模型提供一些类似于问答形式的答案来学习,有了前面预训练的经验后,SFT其实就很好理解的,它本质上也在做next token prediction,只是我们更希望模型关注answer部分的预测,这可以通过生成一个mask向量来屏蔽不希望计算loss的部分,下面就是数据构造的一个示意:做的事情就是拼接prompt和answer,并在answer两侧添加一个开始和结束的符号,算一下prompt/instruction的长度,以及后面需要pad的长度,然后生成一个mask向量,answer部分为1,其他部分为0。

input_id=prompt+[bos]+answer+[eos]
context_length = input_id.index(bos)
mask_position = context_length - 1
pad_len = max_length - len(input_id)
input_id = input_id + [pad] * pad_len
loss_mask = [0]*context_length+[1]*(len(input_id[mask_position+1:])) + [0]*pad_len

????????构造好输入后,token转为embedding,经过transformer的过程跟之前预训练完全一样,也就是我们又得到了一个维度是(1,10,vocab_size)的输出logits=output_layer(transformer(X)),进一步就可以计算answer部分的loss了,其实就是通过mask把不希望考虑的地方乘以0,保留answer部分loss。

loss_mask = loss_mask.view(-1)
loss = torch.sum(loss*loss_mask)/loss_mask.s

有了loss,进行反向传播更新模型参数就OK。

Q&A

Q:预训练的数据是纯文本吧?模型输出应该和什么去对比计算这个loss?纯文本就没有一个类似于sft的output/answer的标签吧?这个时候target是啥呢?
A:就是下一个词预测,和下一个词去计算loss

Q:词表的大小就是语料库大小吧
A:不是的,是分词器的token总数

Q:会不会生成和 标准答案长度不一样的 答案呢?这样的画怎么计算loss?
A:逐个token生成和计算的哈;训练是逐个token预测的。 推理没有长度限制

Q:SFT时,question部分也是预测出来的?如果预测的结果与input不一致怎么办?我理解question部分应该直接用input去提取特征,然后去预测answer部分。
A:不一致是正常的,不计算loss即可,包括answer也是不一致的,但是一定会计算loss;
A:会预测,不一定需要计算loss,业界做法有的会计算loss有的不会

Q:请问SFT样本的prompt可以是图片+文本的形式吗
A:可以的,可以接一个图像encoder,然后把图像encoder的输出拼在文本后面

Q:请问LLM训练过程中,如果因为设置的max_len过大导致padding过多,会有什么影响吗
A:不会计算loss就不影响,只是浪费计算,Padding不参与计算;Padding不会计算loss。

文章来源:https://blog.csdn.net/weixin_43431218/article/details/135670595
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。