OpenAI开发系列(二):大语言模型发展史及Transformer架构详解
全文共1.8w余字,预计阅读时间约60分钟 | 满满干货,建议收藏!
一、介绍
在2020年秋季,GPT-3因其在社交媒体上病毒式的传播而引发了广泛关注。这款拥有超过1.75亿参数和每秒运行成本达到100万美元的大型语言模型(Large Language Models,LLMs)开启了自然语言处理(NLP)领域的新纪元。
在这个阶段,大规模预训练模型的涌现彻底改变了NLP的研究和应用格局。
大规模语言模型充分挖掘了大量未标注数据的潜力,从而赋予模型更强的语言理解和泛化能力。采用预训练和微调策略的大模型在多个NLP任务上都实现了前所未有的成就,无论是在模型准确性、泛化能力还是复杂任务处理方面,都展示了出色的表现。这不仅吸引了大量投资,也催生了NLP领域全新的发展和研究方向。
同时,随着大模型应用门槛和使用门槛都逐步降低,大量的大模型产品不断涌现——ChatGPT、跨语言代码编译工具Cursor、Github官方代码编写工具CopilotX、一键生成PPT内容的Gamma AI,office全家桶中配置的Copilot、Photoshop中配置的fill features,广泛生成图像的MidJourney和Stable Diffusion……这些应用不仅改变了商业的运营方式,也极大地影响了人们的生活和工作。
二、大语言模型的发展脉络
说起大模型,比较有趣的一件事发生在2021年,一名开发者使用GPT-3创建了一款名为"Project December"的文本聊天游戏。这款游戏使用了从一位名为Samantha的已故女性的Facebook和个人短信中收集的文本数据(Samantha在2012年去世)。令人惊讶的是,她的男友通过这款游戏与模仿Samantha的AI进行了短信聊天,竟然聊了几个月都没有察觉出异常。这一事件引发了一系列伦理和道德问题。
这一事件不仅揭示了大模型的强大潜力,也预示了它未来可能的发展方向。在过去,我们印象中的机器人是一种简单、机械式的交互方式,即便有着不断优化的自然语言处理技术作为支撑,这些机器人的回应依然多数是预设的、固定化的,明显缺乏深度和真实感。然而,现代技术已经打破了这些局限。
未来的机器人,就如同电影《流浪地球2》中引人注目的550w一样,将展示出近乎人类的情感和思考能力。
ChatGPT便是这一变革的先锋,它不仅可以准确地理解和生成复杂的文本,还能与先进的音视频技术配合无间,构造出一个令人惊叹的、近乎具有自我意识的数字生命体,就像电影中的丫丫一样。
在这种变革中,应用底层也在不断的实现技术迭代,如下图:
从早期基于任务驱动的智能助手(如Siri和百度智能音响)开始,人工智能已经经历了一系列显著的变革。这些初期产品,虽然基于各自不同的数据和模型构建,并且在功能扩展性方面表现出色,但它们更多地是一种“伪”人工智能,其能力受限于特定的任务和场景。
随后,Bert模型的出现标志着一个重要的转折点。与之前的任务驱动模型不同,Bert通过预训练和微调的流程,能够更加深入地理解人类语言。它采用了一种非任务导向的预训练方法,然后可以通过微调应用于各种下游任务。尽管如此,模型微调的复杂性仍然是一个难以逾越的障碍。
再发展到现在的GPT模型,其创新之处在于其“基于提示”的设计思路。不仅预训练的规模超过了Bert的500倍,
GPT还能够自主生成语言,适应各种不同的未知任务,仅通过改变输入提示即可,无需对模型本身进行任何修改。这种进步符合我们对人工智能最初的期待和憧憬,预示着一个全新、更加智能和灵活的AI时代即将到来。
所以我们对人工智能的期待就应该是这样的:
这是我们熟悉的ChatGPT,而如果深究,其背后的推理过程是这样的:
需要明确知道:GPT(Generative Pre-trained Transformer)模型是一种自回归(autoregressive)模型,其核心思想是根据已有的文本序列生成下一个最可能出现的单词。这一切都是基于统计学习和推理,而非像人类那样进行逻辑推理或思考。
GPT(Generative Pre-trained Transformer)是基于Transformer架构构建的,这一架构在整个推理流程中占有关键地位。虽然OpenAI并没有完全公开GPT模型的所有训练细节和数据,但其核心机制依然基于Transformer,这一点在多个学术论文和技术文档中都有描述。因此,理解Transformer的基本原理不仅有助于了解GPT模型是如何生成文本的,还对其他自然语言处理任务和开发工作具有极大的价值。
换言之,了解基础即可揭示变化,这在开发中是至关重要的。
三、GPT系列模型架构详解
自然语言处理(NLP)技术的发展历程是一个逐步迭代和优化的过程。在Transformer架构出现之前,该领域经历了从依赖人工规则和知识库到使用统计学和深度学习模型的转变。此后,Transformer的出现标志着一个新纪元,特别是随着BERT和GPT等模型的推出,断崖式的提升了自然语言理解和生成能力。现在,可以说已经进入了大模型时代,基于Transformer架构的应用正在经历一个前所未有的爆发期。
我们对ChatGPT这样的聊天模型可能已经习以为常,一问即答似乎很正常。然而,如果深入思考其背后的工作原理,你会发现这实际上是一件令人惊奇的事情。所以,我想让大家明确一个问题:究竟什么是Transformer,以及它是如何获得这种革命性的影响力的。
3.1 Transformer架构详解
ChatGPT 的后端是基于 GPT(Generative Pre-trained Transformer)模型的,GPT模型通过在大规模文本数据上进行无监督预训练来学习语言的统计特征和语义表示。它使用自回归的方式,即基于前面已经生成的词来预测下一个词,来学习词之间的语义和语法关系,以及句子和文本的整体上下文信息。
GPT 模型本身是构建在 Transformer 结构基础上的,因此,要全面了解生成式大模型为何如此强大,Transformer 架构是不可或缺的关键点。
那么,这个架构是如何实现文本生成、语义理解等高级功能的呢?
Transformer最经典论文【Attention Is All You Need】,没有之一,地址:https://arxiv.org/abs/1706.03762
**Transformer由编码器(Encoder) 和解码器(Decoder)组成,其中编码器用于学习输入序列的表示,解码器用于生成输出序列。 GPT主要采用了transformer的解码器部分,用于构建语言模型。**其结构是这样的:
如果没有NLP算法基础的话,看着可能有点发懵,不过没关系,你并不需要完全掌握所有细节。只需明确两个核心概念即可:
- Transformer 中的注意力机制是如何工作的
- Decoder 部分的生成式输出具体意味着什么
对于一条输入的数据,在这个复杂的架构中是如何流动和处理的,我来给大家拆解一下。
3.1.1 拆解Transformer架构
- 文本表示
在Transformer模型中,首先会对输入文本进行处理以得到合适的表示。
为什么要进行这样的转换呢?
考虑这样一个场景:当你输入"AI+编程 扬帆起航"这句话,计算机能直接理解吗?或者说,当你与ChatGPT互动时,它是否真的“听到”了你说的每一个词或字?实际上并非如此。
ChatGPT并不直接处理自然语言。它需要将我们的输入转换为它能理解的数据形式。简而言之,它会把每个词或每个字符编码成一个特定的向量形式。
这个编码过程具体步骤如下:
- 词嵌入(Word Embedding): 文本中的每个单词都被转换为一个高维向量。这个转换通常是通过预训练的词嵌入模型(如Word2Vec、GloVe等)完成的。
- 位置嵌入(Positional Embedding): 标准的Transformer模型没有内置的序列顺序感知能力,因此需要添加位置信息。这是通过位置嵌入完成的,它与词嵌入具有相同的维度,并且与词嵌入相加。
例如,考虑句子"AI+编程 扬帆起航"。
如果没有位置嵌入,该句子可能会被错误地解析为"编AI+程,航帆扬起"等,这会破坏句子原有的顺序和语义。
位置嵌入的目的就是确保编码后的词向量能准确地反映句子中词语的顺序,从而保留整个句子的原意。
- 相加(Addition): 词嵌入和位置嵌入相加,得到一个包含了文本信息和位置信息的新的嵌入表示。
最终得到输入的Transformer表示x,这样,模型就能知道每个单词不仅是什么,还能知道它在序列中的位置。
举个例子:
通过这样的一个处理过程,模型就可以认识"扬帆起航"这样的一个输入。
那对于Transformer的输入处理部分,从架构图上编码器和解码器部分都有输入,这个怎么理解?
这是因为:在Transformer模型中,编码器(Encoder)和解码器(Decoder)各自有独立的输入。通常,在有监督学习的场景下,编码器负责处理输入样本,而解码器处理与之对应的标签。这些标签在进入解码器之前同样需
要经过适当的预处理。这样的设置允许模型在特定任务上进行有针对性的训练。
通过一个简单的机器翻译任务来说明这个概念。假设有以下的英语到法语的翻译对:
- 英语(输入样本): “Hello, world”
- 法语(标签): “Bonjour, monde”
在这个示例中,编码器(Encoder)会接收"Hello, world"这个句子作为输入。这个句子首先会被转换成一组词向量或者字符向量,然后进入编码器进行处理。
与此同时,解码器(Decoder)会接收"Bonjour, monde"对应的标签作为输入。同样地,这些标签首先会被转换成一种机器可理解的表示(比如词向量或字符向量),然后进入解码器。
编码器处理完输入样本后,它的输出会与解码器的输入进行某种形式的结合,以生成最终的翻译输出。通过这个机制,模型可以在有监督的学习环境中进行训练,以完成特定的任务,如机器翻译。
- Encoder(编码器部分)
Transformer中的编码器部分,作用是学习输入序列的表示,位置如下图所示:
在Transformer模型的编码器(红色虚线框)部分,数据处理流程如下:
首先,输入数据(比如一段文字)会被送入注意力(Attention)机制进行处理,**这里会给数据里的每一个元素(比如每一个字或词)打个分数,以决定哪些更重要,**在"注意力机制"(Attention)这个步骤之后,会有一些新的数据生成。
接着,一个“Add”操作会被执行,在注意力机制"中产生的新数据会和最开始输入的原始数据合在一起,这个合并其实就是简单的加法。"Add"表示残差连接,这一操作的主要目的是确保数据经过注意力处理后的效果至少不逊于直接输入的原始数据。
随后,数据会经过一个简单的数学处理,叫做“层归一化”(Norm),主要是为了让数据更稳定,便于后续处理。
之后,数据将进入一个双层的前馈神经网络。这里的目标是将经过注意力处理的数据映射回其原始的维度,以便于后续处理。这是因为编码器会被多次堆叠,所以需要确保数据的维度在进入下一个编码器前是一致的。
简单来说:就是把经过前面所有处理的数据变回原来的形状和大小。
注意看图中编码器左侧的Nx标识,意味着会有多个编码器堆叠。
最后,为了准备数据进入下一个编码器(如果有的话),数据会再次经过“Add”和“Norm”操作,输出一个经过精细计算和重构的词向量表示。
这样的设计确保了模型在多个编码器层之间能够有效地传递和处理信息,同时也为更复杂的计算和解码阶段做好了准备。
简单来说,Transformer的编码器就是通过这些步骤来理解和处理输入的数据,然后输出一种新的,更容易理解的数据形式。如图:
- Decoder(解码器部分)
Transformer中的解码器部分,作用是用于生成输出序列,位置如下图所示:
在Transformer模型的解码器(紫色虚线框)部分,数据处理流程如下:
在Decoder部分,数据首先进入一个带遮罩(masked)的注意力(Attention)机制,这个遮罩的作用是确保解码器只能关注到它之前已经生成的词,而不能看到未来的词。
然后,这一层输出的信息会与来自Encoder部分的输出进行融合。具体来说,这两部分的信息会再次经历一个注意力机制的处理,从而综合考虑编码与解码的内容。
这个过程之后,解码器的操作与编码器部分大致相同。数据会经过层归一化、前馈神经网络,再次进行层归一化,最终输出一个词向量表示。
输出的词向量首先会通过一个线性层(Linear)。这一步的目的是将向量映射到预先定义的词典大小,从而准备进行词预测。
最后,使用softmax函数计算每个词的生成概率。最终,选取概率最高的词作为该时刻的输出。
举个例子:
现在假设有一个很小的词典,只有3个词:“apple”,“banana”,“cherry”。线性层会将这个3维向量转换成另一个3维向量(对应“词典”大小)。
假设转换后的向量是
[2.5, 1.0, -0.5]
。通过softmax函数,这个向量会转换为概率分布,比如
[0.8, 0.18, 0.02]
。这就意味着模型认为下一个词是“apple”的概率是80%,是“banana”的概率是18%,是“cherry”的概率是2%。
这样,就能从解码器的高维输出中预测出一个实际的词语了。
这样,Decoder不仅考虑了之前解码生成的词,还综合了Encoder的上下文信息,从而更准确地预测下一个词。
与GP有最大关联的,就是采用Decoder这部分架构来构建语言模型的。
3.1.2 注意力机制
注意力机制,到底在注意什么?对于人类来说,当开始做某一件事时,通常会集中注意力在某些关键信息上,而忽视其它不太相关的信息。
举个例子:
当你正在开车并接近一个交叉口时,你可能会特别关注红绿灯、行人以及其他车辆的动向,而忽略了沿路的风景或广告牌等不太相关的信息。这样,你能确保自己作出正确的行动决策,比如停车或继续行驶。
那对于计算机来说,它是如何解析上下文信息,理解不同语义之间的关系呢?
这个图通常用来展示如何通过注意力机制确定代词"it"指代的是哪个名词(在这个例子中是"The Animal")。
原始句子:“The Animal didn’t cross the street because it was too tired"译为:因为动物太累了所以没有过马路。“it"指代的是"The Animal”,然而,如果改变句子中的一个词,将"tired"替换为"narrow”,得到的新句子是"The Animal didn’t cross the street because it was too narrow",译为:由于街道太窄,动物没有过马路。在这个新的句子中,“it"指"the street”。
因此,模型需要能够理解当输入的句子改变时,句子中的词义也可能会随之改变。这种灵活性和准确性在Transformer模型中得到了体现,而之前的模型都无法达到这一目标。
Attention机制的工作原理可以这样形象化地描述:
模型把每个词编码成一个向量,然后把这些向量送入模型中。在这里,每个词都会像发送一条“询问”一样,去问其他词:“咱们之间的关系紧密吗?我们亲近吗?”如果关系紧密,模型就会采取一种行动,反之则会采取另一种行动。
不仅每个词都会发出这样的“询问”,而且也会回应其他词的“询问”。通过这样的一问一答互动,模型能够识别出每两个词之间的紧密关系。一旦这种关系被确定,模型就会把与该词关系更紧密的词的信息“吸收”进来,与其进行更多的信息融合。这样,比如在翻译任务中,模型就能准确地识别“it”应该翻译为“animal”,因为它的向量已经融合了与“animal”这个词紧密相关的信息。
**所以注意力机制的核心就是要做重构词向量这样一件事。**这种机制转化成计算机的计算过程,是这样的:
对于上面形象化的描述中,可以抽取出注意力机制的三要素:
- Q:即query,可以理解为某个单词像其它单词发出询问
- K:即Key,可以理解为某个单词回答其它单词的提问
- V:即Value,可以理解为某个单词的实际值,表示根据两个词之间的亲密关系,决定提取出多少信息出来融入到自身
在Transformer模型中,Q、K和V是通过输入向量表示Transformer(x)与相应的权重矩阵Wq,Wk,Wv进行矩阵运算得到的。
如果你熟悉深度学习,那么应该知道,数据在模型内部主要是与不同的权重参数进行矩阵乘法。如果之前没基础的,就把它当作模型的一个固有模块,一个制定的计算规则。
这些权重矩阵最初是通过数学方法进行初始化的,然后在模型多轮训练的过程中逐渐更新和优化。目标是使得传入的数据与这些权重矩阵相乘后,能够得到最优化的Q、K和V矩阵。
以Q为例,其第一个元素是通过输入向量x的第一行与权重矩阵Wq的第一列进行点乘和加和运算得到的。
因此,在Q矩阵中的第一行实际上是这样的意义:它包含了第一个词(与输入X的第一行对应)在查询其他词时所需的关键信息。同样地,K和V矩阵的计算逻辑与此相似。
在K矩阵的第一行里,存储的是第一个词在回应其他词的查询时所需的信息。而在V矩阵的第一行,所包含的是第一个词自身携带的信息。在通过Q和K确定了与其他词的关系后,这些存储在V中的信息被用来重构该词的词向量。
当得到了Q,K,V之后,Attention做了如下操作:
这个公式就涉及到了一问一答的这个过程,它表现出来的计算过程是这样的:
计算过程同样是矩阵相乘再相加,所以得到的 Q K T QK^T QKT矩阵就表达了词与词之间关系的紧密程度
为什么这样就能衡量词之间的紧密程度?
在计算矩阵乘法的时候,向量对应元素的乘积,这种计算方式在数学上叫向量的内积。
向量的内积在向量的几何含义上表达的是:内积越大,两个向量就更趋向于平行的关系,也就表示了两个向量更加相似,当内积为0,两个向量就会呈现垂直的关系,表示两个向量毫不相关。
那对于Attention机制中这种Q和K一问一答的形式,问的就是两个词之间的紧密程度,所以也就可以通过内积的方式,来衡量两个词之间的相似性
在这个过程中,可能也都注意到了,它对自己也进行了提问,并自己也给出了回答,为什么要这样做呢?
以这个示例:“The Animal didn’t cross the street because it was too tired"译为:因为动物太累了所以没有过马路。“it"正常来说作为代词,指代的是"它”,但在这个句子中,我们希望它指代是"The Animal”,所以它不把自己在这个句子中的重要性也表现出来,不对自己的信息进行重构的话,它可能就没有办法改变自己原有的意思,也就无法从原本的意思"它"改为指代"The Animal"。
也就是因为这种操作,所以在Transformer中的注意力机制被叫做Self-Attention(自注意力机制)。
当衡量句子之间的紧密关系的结果出来之后,那么如何去重构V?转化成计算过程是这样的:
在计算得到 Q K T QK^T QKT矩阵矩阵后,假设第一行的数据分别为:100,80,20,12,那么接下来的问题就变成了如何量化地决定哪些词应贡献多少信息。
为解决这一问题,就会应用Softmax函数来对每一行进行归一化处理,这样做会确保该行中所有元素的和为1。
假如经过Softmax处理后,第一行变成了某种分数形式,例如:0.4,0.2,0.2,0.1,那么这意味着将用第一个词的40%的信息、第二个词的20%的信息…来构建目标词的新表示。这样,Softmax操作实质上是在量化地衡量各个词的信息贡献度。
公式中除以 d k \sqrt{d_k} dk是为了避免在计算向量內积时因为向量矩阵过大,计算出来的数值比较大,而非单纯的因为词之间的紧密程度这一问题。
当得到了每个词之间的信息贡献度概率之后,重构V的过程转化成计算过程是这样的:
进一步拆解这个过程是这样的:
也就是说:从第一个词中拿出40%的信息,从第二个词中拿出20%的信息…以此类推,最终得到Z,通过这种计算的形式得到的Z矩阵,每个位置就包含了所有与之有关系的信息。
这就是Transformer中Self-Attention机制中的计算过程。
3.1.3 Decoder 如何做生成式输出
Transformer的Decoder部分与Encoder部分有许多相似之处,但也存在一些关键的差异。Decoder增加了一个额外的注意力层。此外,除了它自身的输入信息,Decoder还会整合Encoder的输出信息。(如果是监督训练任务)
Transformer模型中的解码器(Decoder),其主要任务是预测下一个输出词,所以称它为生成式模型。
为了更好地理解这个过程,可以用一个机器翻译任务作为例子:
假设有一条中英双语训练样本:
"我是一名学生" (X) --> "I am a student" (Y)
。当解码器开始工作时,它需要一个初始的输入来启动预测过程。但是,为了预测第一个词"I",解码器没有之前的上下文。因此,需要为其引入了一个起始符
<s>
作为初始的输入。所以训练样本的目标序列就被调整为:<s>, I, am, a, student
。解码的过程如下:
- 输入起始符
<s>
到解码器。- 通过Attention机制,解码器对编码器的输出(也就是"我是一名学生"的表示)进行注意,并进行融合。
- 基于起始符
<s>
和编码器的融合输出,解码器预测第一个词,即"I"。- 接下来,"I"和
<s>
都会被用作已知信息,再次输入到解码器。- 解码器继续通过Attention机制对编码器的输出进行注意,然后预测下一个词"am"。
- 这个过程不断重复,直到预测出整个句子"I am a student"。
看下这个动图尝试理解:
http://jalammar.github.io/images/t/transformer_decoding_2.gif
关键点1:Decoder中的Attention与Encoder中的Attention有什么不同
首先,从名称上,就可以发现它们有所区别。在Decoder中,首先遇到的是“Masked Attention”。为什么需要这种设计?在Transformer模型的解码阶段,每个词都是逐个生成的。
例如,当预测“am”时,模型不应该提前“知道”或“看到”接下来的“a student”。
可以将这个过程想象为一个时间线:在预测一个特定的词时,你不能“预知”它之后的词汇,因为在实际情境中,那部分尚未发生。为了确保模型在这一时点上不会受到未来词汇的干扰,解码器采用了掩码操作。通过这种方式,模型在处理某个词时,后续的所有词都会被遮挡,确保模型只基于已知的上下文进行预测。
拆解成Decoder内部的计算过程,是这样的:
首先:准备输入数据矩阵(由标签加上起始符组成)和遮挡矩阵(Mask矩阵)。如图:
遮挡矩阵的设计是为了确保在计算时,被遮挡的部分(上半部分)得到的是一个较小的值,使其对结果的影响最小。
具体地说:
考虑遮挡矩阵的第一行,它表示预测第一个词时的情况。此时,模型只知道起始符
,而对于当前预测的词及其后的词,模型是不知道的。这意味着模型在预测第一个词时,仅能依赖起始符。类似地,当模型在预测第二个词时,即遮挡矩阵的第二行,它仅知道起始符
和第一个词。而第二个词及其后的所有词对模型来说都是未知的。
这样的设计确保了模型在预测某个词时,仅仅依赖于其之前的词,而不会受到后面词的干扰。
然后还是经过和Encoder过程一样的Q,K,V计算过程:
得到的 Q K T QK^T QKT矩阵后(表明词与词之间关系的紧密程度的矩阵),与之前准备的Mask矩阵做按位相乘,如图:
对于 Q K T QK^T QKT矩 与mask矩阵相乘的过程,这个“相乘”是按位相乘,也就是每个对应的元素进行相乘。
为了直观地理解,可以设想mask矩阵的遮挡部分都是0,而未遮挡的部分都是1。那么,在这种按位相乘之后,被遮挡的部分在结果中的对应位置就都是0。例如,对于第一个位置,它只有起始符是“亮”的(也就是为1),而其它部分都是“暗”的(也就是为0)。
举个示例,假设得到的 Q K T QK^T QKT矩阵的前两行Score 是这样的:
这样设计的目的是确保:在预测当前词时,模型只能获取到它之前的词的信息,而对当前词自身及其后面的所有词都是一无所知的。
在计算得到 Q K T QK^T QKT矩阵后,在Mask Q K T QK^T QKT 上进行Softmax操作。此时,每一行的元素和都会等于1。然而,对于单词0,其在单词1、2、3和4上的Attention Score都是0。
最后:将经过Softmax的Masked Q K T QK^T QKT 与Value矩阵V相乘以获取注意力加权的输出,这个输出Z就是Decoder的Masked Self-Attention部分的结果,如下:
关键点2:理解什么是Cross Attention
当输入经过Mask Attention后,要进入第二个Attention,但这个Attention不再是单纯的自注意力机制,而是Cross Attention,如下:
为什么需要Cross Attention?**因为编码器持有了输入序列(比如:“我是一个学生”)的信息,而解码器的目标是在给定该输入时产生正确的输出序列。**为了实现这一点,解码器需要对编码器输出的所有信息都有所了解,从而知道下一个输出词应该是什么。
Cross Attention的操作方式和普通的注意力机制非常相似,但是Q来自于解码器的输出,而K和V来自于编码器的输出。这确保了解码器可以"询问"编码器有关输入序列的信息。这种"一问一答"的描述是形象的,它说明了解码器是如何利用编码器的信息来确定最合适的输出的。
例如,在进行“我是一个学生”到“I am a student”的翻译时,解码器可能会询问编码器:“根据你对‘我’的理解,接下来我应该输出什么?”通过这种方式,解码器可以更准确地预测目标序列的下一个词。
你可以这样简单理解:
第一步是类似于“自己对话”的方式,这被称作Masked Self-Attention。这确保解码器在“猜”某个词时只参考前面的词。
接着是第二步,叫做Cross Attention或“交叉对话”。这里,解码器会“询问”编码器关于原始句子(例如:“我是一个学生”)的信息。这就像解码器问编码器:“你认为我接下来应该说什么?”然后编码器给出建议,例如:“接下来应该是‘I’”。这样,解码器就能更好地完成翻译任务。
所以,简单说,第一步是解码器和自己“对话”,确定应该问什么问题。第二步是向编码器“提问”,得到答案,并继续翻译。这就是Decoder的两步注意力机制的工作原理。
在Decoder的这种Cross Attention之后,模型将继续进行与Encoder部分相似的处理流程,包括多次的注意力计算和前馈神经网络操作。当Decoder的这些步骤全部完成后,输出会进入一个线性层进行映射。这个映射层的作用是把Decoder的输出转化为与词典大小相同的向量。接着,这个向量会经过Softmax层,转化为概率分布。最后根据这个概率分布选择概率最大的词作为输出。
这样,Transformer的整个工作流程就完成了。
3.2 GPT系列模型
通常一个模型或者架构的提出都是为了解决领域内存在的某些问题,在GPT-1提出之前,深度学习在自然语言处理领域的主流方法存在着以下两个比较大的局限性。
- 在早期的深度学习应用中,许多方法都基于监督学习,这意味着需要大量的标注数据。但这种方法有一个明显的缺点:它限制了模型的适应性和灵活性。
以机器翻译和实体识别为例:
如果使用特定的机器翻译数据来训练模型,那么这个模型主要就只能做机器翻译任务。同样,基于实体识别数据的模型也只能做实体识别。每种任务都需要大量的专用标注数据,但每个模型的应用范围都相当有限。
因此,尽管投入了大量的数据,但得到的模型仍然只能在特定的任务中表现出色,无法跨任务灵活应用。这种局限性使得需要在不同的任务中重复劳动,效率低下且成本高昂。
- 即使有了大量的标注数据,仍面临一个核心问题:缺乏一个通用的优化目标来学习有用的文本表示。
比如在NLP领域涵盖了众多任务,包括机器翻译、情感分类等。每一个任务通常都有其专属的目标函数,这意味着需要为每个任务单独设计和调优模型。因此,尽管已经投入了大量的资源和数据,但缺乏一个统一的、跨任务的优化目标导致我们充分地释放数据的潜力,并使得模型训练过程变得复杂和低效。
这种现状强烈揭示了深度学习中一个核心的挑战:如何发现或设计一个既能捕捉到文本内在信息,又具有广泛适应性的优化目标,所以OpenAI提出了GPT1,那初代的GPT 1 是怎么做的呢?
3.2.1 GPT 1 初露锋芒
GPT **1 参考论文:**https://www.cs.ubc.ca/~amuham01/LING530/papers/radford2018improving.pdf
GPT 1引入了使用Transformer架构的无监督预训练方法,有效地从海量无标签文本中提取有意义的表示。这种方法不仅强化了对各种自然语言任务的性能,还显著减少了对标注数据的依赖。
关键点1:无监督的预训练
GPT-1采用无监督训练方式,使用用未标记的数据来训练模型。其目的是使模型学习一套初始参数(这个初始参数也就是Transformer中的Wq,Wk,Wv),从而掌握在给定的上下文之后继续续写文本的能力。
也就是说:让模型具备给定上文,能够继续续写下文的能力。
续写文本示例:
首先,对模型进行了大量的无监督训练,让它阅读了上千万篇文章,从而掌握语言的基本模式。给GPT-1一个简短的提示,例如输入:“在一个寒冷的冬日,”
续写1:“玛丽决定待在家里,烤一些曲奇,并与家人围坐在壁炉旁,分享故事和温暖的时光。外面的雪花飘落,每个人都沉浸在这美好的家庭时刻中,感受到冬日的宁静和温馨。”
续写2:“孩子们激动地跑到户外,开始制作一个大雪人。他们滚起了雪球,找来石头作为雪人的眼睛和嘴巴,还戴上了一顶旧帽子。整个下午,他们都在雪地里嬉戏,忘记了冬日的寒冷。”
思考一下为什么这种模型就能解决之前自然语言处理领域存在的问题?
拿机器翻译为例,假如输入“我是一个学生,请帮我翻译成英文”,一个经过预训练的GPT模型,特别是在微调后,可能会生成“I am a student”这样的输出。尽管它不是传统意义上为机器翻译任务而设计的模型,但由于其强大的文本生成能力和对语言结构的深入理解,它可以实现这样的任务。
所以自然语言处理的许多任务,可以被视为“生成某种输出”的问题,GPT这种预训练模型为这些任务提供了一种高效、灵活的解决方案。
关键点2:如何指导GPT生成目标内容
当GPT具备优秀的文本生成能力后,如何让其产生确切需要的内容呢?
例如,当输入“我是一个学生”时,GPT可能会生成“我每天都要按时去上学…”。尽管这句话是通顺的,但如果任务目标是想获得这句话的英文翻译,如何有效地指引模型呢?
**GPT给出的解决方案就是使用相应的有标签数据进行微调,使得模型能够满足不同任务的要求,这个过程需要的有标签数据就很少了。**那对于GPT的架构,具体是什么样的?
在GPT的设计中,它专门采用了Transformer的Decoder部分,从而实现文本的生成任务。虽然称其为生成式模型可能稍显简化,但这样的定位确实符合其核心功能。
与原始的Transformer结构不同,**GPT没有采用双重Attention机制,也不再需要编码的过程。其关键在于一个逐词预测的流程。**为了实现这个目标,GPT内部采用了Masked Multi-Head Self-Attention机制,并搭配前馈网络。在某些常见的配置中,这种机制具备768维的向量和12个Attention Head,整体模型则堆叠了12层的Decoder。
这一阶段,本质上就是在大量的文本语料库上学习语言信息。其数学原理大概可以拆解如下:
首先定义这样一个无监督语言序列:
U = { u 1 , . . . , u n } (1) U = \{u_1, . . . , u_n\} \tag{1} U={u1,...,un}(1)
这里的U,可以把它理解为一段一段的话的集合,包含的元素就是一个一个的词
它使用标准的语言建模目标函数来最大化给定上下文的词的似然度
标准语言模型:用于预测自然语言序列中词汇的概率分布,目标是给定上下文,对下一个词进行概率预测
目标函数,论文中是这样定义的:
简单来说,这个公式的意思是:对于一个文本序列中的每一个词,我们都看它前面的k个词,然后使用模型(由参数 θ \theta θ决定)来预测这个词的概率。目标是使这个概率尽可能地高。
以一个简单的例子来说:
假设文本是"我喜欢吃苹果",如果现在要预测"吃"这个词,并且考虑前两个词作为上下文,那么就是在问:“给定‘我喜欢’这两个词,下一个词是‘吃’的概率是多少?”公式就是在帮助找到这个概率,并使其最大化。
θ \theta θ简单理解就是模型,其具体指的是多层的Transformer Decoder,其计算过程如下:
理解这个公式:
U是输入矩阵,We是单词编码,Wp是位置编码,然后经过Decoder解码器,最后经过Softmax得到输出,这个过程与<Decoder 如何做生成式输出>一节中的过程完全一致
通过这个过程,模型已经获得了生成后续文本的能力。但产生的内容可能不总是用户所期望的。
那么,GPT是如何确保生成相关内容的呢?GPT给出的有监督模型微调方案是这样的:
首先准备有监督数据: x 1 , x 2 . . . . . . x m x^1,x^2 ...... x^m x1,x2......xm表示的输入列, y y y 表示标签,然后将数据输入到已经预训练好的模型中预测y的概率,如下图:
理解这个公式:
- x 1 , x 2 . . . . . . x m x^1,x^2 ...... x^m x1,x2......xm是输入序列,这是为特定任务准备的有标签数据的输入部分。
- y y y是对应的标签或输出。
- h l m {h_l}^m hlm 表示经过预训练好的模型处理后得到的表示或特征。
- W y W_y Wy 是一个权重矩阵,是微调中需要调整的关键参数。
在微调的过程中,模型的大部分结构和参数(预训练得到的知识)保持不变,但是某些特定的层或权重,如这里的 W y W_y Wy,会根据新任务的有标签数据进行调整。
简单地说,你已经有一个大致了解语言的模型,但是为了使它更好地完成特定任务(例如机器翻译、情感分析等),你需要微调某些参数。在这个公式中,你正在调整权重矩阵 W y W_y Wy 以使模型更好地预测输出 y y y。
同样,微调的有监督数据肯定不止一条样本,会有很多样本,所以微调的任务就变成了最大化这个目标函数:
微调的过程是这样的:
为了理解这个过程,首先我们要明确,微调主要是对模型的线性层进行调整,即图中的“Linear”部分。相对于整个Decoder的参数,这部分的参数较少,使得微调更加高效。
那么,如何让模型知道具体执行哪种任务呢?
其实,GPT采用了一种标记策略。当输入文本时,它通过特定的符号或标记来指示任务类型。比如,对于分类任务,它可能会用"Start"和"Extract"这样的标记来包裹文本。而对于Entailment任务,则可能使用"Start", “Premise”, “Delim”, "Hypothesis"以及"Extract"这样的标记来分割和标注信息。
确切地说,该模型经历了两个阶段:首先是无监督的预训练阶段,这让模型掌握了基本的语言结构和知识,使其具备了生成语言的能力。但这种初步的“说话”可能不够精确或针对特定任务。因此,接下来是有监督的微调阶段,确保模型在特定任务上可以按照期望生成更精确的内容。
也就是这种策略,GPT 1 在12个数据集上进行效果评估,其中9个数据集上都达到了新的SOTA效果:
3.2.2 GPT 2 Zero-shot创新
GPT 2 参考论文1:https://insightcivic.s3.us-east-1.amazonaws.com/language-models.pdf
GPT 2 参考论文2:https://arxiv.org/pdf/2005.14165.pdf
在GPT-1之后,研究人员观察到,随着模型规模的增大,其精确度和泛化能力仍具有显著的提升潜力。因此,GPT-2的主要改进方向已经清晰地呈现出来:
- 利用更为庞大和丰富的数据集,构建更大规模的模型。
- 对模型的结构进行细致的调整和优化。
针对当时的研究现状,如果对于某一个特定的任务,需要该任务专门的数据集,GPT 1 使用的无监督预训练+有监督微调也没能避免这个问题,所以GPT 2在设计之初便引入了Zero-Shot学习的思想,意味着一旦模型训练完成,无需进一步调整其参数或结构,就能够直接处理各种任务并实现优秀的性能。
Zero-Shot的目标是:在处理下游任务时,不再像GPT-1那样依赖开始符、分隔符和抽取符来告诉模型具体的任务,而是采用更直观的自然语言方式来指定任务。例如,要执行翻译任务时,我们可以直接对模型说:“请将’我是一名学生’翻译成英文。”这样,通过这种自然语言提示(Prompt),模型便知道应该执行的任务。
为了达到这一效果,OpenAI着重提高数据质量,他们从社交平台Reddit上抓取了约40GB的内容,类似如下:
这些文本中可能包含了如"提示"、“描述”、"答案"等关键信息。OpenAI坚信,只要数据量足够大且质量高,模型自然能够达到强大的效果。通过吸收这样的文本,GPT可以在学习人类对话模式的同时,逐渐培养出自我学习的能力。这种基于Zero-Shot的训练策略成功地证实了构建一个高效的通用语言模型是完全可能的。
但结果是:GPT 2虽然提出了这种创新,但是论文中展现出来的结果并没有什么惊艳的表现。
3.3.3 GPT 3 in-contenxt learning
GPT 3 参考论文:https://arxiv.org/pdf/2005.14165.pdf
当进入到GPT 3后,它基于GPT 2的Zero-Shot做了进一步的研究,它提出:给模型输入情景的描述,模型就会根据用户提出的情景要求来生成答案,这一过程被称为in-context learning。
这一过程就提出了One-Shot及Few-Shot,如图:
除此之外,GPT 3的模型结构中也引入了sparse transformer,且具有更大的1750亿个参数,从实验结论上来看,GPT 3取得了非常亮眼的表现。
3.3.4 GPT 4 涌现能力
GPT 4 参考论文:https://arxiv.org/pdf/2303.08774v2.pdf
最新的GPT-4模型已经发展为一个高级的多模态系统,能够接受图像和文本输入并输出文本。它在各种学术和专业基准测试中展现出与人类相当甚至更高的性能水平。
OpenAI 在为机器学习模型设计的传统基准上评估了 GPT-4。从实验结果来看,GPT-4 大大优于现有的大型语言模型,以及大多数 SOTA 模型。
其实从GPT 1发展到GPT 4,其实大家可以发现GPT系列的内容越写越短,和GPT的越来越大成正比。这也证实了GPT发展的核心思想就是简单粗暴:大力出奇迹。
那大语言模型为什么能有这样优异的性能,它的优势在什么地方呢?
两个关键点:涌现能力和思维链 ,这两者是大语言模型不断接近人类的关键特征。
涌现能力 (Emergent Abilities)是指模型具有从原始训练数据中自动学习并发现新的、更高层次的特征和模式的能力。就中文释义而言,涌现能力也指大语言模型涌现出来的新能力。
涌现能力的另一个重要表现是多模态模型的泛化能力。在没有专门训练过的情况,GPT 4也可以泛化到新的、未知的多模态数据样本上。这种泛化能力主要取决于模型的结构和训练过程,以及数据的数量和多样 性。如果模型具有足够的复杂性和泛化能力,就可以从原始数据中发现新的、未知的特征和模式。
多模态大语言模型(Multi-modal Large Language Model, MLLM)可实现更好的常识推理性能,跨模态迁移更有利于知识获取,产生更多新的能力,加速了能力的涌现。这些独立模态或跨模态新特征、能力或模式通常不是通过目的明确的编程或训练获得的,而是模型在大量多模态数据中自然而然的学习到的。
思维链 (Chain of Thought)可视为大语言模型涌现出来的核心能力之一。思维链是ChatGPT和GPT 4能 让大众感觉到语言模型“像人”的关键特性。
通过多模态思维链技术, GPT 4将一个多步骤的问题(例如图表推理) 分解为可以单独解决的中间步骤。 在解决多步骤推理问题时,模型生成的思维链会模仿人类思维过程。
虽然GPT 4这些模型并非具备真正的意识或思考能力,但用类似于人的推理方式的思维链来提示语言模型,极大的提高了GPT 4在推理任务上的表现,打破了精调(Fine-tune)的平坦曲线。具备了多模态思维链能力的GPT 4模型具有一定逻辑分析能力, 已经不是传统意义上的词汇概率逼近模型。
3.3 ChatGPT的训练阶段
不断的将模型扩大规模,虽然使其在各种任务展现出了出色的表现,但是在本质上并不能使模型很好 的遵循用户的意图。例如大语言模型可能会生成不真实的、不符合人类道德标准和社会规范的(有毒的) 以及对用户没有用的答案,总的来说就是没法和人类进行沟通。
为什么会出现输出的答案不是人类想要的答案这种现象呢?
一种解释是模型训练时目标函数设定的问题,大语言模型在训练时是以让模型生成文本 下一个词为目标的,与我们希望根据指示来生成高质量的优秀答案的目标是有差别的。那么,如何将模型与人类链接起来呢?
ChatGPT背后采用了这样一种技术:生物反馈强化学习(reinforcement learning from human feedback, RLHF)。具体做法是首先通过提交在OpenAI API上 问题标注数据并写出答案对模型进行微调,然后又收集了模型对一个问题的不同答案的排序数据集,并人 工对其答案的好坏进行排序,然后用强化学习模型对其进行学习。
ChatGPT的训练过程分为以下三个阶段:
第一阶段:训练监督策略模型
GPT 3本身很难理解人类不同类型指令中蕴含的不同意图,也很难判断生成内容是否是高质量的结果。为 了让 GPT 3初步具备理解指令的意图,首先会在数据集中随机抽取问题,由人类标注人员,给出高质量答案,然后用这些人工标注好的数据来微调 GPT 3模型(获得SFT模型, Supervised Fine-Tuning)。
此时的SFT模型在遵循指令/对话方面已经优于 GPT 3 ,但不一定符合人类偏好。
第二阶段:训练奖励模型(Reward Mode, RM)
这个阶段的主要是通过人工标注训练数据(约33K个数据),来训练回报模型。在数据集中随机抽取问题,使用第一阶段生成的模型,对于每个问题,生成多个不同的回答。人类标注者对这些结果综合考虑给出排名顺序。这一过程类似于教练或老师辅导。
接下来,使用这个排序结果数据来训练奖励模型。对多个排序结果,两两组合,形成多个训练数据对。 RM模型接受一个输入,给出评价回答质量的分数。这样,对于一对训练数据,调节参数使得高质量回答的打分比低质量的打分要高。
第三阶段:采用PPO (Proximal Policy Optimization,近端策略优化)强化学习来优化策略。
PPO的核心思路在于将Policy Gradient中On-policy的训练过程转化为Off-policy,即将在线学习转化为离线学习,这个转化过程被称之为Importance Sampling。这一阶段利用第二阶段训练好的奖励模型,靠奖励打分来更新预训练模型参数。在数据集中随机抽取问题,使用PPO模型生成回答, 并用上一阶段训练好 的RM模型给出质量分数。
把回报分数依次传递,由此产生策略梯度,通过强化学习的方式以更新PPO模型参数。
如果不断重复第二和第三阶段,通过迭代,会训练出更高质量的ChatGPT模型。
四、大模型的发展方向
当前,大模型正引发一场技术热潮,其应用如春花般遍地开放,各行各业都在积极探索并抢占这一先机。尽管我们仍处于大模型落地应用的初级阶段,但正是这一探索期让现在入行的人员占据了显著的优势。事实上,大模型及其相关的岗位如今已经供不应求,显示出这一领域的巨大潜力和前景。对于开发来说,我认为可以从以下三方面来进行考虑:
- 如何化技术为产品,实现大语言模型的商业应用?
适用人群:优秀的编程能力和Prompt Engineering能力
大语言模型,尤其是像OpenAI的在线大模型这类产品,不仅在技术性能上具备出色的表现,还在商业变现方面展示了显著优势。其首要优点在于强大的NLP能力,能够广泛支持如自动翻译、智能助手、文本和情感分析等多种经典任务。此外,这些模型通过自然语言与用户进行无缝交互,极大地降低了新产品的使用门槛。
重要的是,使用OpenAI的在线大模型,甚至不需要深入了解底层的机器学习或NLP原理。它可以作为一个“黑盒子”来快速和敏捷地开发各种应用。只要具备基础的编程能力,懂得如何设定合适的提示词,并了解工业级的提示生成流程,就可以轻松地构建各种功能强大、用户友好的NLP应用。在此基础上,一系列充满创意的应用,如AI算命师、AI心理咨询等纷纷涌现,进一步丰富了大模型在日常生活和工作中的应用场景。
- 如何研发、训练私有化的垂直领域大模型?
适用人群:具备扎实的机器学习、深度学习和自然语言处理(NLP)等AI方面的基础知识
尽管GPT系列模型的完整细节尚未完全开源,但其成功已经为提升语言模型性能指明了一条路径。受到GPT的启示,全球各大科技公司正积极开发基于BERT、GPT,或是其他Transformer组合的大模型。以国内一流的ChatGLM系列为例,它便是在BERT和GPT的理念基础上开发的中文大模型。同时,与大模型研发和训练相关的技术,如生物反馈式强化学习(RLFH)、近端策略优化(PPO)、奖励权重策略(Reward-based Weighting),以及DeepSpeed训练引擎等,也在迅速发展,并展现出不可阻挡的势头。虽然目前可能不再是NLP理论高峰,但无疑,大模型的算法研发和训练仍然是NLP领域最前沿的研究方向之一
- 如何降低大模型应用门槛与应用成本?
适用人群:具备扎实的机器学习、深度学习和自然语言处理(NLP)等方面的基础知识,或者具备优秀的Prompt Engineering能力
大模型需要消耗大量的数据和计算资源,这在商业应用中通常意味着高昂的成本。为了降低这些门槛和成本,多种先进的预训练、微调和大规模语料库构建技术正在迅速发展。自2020年以来,已经出现了许多创新的微调和自动语料生成方法,包括有监督微调(SFT)、低阶自适应微调方法(LoRA)、提示词前缀微调(Prefix Tuning)、轻量级提示词微调(Prompt Tuning)、以及百倍效率提升的微调方法P-Tuning V2和自适应预算分配微调方法(AdaLoRA)等。这些技术不仅推动了GPT-4.0等先进模型的发展,而且已经在NLP的研究和应用方面产生了深远影响,大幅度改变了该领域的现状。
最后,感谢您阅读这篇文章!如果您觉得有所收获,别忘了点赞、收藏并关注我,这是我持续创作的动力。您有任何问题或建议,都可以在评论区留言,我会尽力回答并接受您的反馈。如果您希望了解某个特定主题,也欢迎告诉我,我会乐于创作与之相关的文章。谢谢您的支持,期待与您共同成长!
相关文章:
OpenAI开发系列(二):大语言模型发展史及Transformer架构详解
全文共1.8w余字,预计阅读时间约60分钟 | 满满干货,建议收藏! 一、介绍 在2020年秋季,GPT-3因其在社交媒体上病毒式的传播而引发了广泛关注。这款拥有超过1.75亿参数和每秒运行成本达到100万美元的大型语言模型(Large …...
Gson - 一个Java序列化/反序列化库
官网 GitHub - google/gson: A Java serialization/deserialization library to convert Java Objects into JSON and back 项目简介 一个Java序列化/反序列化库,用于将Java对象转换为JSON和返回JSON。 Gson is a Java library that can be used to convert Java…...
6-1 汉诺塔
汉诺(Hanoi)塔问题是一个经典的递归问题。 设有A、B、C三个塔座;开始时,在塔座A上有若干个圆盘,这些圆盘自下而上,由大到小地叠在一起。要求将塔座A上的圆盘移到塔座B上,并仍按同样顺序叠放。在…...
Linux之initd管理系统(海思、ZYNQ、复旦微)添加密码登录验证
设置root用户密码:passwd命令设置密码,即修改/etc/passwd文件 一、串口提示输入用户名密码方法 修改 /etc/inittab 方法一: 增加: ::askfirst:-/bin/login 注释: #::respawn:/sbin/getty -L ttyS000 115200 vt…...
怎么更改代理ip,代理ip如何切换使用?
我们要如何使用HTTP代理,对它进行切换使用呢? 如果你购买了青果网络的HTTP代理,可以在文档这边获取使用方法: 可以在这里调试: 也可以在这里选择key提取。 如果有的朋友们想利用利用python,每隔30秒使用API…...
【C++从0到王者】第三十三站:AVL树
文章目录 前言一、AVL 树的概念二、AVL树的实现1. AVL树的结点定义2. AVL树的插入之插入部分3. AVL树的插入之平衡因子的改变4. AVL树的插入之左旋5. AVL树的左旋抽象图6.AVL树的右旋抽象图7. AVL树的双旋8. AVL树的右左双旋9. AVL树的右左双旋的本质10. AVL树的左右双旋11. AV…...
手机机型响应式设置2
window.screen.height:屏幕高度 window.innerHeight:视口高度(去除浏览器头尾的高度) document.body.clientHeight:内容高度 vh:网页视口高度的1/100 vw:网页视口宽度的1/100 vmaxÿ…...
uni-app 之 解决u-button始终居中问题
uView中u-button始终居中问题如何解决的简单方法? 1:给该元素margin-right: 0;可以达到向右靠齐; 2:给该元素的父元素设置float: right image.png <u-button style"width: 50px; margin-left: 0;" plain"t…...
Python日期处理库:掌握时间的艺术
💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 日期和时间在计算机编程…...
JOSEF约瑟 智能电流继电器KWJL-20/L KWLD26 零序孔径45mm 柜内导轨式安装
KWJL-20智能电流继电器 零序互感器: KWLD80 KWLD45 KWLD26 KWJL-20 一、产品概述 KWJL-20系列智能剩余电流继电器(以下简称继电器)适用于交流电压至660V或更高的TN、TT、和IT系统,频率为50Hz。通过零序电流互感器检测出超过…...
NLP技术如何为搜索引擎赋能
目录 1. NLP关键词提取与匹配在搜索引擎中的应用1. 关键词提取例子 2. 关键词匹配例子 Python实现 2. NLP语义搜索在搜索引擎中的应用1. 语义搜索的定义例子 2. 语义搜索的重要性例子 Python/PyTorch实现 3. NLP个性化搜索建议在搜索引擎中的应用1. 个性化搜索建议的定义例子 2…...
演唱会没买到票?VR直播为你弥补遗憾
听说周杰伦开了演唱会?没买到票的人是不是有着大大的遗憾呢?很多时候大型活动、演唱会都会因为场地限制而导致很多人未能有缘得见,而且加上票价成本高,“黄牛票”事件频出,我们的钱包受不住啊!!…...
myabtis的缓存级别
文章目录 MyBatis缓存的区别是什么作用范围方面有哪些差异生命周期数据进行了存储缓存的优缺点 MyBatis缓存的区别是什么 MyBatis 提供了一级缓存和二级缓存,这两者的主要区别在于其作用范围和生命周期。 一级缓存:一级缓存是 SqlSession 级别的缓存。…...
gin框架再探
Gin框架介绍及使用 | 李文周的博客 (liwenzhou.com) lesson03_gin框架初识_哔哩哔哩_bilibili 1.路由引擎 //路由引擎 rgin.Default() 2.一些http请求方法 get post put delete等等 遇到什么路径,执行什么函数 r.GET("/hello",func{做你想做的事返回…...
经典算法-----约瑟夫问题(C语言)
目录 前言 故事背景 约瑟夫问题 环形链表解决 数组解决 前言 今天我们来玩一个有意思的题目,也就是约瑟夫问题,这个问题出自于欧洲中世纪的一个故事,下面我们就去通过编程的方式来解决这个有趣的问题,一起来看看吧!…...
代码随想录 动态规划Ⅴ
494. 目标和 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - ,然后串联起所有整数,可以构造一个 表达式 : 例如,nums [2, 1] ,可以在 2 之前添加 ,在 1 之前添加 - …...
驱动DAY9
驱动文件 #include <linux/init.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/gpio.h> #include <linux/fs.h> #include <linux/io.h> #include <linux/device.h> #incl…...
03贪心:摆动序列
03贪心:摆动序列 376. 摆动序列 局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。 整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。…...
javascript获取元素在浏览器中工作区域的左、右、上、下距离,或带滚动条的元素在页面中的大小
//获取元素在包含元素框中的大小 //第1个函数为获取元素在包含元素中左内边框的距离 function getELementLeft(element){//获取元素在包含元素左边距离var actualeftelement.offsetLeft;//获取元素的上级包含元素var currentelement.offsetParent;//循环到一直没有包含元素whil…...
VSCode 安装使用教程 环境安装配置 保姆级教程
一个好用的 IDE 不仅能提升我们的开发效率,还能让我们保持愉悦的心情,这样才是非常 Nice 的状态 ^_^ 那么,什么是 IDE 呢 ? what IDE(Integrated Development Environment,集成开发环境)是含代码…...
c盘中temp可以删除吗?appdata\local\temp可以删除吗?
http://www.win10d.com/jiaocheng/22594.html C盘AppData文件夹是一个系统文件夹,里面存储着临时文件,各种应用的自定义设置,快速启动文件等。近期有用户发现appdata\local\temp占用了大量的空间,那么该文件可以删除吗?…...
Java手写聚类算法
Java手写聚类算法 1. 算法思维导图 以下是聚类算法的实现原理的思维导图,使用Mermanid代码表示: #mermaid-svg-AK9EgYRS38PkRJI4 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-AK9EgYRS38…...
解密Java多线程中的锁机制:CAS与Synchronized的工作原理及优化策略
目录 CAS什么是CASCAS的应用ABA问题异常举例 Synchronized 原理基本特征加锁过程偏向锁轻量级锁重量级锁 其他优化操作锁消除锁粗化 CAS 什么是CAS CAS: 全称Compare and swap,字面意思:”比较并交换“,CAS涉及如下操作: 假设内存中的原数据…...
solid works草图绘制与设置零件特征的使用说明
(1)草图绘制 • 草图块 在 FeatureManager 设计树中,您可以隐藏和显示草图的单个块。您还可以查看块是欠定义 (-)、过定义 () 还是完全定义。 要隐藏和显示草图的单个块,请在 FeatureManager 设计树中右键单击草图块,…...
vue3使用router.push()页面跳转后,该页面不刷新问题
文章目录 原因分析最优解决 原因分析 这是一个常见问题,当使用push的时候,会向history栈添加一个新记录,这个时候,再添加一个完全相同的路由时,就不会再次刷新了 最优解决 在页面跳转时加上params参数时间 router.…...
如何理解数字工厂管理系统的本质
随着科技的飞速发展和数字化转型的推动,数字工厂管理系统逐渐成为工业4.0时代的重要工具。数字工厂系统旨在整合和优化工厂运营的各个环节,通过实时数据分析和处理,提升生产效率,降低成本,并增强企业的整体竞争力。为了…...
笔记1.3 数据交换
如何实现数据通过网络核心从源主机到达目的主机? 数据交换 交换网络: 动态转接动态分配传输资源 数据交换类型: (1)电路交换 (2)报文交换 (3)分组交换 电路交换的特…...
实时车辆行人多目标检测与跟踪系统(含UI界面,Python代码)
算法架构: 目标检测:yolov5 目标跟踪:OCSort其中, Yolov5 带有详细的训练步骤,可以根据训练文档,训练自己的数据集,及其方便。 另外后续 目标检测会添加 yolov7 、yolox,目标跟踪会…...
谷歌AI机器人Bard发布强大更新,支持插件功能并增强事实核查;全面整理高质量的人工智能、机器学习、大数据等技术资料
🦉 AI新闻 🚀 谷歌AI机器人Bard发布强大更新,支持插件功能并增强事实核查 摘要:谷歌的人工智能聊天机器人Bard发布了一项重大更新,增加了对谷歌应用的插件支持,包括 Gmail、Docs、Drive 等,并…...
NI SCXI-1125 数字量控制模块
NI SCXI-1125 是 NI(National Instruments)生产的数字量控制模块,通常用于工业自动化和控制系统中,以进行数字输入和输出控制。以下是该模块的一些主要产品特点: 数字量输入:SCXI-1125 模块通常具有多个数字…...
网站推广托管/福州seo结算
请创建一个一维整型数组用来存储待排序关键码,关键码从数组下标为1的位置开始存储,下标为0的位置不存储关键码。输入关键码的个数,以及各个关键码,采用起泡排序的方法对关键码数组进行排序,输出每轮比较的过程。 输入描…...
做条形码哪个网站比较好/线上销售渠道有哪些
用过Windows XP系统的用户都知道,Windows XP有专用的窗口主题,很具特色。可是,Windows XP样式的窗口主题在默认的情况下,其标题栏都比较宽,尤其是显示器的分辨率为800600的时候,用IE浏览器或资源管理器时&a…...
池州哪家做网站/北京培训seo哪个好
在通过java连接cassandra时,其中com.datastax.driver.core是通过maven加入的,通过Idea运行时是正常的,在导出jar时如果不是将所有的jar打包成一个jar时也是正常的,但是如果将所有的第三方打包成jar,则会出现如下错误&a…...
建设网站需要的人员及资金/网红营销
极限的计算方法 一、初等函数: 1.limCC(C是常值函数);2.若 fx≤M(即fx是有界量),limα0(即α是无穷小量),⇒limfx⋅α0, 特别:fxC⇒limC⋅α0 ;3.若 fx≤…...
常州本地网站/windows优化大师官方网站
1.什么是multidict词典> 在python中,“ multidict ”一词用于指代字典,在字典中可以将单个键映射到多个值。例如 多重结构 multidictWithList {key1 : [1, 2, 3],key2 : [4, 5]}multidictWithSet {key1 : {1, 2, 3},key2 : {4, 5}}1. list如果要保留…...
屏山县龙华镇中心村建设招标网站/网络营销推广方案有哪些
文件上传 文件上传几乎我们天天都在使用,在工作中也会遇到这样的需求。那么我们如何前端和后端配合上传文件呢? 完整案例下载 我们在开始讲解之前,我已经提前为大家准备了一个前后端完整的案例 gitee地址: 上传文件ÿ…...