神经网络学习笔记10——RNN、ELMo、Transformer、GPT、BERT

news2024/10/11 12:31:35

系列文章目录

参考博客1

参考博客2

文章目录

  • 系列文章目录
  • 前言
  • 一、RNN
    • 1、简介
    • 2、模型结构
    • 3、RNN公式分析
    • 4、RNN的优缺点及优化
      • 1)LSTM是RNN的优化结构
      • 2)GRU是LSTM的简化结构
  • 二、ELMo
    • 1、简介
    • 2、模型结构
      • 1)输入
      • 2)左右双向上下文信息
      • 3)上下双层LSTM
      • 4)总结
    • 3、ELMo的优缺点及优化
  • 三、Transformer
    • 1、简介
    • 2、基础结构
      • 1)Encoder-Decoder编码器-解码器
      • 2)Attention注意力机制
      • 3)self-Attention自注意力机制
      • 4)Multi-Head Attention多头注意力机制
    • 3、Transformer优缺点及扩展
  • 四、Gpt
    • 1、简介
    • 2、GPT-1
      • 1) 无监督预训练
      • 2) 有监督微调
      • 3) 同一个预训练模型在不同任务下的微调规律
    • 3、GPT-2
      • 1)Zero-shot
    • 4、GPT-3
      • 1)Zero-Shot、One-shot、Few-Shot
      • 2)few-shot与In-context Learning
    • 5、GPT-123的局限性和挑战
  • 五、BERT
    • 1、简介
    • 2、BERT、ELMo、GPT
    • 3、基础结构
      • 1)Masked Language Model和Next Sentence Prediction
      • 2)基础结构
      • 3)预训练
      • 4)微调
    • 4、BERT优缺点


前言

一、NLP(自然语言处理)是什么
自然语言处理(Natural Language Processing,简称NLP)是用计算机来处理、理解以及运用人类语言(如字符、中文、英文等),它属于人工智能的一个分支,是计算机科学与语言学的交叉学科,又常被称为计算语言学。人类语言是抽象的信息符号,其中蕴含着丰富的语义信息,人类可以很轻松地理解其中的含义。而计算机只能处理数值化的信息,无法直接理解人类语言,所以需要将人类语言进行数值化转换。不仅如此,人类间的沟通交流是有上下文信息的,这对于计算机也是巨大的挑战。

从研究内容来看,自然语言处理包括语法分析、语义分析、篇章理解等。从应用角度来看,自然语言处理具有广泛的应用前景。特别是在信息时代,自然语言处理的应用包罗万象,例如:机器翻译、手写体和印刷体字符识别、语音识别及文语转换、信息检索、信息抽取与过滤、文本分类与聚类、舆情分析和观点挖掘等,它涉及与语言处理相关的数据挖掘、机器学习、知识获取、知识工程、人工智能研究和与语言计算相关的语言学研究等。

NLP由以下两个部分组成:

  • NLU(Natural Language Understanding,自然语言理解)是所有支持机器理解文本内容的方法模型或任务的总称,包括分词,词性标注,句法分析,文本分类/聚类,信息抽取/自动摘要等任务。
  • NLG(Natural Language Generation,自然语言生成)是一种自动将结构化数据转换为人类可读文本的软件过程。

近年来的NLP发展趋势及方向:
NNLM → Word2Vec → Seq2Seq → Seq2Seq with Attention → Transformer → Elmo → GPT → BERT

  • NNLM(Neural Network Language Model):神经网络语言模型,是一种基于神经网络的语言模型,用于预测文本序列中下一个词的概率。它通过学习单词之间的关联性来提高自然语言处理任务的性能。

  • Word2Vec:一种用于将单词映射到向量空间的技术,通过训练神经网络模型来学习单词的分布式表示,它将单词映射到一个连续的向量空间中,使得具有相似含义的单词在向量空间中距离较近。

  • Seq2Seq(Sequence-to-Sequence):一种序列到序列的模型,常用于机器翻译和文本摘要等任务,通过编码器将输入序列编码成固定长度的向量,再通过解码器生成目标序列。

  • Seq2Seq with Attention:在Seq2Seq模型的基础上加入了注意力机制,可以在解码阶段对输入序列的不同部分进行加权处理,提高模型对长距离依赖的建模能力。

  • Transformer:一种基于自注意力机制的模型架构,用于处理序列到序列的任务,如机器翻译和文本生成等,具有较好的并行化能力。

  • Elmo(Embeddings from Language Models):一种基于语言模型的词向量表示方法,通过预训练语言模型来获取单词的上下文相关表示。

  • GPT(Generative Pre-trained Transformer):一种基于Transformer架构的预训练语言模型,可以用于生成文本、问答等多种自然语言处理任务。

  • BERT(Bidirectional Encoder Representations from Transformers):一种基于Transformer的预训练语言模型,通过双向编码器来学习单词的上下文表示,在多项自然语言处理任务上取得了state-of-the-art的效果。

本文主要学习记录NLP领域中的经典算法:RNN、ELMo、Transformer、GPT以及BERT算法。
参考博客

一、RNN

1、简介

循环神经网络(Recurrent Neural Network, RNN)是一种特殊的神经网络结构, 它是根据"人的认知是基于过往的经验和记忆"这一观点提出的。不仅考虑前一时刻的输入,而且还赋予了网络对前面的内容的一种’记忆’功能。是一类以序列数据为输入,在序列的演进方向进行递归且所有节点(循环单元)按链式连接的递归神经网络。

在传统的神经网络模型中,是从输入层到隐含层再到输出层,层与层之间是全连接的,每层之间的节点是无连接的。但是这种普通的神经网络对于很多问题却无能无力。例如,你要预测句子的下一个单词是什么,一般需要用到前面的单词,因为一个句子中前后单词并不是独立的。RNN之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。理论上,RNN能够对任何长度的序列数据进行处理。但是在实践中,为了降低复杂性往往假设当前的状态只与前面的几个状态相关。

2、模型结构

视频参考

传统神经网络
在这里插入图片描述

卷积神经网络CNN在这里插入图片描述
卷积神经网络CNN能够很好地处理图片,但是在处理语句问题上就会出现问题,这是因为CNN没有记忆性,输入和输出的一一对应,也就是一个输入得到一个输出。不同的输入之间是没有联系的。换就话说,在处理语句问题中它把前后几句话,几个词语孤立起来,这样子整句话的意思可能就有了翻天覆地的变化。

循环神经网络RNN
在这里插入图片描述

CNN和RNN的区别是什么:

  • CNN主要用于处理具有网格状拓扑结构的数据,如图像(2D网格)和视频(3D网格)。它通过卷积层来提取局部特征,这些卷积层可以捕捉空间上的相关性,如形状、纹理等。CNN通常还包括池化层(用于降低特征维度和增加网络深度)和全连接层。

  • RNN专门用于处理序列数据,如文本、时间序列数据等。它的特点是在时间步之间有循环连接,这意味着当前时间步的输出依赖于前一时间步的输出。这种结构使RNN能够记忆之前的信息,并在当前上下文中使用这些信息。

RNN之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。
具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。如下图为循环神经网络。

3、RNN公式分析

二维展开:

在这里插入图片描述

简单公式分析:

在这里插入图片描述

总式中的参数解释:
x x x 是输入向量
s s s表示隐藏层的值
o o o是输出向量
U U U是输入层到隐藏层的权重矩阵
V V V是隐藏层到输出层的权重矩阵
W W W是隐藏层上一次的值作为这一次的输入的权重。

隐藏层:
s = f ( U ∗ x + b ) s = f(U * x + b) s=f(Ux+b)
s t = f ( U ∗ x t + W ∗ s t − 1 + b ) s_t = f(U * x_t + W * s_{t-1} + b) st=f(Uxt+Wst1+b)

输出层:
o t = g ( V ∗ s t + b ) o_t = g(V * s_t + b) ot=g(Vst+b)

公式中的 s s s s t − 1 s_{t-1} st1代表不同时刻的特征进行了关联,让神经网络有了一种记忆能力,理论上来说从 t t t时刻到 t n t_n tn时刻都可以反复代入之前的历史信息。

b b b是偏置假设为0。

4、RNN的优缺点及优化

优点:

  • 处理序列数据:RNN 是一种适用于处理序列数据的神经网络,能够有效地捕捉序列中的时序信息。
  • 共享权重:RNN 在每个时间步都使用相同的参数,可以有效地共享权重,减少模型的复杂度和训练的参数数量。
  • 上下文依赖建模:RNN 能够记忆之前的信息,并在后续时间步中利用该信息进行预测或决策,对于处理依赖于上下文的任务非常有用。

缺点:

  • 梯度消失/爆炸:RNN 在反向传播时,由于参数共享和多次连乘的特性,容易出现梯度消失或梯度爆炸的问题,导致模型难以训练或无法收敛。
  • 长期依赖问题:由于梯度消失的原因,RNN 在处理长序列时难以捕捉到长期依赖关系,只能有效利用较短的上下文信息。
  • 计算效率较低:RNN 的计算过程是基于时间步展开的,无法并行,每个时间步都需要依次计算,造成计算效率较低,尤其是处理较长序列时,早期的时序信息需要丢弃。
    在这里插入图片描述

1)LSTM是RNN的优化结构

LSTM是RNN的一种,可以解决RNN长序列训练过程中的梯度消失和梯度爆炸问题,当一条序列足够长,那RNN将很难将信息从较早的时间步传送到后面的时间步,而LSTM能学习长期依赖的信息,记住较早时间步的信息,因此可以做到联系上下文。
不同与RNN,RNN是想要记住所有的信息,不在乎不关注信息是否有用是否重要,而LSTM则设计了一个记忆细胞,起到筛选功能,具备选择记忆的功能,用于选择记忆重要的信息,过滤噪音与非重要信息以减轻记忆负担。它的出现解决了梯度失真的问题。而且使得RNN的收敛速度比普通的RNN要快上不少。

LSTM 的核心概念在于细胞状态以及“门”结构。细胞状态相当于信息传输的路径,让信息能在序列连中传递下去。你可以将其看作网络的“记忆”。理论上讲,细胞状态能够将序列处理过程中的相关信息一直传递下去。
在这里插入图片描述

2)GRU是LSTM的简化结构

GRU(Gate Recurrent Unit)是循环神经网络(RNN)的一种,可以解决RNN中不能长期记忆和反向传播中的梯度等问题,与LSTM的作用类似,不过比LSTM简单,容易进行训练。它与 LSTM 非常相似,与 LSTM 相比GRU 去除掉了细胞状态,使用隐藏状态来进行信息的传递。它只包含两个门:更新门和重置门。

GRU是LSTM的一个变种,也是为了解决长期记忆和反向传播中的梯度等问题而提出来的。GRU和LSTM在很多情况下实际表现上相差无几,但是GRU计算更简单,更易于实现。
在这里插入图片描述

扩展:LSTM和GRU的详细博文

二、ELMo

视频参考

1、简介

在NNLM模型中,尝试去预测文本序列中下一个词,使得在文本序列中,单个词语成为了一个输入单位一个矩阵向量也就是词向量,而Word2Vec模型根据这个思路,专门将单词映射到一个连续的向量空间中。

在NLP中使用词向量主要是用来解决两大问题:

  1. 单词使用的复杂性,例如语法、语义
  2. 不同语境下的单词使用,例如同义词

在ELMo之前,传统的Word2Vec或者Glove只能解决第一个问题,但是他们本身都是静态的词向量,也就是说每个词的向量化表示是固定的,无法解决一词多义,也不含有上下文信息,是没有语境的词语表示。但是很多词在不同的语境下表达的意思是完全不同的。例如“水果苹果”和“苹果公司”这两句话中的“苹果”表达的意思显然不同。因此在这种情况下,我们自然希望有一种动态的词向量能够根据语境来表示单词。

而ELMo提出一种高效的动态词向量,并提出了深层语境化的词语表示法,从左到右和从右到左两个方向的双向语言模型来生成词表示。即词语的表示能够含有上下文信息,是处于一定语境下的词语表示,以此作为下游任务(如情感分析等)的输入,来代替传统的word embedding,解决单词使用的复杂性,解决在不同语境下同一个单词的不同语法和语义。

它的词向量工作如下:

  • 对单词使用的复杂特征(例如,语法和语义)建模
  • 对这些特征在上下文中的变化(如歧义等)建模

ELMo的主要思想是通过从左到右和从右到左两个方向的预训练语言模型得到每层的状态表示,然后基于这些状态向量和初始embedding学习一个线性组合作为最终的词向量表示。

另外值得一提的是,ELMo也因此开创了预训练语言模型的先河。

ELMo论文

在这里插入图片描述
ELMo这个名字取自美国儿童剧《芝麻街》节目的一个角色简称,如上。
NLP模型家族大多数都是以芝麻街角色来命名,人称NLP之街。

2、模型结构

ELMo网络结构图(来源于BERT论文):
在这里插入图片描述
{ E 1 . . . E n E_1...E_n E1...En}:原始词向量矩阵

L S T M LSTM LSTM:LSTM模型

{ T 1 . . . T n T_1...T_n T1...Tn}:获取到的三层叠加词向量矩阵

这个ELMo模型可以划分为左右上下四种特殊结构,分别是左右各一个虚线框的LSTM集合,每个虚线框又可以分成上下两层LSTM。

1)输入

在{ E 1 . . . E n E_1...E_n E1...En}是一个有n个单词特征矩阵组成的序列,顺序从左到右,也就是说 E n − 1 E_{n-1} En1是上文信息, E n E_n En是下文信息。

E E E L S T M LSTM LSTM的连接中, E 1 E_1 1作为输入传入第一个LSTM模型, E 2 E_2 2作为输入传入第二个LSTM模型,,, E n E_n En作为输入传入第n个LSTM模型。

2)左右双向上下文信息

在左边的虚线框中,下层第一个LSTM的输入是 E 1 E_1 E1,下层第二个LSTM的输入是 E 2 E_2 E2和左边第一个LSTM传递的上文信息,也就是说下层第n个LSTM的输入是 E n E_n En和第n-1个LSTM传递的上文信息。

在右边的虚线框中,下层最后一个LSTM的输入是 E n E_n En,下层倒数第二个LSTM的输入是 E n − 1 E_{n-1} En1和最后一个LSTM传递的下文信息,也就是说下层第n-1个LSTM的输入是 E n − 1 E_{n-1} En1和第n个LSTM传递的下文信息。

3)上下双层LSTM

在两个虚线框中,会划分两层LSTM,下层获取到的LSTM会作为上层LSTM的输入,上层LSTM的输入来自于下层LSTM的输出以及上层前面或后面获取到的上/下文信息。

上下双层LSTM实际上就是为了增加单个词向量的不同方向的特征信息,如果信息够深还可以继续叠加层数,比如三层四层等等,只要最终的效果做够好并不限制层数。

4)总结

总结来说, E n E_n En这个单词特征矩阵会作为两种输入,为双层双向LSTM提供上文信息和下文信息。

左边虚线框下层LSTM的输入来自对应单词E的输入和前面的上文信息,
右边虚线框下层LSTM的输入来自对应单词E的输入和后面的下文信息,
左边虚线框上层LSTM的输入来自对应下层LSTM的输入和前面的上文信息,
右边虚线框上层LSTM的输入来自对应下层LSTM的输入和后面的下文信息,
左右虚线框的历史信息的输入方向相反。

最终将以 E n E_n En作为输入的那两个双层LSTM进行合并叠加得到了新的词向量 T n T_n Tn,此时的 T n T_n Tn的特征矩阵中包含了三种特征信息:

  • 原始词向量特征( E n E_n En
  • 包含原始词向量上下文信息的词向量特征(下层LSTM)
  • 包含原始词向量上下文信息的词向量特征的上下文信息的词向量特征(上层LSTM)

也有说法是 T n T_n Tn所包含是这三层特征信息:

  • 原始词向量特征( E n E_n En
  • 句法特征(下层LSTM)
  • 语义特征(上层LSTM)

虽然说法不一,但是得到的三层输出是一致的。

最终根据 T n T_n Tn里的这些特征数据进行句子语义关系判断,分类任务,阅读理解等多个领域工作。

3、ELMo的优缺点及优化

优点:

  • 上下文相关:动态单词的表示基于上下文的调整向量,而不在是使用静态固定的向量,解决了一词多义问题
  • 特征深度:使用了双向多层的LSTM可以提取到更多不同的词语特征和更多的语义信息
  • 字符表达:ELMo表示纯粹基于字符,然后经过CharCNN之后再作为词的表示,解决了OOV问题,而且输入的词表也很小。
  • 新的思路:上下文逻辑推动了多个NLP的任务出现

缺点:

  • 特征提取效率:特征提取方面使用到的是LSTM而不是新贵transformer,transformer的特征提取能力远强于LSTM
  • 特征融合效果:采用拼接信息的方式对于特征融合的效果较弱,并不是最好的方式
  • 计算量大:ELMo模型相对较大,需要更多的计算资源和时间进行训练和推理
  • 上期记忆限制:因为使用的是LSTM,导致ELMo只考虑了有限的上下文信息,可能无法捕捉到更远的语境信息

结合ELMo思路而发展出来的新模型:

  • ULMFiT(Universal Language Model Fine-tuning):通过在通用语言模型上进行预训练,再在特定任务上微调,提高了模型性能。
  • BERT(Bidirectional Encoder Representations from Transformers):基于Transformer架构,通过Masked Language Model和Next - Sentence Prediction任务进行预训练,取得了很好的效果。
  • GPT(Generative Pre-trained Transformer):基于Transformer的自回归语言模型,通过无监督学习进行预训练,适用于生成式任务。
  • RoBERTa(A Robustly Optimized BERT Approach):对BERT进行了一系列优化,包括更大的批量大小、更长的训练时间等,提高了模型性能。
  • XLNet:结合了Transformer-XL和自回归模型的优点,通过Permutation Language Modeling任务进行预训练,提高了模型的表现。

三、Transformer

视频参考1

视频参考2

1、简介

从RNN到Transformer的时间间隔较大,其中出现了很多优秀的自然语言算法比如LSTM、GRU、seq2seq以及attention,使得RNN一步一步发展到如今的Transformer,他虽然比循环神经网络成熟体ELMo发布时间要早,但是它的算法思路却脱离了当时循环网络主流,进入了新的神经网络赛道。

2017 年6月,Google 在论文 《Attention is All you need》中提出了 Transformer 模型,虽然比ELMo出现的要早,但是其使用 Self-Attention 结构取代了在 NLP 任务中传统的 类RNN 网络结构。
在这里插入图片描述

Transformer中抛弃了传统的CNN和RNN,整个网络结构完全是由Attention机制组成。更准确地讲,Transformer由且仅由self-Attenion和Feed Forward Neural Network组成。一个基于Transformer的可训练的神经网络可以通过堆叠Transformer的形式进行搭建,作者的实验是通过搭建编码器和解码器各6层,总共12层的Encoder-Decoder,并在机器翻译中取得了BLEU值得新高。
作者采用Attention机制的原因是考虑到RNN(或者LSTM,GRU等)的计算限制为是顺序的,也就是说RNN相关算法只能从左向右依次计算或者从右向左依次计算,这种机制带来了两个问题:

  • 时间片 t t t的计算依赖 t − 1 t-1 t1时刻的计算结果,这样限制了模型的并行能力;
  • 顺序计算的过程中信息会丢失,尽管LSTM等门机制的结构一定程度上缓解了长期依赖的问题,但是对于特别长期的依赖现象,LSTM依旧无能为力。

Transformer的提出解决了上面两个问题,首先它使用了Attention机制,将序列中的任意两个位置之间的距离是缩小为一个常量;其次它不是类似RNN的顺序结构,因此具有更好的并行性,符合现有的GPU框架。现在的Transformer被认为成为类似NLP、CNN、RNN之后的第四大类基础模型,或许这就是Attention Is All You Need的含金量吧。transformer的一大核心就是提出一个依赖于注意力机制Attention的模型。

Transformer论文

2、基础结构

原理图:
在这里插入图片描述
接下来解析该网络结构图

1)Encoder-Decoder编码器-解码器

Encoder-Decoder框架顾名思义也就是编码-解码框架,目前大部分attention模型都是依附于Encoder-Decoder框架进行实现,在NLP中Encoder-Decoder框架主要被用来处理序列-序列问题,也就是输入一个序列,生成一个序列的问题。这两个序列可以分别是任意长度,具体到NLP中的任务比如:
文本摘要,输入一篇文章(序列数据),生成文章的摘要(序列数据)
文本翻译,输入一句或一篇英文(序列数据),生成翻译后的中文(序列数据)
问答系统,输入一个question(序列数据),生成一个answer(序列数据)

编码器负责把自然语言序列映射为隐藏层(含有自然语言序列的数学表达),然后解码器把隐藏层在映射为自然语言序列。


编码器:
在这里插入图片描述
Inputs:编码器的输入,比如一段中文
Input Embedding:嵌入层,将序列表示为一个个向量
Positional Enocding:时序位置编码
Nx:n个这样的block块堆叠
Multi-Head Attention:多头注意力机制层
Add & Norm:类似残差设置,归一化
Feed Forward:前馈神经网络

第一个子层连接结构包括一个多头自注意力子层(qkv来自编码器输入,q=k=v)和归一化层以及一个残差连接。
第二个子层连接结构包括一个前馈全连接子层和归一化层以及一个残差连接。

编码器Encoder: 由N=6个相同的layers组成, 每一层包含两个sub-layers. 第一个sub-layer 就是多头注意力层(multi-head attention layer)然后是一个简单的MLP全连接层。 其中每个sub-layer都加了residual connection(残差连接)和normalisation(归一化)。根据残差结构把每一个层的输出维度维持在固定长度,比如512。那么调参的时候就兼顾每层的输出维度与需要多少层layers。


解码器:
在这里插入图片描述
Outputs:解码器输入,shifted right 从左向右移位,也就是将解码器之前时刻的输出作为当前时刻的输入
Input Embedding:嵌入层,将序列表示为一个个向量
Positional Enocding:时序位置编码
Nx:n个这样的层堆叠
Masked Multi-Head Attention:带掩码的多头注意力机制层,掩盖后面的值,使其权重为0,掩码的作用
Multi-Head Attention:多头注意力机制层
Add & Norm:类似残差设置,归一化
Feed Forward:前馈神经网络

第一个子层连接结构包括一个多头掩码自注意力子层(qkv来自解码器输入,q=k=v,做Masked掩码)和归一化层以及一个残差连接。
第二个子层连接结构包括一个多头注意力子层(kv来自编码器输出,q来自解码器第一子层的输出)和归一化层以及一个残差连接。
第三个子层连接结构包括一个前馈全连接子层和归一化层以及一个残差连接。

解码器Decoder: 由N=6个相同的Layer组成,但这里的layer和encoder不一样, 这里的layer包含了三个sub-layers, 其中有一个self-attention layer, encoder-decoder attention layer 最后是一个全连接层。前两个sub-layer 都是基于multi-head attention layer。这里有个特别点就是masking, masking 的作用就是防止在训练的时候 使用未来的输出的单词。比如训练时,第一个单词是不能参考第二个单词的生成结果的。Masking就会把这个信息变成0,用来保证预测位置 i 的信息只能基于比 i 小的输出。


解码器的输入一个是之前时刻的输出,另一个是当前编码器的输出,两者作为当前时刻解码器的输入,其中之前时刻的输出需要经过带掩码的多头注意力机制层处理,再汇合当前编码器的输出,然后重复一次和编码器一样的操作。

最后将解码器的输出传入linear层和softmax层这个神经网络层中进行预测。

2)Attention注意力机制

深度学习中的注意力和人类的注意力机制有关,因为人类的注意力资源是有限的,我们在关注的目标区域投入更多的注意力资源,从而在目标区域获得更多的信息,抑制其它无用的信息。这种机制可以让我们从大量信息中快速筛选出有价值的信息。所以在当前计算机算力资源的限制下,注意力机制绝对是提高效率的一种必要手段,将注意力集中到有用的信息上,从而减小在噪声中花费的时间。注意力的核心目标就是从众多信息中选择出对当前任务目标更关键的信息,将注意力放在上面。

一个典型的Attention思想包括三部分:
Q(query)要查询相关性的向量,后续会去和每一个k进行匹配
K(key)用于查询向量进行比较的向量,后续会被每个q匹配
V(value)查询信息得到的向量值,从a中提取得到的信息

QKV是什么:
在Transformer中,QKV是是根据输入特征产生的向量,通过输入序列中每个元素的嵌入向量(embedding)通过三个线性变换得到的。

具体来说,对于输入序列中的每个元素,都可以通过一个嵌入矩阵将其转化为一个固定维度的向量表示。假设嵌入向量的维度为d,那么对于输入序列中的每个元素,都可以得到一个d维的嵌入向量表示。然后,对于每个嵌入向量,通过三个不同的线性变换(即Query、Key、Value变换)得到三个向量Q、K、V,这些向量的维度仍然是d。其中,Query向量表示当前元素的查询向量,Key向量表示所有元素的关键字向量,Value向量表示所有元素的值向量。

这三个向量的计算公式如下:其中,Embedding为输入序列中的嵌入向量矩阵, W Q W_Q WQ W K W_K WK W V W_V WV分别为Query、Key、Value向量的权重矩阵。通过这三个变换,每个元素都会得到一个Query向量、一个Key向量和一个Value向量。

为什么要设置QKV:

  • 打破对称性
    具体来说, A对B的重要程度和B对A的重要程度可以是不同的。A对B的重要程度是Key(A) * Query(B), 而B对A的重要程度是Key(B) * Query(A)。 可以看出,A对B的重要程度与B对A的重要程度是不同的。 然而,如果K和Q是一样的,那么A对B的重要程度和B对A的重要程度是一样的。

  • 增强模型表示能力。

  • 避免自己和自己的点积太大。

QKV怎么用:
给Q与K设置一个注意力公式 F ( Q , K ) F(Q,K) F(Q,K),大概就是一个相似值的计算公式,来获取对不同K的注意力得分 s s s,将得分进行softMax归一化得到不同的相似度作为权重值 a a a,根据对应的V和权重 a a a进行加权计算,将所有结果 ∗ * 进行相加得到的加权和就是Attention Value。

在这里插入图片描述

3)self-Attention自注意力机制

自注意力机制实际上是注意力机制中的变种型,Attention和Self-Attention的区别:

  • Attention中K和V往往是同源的(也可以不同源),而Q没有任何要求,所以attention其实是一个很宽泛的概念,没有规定Q、K、V是怎么来的,只要满足QKV相乘计算相似度这种流程的都是注意力机制(所以才有通道注意力机制、空间注意力机制);

  • Self-Attention属于Attention,要求QKV必须同源,依然代表X,本质上可以看作是相等的,只是对同一个词向量X乘上了参数矩阵,作了空间上的变换;

A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q, K, V ) = softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dk QKT)V

在transform中的自注意力机制计算公式其实和上文中的QKV计算是基本一样的,计算QK的注意力得分,将得分归一化,然后作为V的权重计算出最终结果。
不同的是有一个维度 d k d_k dk,它的作用就是为了使得不同的QK之间分布更加均衡,避免出现过大或过小的QK值,使得在计算归一化时,这些权重能够合理分布在{0,1}之间,而不是全都向两端靠拢,过分接近一或者零。

公式图形化:

在这里插入图片描述
输入Q和K的矩阵进行矩阵乘法(MatMul), 然后经过除根号(scale),进行掩码(Mask)操作避免 t n t_n tn时刻就看见 t n + 1 t_{n+1} tn+1及以后时刻的内容,softmax得到新的权重,再将权重矩阵和V矩阵进行矩阵乘法操作得到最终输出。

其实mask的目的是使得矩阵中不需要的内容变得负无穷(或是一个很小的负数),这样通过softmax后就趋近于0。这样处理的目的是考虑到实际应用中的情况,例如翻译任务中,我们希望在读取句子序列时每次只利用前面读过的词,与后面还没有读到的词句无关。

4)Multi-Head Attention多头注意力机制

MHA是一种多头注意力模型,每个头都使用了一层自注意力机制,从而增强模型对于不同特征的关注度。

MHA 的输入实际上依然是三个向量:查询向量(query)、键向量(key)和值向量(value)。对于每一个向量,MHA 都会执行一个线性处理投影到比较低的维度,再输入自注意力层中,得到h个输出后合并输出再做一次线性投影。

在这里插入图片描述

通常Query、Key、Value矩阵是通过Embedding嵌入向量矩阵和 W Q W_Q WQ W K W_K WK W V W_V WV计算得到的。在多头注意力机制中有H个Attention,每个Attention采用不同的QKV矩阵,每个矩阵都是随机的W初始化生成的。

或者对每个输入进行子空间拆分,比如将原始的512维嵌入空间被拆分成多个子空间(8个头,则每个子空间64维)。

通过一个注意力机制的多次并行运行,将独立的注意力输出串联起来,线性地转化为预期维度。直观看来,多个注意头允许对序列的不同部分进行注意力运算,允许模型同时关注来自不同位置的不同表示子空间的信息。

M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , . . . , h e a d h ) W O MultiHead(Q,K,V)=Concat(head_1, ..., head_h)W^O MultiHead(Q,K,V)=Concat(head1,...,headh)WO

W h e r e H e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) Where_{ }^{ } Head_i=Attention(QW_i^Q, KW_i^K, VW_i^V) WhereHeadi=Attention(QWiQ,KWiK,VWiV)

MHA 的多头机制可以有效提高模型的表达能力,同时也可以使模型学习到更加多样化和复杂的特征。在多头机制下,输入的序列数据会被分成多个头,每个头进行独立的计算,得到不同的输出。这些输出最后被拼接在一起,形成最终的输出。

多头注意力通过利用同一查询的多个不同版本并行实现多个注意力模块来工作。其思想是使用不同的权重矩阵对查询进行线性变换得到多个查询。每个新形成的查询本质上都需要不同类型的相关信息,从而允许注意模型在上下文向量计算中引入更多信息。

3、Transformer优缺点及扩展

优点:

  • 长距离依赖关系建模:Transformer模型通过自注意力机制能够更好地捕捉长距离依赖关系,使其在处理长序列和涉及远距离语义关系的任务中表现优秀。
  • 并行计算能力:相比传统的循环神经网络(RNN)模型,Transformer模型中多头注意力机制的并行计算极大提高了训练和推理的效率,允许更大规模的模型和更长的序列处理。
  • 通用性:Transformer模型在自然语言处理领域表现出色,但其架构也适用于其他领域的序列建模任务,如图像处理、时间序列分析等。

缺点:

  • 高计算成本:Transformer模型的复杂性导致在训练和推理过程中需要大量的计算资源,尤其是在处理大规模数据集时,需要大规模并行计算能力。
  • 优化难度:模型的复杂性和超参数的数量增加了优化的难度,需要仔细调整学习率、批量大小等超参数,以获得较好的性能。
  • 对长文本处理挑战:在处理长文本时,由于位置编码和注意力机制的限制,Transformer模型可能受到内存限制和效率影响,导致处理效率下降。
  • 对特定任务需要大量数据:对于某些任务,特别是涉及复杂语义关系和细粒度分类的任务,Transformer模型可能需要大量的标注数据才能发挥其最佳性能。

总的来说,Transformer模型因其强大的建模能力和并行计算优势,在许多序列建模任务中取得了显著的成功。然而,仍然需要解决其高计算成本和对特定任务需要大量数据的问题,并不断改进其在处理长文本和复杂语义关系方面的能力。

扩展:Transformer、VIT与BoTNet的详细博文

四、Gpt

视频参考

1、简介

GPT系列自然语言处理模型是openai开发推出的,是自然语言处理领域中最受欢迎的系列模型:

  • GPT-1:GPT-1于2018年6月发布,是GPT系列的第一个版本,第一个生成式预训练语言模型,参数量达到了1.17亿。它使用了12个Transformer编码器层和1.5亿个参数。GPT-1的训练数据包括了互联网上的大量文本,可用于生成文章、代码、机器翻译、问答等各类内容。

  • GPT-2:GPT-2于2019年2月发布,是GPT系列的第二个版本,参数量达到了15亿。它比GPT-1更大更强大,使用了24个Transformer编码器层和1.5亿到15亿个参数之间的不同配置。GPT-2在生成文本方面表现出色,但由于担心滥用风险,OpenAI最初选择限制了其训练模型的发布。

  • GPT-3:GPT-3于2020年5月发布,是GPT系列的第三个版本,参数量达到了1750亿。它采用了1750亿个参数,拥有1750亿个可调节的权重。GPT-3在自然语言处理(NLP)任务中表现出色,可以生成连贯的文本、回答问题、进行对话等。

  • GPT-3.5:GPT-3.5于2022年11月发布,参数量未知。GPT-3.5是在GPT-3基础上进行微调和改进的一个变种,它是对GPT-3的进一步优化和性能改进。

  • GPT-4:GPT-4于2023年3月发布,参数量未知。是openai迄今为止推出的最先进的语言模型,对比之前的模型能够提供更安全、更有效的响应。在生成创意内容和技术性文本方面更为先进,提供更准确的信息,能够处理图像输入并识别图像中的对象, 能够执行一系列精细复杂的高级任务。

GPT系列的模型在自然语言处理领域取得了巨大的成功,并在多个任务上展示出了强大的生成和理解能力。它们被广泛用于文本生成、对话系统、机器翻译、摘要生成等各种应用中,对自然语言处理和人工智能领域的发展有着重要的影响。

GPT系列是当前自然语言处理领域下最流行,也是商业化效果最好的自然语言大模型,并且他的论文也对NLP的领域产生巨大影响,Transformer以其卓越的性能击败了LSTM,GPT也以优异的表现战胜了ELMo,同时提出了多种具有前瞻性的训练方法,被后来的BERT等有重大影响的NLP论文所借鉴。

2、GPT-1

GPT的核心工作可以分为两个阶段:

  • 预训练阶段:使用transformer的decoder解码器在没有标注的大量文本数据中训练一个预训练语言模型
  • 微调阶段:调用标注的数据集对子任务进行微调,得到该任务对应的分类器

这个和视觉领域的预训练加上微调的思路是类似的,视觉领域中使用超大的标注数据集进行预训练,然后再进行微调。而GPT则是使用超大的无标注数据集进行预训练,然后再调用标注的数据集对子任务进行微调,在微调过程中只需要调整模型的输入就可以很好的适用于不同的任务。

这里提及几个名词的简单理解:

  • 有监督:是指从标注数据中学习预测模型的机器学习方法,其本质是学习输入到输出的映射的统计规律。
  • 无监督:是指从无标注数据中学习预测模型的机器学习方法,其本质是学习数据中的统计规律或潜在结构。
  • 半监督:是指从大量的未标记数据以及部分标记数据中学习预测模型的机器学习方法。
  • 自监督:是指直接从大规模的无监督数据中挖掘自身监督信息来进行监督学习和训练的一种机器学习方法(无监督学习的一种特殊情况),自监督学习需要标签,不过这个标签不来自于人工标注,而是来自于数据本身。

这几个监督方法存在兼容情况,并不是绝对的区分。

1) 无监督预训练

第一阶段的预训练的训练方法可以理解为无监督方法,毕竟还是使用无标注数据为主。

在一段无标注的tokens文本数据 U = { u 1 , . . . , u n } U = \lbrace{u_1 , . . . , u_n}\rbrace U={u1,...,un}中, U U U表示的是这段文本tokens, u i u_i ui表示的是这段文本中的第i个词token,然后使用 U U U来计算标准语言建模最大化似然目标函数。

在概率论和统计学中,似然函数是固定数据并视参数为变量的函数,而概率函数则是固定参数并视数据为变量的函数。

L 1 ( U ) = ∑ i l o g P ( u i ​ ∣ u i − k , . . . , u i − 1 ; θ ) L_1(U)= \sum_{i}log_{}P(u_i​∣u_{i−k} ,...,u_{i−1};θ) L1(U)=ilogP(uiuik,...,ui1;θ)

对于想要预测 u i u_i ui这个词,就需要获取 u i u_i ui的前一个词 u i − 1 u_{i-1} ui1 u i u_i ui的前K个词 u i − k u_{i-k} uik这一共K个连续词。

给定K个连续词,给定基于参数θ的语言模型 L 1 ( U ) L_1(U) L1(U),预测K个词下一个词 u i u_i ui的概率。对所有不同的词位置i进行求和,即对整个句子中的每个位置都进行相同的操作,这样可以计算整个句子的概率。

其中 超参数k 是上下文窗口的大小限制,也就是输入序列的长度。

那么这个使用参数为 θ 的神经网络就是transformer的decoder解码器,transformer由Encoder-Decoder编解码器框架组成,其中编码器能够获取到输入文本数据 U = { u 1 , . . . , u n } U = \lbrace{u_1 , . . . , u_n}\rbrace U={u1,...,un}中所有的元素,而解码器因为掩码的原因对第i个词抽取特征时,只会获取到i元素和i之前的元素,i之后的元素会被掩码锁住。所以使用解码器计算 L 1 ( U ) L_1(U) L1(U)时预测词 u i u_i ui时就不会获取到 u i u_{i} ui之后的数据。

h 0 = U W e + W p h_0 =UW_e +W_p h0=UWe+Wp
h l = t r a n s f o r m e r b l o c k ( h l − 1 ) ∀ i ∈ [ 1 , n ] h_l =transformer_{} block(h_{l−1})\forall{i}∈[1,n] hl=transformerblock(hl1)i[1,n]
P ( u ) = s o f t m a x ( h n W e T ) P(u)=softmax(h_n W_e^T) P(u)=softmax(hnWeT)

其中 U = ( u k , . . . , u 1 ) U = ( u_{k} , . . . , u_{1} ) U=(uk,...,u1)是表示K个词,也就是输入序列的长度, U W e UW_e UWe是上下文对应的embedding词嵌入投影, W p W_p Wp是词位置嵌入矩阵,两者相加得到 h 0 h_0 h0也就是初始输入。

通过上一次的输出 h l − 1 h_{l-1} hl1作为Transformer解码器的当前输入,得到当前输出 h l h_l hl,然后重复n次,n就是transformer的层数(12层,维度768)。

重复n次后得到最后的transformer输出,最终通过softmax函数和输出词嵌入矩阵的转置 W e T W_e^T WeT得到对下一个词的概率分布P(u)。

对于所有的U,得到的所有的P的对数和就是我们需要优化的目标,即上面说的 L 1 L_1 L1

2) 有监督微调

在预训练中,使用的数据是无标注的,而微调工作中,使用的数据是有标注的。

当预训练语言模型训练完成后,将其迁移到具体的NLP任务中,假设将其迁移到一个文本分类任务中,一段文本数据为 C C C,在序列中有 x 1 , . . , x m x^1,..,x^m x1,..,xm的m个元素,而该序列的标注是 y y y。将 x 1 , . . , x m x^1,..,x^m x1,..,xm的m个元素输入通过预先训练的模型来获得最后的transformer输出 h l m h^m_l hlm,然后softmax计算预测为y的概率:

P ( y ∣ x 1 , . . , x m ) = s o f t m a x ( h l m W y ) P(y|x^1,..,x^m)=softmax(h^m_l W_y) P(yx1,..,xm)=softmax(hlmWy)

那么预训练的时候使用的语言建模目标函数是 L 1 ( U ) L_1(U) L1(U),在文本分类微调工作相应的目标函数就需要修改为 L 2 ( C ) L_2(C) L2(C)

L 1 ( U ) = ∑ i l o g P ( u i ​ ∣ u i − k , . . . , u i − 1 ; θ ) L_1(U)= \sum_{i}log_{}P(u_i​∣u_{i−k} ,...,u_{i−1};θ) L1(U)=ilogP(uiuik,...,ui1;θ)

L 2 ( C ) = ∑ x , y l o g P ( y ​ ∣ x 1 , . . , x m ) L_2(C)= \sum_{x,y}log_{}P(y​∣x^1,..,x^m) L2(C)=x,ylogP(yx1,..,xm)

按道理来说只需要使用 L 2 ( C ) L_2(C) L2(C)进行分类工作就可以了,但在测试时发现将语言建模目标函数 L 1 ( U ) L_1(U) L1(U)作为文本分类微调工作的辅助可以提高监督模型的泛化能力和加速汇聚能力,所以将文本分类微调工作相应的目标函数 L 2 ( C ) L_2(C) L2(C)结合语言建模目标函数 L 1 ( U ) L_1(U) L1(U)进行优化得到 L 3 ( C ) L_3(C) L3(C)(超参数权重为λ):
L 3 ( C ) = L 2 ( C ) + λ ∗ L 1 ( C ) L_3(C)=L_2(C)+λ*L_1(C) L3(C)=L2(C)+λL1(C)

3) 同一个预训练模型在不同任务下的微调规律

在这里插入图片描述
左边是常见的transformer的decoder解码器。
右边是使用什么样的输入进行预训练然后用于不同的任务。

  • classification文本分类任务:
    在输入的text文本前面添加一个特殊记号作为初始符start,后面添加另一个特殊记号抽取符extract,再将这个序列输入transformer的decoder解码器中,然后在微调时将预训练模型最后得到的特征进行线性处理和分类工作。

  • entailment 文本蕴含任务:
    提供两段文本,一段是前提文本(premise)和一段是假设文本(hypothesis),前面添加初始符start,后面添加抽取符extract,文本中间加上了一个分隔符(delim)。将这个序列输入transformer的decoder解码器中,然后在微调时将预训练模型最后得到的特征进行线性处理和分类工作。
    注:文本蕴含任务(text entailment),它的任务形式是:给定一个前提文本(premise),根据这个前提去推断假设文本(hypothesis)与前提文本的关系,一般分为蕴含关系(entailment)、矛盾关系(contradiction)以及无关系,蕴含关系(entailment)表示从前提文本中可以推断出假设文本;矛盾关系(contradiction)即假设文本与前提文本矛盾。文本蕴含的结果就是这几个概率值。

  • similarity 文本相似性度量任务:
    提供两段文本,判断两段文字是否相似,因为相似是一个对称关系,文本间不需要区分相对顺序所以只需要区分不同的输入先后顺序。把文本划分两段不同的先后输入的序列,前面添加初始符start,后面添加抽取符extract,文本中间加上了一个分隔符(delim)。分别处理后得到两组transformer输出,然后在微调时按位相加再进行线性处理,从而得到相似还是不相似的二分类问题。

  • multiple choice问答和常识推理任务:
    提供多段文本,其中包含了一个问题和n个答案,将问题(question)与不同的答案(answer)分别拼接起来,前面添加初始符start,后面添加抽取符extract,文本中间加上了一个分隔符(delim)。分别处理后得到n组transformer输出经过模型后,再经过softmax层计算每个答案的置信度。

总而言之,GPT-1在面对不同任务,只需要将修改好输入的格式,再修改好输出的构造就好了,中间的预训练好的transformer模型是不需要改变的。

GPT1论文:Improving Language Understanding by Generative Pre-Training

3、GPT-2

GPT-1于2018年6月发布,而在同年10月BERT发布,它参考了GPT-1的同时也在全方位上击败了GPT-1。面对后来者BERT使用了相似的思路、不同的结构、更多的数据以及更大的模型来超越曾经的自己,openai在2019年2月发布了GPT-2来回击了BERT,来自学术界大佬的擂台争霸。

相似的思路:同样使用Transformer
不同的结构:GPT使用transformer解码器Decoder,BERT使用transformer编码器
更多的数据以及更大的模型:BERT使用了同样的数据集上正面击败GPT-1,同时使用更大的数据集再次超越之前训练的模型。

作为反击,GPT-2可以同样使用更多的数据、更大的模型、更极限的微调变种来展现更好的模型效果,继续和BERT进行编解码器之争,然后陷入各式各样微调变种的工程大战。

但是GPT-2没有这么做,如果为了击败而击败,反而让人觉得没意思,所以它引入了新的概念:零样本学习(Zero-shot learning)。

GPT2有4个不同的版本,分别如下图所示,区别在于embedding的维度和transformer-decoder的层数。

在这里插入图片描述

尽管目前很多有监督学习NLP模型效果已经很好,但都需要有针对单个任务训练使用大量有标注数据训练,当目标的分布稍有变化则不能继续使用,因此只能在狭窄的领域中起作用。GPT-2希望通过海量数据和庞大的模型参数训练出一个类似百科全书的模型,无需标注数据也能解决具体问题。

作者认为,当一个语言模型的容量足够大时,它就足以覆盖所有的有监督任务,也就是说所有的有监督学习都是无监督语言模型的一个子集。例如当模型训练完“Micheal Jordan is the best basketball player in the history”语料的语言模型之后,便也学会了(question:“who is the best basketball player in the history ?”,answer:“Micheal Jordan”)的Q&A任务。GPT-2的核心思想概括为:任何有监督任务都是语言模型的一个子集,当模型的容量非常大且数据量足够丰富时,仅仅靠训练语言模型的学习便可以完成其他有监督学习的任务。

1)Zero-shot

zero-shot的作用就是在做下游任务时不需要下游任务的任何标签信息,也不需要重新训练一个模型,即在更难的一个设定上体现他的一个新意度。

首先,预训练模型通常通过大规模的未标记数据进行训练,学习到丰富的语义表示和知识。这些预训练的模型可以用来提取特征或进行推理,从而在zero-shot learning任务中发挥作用。通过将预训练模型与zero-shot learning相结合,可以在没有标记数据的情况下执行新任务或识别新类别,从而提高模型的泛化能力和适应性。

比如在预训练数据集中并没有斑马的图像,但是有带条纹的动物(如老虎),有跟马长得相似的一类动物(如马、驴、小马等),还有黑白色的动物(如熊猫、企鹅等)的各种图像。可以提取这些图像的特征(条纹、形状似马、黑/白色)并生成词嵌入,组成字典。
然后,我们描述斑马的外观,并使用前面训练集里提出的特征来将斑马的外观转化成相应的词嵌入。
最后,当你给模型输入一张斑马的图像,它会先提取图像的特征,转化成词嵌入,然后与字典中最接近的词嵌入进行比较,得出那图像可能是只斑马。

在这里插入图片描述
以一般的图片分类问题为例:
(1)训练集数据X1及其标签Y1,包含了模型需要学习的类别(马、老虎和熊猫),这里和传统的监督学习中的定义一致;
(2)测试集数据 X2及其标签 Y2,包含了模型需要辨识的类别(斑马),这里和传统的监督学习中也定义一致;
(3)训练集类别的描述 A1,以及测试集类别的描述 A2;将每一个类别 Yi,都表示成一个语义向量ai的形式,而这个语义向量的每一个维度都表示一种高级的属性,比如“黑白色”、“有尾巴”、“有羽毛”等等,当这个类别包含这种属性时,那在其维度上被设置为非零值。对于一个数据集来说,语义向量的维度是固定的,它包含了能够较充分描述数据集中类别的属性。

在zero-shot中,希望利用X1和Y1来训练模型,而模型能够具有识别X2的能力,因此模型需要知道所有类别的描述A1和A2。zero-shot这样的设置其实就是上文中识别斑马的过程中,已知的条件。

zero-shot就可以被定义为:利用训练集数据训练模型,使得模型能够对测试集的对象进行分类,但是训练集类别和测试集类别之间没有交集;期间需要借助类别的描述,来建立训练集和测试集之间的联系,从而使得模型有效。

在这里插入图片描述

GPT-2的预训练结构类似于GPT-1,仍然使用单向的Transformer模型,只做了一些局部修改:
Layer normalization被转移到每个sub-block的输入上
在最后一个自注意力block后添加一个layer normalization。
采用一种改进的初始化方法,在初始化时将残差层的权重按的因子进行缩放,其中是残差层的数量。

但是GPT-2去掉了fine-tuning层的微调工作:不再针对同一个预训练模型在不同任务下进行微调,而是引入大量的训练文本,只要训练文本够大,网络够大,模型根据会输入自动识别出来需要做什么任务。当然GPT-2的输入也会加入提示词,比如:“TL;DR:”,GPT-2模型就会知道是做摘要工作了,是不是有点prompt-learning/In Context Learning的感觉了。

最后在GPT-2的论文中也提及使用transformer解码器和Zero-shot的方法在不同任务上的效果,总体而言是有效果的,在一些任务上能够做到排名靠前,但是在一些任务上似乎效果较差,但是随着模型的增大,整体任务上,效果是上升的。也就是说继续增加数据集做更大的模型还是能实现力大飞砖的,从而使得纯粹的无监督也能像有监督的效果一样好。

GPT2论文:Language Models are Unsupervised Multitask Learners

4、GPT-3

GPT-1使用了有监督的微调,GPT-2抛弃了微调使用了无监督Zero-shot,但是从整体上来说有标注样本往往能够推动模型有效学习。可GPT-1需要大量的标注数据又导致了标注成本过大,GPT-2使用无监督Zero-shot极致的压缩标注成本又导致有效性不是那么的好。

所以GPT-3提出了Few-shot少样本学习,也就是提供少量样本来引导模型有效学习,即减少标注成本又提高训练有效性。即使是使用了少量标签样本,但是在做子任务的时候同样延续了GPT-2的思路,不做fine-tuning微调与权重和梯度的更新。

GPT-3模型架构和GPT-2是一致的,只是引入了 Sparse Transformer 中的 sparse attention 模块(稀疏注意力)。

GPT-3提出的问题:

  • 子任务微调数据集的标注成本
  • 预训练模型与微调模型的泛化性不一致,意思是即使预训练模型在某个任务上的效果一般般,但是通过微调后都可以显著提高效果,那么预训练模型的泛化性就不再重要了,导致只能过份依赖微调手法。
  • 预训练-微调的方式不是那么符合人的思维逻辑

1)Zero-Shot、One-shot、Few-Shot

openai在训练GPT下游任务时使用的几种训练方式,简单概括如下:

  • fine-tuning微调:预训练 + 微调计算loss更新梯度,然后预测。会更新模型参数
  • zero-shot零样本:预训练 + task description + prompt,直接预测。不更新模型参数
  • one-shot单样本:预训练 + task description + example + prompt,预测。不更新模型参数
  • few-shot少样本:预训练 + task description + examples + prompt,预测。不更新模型参数

在这里插入图片描述

对于Zero-Shot、One-shot、Few-Shot三种方法在下游的各种子任务的实际效果进行测试,虚线代表的是下游的各种子任务的实际效果,实线是对所有下游的各种子任务的实际效果的平均计算值。

总体来说,在不同参数级的模型对所有下游的各种子任务的测试中,Few-Shot方法优于One-shot方法优于Zero-Shot方法,模型参数量的大小与测试效果成正比,模型越大效果越好,且不同方法的差距也越大。

在这里插入图片描述

2)few-shot与In-context Learning

few-shot的核心是In-context Learning情境学习,关键思想就是从类比中学习。首先ICL(In-context Learning) 需要一些示例来形成一个演示上下文,这些示例通常是用自然语言模板编写的,然后 ICL 将查询的问题(即你需要预测标签的 input)和一个上下文演示(一些相关的 cases)连接在一起,形成带有提示的输入,并将其输入到语言模型中进行预测。 值得注意的是,与需要使用反向梯度更新模型参数的fine-tuning微调训练阶段的有监督学习不同,ICL 不需要参数更新,并直接对预先训练好的语言模型进行预测。

GPT-3使用了和 GPT-2 基本相同的模型和架构,包括改进的初始设置、预归一化和 reversible tokenization。区别在于 GPT-3 在 transformer 的各层上都使用了交替密集和局部带状稀疏的注意力模式,类似于 Sparse Transformer。

在研究模型大小对模型性能的影响情况,OpenAI训练了 8 种不同的模型大小,涵盖 3 个数量级,从 1.25 亿参数到 1750 亿个参数不等,具备 1750 亿个参数的模型即为 GPT-3。

在有足够训练数据的情况下,验证损失的缩放比例应该近似为模型大小的光滑幂律函数。这项研究训练了多个不同大小的模型,这使得研究者可以对验证损失和下游语言任务检验该假设。

这里 n_params 表示可训练参数总量,n_layers 表示层数,d_model 表示每个瓶颈层中的单元数量(在该研究中前馈层总是瓶颈层大小的 4 倍,即 d_ff = 4 ∗ d_model),d_head 表示每个注意力头的维度。所有的模型均使用 n_ctx = 2048 tokens 的语境窗口。
在这里插入图片描述

5、GPT-123的局限性和挑战

  • 生成长文本依旧困难,比如写小说,可能还是会重复;
  • 语言模型使用了解码器,只能看到前面的信息;
  • 语言模型只是根据前面的词均匀预测下一个词,而不知道前面哪个词权重大;
  • 只有文本信息,缺乏多模态;
  • 样本有效性不够;
  • 模型是从头开始学习到了知识,还是只是记住了一些相似任务,这一点不明确;
  • 可解释性弱,模型是怎么决策的,其中哪些权重起到决定作用都不好解释
  • 有毒性:可能会生成假新闻;可能有一定的性别、地区及种族歧视。
  • 能耗问题。
  • 复现成本极高。

当时的GPT-3太大了,大到无法判断出GPT-3的学习方式,当时甚至对GPT-3是否真的在学习产生疑问,面对这么大的数据集,模型究竟是从头到尾学习到了具体的知识,还是只是根据问题从记录下来的数据中查找到相关性高的内容进行回复呢?
甚至当时面对如此庞大的参数量,都无法解释它的输出是如何生成的,是哪些权重参数做的决策?

GPT3论文:Language Models are Few-Shot Learners
GPT4技术文档:GPT-4 Technical Report

五、BERT

1、简介

2018年的10月11日,也就是GPT发布的几个月后,Google踩着GPT的尾巴,发布的论文《Pre-training of Deep Bidirectional Transformers for Language Understanding》,成功在 11 项 NLP 任务中取得 state of the art 的结果,霸占了各大自然语言处理榜单的榜首。而且在后面几年,BERT的追随者越来越多,衍生出了一系列跟BERT相关的模型,比如RoBERTa、SpanBERT、ALBERT、MacBERT等等,赢得自然语言处理学界的一片赞誉之声,BERT的影响力可见一斑。

在自然语言处理领域,有两个相当著名的大语言模型——BERT和GPT,如果说GPT是狂野粗暴的,那么BERT则称的上精致理想的。两个模型是同一年先后提出的,那一年BERT以不可抵挡之势,让整个人工智能届为之震动。据说当年BERT的影响力是GPT-1的十倍以上,庞大的参数量也引发了之后与GPT架构的模型大战。
在这里插入图片描述
BERT这个名字取自美国儿童剧《芝麻街》节目的一个角色简称,如上。
NLP模型家族大多数都是以芝麻街角色来命名,人称NLP之街。

2、BERT、ELMo、GPT

BERT分别引用参考了ELMo和GPT-1的思路,

  • 采用了ELMo的双向结构获取上下文信息,但是抛弃了RNN架构和预训练-基于特征的训练方式,拥抱了transformer架构。
  • 采用了GPT-1的transformer替代传统循环神经网络和预训练-微调的训练方式,但是使用的是transformer的编码器作为模型核心结构,并且使用左右双向上下文信息取代单向上下文信息。

在这里插入图片描述

换句话说BERT是当时ELMo和GPT-1之后的集大成者,取优去劣的后来者。

为什么使用Transformer编码器而不使用解码器和它的双向获取上下文信息有关,因为编码器可以看得见输入序列的全部位置的信息,而解码器因为掩码的存在,只能看见当前位置的前面的信息也就是左边的信息,后面的信息已经被掩码锁住遮掩掉了,所以使用Transformer编码器。

那为什么要获取左右双向上下文的信息,因为标准的语言模型只会从左到右的获取信息,如果在句子层面上进行情感分析任务和问答任务时,不需要很严谨的一步步获取每个词元的特征,无论是从左到右还是从右到左都是差不多的,那么做双向信息获取应该能够提供更多特征。

BERT论文

3、基础结构

1)Masked Language Model和Next Sentence Prediction

单向模型只能利用当前位置之前的信息进行预测,而无法利用当前位置之后的信息,通过使用Transformer编码器和MLM(带掩码的语言模型:Masked Language Model)从而更好地捕捉句子中的全局语义和结构信息。MLM主要的工作是:对于提供的一段输入序列,随机使用掩码遮掩掉这段序列中的一个或几个词,要求根据剩余词汇预测被遮掩的几个词分别是什么,如下图所示。

在这里插入图片描述

对被MLM处理的序列进行学习就像完形填空一样,又有前文信息和后文信息,缺失中间信息,那么想要推导缺失的内容就需要结合前后文进行预测。

在预训练中对一段序列中随机选择 15% 的词汇用于预测。对于在原句中被抹去的词汇, 80% 情况下采用一个特殊符号 [MASK] 替换, 10% 情况下采用一个任意词替换,剩余 10% 情况下保持原词汇不变。但是在微调任务的序列中并不会出现 [MASK] 标记。

而且使用MLM的另一个好处是:预测一个词汇时,模型并不知道输入对应位置的词汇是否为正确的词汇( 10% 概率),这就迫使模型更多地依赖于上下文信息去预测词汇,并且赋予了模型一定的纠错能力。上述提到了这样做的一个缺点,其实这样做还有另外一个缺点,就是每批次数据中只有 15% 的标记被预测,这意味着模型可能需要更多的预训练步骤来收敛。

除了MLM的词预测工作外还有NSP(下一句预测Next Sentence Prediction)的句子预测工作,简单理解就是描述为:从文本语料库中随机选择50%正确语句对和50%错误语句对进行训练,判断两段句子是否相邻,让模型能够更准确地刻画语句乃至篇章层面的语义信息,如下图所示。

在这里插入图片描述

除此之外还可以和与 MLM 任务相结合,让模型能够更准确地刻画语句乃至篇章层面的语义信息,通过对 MLM 任务和 NSP 任务进行联合训练,使模型输出的每个字 / 词的向量表示都能尽可能全面、准确地刻画输入文本(单句或语句对)的整体信息,为后续的微调任务提供更好的模型参数初始值。

2)基础结构

在这里插入图片描述
{ E 1 . . . E n E_1...E_n E1...En}:原始词向量矩阵

T r m Trm Trm:Transformer的Encoder编码器

{ T 1 . . . T n T_1...T_n T1...Tn}:经过L层学习到的词向量矩阵

L:transformer块的个数,或者说是层数

H:隐藏层的大小,也就是维度大小

A:transformer多头自注意机制里的头的个数

在预训练阶段,对于序列中的 E i E_i Ei是来自序列中的第i个词的向量矩阵,而第i个词对应的 T r m Trm Trm的输入分别来自前文的 E i − 1 E_{i-1} Ei1、当前的 E i E_i Ei和后文的 E i + 1 E_{i+1} Ei+1,因为MLM的掩码设置,模型往往需要根据 E i − 1 E_{i-1} Ei1 E i + 1 E_{i+1} Ei+1来预测 E i E_i Ei是否正确。然后第一层的 T r m i Trm_i Trmi的输出作为第二层 T r m i Trm_i Trmi的输入,同时还有来自第一层前文 T r m i − 1 Trm_{i-1} Trmi1的输出和第一层后文 T r m i + 1 Trm_{i+1} Trmi+1的输出同样作为第二层 T r m i Trm_i Trmi的输入,重复经过L层Trm后,输出对应的 T i T_i Ti词向量矩阵。

在这里插入图片描述
[cls]:分类符,无明显语义信息的符号,作为整段序列的语义表示

[SEP]:分隔符,分开两个输入句子

Mask LM:掩码

NSP:下一句预测

BERT的输入是一个序列,但是因为BERT使用的是transformer的编码器,所以只有一个输入序列,可以将两个句子编成一个序列进行输入。首先把 c l s cls cls插入序列的第一个句子的最前面,作为分类表示,将 s e p sep sep作为两段句子的分隔符,使用token表示词元,而 T o k 1 , . . . , T o k N / M Tok1,...,TokN/M Tok1,...,TokN/M表示对应的句子A/B的内容。

在这里插入图片描述
对于输入的所有token都需要转换为embedding词嵌入也就是 E E E,而BERT的embedding是由token本身的embedding加上分割句子位置的embedding加上词元在整个序列中的位置的embedding。也就是该词元本身的嵌入加上该词元属于哪个句子的嵌入加上该词元属于序列中的位置嵌入。

最后将对应词元的输入 E E E然后传入BERT中,讲过transformer结构和双向上下文信息获取结构,得到了对应的 T i T_i Ti词向量矩阵。

3)预训练

在这里插入图片描述
预训练中的Masked Language Model任务

在预训练过程中,为了提高模型对序列的学习效果,会随机地屏蔽了每个序列中15%的token,使用掩码语言模型的目的就是为了防止:自己看见自己。MLM(Masked Language Model/Mask LM)在训练的时候随机也就是15%从输入的序列中使用[MASK]替换掉一些单词。

为了使模型更加稳定,在随机mask掉 15%的单词后,再让BERT来预测这些Mask的词,通过调整模型的参数使得模型预测正确的概率尽可能大,这等价于交叉熵的损失函数。这样的Transformer在编码一个词的时候会(必须)参考上下文的信息。

但这种方法有两个缺点。首先在微调的时候是没有[MASK]的,从而导致预训练和微调之间会有不匹配,为了减轻训练和预测之间的不匹配,需要在这15%个token上进行优化。

为了解决这个问题,BERT在这15%的token中并不总是用实际的[MASK]进行替换:

  • 有80%的概率用“[MASK]”标记来替换:my dog is hairy → my dog is [MASK]
  • 有10%的概率用随机采样别的单词来替换:my dog is hairy → my dog is apple
  • 有10%的概率即使抽中了也不进行替换:my dog is hairy → my dog is hairy

这样会使得Transformer encoder不知道它将被要求预测哪些单词或哪些单词已被随机单词替换,因此它被迫保持每个输入token的分布式上下文表示。此外,因为随机替换只发生在所有token的1.5%(即15%的10%),这似乎不会损害模型的语言理解能力。

使用MLM的第二个缺点是每个batch只预测了15%的token,这表明模型可能需要更多的预训练步骤才能收敛。MLM的收敛速度略慢于 left-to-right的模型(预测每个token),但MLM模型在实验上获得的提升远远超过增加的训练成本。

这样做的好处是,BERT并不知道[MASK]替换的是哪一个词,而且任何一个词都有可能是被替换掉的,比如它看到的apple可能是被替换的词。这样强迫模型在编码当前时刻的时候不能太依赖于当前的词,而要考虑它的上下文,甚至更加依赖上下文进行”纠错”。比如上面的例子模型在编码apple是根据上下文my dog is应该把apple(部分)编码成hairy的语义而不是apple的语义。

预训练中的next sentence prediction任务

许多重要的下游任务,如问答(QA)和自然语言推理(NLI)都是需要理解句子之间的关系,在BERT需要使用NSP(next sentence prediction)去训练模型去理解句子层面的语义语境的信息。

具体地说,选择句子A和句子B组合成一个序列进行输入,其中句子A的下一个句子有50%的概率是句子B,也有50%的可能是来自语料库的随机句子,也就是这个序列有50%是正例,50%是负例。

对正负序列的句子AB的设置如下:

  • Input = [CLS] the man went to [MASK] store [SEP]he bought a gallon [MASK] milk [SEP]

  • Label = IsNext

  • Input = [CLS] the man [MASK] to the store [SEP]penguin [MASK] are flight ##less birds [SEP]

  • Label = NotNext

通过IsNext和NotNext类别来表示AB之间的关系,对[cls]进行编码的时候也需要做一个分类任务,就是一个二分类任务,输出结果是判断两个句子是否应该连在一起,最终的预训练模型在此任务上实现了97%-98%的准确率。

BERT在序列最前面添加一个[CLS]标志,最后一层该位对应向量可以作为整句话的语义表示,因为与文本中已有的其它词相比,这个无明显语义信息的符号会更“公平”地融合文本中各个词的语义信息,从而更好的表示整句话的语义,从而用于下游的分类任务等。

WordPiece:将一个出现比例较小的词进行分割,获取它的词根,如果这个词根出现的概率较大那么就将这个词根保留下来,使得一个大规模的文本中能够通过压缩特殊字的方式来减小词典,比如负例中出现的“##less”。

4)微调

在这里插入图片描述

微调就是在预训练好的模型上使用有标注的数据集进行训练,注意预训练模型的数据集是无标注的。

不同下游子任务上的不同输入输出需求:

  • MNLI(Multi-Genre Natural Language Inference):给定一对句子,目标是预测第二句子和第一个句子是相关的、无关的还是矛盾的。

  • QQP(Quora Question Pairs):判断两个问句是否是同一个意思。

  • QNLI(Question Natural Language Inference):样本是(question,sentence)在一段文本中sentence是否是question的答案。

  • STS-B(Semantic Textual Similarity Benchmark):给出一对句子, 使用1~5的评分评价两者在语义上的相似程度。

  • MRPC (Microsoft Research Paraphrase Corpus):句子对来源于对同一条新闻的评论. 判断这一对句子在语义上是否相同。

  • RTE(Recognizing Textual Entailment):是一个识别文本蕴涵的二分类问题, 类似于MNLI。

  • SST-2(The Stanford Sentiment Treebank):单句的二分类问题, 句子来源于人们对一部电影的评价, 判断这个句子的情感。

  • CoLA (The Corpus of Linguistic Acceptability):单句的二分类问题, 判断一个英文句子在语法上是不是可接受的。

  • SQuAD(Standford Question Answering Dataset):给定一个问题和一个来自包含答案的Wikipedia段落,任务是预测答案在段落中所在的位置。

  • CoNLL-2003 NER:命名实体识别任务,预测每个字的标签是什么。

在微调工作中对于不同的下游子任务,需要使用标注的数据集进行训练,同时在微调训练时需要根据不同下游子任务上的不同输入输出需求修改微调模型的输入输出,但是最重要的预训练模型是不需要改变的。所以面对不同下游子任务只需要修改好对应的输入输出就可以了。

这些任务在BERT的微调工作中可以使用abcd四种方式进行训练:

  • 图a表示两个句子的分类任务,输入是两个句子A和B,中间用[SEP]分隔,最终得到第一个词元[cls]的输出class label结合输出层,然后使用softmax进行分类。

  • 图b表示单句分类任务,输入就是一个单独的句子,最终得到第一个词元[cls]的输出class labe结合输出层,然后使用softmax进行分类。

  • 图c表示问答任务,输入是一个问题A和答案所在的段落B,中间用[SEP]分隔,这里需要得到的输出就不是[cls]而是学习两个新的向量也就是段落中答案的开始 S S S词元的概率和答案的终止 E E E词元的概率,具体来说就是对段落B的每一个词元进行 S S S E E E的计算,然后使用softmax计算是答案开始终止的概率。

  • 图d表示单个句子标注任务,输入就是一个单独的句子,输出是句子中每个token对应的类别标注。

4、BERT优缺点

优点:

  • BERT双向上下文信息对预训练模型的发展有很大影响
  • 推动预训练模型的计算可并行化
  • 基于预训练-微调压缩了对下游任务的成本
  • 为了适配多任务下的迁移学习,BERT设计了更通用的输入层和输出层
  • 对比GPT使用了transformer编码器,对于像分类式的任务效果更好

缺点:

  • [MASK]标记在实际预测中不会出现,训练时用过多[MASK]影响模型表现
  • 每个batch只有15%的token被预测,所以BERT收敛得比left-to-right模型要慢(它们会预测每个token)
  • 对比GPT使用了transformer编码器,导致对于像生成式的任务效果较差
  • BERT对参数需求更大,对硬件资源的消耗巨大,预示着模型大战的到来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1567717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【史上最细教程】 Typora+PicGo+Gitee 实现发给别人的Typora笔记也能看到图片

文章目录 问题描述前提准备:操作步骤:1.Gitee新建项目作为图床、获取仓库访问密钥2.PicGo连接Gitee图床3.Typora连接PicGo 问题描述 Typora记录的笔记,图片保存默认在本地,这时候复制出来上传CSDN、或发给别人的时候图片就是空链…

Qt 的发展历史、现状与启示

Qt 最早在1991年由挪威的两位程序员 Eirik Chambe-Eng 和 Haavard Nord 开发,他们在1994年创立 Trolltech 公司(奇趣科技)正式经营软件业务。Qt 的第一个公众预览版于1995年面世,之后在2008年被诺基亚收购;2011年到201…

【漏洞复现】万户 ezOFFICE wf_printnum SQL注入漏洞

免责声明:文章来源互联网收集整理,请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该…

Linux :进程的程序替换

目录 一、什么是程序替换 1.1程序替换的原理 1.2更改为多进程版本 二、各种exe接口 2.2execlp ​编辑 2.2execv 2.3execle、execve、execvpe 一、什么是程序替换 1.1程序替换的原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往…

【Redis系列】Redis安装与使用

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【群晖】NASTOOL-自动化处理影音视频工具

【群晖】NASTOOL-自动化处理影音视频 本文主要从获取、部署、使用、配置等方面进行手把手教学如何使用nastool工具进行影音视频自动化处理。从此靠别繁琐的网上各个网址找资源-下载-复制-改名-刮削等操作。 准备 DSM 7.1 (我使用的是群晖 7.1 系统,不管…

JVM剖析

0.前言 Java 是当今世界使用最广泛的技术平台之一。使用 Java 或 JVM 的一些技术包括: Apache spark用于大数据处理,数据分析在JVM上运行;用于数据流的Apache NiFi在内部使用的也是 JVM;现代 Web 和移动应用程序开发中使用的React native使用 的也包含…

【代码篇】事件监听函数的内存泄漏,都给我退散吧!

前言 内存泄漏是个很严肃的问题,可是迄今也没有一个非常有效的排查方案,本方案就是针对性的单点突破。 工作中,我们会对window, DOM节点,WebSoket, 或者单纯的事件中心等注册事件监听函数, 添加了,没有移除&#xff…

网络爬虫:爬取假数据

网络爬虫:爬取假数据 文章目录 网络爬虫:爬取假数据前言一、项目介绍:二、项目来源:三、架构图:(流程图)四、使用了什么技术:(知识点)五、结果示意图&#xf…

网络安全 | 什么是单点登录SSO?

关注WX:CodingTechWork SSO-概念 单点登录 (SSO) 是一种身份认证方法,用户一次可通过一组登录凭证登入会话,在该次会话期间无需再次登录,即可安全访问多个相关的应用和服务。SSO 通常用于管理一些环境中的身份验证,包…

obs直播推流 + ffmpeg参数

OBS 启动参数设为 --startstreaming , 可以让它启动后自动开始直播 对应ffmpeg参数: echo off :loop ffmpeg -re -i a.mp4 -r 24 -c:v libx264 -preset ultrafast -profile:v baseline -g 24 -keyint_min 24 -x264-params nal-hrdcbr -b:v 2500k -minr…

线上研讨会 | 应对汽车毫米波雷达设计中的电磁挑战

智能汽车、新能源汽车最近几年一直是汽车行业关注的热点,随着5G技术越来越普及,汽车智能化发展将越来越迅速。从传统汽车到智能汽车,不是简单功能的增强,而是从单一功能的交通工具变成可移动的办公和娱乐空间,成为物联…

蓝桥杯python组真题练习1

目录 1.单词分析 2.成绩统计 3.门牌制作 4.卡片 5.跑步训练 6.蛇形填数 7.时间显示 1.单词分析 1.单词分析 - 蓝桥云课 (lanqiao.cn) s list(input()) maxx 0 for i in s:num s.count(i)if num>maxx:sm imaxx numif num maxx:if ord(sm)>ord(i):sm i print…

AcWing-孤独的照片

4261. 孤独的照片 - AcWing题库 所需知识:贡献法 整体思路:首先想到暴力枚举所有区间,判断每个区间内是否有一种牛的数量是一只(提前用前缀和存放每个位置及以前的牛的数量) C代码:(过不了&a…

【科研笔记】知识星球不可选择内容爬虫

知识星球不可选择内容爬虫 1 背景2 实现3 拓展遗留问题1 背景 针对与知识星球中,电脑打开网页不可选择复制粘贴的问题,进行爬虫处理,获取网页的内容,并保存在本地 2 实现 需要下载python,和爬虫的第三方库selenium,可以查看博客中有关selenium的内容进行回顾。当前使用…

安装Pillow库的方法最终解答!_Python第三方库

安装Python第三方库Pillow 我的环境:Window10,Python3.7,Anaconda3,Pycharm2023.1.3 pillow库 Pillow库是一个非常强大的图像处理库。它提供了广泛的图像处理功能,让我们可以轻松地读取和保存图像、创建缩略图和合并到…

开源软件技术社区方案

开源软件技术社区是一个由开发者、贡献者、用户和维护者组成的共享平台,主要目的是打造技术、软件产品良性互动、开源技术安全可控的软件生态环境,实现可复用应用或服务的快速部署与使用、完成资源与能力的高度共享、促进社区成员的共建共赢,…

利用Python和Selenium实现定时任务爬虫

网络爬虫在信息获取、数据分析等领域发挥着重要作用,而定时爬虫则可以实现定期获取网站数据的功能,为用户提供持续更新的信息。在Python中,结合Selenium技术可以实现定时爬虫的功能,但如何设置和优化定时爬虫的执行时间是一个关键…

4.7 数组的读取和写入,type指令和一些杂项

4.7 数组的读取和写入,type指令和一些杂项 可以通过word ptr将db转为dw,然后按照dw的方式去存储数据 1. 段名也可以把其地址赋给变量 assume cs:codesg,ds:data,ss:stack data segmentdb 12,34dw 12,34db hello world data ends stack segmentdb 10 dup…

Android JNI基础

目录 一、JNI简介1.1 什么是JNI1.2 用途1.3 优点 二、初探JNI2.1 新建cpp\cmake2.2 build.gradle配置2.3 java层配置2.4 cmake和c 三、API详解3.1 JNI API3.1.1 数据类型3.1.2 方法 3.2 CMake脚本 四、再探JNI 一、JNI简介 1.1 什么是JNI JNI(Java Native Interfa…