微调的方式总体上有2种:
1,使用 指定任务类型的微调脚本 预训练模型,然后带有输出头的预定义网络输出结果。
2,直接加载 预训练模型进行输入文本的特征表示,后接自定义网络进行微调输出结果。
LoRA:
通过低秩分解来模拟参数的改变量,从而以极小的参数量来实现大模型的间接训练。
LoRA思路:
在原模型旁边增加一个旁路,通过低秩分解(先降维后升维)来模拟参数的更新量。
训练时,原模型固定,只训练降维矩阵A和升维矩阵B
推理时,可将BA加到原参数上,不引入额外的推理延迟。
初始化时,A采用高斯分布初始化,B初始化全为0,保证训练开始时旁路为0矩阵
可插拔式的切换任务,当前任务W0+B1A1,将lora部分减掉,换成B2A2,即可实现任务切换。
QLoRA使用量化思想对LoRA进行优化的量化算法,可以显著降低 训练所需的 显存资源。
三个优点:
定义4位标准浮点数量化(Normal Float 4-bit, NF4),结合分位数量化和分块量化,解决参数极大极小异常值;提高并行化。
双重量化:
保存时模型量化为4bit;
双量化时对量化常数再做一次8bit的量化
分页优化器:显存过高时,用一部分内存代替显存;梯度检查点是折中方案,保存了部分激活值,减少了缓存占用,却增加了计算量,减缓了训练速度。
为什么进行PEFT微调?
全参数微调代价太大,
显存占用主要是:【模型权重】、【优化器状态】、【梯度】、【激活状态】。
PEFT:在LoRA的基础上,通过最小化微调参数的数量和计算复杂度,来提高预训练模型在新任务的性能,从而缓解大型预训练模型的训练成本。
PEFT中Adapter-tuning适配器微调:
适配器微调思路:
设计了Adapter结构:首先是一个down-project层将高维度特征映射到低维特征,然后过一个非线性层之后,再用一个up-project结构将低纬度特征映射回原来的高维特征;同时也设计了skip- connection结构,确保了在最差的情况下能够退化为Identity,并将其嵌入Transformer的结构里面。
在训练时,固定住原来预训练模型的参数不变,只对新增的Adapter结构进行微调,同时保证训练的高效。
特点:
通过在Transformer层中嵌入Adapter结构,在推理时会额外增加推理时长。
AdapterFusion思路:
一种融合多任务信息的Adapter变体,在Adapter基础上进行优化,通过将学习过程分为两阶段来提升下游任务表现。
AdapterDrop思路:
在不影响任务性能的情况下,对Adapter动态高效的移除,尽可能减少模型的参数量,提高模型在训练阶段BP传播和推理阶段正向传播时的效率。
PEFT中的prompt tuning:
原理:给每个任务定义各自的prompt,拼接到数据上作为输入,但只在输入层嵌入prompt-token。
PEFT中的P- tuning思路:
可学习的Embedding层设计:将Prompt转换 为 可学习的Embedding层。
与Prefix- tuning区别:只在输入层加,不一定在前面加,可在任意位置加。
Prompt encoder设计:用prompt encoder(由一个双向的LSTM + 两层MLP组成)的方式对prompt embedding进行表征处理(只在输入层),建模 伪token的相互依赖,后面只对伪token进行训练。
PEFT中p- tuning v2原理:是prefix-tuning的改进
每层都加前缀伪token、
移除权重参数化编码器、
更多可学习参数、
不同任务提示长度不同、
引入多任务、
LoRA和P-Tuning v2的对比:
相同点: 都是冻结大模型参数、通过小模块来学习微调产生的低秩改变。
存在问题:两种训练方式都很容易产生 参数灾难性遗忘【整个模型层参数未改变、而少参数的学习模块微调时却是变量巨大】
——————————————————————
高级微调方法:
1,基于加速库Accelerator的全量数据微调
2,基于LoRA的模型微调。
3,基于HuggingFace的PEFT模型微调
大模型典型推理加速框架举例:VLLM
1,写时复制机制,要修改时才会复制块副本。
2,pagedattention机制,LLM推理阶段是逐词生成,串行速率很慢。为了提高吞吐,将多个请求作为一个批次处理,但不同的输入输出字符长度不同会导致内存浪费。pagedAttention的核心就是一张表【block table】,采用了一种类似“见缝插针”+“门牌索引”的方式,灰度去每一个批次请求的字符个数,并从内存中找到有闲置的地址存放并记录地址,这样就省去了寻找一整块连续存储空间的问题。
大模型训练显存主要由 【模型参数】+【梯度】+【优化器状态】+【中间激活值】4部分组成。
模型:Parameters权重参数(half)2字节、Gradient梯度参数(half)2字节
对于Adam优化器状态:weight(FP32-4字节)、m(存储梯度的移动的平均值)、v(存储梯度的平方);
激活值:forward中保存,用于反向传播
大模型推理显存主要由模型参数和KV cache组成,推理性能最大瓶颈在于【显存】。KV-Cache占用的显存是模型参数显存的0.5x。
关于梯度的两种显存优化方式:
梯度累积:
将多个小批量数据的梯度累积起来,然后一次性更新模型参数。
对每个小批量数据,计算其梯度,并将这些梯度累积在一起,当累积的梯度达到一定数量(累积步数),才执行一次参数更新操作。
累积过程不会占用额外的内存空间、大批量数据可能包含更全面丰富的信息可以减少梯度方差、通过设置累积步数可以控制参数更新的频率。
梯度检查点(Gradient Checkpointing):
是一种优化深度学习模型训练中内存使用的技术。在BP过程中,只需计算从检查点到当前节点的梯度,大大减少了内存需求。
通过在模型的计算图中插入检查点,将一部分计算推迟到后续步骤进行,从而减少内存占用。使用大批量数据进行训练可以加速收敛速度和稳定性,梯度检查点允许在大批量训练中有效地使用内存。可以控制内存开销。
分布式训练: 数据并行、型并行、算子并行、混合并行等
大模型微调:全参微调、低参微调、指令微调等,例如PEFT(添加Adapter模型、LORA(旁支A+B参数矩阵)、prompt- tuning添加前缀伪token)
LLM节省内存的方式:
参数共享、梯度累积、梯度裁剪、分布式训练、量化、裁剪、蒸馏、分块处理、
GPU显存共分6大类:全局内存、本地内存、共享内存、寄存器、常量内存、纹理内存。
全局内存:所有内存都可以访问,大约80G,
本地内存:只能当前线程可以访问。
全局内存和本地内存 属于 HBM 高宽带内存。
共享内存:只有在同一个GPU上的线程块内的线程可以访问。
寄存器:仅限 同一个 线程内 可以访问
共享内存(sRAM)和寄存器 位于 GPU芯片上。
模型剪枝:删除不重要的权重参数;
模型量化:减少存储权重的bit位数,将权重存储在更小空间。
大模型推理时,按照可生成最大序列长度分配显存,会造成三种类型的浪费:
1,预分配,但不会用到; 2,预分配,但尚未用到; 3,显存之间的间隔碎片,不足以预分配给下一个文本生成。
模型评估:
分类任务的常用指标:准确率、精确率、召回率、F1分数、ROC曲线AUC值、FR曲线-AP值;
回归任务中常用评估指标:MSE均方误差和平均绝对误差MAE。
AUC 是基于二分类问题的性能指标,只能用来评价二分类,非常适合评价样本不均衡中的分类器性能。
ROC曲线是一种评估分类模型性能的工具。它通过绘制真阳率TPR和假阳率FPR之间的关系,显示了在不同阈值下分类器的性能,曲线下面积AUC越大,模型性能越好。
————————————————————————
大模型训练分为:
预训练阶段 -> 微调阶段【SFT监督微调 -> RM奖励模型训练 -> RL增强学习微调】
LLM模型构建流程:
预训练阶段、对齐阶段:SFT + RLHF
LLM推理由两个阶段组成:
预填充:模型处理上下文,计算它们的embedding。
解码:模型根据输入上下文和所有先前生成的token逐个生成token。
大模型LLM在进行SFT操作的时候,在学习什么?
预训练:在大量无监督数据上进行预训练,得到基础模型,将预训练模型作为SFT和RLHF的起点。
SFT:在有监督的数据集上进行SFT训练,利用上下文信息等监督信号进一步优化模型,将SFT训练后的模型作为RLHF的起点。
RLHF:利用人类反馈进行强化学习,优化模型以更好地适应人类意图和偏好,将RLHF训练后的模型进行评估和验证,并进行必要的调整。
SFT训练的交叉熵损失 仅会增加标签对应的token的概率,不会降低生成 不期望回答的概率(只会提高正反馈概率,不会降低负反馈概率)
PPO主要涉及4个模型:
Actor Model & Critic Model:在强化阶段参与训练,参数要更新
Reward Model & ReferenceModel 不参与训练,参数冻结。
DPO不包含RM和RL过程,直接通过偏好数据 进行微调,将强化学习过程直接转换为SFT过程,训练过程相对简单,主要的改进之处体现 在损失函数
Pretrain预训练阶段收集知识数据集--->SFT是通过Promot- Response进行微调--->RLHF阶段【SFT微调语言模型对一个Prompt可能会生成几个Response,然后训练RM奖励模型对这几个Response进行打分排序然后进行RL强化学习,RL通过奖励模型对语言模型对行为进行奖励或者惩罚的概率增大或抑制】
RLHF是一种用于训练语言模型的方法,通过人类的反馈来改进模型的生成行为。
工作流程如下:
1,数据收集:收集人类提供的反馈数据,包括选择和拒绝 不同样本的偏好对。这些样本是语言模型生成的文本或与之相关的上下文;
2,偏好模型训练:使用收集到的偏好对数据来训练一个偏好模型。偏好模型的目标是判断给定样本的优劣,即确定哪些样本更符合人类的偏好。训练偏好模型可以使用监督学习或其他适合的机器学习算法。
3,强化学习:将训练好的偏好模型与语言模型结合,使用强化学习方法来调整语言模型的参数。在这个过程中,模型根据偏好模型的评估结果,通过增强或抑制生成不同样本的概率分布,以改善生成的文本质量和符合人类偏好的程度。
4,迭代训练:通过多次迭代训练,不断优化偏好模型和语言模型的性能。每次迭代都可以使用更多的反馈数据和更复杂的训练技术来提高模型的表现。
通过RLHF,语言模型可以从人类的反馈中学习到更好的生成策略,以提供更符合用户期望和需求的文本输出。
# RLHF中PPO分为采样---反馈---学习
for k in range(20000):
#采样(生成答案)
prompts = sample_prompt()
data = respond(policy_model, prompts)
#反馈 计算奖励
rewards = reward_func(reward_model, data)
#学习 更新参数
for epoch in range(4):
policy_model = train(policy_model, prompts, data, rewards)
————————————
为何选择的大模型大部分是Decoder only结构?
因为decoder-only结构模型在没有任何微调数据的情况下,zero-shot表现能力最好。而encoder- decoder则需要在一定量的标注数据上做Multi Task- Fine Tuning多任务微调才能激发最佳性能。Encoder-Decoder模型架构能够在某些场景下表现更好,大概是因为它多了一倍参数。所以在同等参数量、同等推理成本下,Decoder-Only架构是最优的选择。
文本生成评估指标:
BLUE用于评估模型生成的翻译句子和参考翻译句子之间差异的指标。BLUE的核心思想就是衡量 机器翻译 产生的译文 和 参考翻译之间的匹配程度,机器翻译越接近专业人翻译质量越高。使用了n-gram规则。
————————————
LlamaIndex的重点是在Index上,也就是通过各种方式为文本建立索引,有通过LLM的,也有很多并非和LLM相关的。
LlamaIndex是一个用于构建上下文增强LLM应用的框架,一个很大的优势是能够创建层次化的索引,在这个语料库增长到一定大小时非常有帮助;
LangChain的重点在Agent和Chain上,也即流程组合,提供了更细粒度的控制
——————————————
数据检索方式:
元数据过滤:
图关系过滤:引入知识图谱,将实体变成Node。
检索技术:向量化相似度检索、关键词检索、全文搜索、SQL检索、重排序、查询轮换
——————————————
RAG检索是基于【向量索引】和【语义相似度】的检索
Navie RAG:
1,构建数据索引(Index)
a, 加载不同来源的不同格式文档;
b, 将文档分割成块(chunks)
c, 对切块的数据进行向量化并存储到向量库数据库。
2,检索 - 增强(Retrieved - Augmented)
a, 通过向量相似度检索与问题相关的K个文档。
b, 检索召回知识附加上下文填充至 Prompt
3,生成 (Generation)
检索增强提示输入至 LLM生成请求响应。
大模型场景RAG基本应用:
1,超出上下文长度 文本划分成chunks,不同chunks转换为 向量embedding,并存储到向量数据库
2,输入prompt到LLM之前,将prompt转换为向量embedding。
3,将prompt向量进行相似度搜索,寻找到最相似的Top-k个chunks向量或文档。
4,将最相似的chunk向量与prompt向量拼接,作为LLM的输入,生成最终的回答。
RAG优化方式:
1,fusion融合技术:对问题进行多角度重写、多类型索引、多种检索算法、解锁结果融合
检索算法列举:
*BM25是一种用于信息检索的评分函数,用于衡量查询与文档之间的相关性;是对TF-IDF算法的改进与扩展,通过考虑文档长度和查询词频的统计特性来计算文档的相关性得分
*RRF【Ranking refinement fusion排序细化融合】:是一种用于搜索结果排序的算法,它通过融合多个排序模型的结果来提高搜索结果的质量;RRF将不同排序模型的得分进行归一化和加权,然后将它们相加得到最终的排序得分
*BeamSearch基本思想:通过保证局部最优解的方式来获取全局最优解,在当前时间步获取当前概率最高的K个候选词,下一个时间步会基于这K个候选词操作,然后重复如此直到生成最终结果。
2,递归搜索方式
第一种:通过一级chunks链接到二级chunks直到链接到不节点;
第二种:通过一级chunks链接到二级检索器,然后再检索文档;
第三种:通过一级chunks链接到RAG引擎,RAG可输出答案为后续生成上下文;
第四种:通过一级chunks链接到Agent,Agent具备更强大的查询和工具能力可为后端提供二次输出
3,构建摘要索引,通过LLM生成文档摘要,然后摘要潜入内容限量
4,文档树,通过聚类算法对所有文档分类,然后对每个簇类生成摘要优先级
Advanced-RAG:
索引优化:
父-子索引、摘要索引、假设性问题索引、
检索优化:
RRF排序细化融合、重排、过滤、查询转换、
混合搜索:将关键字搜索[BM25]和Vector搜索[余弦相似度]获得的搜索结果结合,需要交叉编码器(CrossEncoder:将两个句子同时输入Encoder模型,不生成Embedding),重新排序
RAG优势:
根据问题的特点、上下文生成更加个性化和精确的回答;因为它不仅依赖于现有的数据库,还能根据生成模型进行补充和扩展;可以应用于检索和自动摘要;
RAG缺点:
检索效果依赖embedding和检索算法;
大模型如何利用检索到的信息 仍然是黑盒。
对所有任务都无差别检索k个任务片段,效率不高。
无法引用来源,因此无法精准查证事实。
RAG评估方式:
1,使用大语言模型评估打分
2,基于规则的评估打分,常用的ACC、F1等评价方式
3,通过人工评价的方式
RAGAS:
基于简单手写提示的评估框架,通过这些提示 全自动地 衡量 答案的准确性、相关性、上下文相关性。
算法原理:
答案忠实度评估:利用LLM分解答案为多个陈述,检验每个陈述与上下文的一致性。最终根据支持的陈述数量与总陈述数量的比例,计算出一个"忠实度得分"
答案相关性评估:使用LLM创造可能的问题,并分析这些问题与原始问题的相似度。答案相关性得分 是 通过计算 所有 生成问题与 原始问题相似度的平均值 来得出的。
上下文相关性评估:运用LLM筛选出直接与问题相关的句子,以这些句子占 上下文总句子数量的比例来确定上下文相关性得分。
ARES:
自动化评价RAG系统在【上下文相关性、答案忠实性、答案相关性】3个方面的性能。
ARES减少了评估成本,通过使用少量的手动标注数据和合成数据,并应用预测驱动推理PDR提供统计置信区间,提高了评估的准确性。
算法原理:
1,生成合成数据集:ARES首先使用语言模型从目标语料库中的文档生成合成问题和答案,创建正负两种样本;
2,训练大语言模型LLM裁判:ARES对轻量级语言模型微调,利用合成数据集训练它们以评估上下文相关性、答案忠实性、答案相关性;
3,基于置信区间对RAG系统排名:最后ARES使用这些裁判模型为RAG系统打分,并结合手动标准的验证集,采用PPI方法生成置信区间,从而可靠地评估RAG系统的相关性。
——————————————————————————————————
Self-RAG重要创新:Reflection tokens(反思字符:Retrieve和Critique)
————————————————————————————————
LangChain的链和LCEL:
Chain(链)是LangChain中最核心的概念之一,简单来说,就是把自然语言输入、关联知识检索、Prompt组装、可用Tools信息、大模型调用、输出格式化等这些LLM应用中的常见动作,组装成一个可运行的“链”式过程。
LCEL即LangChain Express Language,即LangChain表达语言。举例如下
`#组装prompt:`
`prompt = ChatPromptTemplate.from_template("讲一个关于{topic}的笑话")`
`#调用大模型`
`model = ChatOpenAI(model="GPT-4") `
`#输出处理`
`output_parser = StrOutputParser() `
`chain = prompt | model | output_parser `
`#调用chain `
`chain.invoke({"topic":"毛毛虫"})`
“链”的缺点:无法满足在循环中调用LLM以完成任务;即“链”中的每个组件之间的联系相当于是有向无环图,在一次Chain运行中,一个调用节点 无法重复/循环进入。例如当检索出来的文档质量很差,就必须对检索问题重写,再把重写结果结果重新交给检索器,重新检索出新的关联文档,Agent Executor虽支持“链”的循环,但缺乏精确控制能力,过于黑盒。
由此便引出来LangGraph的设计,LangGraph是基于Langchain之上构建的一个扩展库,是以状态图的方式重新构建了AgentExecutor;把基于LLM的任务(比如RAG、代码生成等)细节用Graph进行精确定义,基于Graph来编译生成应用。在任务运行期间,维持一个中央状态对象state。
LangGraph的几个基本概念:
StateGraph:这是带遍整个状态图的基础类。
Nodes:节点;
Edges:边
Starting Edge:定义任务运行的开始节点
Normal Edge:普通边,代表上一个节点运行完成后立即进入下一个节点。
ConditionalEdge:条件边。代表上一个节点运行完成,需要根据条件跳转眸节点
PDF解析方法:
1,基于规则,根据文档的组织特点去“算”每部分的样式和内容。很难通用,
2,基于AI,目标检测+OCR文字识别pipeline方法
长文档关键信息解析:
1,分块索引法,
直接对长文档进行分块,然后构建索引入库。后期问答,只需要从库中召回和用户query相关对内容块进行拼接成文章,输入到LLMs生成回复。
2,文本摘要法。
直接利用 文本摘要 模型 对每一篇 长文档做文本摘要,然后对 文本摘要构建索引库,后期问答,只需要从库中 召回和用户query相关的摘要内容,输入到LLMs生成回复
3,多级标题构建文本摘要法。
——————————————————
ELmo采用的双向LSTM提取;
采用双向语言模型,可以同时采集前后语义的关系和含义;ELmo通过结合语言模型在给定上下文中的预测能力,为每个词生成一个动态的、与上下文相关的表示。ELmo模型由两个部分组成:一个双向的LSTM(长短期记忆网络)语言模型和一个权重组合层。
Bert采用双向Transformer提取;
采用了双向语言模型,相当于只用了Transformer中的Encoder,可以看见了完整的句子,是三者中提取特征能力最强大的。
GPT采用单向Transformer提取;
相当于只用了Transformer中的Decoder,看不见完整的句子,特征采集能力不如Bert。
GPT的auto-regressive自回归缺陷:
单向性,缺乏全局信息:每个时间步只依赖之前的时间步。
固定长度限制:在生成输出时,GPT模型通常采用固定长度的上下文窗口,例如512个token。这意味着只能考虑前512个token的信息,而无法处理更长的序列。这限制了模型在处理长文本的能力,导致信息丢失或不完整。
缺乏交互性:每个时间步只依赖前面的信息,无法考虑后续时间步的信息,无法有效进行双向交互,无法生成基于当前token词同时考虑前文和后文的信息,限制了模型。
——————————————————————
智能代理的组成主要由以下几个核心模块组成:
思考模块:主要用于处理输入信息、完成分析和推理。
具备能力:自然语言理解与生成能力、推理与规划能力、反思与学习能力。
记忆模块
工具调用模块。
AutoGen本质上允许动态对话。动态会话 允许 代理拓扑 根据 不同输入问题实例下的实际会话流程而改变, 而 静态会话的流程 始终 遵循 预定义的 拓扑。动态对话模式在 交互模式 无法提前预定的复杂应用程序非常有用。
AutoGen提供了两种实现动态对话的通用方法:
已注册自动回复。通过 可插入的自动回复功能,人们可以根据 当前信息的内容和上下文 选择与其他代理 进行对话。在群聊管理器中进行注册自动回复功能,可让LLM 决定群聊设置中 下一个发言者使谁。
基于LLM的函数调用。LLM根据每个推理调用中的对话表态来决定是否调用特定函数。通过在被调用函数中 向其他代理 发送信息,LLM可以驱动决定 多代理对话。
————————————————————
Llama3与传统Transformer结构的比较:
相同之处:
基本结构:两者都基于 标准的transformer解码器架构
多头自注意力:都使用多头自注意力机制
前馈网络FFN:包含两层 全连接网络
不同之处:
1,注意力机制:
传统Transformer:使用标准多头自注意力机制。
· Llama3: 引入了 分组查询注意力(Group-Query Attention)
2,激活函数:
· 传统Transformer:使用了ReLu或GELU激活函数
· Llama3: 使用更高效的SwiGLU激活函数
3,位置编码:
· 采用RoPE 旋转位置编码
Llama3的模型架构主要包括以下组件:
分层堆叠:
嵌入层:将输入的token转换为固定维度的嵌入表示
自注意力层:包含多头自注意力机制和归一化
前馈网络(FFN):包含激活函数 和 两层 全连接网络
位置编码:采用RoPE位置编码