【学习笔记】ChatGPT原理与应用开发——基础科普
HuggingLLM(ChatGPT原理与应用开发)
原文链接:HuggingLLM(ChatGPT原理与应用开发)-课程详情 | Datawhale
此处仅为学习记录和总结
1:基础科普
1.1:自然语言背景
图灵测试
如果一个人(代号C)使用测试对象皆理解的语言去询问两个他不能看见的对象任意一串问题,其中一个是正常思维的人(代号B),另一个是机器(代号A)。
如果经过若干询问以后,C不能得出实质的区别来分辨A与B的不同,则此机器A通过图灵测试。
1.2:语言模型基础
Token是最小语义单位,即句子由token组成
获取token的方式
🤔英文单词被分割为子词,例如:
annoyingly
=>
["annoying", "##ly"]
##
表示和前一个token直接拼接,没有空格
子词可以同时兼顾词表大小和语义表示
🤔中文被分割为字 + 词
字:独立表示意义(例如:是、有)
词:一个以上字组成的语义单位,拆开可能会丢失语义(例如:长城)
词袋模型
bag of words,BOW
🤔词袋的原理
- 文本中的每个单词都看作是独立的,忽略单词之间的顺序和语法,只关注单词出现的次数
- 每个句子可以表示为一个向量(长度为词表大小),向量的每个维度对应一个单词,维度的值表示该单词在句子中出现的次数
🤔词表表示法的问题
- 向量维度大且稀疏,计算不便
- 忽略了token之间的顺序,丢失语义
词向量
word embedding / word vector
一个token表示成一定数量个的小数(即词向量的维度),例如:
我 [0.07928, 0.37101, 0.94462, 0.87359, 0.55773, 0.13289, 0.22909, ...]
爱 [0.61048, 0.46032, 0.7194, 0.85409, 0.67275, 0.31967, 0.89993, ...]
你 [0.392, 0.13321, 0.00597, 0.74754, 0.45524, 0.23674, 0.7825, ...]
词向量的维度常用:200、300、768、1536等
Embedding技术
将任意文本(或其他非文本符号)表示成稠密向量的方法
概率语言模型
核心:预测下一个token的概率
🤔解码策略
- 贪心搜索(greedy search):只往后看一个词,只考虑下一步最大概率的词
- 集束搜索(beam search):一步多看几个词,看最终句子(生成到句号、感叹号或其他停止符号)的概率。看的越多(num_beams越大),越不容易生成固定的文本
N-Gram语言模型
N表示每次用到的上下文token个数
N=2是Bi-Gram,N=3是Tri-Gram,例如:
句子:人工智能让世界变得更美好
tokens:人工智能/让/世界/变得/更/美好
N=2:人工智能/让,让/世界,世界/变得,变得/更,更/美好
N=3:人工智能/让/世界,让/世界/变得,世界/变得/更,变得/更/美好
token的表示是离散的,本质是词表中的每个单词
Gram次数除以Gram总数,就是出现概率
在给定很多语料的情况下,固定当前词,统计下个词出现的频率,例如:
当前词:人工智能
N=2时,统计可能的tokens组合
(1)人工智能/让:8次
(2)人工智能/是:2次
计算概率
(1)人工智能/让:0.8
(2)人工智能/是:0.2
将token转变为embedding向量
输入:token对应的d维向量X
(1 × d维)
输出:词表大小的N维向量Y
(1 × N维)
计算过程:假设W
(d × N维)是模型参数,则X · W = Y
例如:
import torch
import torch.nn as nn
rnn = nn.RNN(32, 64)
input = torch.randn(4, 32)
h0 = torch.randn(1, 64)
# input是包含4个token,每个token是32维
# h0是随机的初始化输出
output, hn = rnn(input, h0)
# ouput包含4个token,每个token是64维
# hn是最后一个token的输出
output.shape, hn.shape
# (torch.Size([4, 64]), torch.Size([1, 64]))
# 假设词表大小N=1000
wo = torch.randn(64, 1000)
# 得到4×1000的概率矩阵,每一行概率和为1
probs = nn.Softmax(dim=1)(output @ wo)
probs.shape, probs.sum(dim=1)
# torch.Size([4, 1000]), tensor([1.0000, 1.0000, 1.0000, 1.0000], grad_fn=<SumBackward1>)
1.3:ChatGPT原理基础
transformer
基于注意力机制的编码器-解码器(encoder-decoder架构)
- 编码器:同时利用当前token前后的所有tokens(看历史+未来)
- 解码器:只能利用当前token之前的所有tokens(只看历史)
Seq2Seq(sequence to sequence)架构
- 输入是一个文本序列,输出是另一个文本序列
注意力机制
- 自注意力:自己的每一个token和自己的每一个token的重要性权重
- 多头注意力:自己注意自己重复多次,每个头注意到的信息不同(根据不同权重的注意力提取特征)
- 遮盖多头注意力:遮盖掉未来的所有token,即只看历史
编码器更加适合非生成类任务,解码器则更加适合生成类任务
- 编码器对应自然语言理解(natural language understanding,NLU)
- 句子级别分类:给定一个句子,输出一个类别
- token级别分类:给定一个句子,要给其中每个token输出一个类别
- 解码器对应自然语言生成(natural language generation,NLG)
- 文本续写
- 生成式文本摘要
- 机器翻译
- 改写纠错
命名实体识别
NLU任务中的token级别分类
作用:把句子中的实体(人名、地名、作品等你关注的词,一般是名词)给提取出来
地名实体识别,例如:
句子:中国的首都是北京
tokens:每个字,即:中/国/的/首/都/是/北/京
token对应的类别:Begin/End/Others/Others/Others/Others/Begin/End
深度学习模型的微调
把一个开源的预训练模型,放在特定的数据集上微调,让模型能够完成特定的任务
BERT
bidirectional encoder representations from transformers
只使用transformer的编码器
步骤:
- 随机把15%的token盖住(其中80%用
[MASK]
替换,10%保持不变,10%随机替换为其他token) - 利用其他没盖住的token来预测盖住位置的Token
GPT
generative pre-trained transformer
只使用transformer的解码器
🤔GPT的2个特点
- 生成式:一个Token接着一个Token生成文本
- 预训练:在大量语料上训练的语言模型
🤔GPT的发展方向
- 扩大参数规模
- 零样本
样本训练方法
零样本(Zero-shot):直接给模型任务输入让它输出任务结果
少样本(Few-shot):给模型提供一些示例,然后再给出任务,让它给出输出结果
单样本(One-shot):给模型提供一个示例,然后再给出任务,让它给出输出结果
温度(temperature)
🤔集束搜索存在的问题
- 生成的内容容易重复
- 高质量的文本和高概率并不一定相关
🤔温度的作用
- 在多样性生成中,基于已有的上下文随机选择下一个token,温度用于控制这个选择的随机性,即调整输出的概率分布
- 温度越大,输出的概率分布越平滑,高概率词和低概率词的差距越小
- 温度趋近于0,则等价于贪心搜索
重复惩罚参数(repetition_penalty)
重复惩罚参数的作用:避免生成重复的token
🤔温度和重复惩罚参数的区别
- 温度的对象是词表中的所有的token
- 重复惩罚参数的对象是“已生成”的token
- 在生成下个token时,对之前已经生成过的tokens的分数进行平滑
基于采样的方法(选择下一个token)
Top-K:在概率降序排序的情况下,选择K个词(硬截断)
Top-P:在累计概率超过P的词里进行选择
随机采样:基于已有的上下文随机选择
RLHF
Reinforcement Learning from Human Feedback(从人类反馈中进行强化学习)
🚀InstructGPT:用强化学习的算法微调一个根据人类反馈改进的语言模型
🤔Instruct GPT的步骤
- SFT,Supervised Fine-Tuning,有监督微调
- 在有标注的数据上微调训练
- 有标注的数据:输入提示词,输出相应的回复
- RM,Reward Model,奖励模型
- 一个提示词丢给SFT,输出若干个回复,人工对这些回复进行排序
- 每次取排序后的2个结果,让模型学习到好坏评价
- RL,Reinforcement Learning,强化学习
- 使用PPO策略进行训练
- PPO,Proximal Policy Optimization,近端策略优化
- 避免每次太大的更新,提高训练的稳定性
- RM对某个回复打分后,这个打分回传给模型更新参数
- 需要考虑每个token的输出和第一步SFT输出之间的差异性,防止强化学习的过度优化
- 使用PPO策略进行训练
🤔强化学习在文本生成工作的难点
- 训练的稳定性
- 解决方法:PPO策略和与SFT的差异衡量
- 奖励函数的设计
- 解决方法:加入一些语法规则限制,采用最省力法则(语言具有惰性,会朝着使用较少的词语表达尽可能多的语义这个方向进行演化)
🤔Instruct GPT的通用指标
- 有帮助
- 真实性
- 无害性
- 需要解决指标之间的冲突权衡问题