跳转至

【字节】 大厂NLP技术面试 (1)

大厂NLP技术面试

本文讨论了大厂NLP技术面试相关内容,涵盖AI大模型教程、就业现状以及多种NLP模型和技术的介绍。关键要点包括:

AI大模型教程:提供AI大模型全套教程和企业级应用开发教程,还有MCP Server开发零基础教程。

BERT模型:谷歌提出的Word2Vec替代者,使用双向Transformer框架、多任务训练目标,输入编码向量含位置、WordPiece、分割嵌入,有Masked LM和Next Sentence Prediction两个任务。

文本嵌入:传统NLP用one-hot向量表示单词,Skip-Gram和CBOW是基于窗口的词嵌入模型,但存在不足。

模型架构对比:BERT用双向Encoder,OpenAI GPT用单向Encoder,ELMo用独立训练的LSTM级联。

负采样作用:用于提高Word2Vec效率,每次只更新部分权重,降低计算复杂度。

特征抽取器:RNN、CNN、Transformer是NLP三大特征抽取器,Transformer综合表现更优。

参数更新方法:包括梯度下降、随机梯度下降、小批量梯度下降等多种方法,各有特点和适用场景。

1. BERT

基础知识

BERT 是 $ \underline{\text{谷歌}} $ 提出,作为一个 Word2Vec 的替代者,其在 $ \underline{\text{NLP领域的11个方向大幅刷新了精度}} $,可以说是近年来自残差网络最优突破性的一项技术了。 主要特点以下几点:

使用了双向Transformer作为算法的主要框架,之前的模型是从左向右输入一个文本序列,或者将left-to-right和right-to-left的训练结合起来,实验的结果表明,双向训练的语言模型对语境的理解会比单向的语言模型更深刻

使用了 Mask Language Model(MLM) 和 Next Sentence Prediction(NSP) 的多任务训练目标;

使用更强大的机器训练更大规模的数据,使BERT的结果达到了全新的高度,并且Google开源了BERT模型,用户可以直接使用BERT作为Word2Vec的转换矩阵并高效的将其应用到自己的任务中。

BERT只利用了 $ \underline{\text{Transformer 的 encoder}} $部分。因为BERT 的目标是生成语言模型, $ \underline{\text{所以只需要 encoder 机制}} $。

BERT有两个任务:

Masked LM (MLM) : 在将单词序列输入给 BERT 之前,每个序列中有 15% 的单词被 [MASK] token 替换,然后模型尝试基于序列中其他未被 mask 的单词的上下文来预测被掩盖的原单词。在BERT的实验中,15% 的WordPiece Token会被随机Mask掉。在训练模型时,一个句子会被多次喂到模型中用于参


数学学习,但是Google并没有在每次都mask掉这些单词,而是在确定要Mask掉的单词之后,80%的概率会直接替换为[Mask],10%的概率将其替换为其它任意单词,10%的概率会保留原始Token。

Next Sentence Prediction (NSP): 在 BERT 的训练过程中,模型接收成对的句子作为输入,并且预测其中第二个句子是否在原始文档中也是后续句子。

ERT的输入的编码向量(长度是512)是3个嵌入特征的单位和,这三个词嵌入特征是:

位置嵌入(Position Embedding):位置嵌入是指将单词的位置信息编码成特征向量,位置嵌入是向模型中引入单词位置关系的至关重要的一环;

WordPiece 嵌入:WordPiece是指将单词划分成一组有限的公共子词单元,能在单词的有效性和字符的灵活性之间取得一个折中的平衡。例如上图的示例中 ‘playing’ 被拆分成了 ‘play’ 和 ‘ing’;分割嵌入(Segment Embedding):用于区分两个句子,例如B是否是A的下文(对话场景,问答场景等)。对于句子对,第一个句子的特征值是0,第二个句子的特征值是1。

2. 文本嵌入

在传统的NLP中,将单词视为离散符号,然后可以用 $ \underline{\text{one-hot}} $ 向量表示。 $ \underline{\text{向量的维度是整个词汇表中单词的数量}} $。单词作为离散符号的问题在于,对于one-hot向量来说,没有自然的相似性概念。因此,另一种方法是学习在向量本身中编码相似性。核心思想是一个词的含义是由经常出现在其旁边的单词给出的。

文本嵌入是字符串的实值向量表示。为每个单词建立一个密集的向量,选择它以便类似于类似上下文中出现的单词的向量。

在词嵌入中最流行的应该是 $ \underline{\text{Word2vec}} $,它是由谷歌(Mikolov)开发的模型,其中固定词汇表中的每个词都由一个向量表示。然后,通过文本中的每个位置 $ \underline{t} $,其中有一个中心词 $ \underline{c} $和上下文词 $ \underline{o} $

Image

Word2vec有两个变体:

Skip-Gram:考虑一个包含 k 个连续项的上下文窗口。然后,跳过其中一个单词,尝试学习一个神经网络,该网络可以获得除跳过的所有术语外的所有术语,并预测跳过的术语。因此,如果两个单词在大语料库中反复共享相似的上下文,那么这些术语的嵌入向量将具有相似的向量。

Continuous Bag of Words:在一个大的语料库中获取大量的句子,每当看到一个词,就会联想到周围的词。然后,将上下文单词输入到神经网络,并预测该上下文中心的单词。当有数千个这样的上下文单词和中心单词时,就有了一个神经网络数据集的实例。训练神经网络,最后编码的隐藏层输出表示一个特定的词嵌入。当通过大量的句子进行训练时,类似上下文中的单词会得到相似的向量。


3. 对比BERT、OpenAI GPT、ELMo架构之间的差异

BERT 使用 双向 Encoder,模型的表示在所有层中,共同依赖于左右两侧的上下文

OpenAI GPT 使用 单向 Encoder,利用了 Transformer 的编码器作为语言模型进行预训练的,之后特定的自然语言处理任务在其基础上进行微调即可。

ELMo 使用独立训练的从左到右和从右到左LSTM级联来生成下游任务的特征。是一种双层双向的LSTM 结构,其训练的语言模型可以学习到句子左右两边的上下文信息,但此处所谓的上下文信息并不是真正意义上的上下文。

三种模型中只有BERT表征基于所有层左右两侧语境

Image

4. Word2Vec 中为什么使用负采样(negative sample)?

负采样是另一种用来提高Word2Vec效率的方法,它是基于这样的观察:训练一个神经网络意味着使用一个训练样本就要稍微调整一下神经网络中所有的权重,这样才能够确保预测训练样本更加精确,如果能设计一种方法每次只更新一部分权重,那么计算复杂度将大大降低。

将以上观察引入Word2Vec就是:当通过("fox",“quick”)词对来训练神经网络时,回想起这个神经网络的“标签”或者是“正确的输出”是一个one-hot向量。 $ \underline{\text{也就是说,对于神经网络中对应于}} $“quick”这个单词的神经元对应为1,而其他上千个的输出神经元则对应为0。

使用负采样,通过随机选择一个较少数目(比如说5个)的“负”样本来更新对应的权重。(在这个条件下,“负”单词就是希望神经网络输出为0的神经元对应的单词)。并且仍然为“正”单词更新对应的权重(也就是当前样本下“quick”对应的神经元仍然输出为1)。

负采样这个点引入word2vec非常巧妙,两个作用:

加速了模型计算

保证了模型训练的效果

其一:模型每次只需要更新采样的词的权重,不用更新所有的权重,那样会很慢

其二:中心词其实只跟它周围的词有关系,位置离着很远的词没有关系,也没必要同时训练更新,作者这点非常聪明。


5. word2vec 相比之前的 Word Embedding 方法好在什么地方?

无论是 CBOW 还是 Skip-Gram ,本质还是要 $ \underline{\text{基于word和context做文章,即可以理解为模型在学习word和context的co-occurrence}} $

Word2vec训练方面采用的 $ \underline{\text{HSoftmax}} $以及负采样确实可以认为是创新不大。 $ \underline{\text{但Word2vec流行的主要原因也不在于此。主要原因在于以下3点:}} $

极快的训练速度。以前的语言模型优化的目标是MLE,只能说词向量是其副产品。Mikolov应该是第一个提出抛弃MLE(和困惑度)指标,就是要学习一个好的词嵌入。如果不追求MLE,模型就可以大幅简化,去除隐藏层。再利用HSoftmax以及负采样的加速方法,可以使得训练在小时级别完成。而原来的语言模型可能需要几周时间。

一个很酷炫的man-woman=king-queen的示例。这个示例使得人们发现词嵌入还可以这么玩,并促使词嵌入学习成为了一个研究方向,而不再仅仅是神经网络中的一些参数。

word2vec里有大量的tricks。比如噪声分布如何选?如何采样?如何负采样?等等。这些tricks虽然摆不上台面,但是对于得到一个好的词向量至关重要。

6. NLP预训练发展史:从Word Embedding到BERT

图像预训练 → word embedding → word2vec → elmo → transformer → gpt → bert → GPT 234

7. NLP三大特征抽取器(CNN/RNN/TF)

RNN已经基本完成它的历史使命,将来会逐步退出历史舞台;CNN如果改造得当,将来还是有希望有自己在NLP领域的一席之地;而Transformer明显会很快成为NLP里担当大任的最主流的特征抽取器。

NLP任务的特点:

输入是个一维线性序列;输入不定长;单词或句子的位置关系很重要

句子中长距离特征对于语义理解也很重要

RNN

采取线性序列结构不断从前往后收集输入信息, $ \underline{\text{但这种线性序列结构在反向传播的时候存在优化困难问题}} $,因为反向传播路径太长,容易导致严重的梯度消失或梯度爆炸问题。为了解决这个问题,后来引入了 $ \underline{\text{LSTM和GRU模型}} $,通过增加中间状态信息直接向后传播, $ \underline{\text{以此缓解梯度消失问题}} $,获得了很好的效果,于是很快LSTM和GRU成为RNN的标准模型。经过不断优化,后来NLP又从图像领域借鉴并引入了attention机制(从这两个过程可以看到不同领域的相互技术借鉴与促进作用),叠加网络把层深作深, $ \underline{\text{以及引入Encoder-Decoder框架,这些技术进展极大拓展了RNN的能力以及应用效果}} $。


RNN的结构天然适配解决NLP的问题,NLP的输入往往是个不定长的线性序列句子,而RNN本身结构就是个可以接纳不定长输入的由前向后进行信息线性传导的网络结构,而在LSTM引入三个门后,对于捕获长距离特征也是非常有效的。所以RNN特别适合NLP这种线形序列应用场景,这是RNN为何在NLP界如此流行的根本原因。

RNN在新时代面临的两个问题:

一些新模型的崛起:特殊改造的CNN;Transformer

RNN结构存在序列依赖,对大规模并行非常不友好

CNN

CNN捕获的特征其实的单词的 k-gram 片段信息, k 的大小决定了能捕获多远距离的特征。

目前NLP界主流的CNN:

通常由1-D卷积层来叠加深度,使用Skip Connection来辅助优化,也可以引入Dilated CNN等手段。

CNN的卷积层其实是保留了相对位置信息的,CNN的并行计算能力,那是非常强的。

Transformer

自然语言一般是个不定长的句子,那么这个不定长问题怎么解决呢?

Transformer做法跟CNN是类似的,一般设定输入的最大长度,如果句子没那么长, $ \underline{\text{则用Padding填充,这样整个模型输入起码看起来是定长的了}} $。

三 大抽取器比较

语义特征提取能力:Transformer在这方面的能力非常显著地超过RNN和CNN,RNN和CNN两者能力差不太多。

长距离特征捕获能力:原生CNN特征抽取器在这方面极为显著地弱于RNN和Transformer,Transformer微弱优于RNN模型(尤其在主语谓语距离小于13时),能力由强到弱排序为Transformer>RNN>>CNN;但在比较远的距离上(主语谓语距离大于13),RNN微弱优于Transformer,所以综合看,可以认为Transformer和RNN在这方面能力差不太多,而CNN则显著弱于前两者。

任务综合特征抽取能力(机器翻译):Transformer综合能力要明显强于RNN和CNN,而RNN和CNN看上去表现基本相当,貌似CNN表现略好一些。

并行计算能力及运行效率:RNN在并行计算方面有严重缺陷,这是它本身的序列依赖特性导致的;对于CNN和Transformer来说,因为它们不存在网络中间状态不同时间步输入的依赖关系,所以可以非常方便及自由地做并行计算改造。Transformer和CNN差不多,都远远远远强于RNN。

综合排名

单从任务综合效果方面来说,Transformer明显优于CNN,CNN略微优于RNN。速度方面Transformer和CNN明显占优,RNN在这方面劣势非常明显。


8. 常用参数更新方法

梯度下降: $ \underline{\text{在一个方向上更新和调整模型的参数,来最小化损失函数}} $。

随机梯度下降(Stochastic gradient descent,SGD)对每个训练样本进行参数更新,每次执行都进行一次更新,且执行速度更快。

为了避免SGD和标准梯度下降中存在的问题, $ \underline{\text{一个改进方法为小批量梯度下降}} $,因为对每个批次中的n个训练样本,这种方法只执行一次更新。

使用小批量梯度下降的优点是:

可以减少参数更新的波动,最终得到效果更好和更稳定的收敛。

还可以使用最新的深层学习库中通用的矩阵优化方法,使计算小批量数据的梯度更加高效。

通常来说,小批量样本的大小范围是从50到256,可以根据实际问题而有所不同。

在训练神经网络时,通常都会选择小批量梯度下降算法。

SGD方法中的高方差振荡使得网络很难稳定收敛,所以有研究者提出了一种称为 动量

(Momentum)的技术,通过优化相关方向的训练和弱化无关方向的振荡,来加速SGD训练。

Nesterov梯度加速法,通过使网络更新与误差函数的斜率相适应,并依次加速SGD,也可根据每个参数的重要性来调整和更新对应参数,以执行更大或更小的更新幅度。

AdaDelta方法是AdaGrad的延伸方法,它倾向于解决其学习率衰减的问题。Adadelta不是累积所有之前的平方梯度,而是将累积之前梯度的窗口限制到某个固定大小w。

Adam算法即自适应时刻估计方法(Adaptive Moment Estimation),能计算每个参数的自适应学习率。这个方法不仅存储了 $ AdaDelta $先前平方梯度的指数衰减平均值,而且保持了先前梯度 $ M(t) $的指数衰减平均值,这一点与动量类似。

Adagrad方法是通过参数来调整合适的学习率 $ \eta $,对稀疏参数进行大幅更新和对频繁参数进行小幅更新。因此, $ \underline{\text{Adagrad方法非常适合处理稀疏数据}} $。