NLP中的Embedding方法总结

说在前面:

  1. 本文提到embeddingembedding时,有可能指将一个词转换成(稠密)向量这一过程,也可能指转换的结果,即得到的词的向量,每个地方的具体含义需要根据上下文来确定。
  2. 下面的术语在本文中具有相同的含义:embedding matrix=lookup tableembedding\space matrix = lookup\space tableembedding=representation=embedding = representation=特征

词向量

One-Hot Encoding

学习资料

  1. https://flashgene.com/archives/66661.html

要点

例如词汇表大小V=N|V|=N,则用一个NN维的one-hot向量来表示一个词,每个词的one-hot中11的位置就对应了该词在词汇表的索引。

缺点

  1. 语义鸿沟:其无法通过词向量来衡量相关词之间的距离关系,即这样的表征方法无法反映词之间的相似程度,因为任意两个向量的相似度是相同的。例如(whotel)Twmotel=(whotel)Twcat=0(w^{hotel})^Tw^{motel} = (w^{hotel})^Tw^{cat} = 0
  2. 维度灾难:高维情形下将导致数据样本稀疏,距离计算困难,这对下游模型的负担是很重的。

Word2Vec

学习资料

  1. https://zhuanlan.zhihu.com/p/27234078
  2. https://www.bilibili.com/video/av41393758/?p=2
  3. https://flashgene.com/archives/66661.html
  4. https://github.com/iamxpy/nlp-tutorial/tree/master/1-2.Word2Vec
  5. https://zhuanlan.zhihu.com/p/32965521
  6. https://github.com/iamxpy/word2vecpy
  7. https://code.google.com/archive/p/word2vec/
  8. Word2Vec原始论文

要点

Word2Vec包括Skip-Gram(SG)和CBOW。SG模型需要根据target来预测上下文的词(即target左右的词,称为context);而CBOW相反,需要根据context来预测target,准确来说,是使用规定窗口范围内的context的平均(或求和)来预测target。

SG的训练过程:

当window size为2时,表示取center的左右各两个context。那么从Coupus中的一个句子构造训练样本的过程可以图示为如下(只演示到target为fox就停止了)。

在这里插入图片描述

在这里插入图片描述
CBOW的训练过程:

这里需要特别注意SG和CBOW的区别,其实他们的本质区别不在于用context来预测target还是用target来预测context。例如,如果以同样的句子来构造CBOW的样本,假设我们不对context取平均(这并不是真正的CBOW!),而是每个context都构造一个<context, target>样本,那么target从“The”到“fox”所得到的所有样本如下图,并且,我们可以与SG得到的样本进行对比,发现训练集几乎是一样的,<jumps, brown>, <jumps, fox>等样本随着两个模型的窗口继续移动也会得到匹配,也就是说从整个corpus来看,用SG和用不对context取平均的“CBOW”得到的训练集是一样的,所以SG和“CBOW”是等价的。

在这里插入图片描述
其实这一现象在StackOverflow上也有讨论:CBOW v.s. skip-gram: why invert context and target words?

那么SG的CBOW的区别在哪?没错,就是在对context取平均。不信?来看看FastText的官方文档是怎么介绍这两种word2vec模型的。(P.S. FastText由Tomas Mikolov团队开发,这一团队正是在2013年提出word2vec的团队。)

引用链接: skipgram versus cbow

FastText provides two models for computing word representations: skipgram and cbow (‘continuous-bag-of-words’).
The skipgram model learns to predict a target word thanks to a nearby word. On the other hand, the cbow model predicts the target word according to its context. The context is represented as a bag of the words contained in a fixed size window around the target word.
Let us illustrate this difference with an example: given the sentence ‘Poets have been mysteriously silent on the subject of cheese’ and the target word ‘silent’, a skipgram model tries to predict the target using a random close-by word, like ‘subject’ or ‘mysteriously’. The cbow model takes all the words in a surrounding window, like {been, mysteriously, on, the}, and uses the sum of their vectors to predict the target. The figure below summarizes this difference with another example.
在这里插入图片描述

可以看到,FastText文档在介绍SG和CBOW时,都介绍为“根据nearby word/context来预测target word”,看下面的图,也可以发现这里讲的SG是用context来预测target。是不是作者搞错了?肯定不是,作者所在团队就是提出这些模型的团队,现在在Facebook的AI research团队,怎么可能搞错?实际上,我在前面已经解释了,用context来预测target和用target来预测context得到的训练集几乎没有区别,所以这篇文章在介绍两个模型时都直接使用了“用context来预测target”这一语言模型任务。但是SG和CBOW是有区别的,那就是对context取平均这一操作。这一操作会带来什么影响呢?

  1. 训练的速度不同。从训练集的样本数量来说,CBOW的样本数量比SG样本数量少得多。假设有n个target,窗口大小为w(target左右取w个context word),那么SG的样本数量接近2wn2*w*n,而CBOW的样本数量近似为nn.
  2. 训练的效果不同。Mikolov的话意译过来就是:SG适用于相对少量的训练数据,对于稀有词的效果更好(可以得到表征能力很好的embedding)。CBOW比SG的训练速度快了几倍,而其常用词的表征的效果要比SG好一点。

Skip-gram: works well with small amount of the training data, represents well even rare words or phrases.
CBOW: several times faster to train than the skip-gram, slightly better accuracy for the frequent words

原始Word2Vec的问题以及解决办法

  • 最后的SoftMax层计算量过大:改用层次Softmax(Hierarchical Softmax)、负采样(Nagative Sampling)。
  • 高频但意义不大的Stop Word(例如The)充斥训练样本:对于我们在训练原始文本中遇到的每一个单词,它们按照一定概率保留,保留的概率与单词的频率成反相关。

超参数的选择对Word2Vec的效果影响[1,,7,8]^{[1,,7,8]}

  • 对高频词进行下采样(sub-sampling)可以提高精度与速度,其对应的sample参数通常在 1e31e-31e51e-5 之间,默认 1e31e-3
  • 负采样的参数选择:对于小规模数据集,选择5-20个negative words会比较好,对于大规模数据集可以仅选择2-5个negative words
  • 通常来说Embedding维度越高,效果越好,但不是总是这样
  • 窗口大小,SG常使用10左右,而CBOW常使用5左右

负采样(negative sampling)与分层softmax(hierarchical softmax)

负采样原理见本小节(后面省略,默认指对应小节的)学习资料1,分层softmax(后称h-softmax)原理见学习资料5,代码实现见学习资料6。

要点:

下面讨论时,以CBOW为背景,即我们要根据多个context的embedding的平均作为输入,来预测center。

负采样和分层softmax都是将原来的多分类问题(设类别数为VV)转化为了kk个二分类问题,其中kk远远小于VV。(在负采样中,kk是固定的,一般在2~20中取;在h-softmax中,kk是变化的,平均情况下,k=logVk=logV)。

我们仍然有两个参数矩阵,WWWW^\primeWW就是context的lookup table,即WW的每一行/列就对应了一个单词的embedding。而WW^\prime在两种方法中作用不一样:在负采样中WW^\prime是center的lookup table;在h-softmax中,WW^\prime存放的是V1V-1个二分类器的参数。

负采样时,对于1个正确的<context,center><context, center>样本,假设context对应的向量为WiW_i,center对应WjW^\prime_j。然后我们采样得到kk个(错误的)center,与context组成kk个(错误的)<context,center><context, center>,然后从WW^\prime中取出center对应的向量WkW^\prime_k,那么我们可以得到(k+1)(k+1)个二分类(x,y)(x, y)问题,即(WiTWj,1)(W_i^TW^\prime_j, 1)kk(WiTWk,0)(W_i^TW^\prime_k, 0).

h-softmax中,我们对于VV个词汇(类别)根据其在corpus中出现的频率进行哈夫曼编码,那么对应的哈夫曼树有VV个叶子结点,分别对应了每一个词汇,并有V1V-1个内部结点,对应了V1V-1个二分类器(每个分类器的参数就是WW^\prime的每行/每列,i.e., h-softmax中的WW^\prime含义不再是center的lookup table)。

在这里插入图片描述

例如上图中的center词汇y2y_2对应的哈夫曼编码为110110(假设规定是向左为1),那么我们从WW^\prime中得到该条路径上的3个非叶子结点对应的向量Wk1,Wk2,Wk3W^\prime_{k1},W^\prime_{k2},W^\prime_{k3},那么我们就可以得到3个二分类问题:(WiTWk1,1),(WiTWk2,1),(WiTWk3,0)(W_i^TW^\prime_{k1}, 1),(W_i^TW^\prime_{k2}, 1),(W_i^TW^\prime_{k3}, 0)

代码分析:

'''
下面的代码以CBOW为基础,提供negative sampling和h-softmax两种训练方法
代码中的syn0与syn1分别指的是前文所提到的W和W`
'''

# 计算neu1,即多个context词汇的embedding取平均
neu1 = np.mean(np.array([syn0[c] for c in context]), axis=0)
assert len(neu1) == dim, 'neu1 and dim do not agree'

# Init neu1e with zeros
neu1e = np.zeros(dim)

# Compute neu1e and update syn1
if neg > 0:  # neg训练时传入的参数,指的是负样本个数,大于0代表使用负采样
	# token是真实的center,target是采样得到的center,一共有(neg+1)个二分类器
    classifiers = [(token, 1)] + [(target, 0) for target in table.sample(neg)]
else: # 使用h-softmax
	# path是由路径上的内部结点的编号所组成的list
	# 例如给前面例子中y2对应的内部结点编号1、2、4,则path=[1,2,4],后面将作为W`的索引使用
	# code是token(即真实center)的哈夫曼编码,对应了每个内部结点应该向左还是向右
	# 例如前面例子中y2的哈夫曼编码为110,则code=[1,1,0],后面将作为二分类的label使用
    classifiers = zip(vocab[token].path, vocab[token].code)
for target, label in classifiers: # 对每个二分类器计算损失并更新syn1(即W`)的参数
	# 逻辑斯谛回归的前向和反向传播
    z = np.dot(neu1, syn1[target])
    p = sigmoid(z)
    g = alpha * (label - p)
    neu1e += g * syn1[target]  # Error to backpropagate to syn0
    syn1[target] += g * neu1  # Update syn1

# 更新syn0(即W)的参数
for context_word in context:
    syn0[context_word] += neu1e

h-softmax和负采样的(实验)效果对比[7,8]^{[7,8]}

  • h-softmax对生僻词的训练效果更好
  • 负采样对常用词的效果更好,并且在Embedding维度较低的限制下效果比h-softmax更好

对于 “hierarchical softmax对生僻词很不友好” 的观点,我专门写了一篇博客来反对:hierarchical softmax对生僻词很不友好?扯淡!

FastText

学习资料

  • https://zhuanlan.zhihu.com/p/32965521
  • http://albertxiebnu.github.io/fasttext/
  • https://blog.csdn.net/feilong_csdn/article/details/88655927
  • https://arxiv.org/pdf/1607.04606.pdf (原始论文)
  • https://www.kaggle.com/nzw0301/simple-keras-fasttext-val-loss-0-31 (代码实现)

要点

在word2vec中,我们需要计算target与context(分别记为wwcc)的相似度score,一般使用内积,即s(w,c)=uwTvcs(w,c)=u_{w}^Tv_{c}uvu、v分别来自WWW、W^\prime两个lookup table)。

在FastText中,每个词w都是由字符级的n-gram加上<w>(即自己)来表示的。首先在词的两边加上尖括号“<”和“>”,好处是使得模型能够从character n-gram中区分出前后缀。另外,每个词还要加上自身加上尖括号的结果(为了学习每个词的表征)。例如对于where,当n=3n=3时,其对应的character n-grams为["<wh", “whe”, “her”, “ere”, “re>”],而 where 的Embedding由自身<where>以及所有字符级n-gram的Embedding相加得到。

假设我们由corpus得到的character n-gram加上<word>组成集合GG,对于GG内每一个gg,我们在lookup table都有一个表征 zgz_g。那么对于一个词ww,假设其character n-gram加上<w>组成了集合GwGG_w\subset G,那么在FastText中,score的计算公式改为:

在这里插入图片描述

另外,FastText除了训练词向量,更重要的一个功能是可以文本分类。

FastText特点小结如下:

1、对于一个词,将其字符级 n-gram 的Embedding与该词的Embedding求和作为原词的最终Embedding,作用:

  • 为生僻词生成更好的Embedding,即使一个单词出现的次数很少,组成该单词的字符和其他单词也有共享的部分,而那些字符级n-gram可以通过对常用词来训练得很好.
  • 为未登录词(OOV)提供更好的Embedding,即使单词没有出现在训练语料库中,仍然可以从字符级n-gram中构造单词的词向量

2、为了节省内存,对哈希到同一个位置的字符n-gram使用相同的Embedding,哈希函数使用的是FNV函数(具体来说是衍生版本Fowler–Noll–Vo 1a).

3、在分类任务中,使用词语级别的n-gram,与Text-CNN很类似,都是基于n-gram理论,可以捕捉到词序信息

Glove

学习资料

  1. https://blog.csdn.net/u014665013/article/details/79642083
  2. https://www.bilibili.com/video/av41393758/?p=3
  3. https://zhuanlan.zhihu.com/p/56382372

要点

在统计共现矩阵Xi,jX_{i,j}之后,对其进行奇异值分解(SVD),得到的左奇异矩阵就是我们想要的Embedding矩阵。但是对一个巨大的共现矩阵进行SVD的代价很大,所以我们想办法利用神经网络的方式将共现矩阵“分解”(用神经网络来拟合共现矩阵中的信息)。

Glove先从corpus统计共现矩阵,然后使用神经网络来拟合共现矩阵,目标函数如下:

在这里插入图片描述
最后我们对于一个词ww的target embedding和context embedding,就是它对应的viv_ivjv_j求和(viv_ivjv_j来自不同的lookup table)。

权重函数的设计

  1. f(x)f(x)应该满足f(0)=0f(0)=0,主要出于两点考虑。首先,从数值计算的角度来说,当Xi,jX_{i,j}为0,此时log(Xi,j)log(X_{i,j})为负无穷,若0log(0)=00*log(0)=0(其实需要取极限,log(0)log(0)没有定义),则在计算JJ时不用计算Xi,j=0X_{i,j}=0的项。其次,更重要的是,从权重函数的含义来看,对于从来没有共现的wiw_iwjw_j,他们应该不参与到目标函数的计算当中去,所以不计算对应的项也是非常自然的。
  2. 对于Xi,jX_{i,j}过大的stop word,如果不控制权重,由于长尾效应,其他更有意义的词将会被忽略。所以f(x)f(x)应该满足当xx大于一个阈值时,f(x)f(x)不至于过大(例如设为定值)。
  3. 在设计f(x)f(x)时,还要注意的是f(x)f(x)应该是单调不减函数,因为我们希望Xi,jX_{i,j}更大的项,对应的权重也越大。

最后f(x)f(x)的设计如下,论文中的xmaxx_{max}取100,α\alpha取0.75:

在这里插入图片描述在这里插入图片描述

Glove对比Word2Vec

  1. 训练方式的不同。Glove在共现矩阵的非零数据上训练,有效地利用了语料库的全局统计信息,而Word2Vec是利用语料库的上下文窗口的数据来训练。
  2. Glove仅需要全局统计信息来训练,所以在训练时收敛更快,训练周期较word2vec较短且效果更好。
  3. Glove可拓展性好,对于很小或很大的corpus都可以有效地训练;另外,对于限制embedding维度更低的情况,Glove也表现很好。
  4. 如果单纯从是否需要人工标注数据来看,Glove与Word2Vec都是无监督学习。但本质上它们的训练过程都是有label的,只不过这些label不是人工标注的,而是训练数据(corpus)本身的内部信息。所以我认为可以把它们当做特殊的无监督学习。

ELMo、GPT、BERT

学习资料

  1. https://www.bilibili.com/video/av56235038
  2. http://jalammar.github.io/illustrated-transformer/
  3. http://jalammar.github.io/illustrated-bert/
  4. https://zhuanlan.zhihu.com/p/49271699
  5. https://zhuanlan.zhihu.com/p/75391062
  6. https://zhuanlan.zhihu.com/p/56382372
  7. https://zhuanlan.zhihu.com/p/49271699
  8. ELMo原始论文
  9. GPT原始论文
  10. BERT原始论文

要点

不难发现其实所有的Embedding方式都是Transfer Learning的模式,先在预训练(pre-training)阶段利用语言模型(LM)或其他任务训练得到词的representation,然后在下游任务中,只需要将之前训练好的Embedding Matrix(lookup table)加载到下游任务的Embedding Layer,然后,既可以fix(frozen)Embedding层的参数,也可以将这些参数与下游任务的其他参数一起训练,即fine-tune的过程。注意,pre-training阶段一般是利用LM,可以利用大量无标签的corpus,即unsupervised的方式;而下游任务一般是supervised的,即一般使用有标签的corpus。

只不过,之前介绍的Embedding方法有个最大的缺陷就是,它们都只能为每个词学习到单个固定的,因此也是上下文无关(context independent)的representation。然而一个单词,可能有多种词性或者多种词义,甚至每种词性都有多种含义。我们希望得到embedding可以很好地对一词多义现象进行建模,包括语法( syntax)和语义(semantics)两方面,即多种词性、多种语义。

第一个做到这点(并为大家所熟知)的是ELMo模型,后面相继出了GPT、BERT、XLNet等模型。这些模型都需要面对两个难题

难题一

预训练阶段应该使用哪些tasks或optimization objectives

目前尚不清楚使用何种task来学习文本的representation在迁移到下游任务时最有效,为了预训练模型的通用性,目前大家一般用language model作为预训练阶段的task

三个模型pre-training阶段的架构对比ELMo的task是标准的LM,只不过ELMo训练了两个LM—— 一个forward LM
,一个backward LM(在BERT的论文中被称为left-to-right LMright-to-left的LM)。

在这里插入图片描述

(图片来源:A Step-by-Step NLP Guide to Learn ELMo for Extracting Features from Text)

给定一个N个token的序列,forword LM就是给定前kk个token,预测序列中的后一个token,用公式来表达它对句子分布的建模如下:

在这里插入图片描述

而backward LM类似,只是方向相反,即给定后kk个token,模型需要预测序列中的前一个token,用公式来表达它对句子分布的建模如下:

在这里插入图片描述

特别需要指出的是,ELMo中,每个LM在预测下一个token(后一个或前一个)时,都没有利用到句子的另一半段/另一个方向/另一个LM的信息,这一点与BERT很容易混淆,需要注意区分。

GPT的task也是标准的LM,只不过与ELMo的区别有二:

  1. 只训练了一个前向的LM
  2. 特征提取器使用的是Transformer Decoder。

细节见学习资料。

BERT的task有两个:

一是Masked LM(MLM),随机选择输入序列中15%的WordPiece(设为TiT_i),然后使用这15%的WordPiece的输出用于预测输入TiT_i。另外,为了缓和pre-training与fine-tuning阶段的mismatch(pre-training阶段有[MASK]字符,而fine-tuning阶段没有),对于选中的15%,按80%概率将其替换为特殊字符[MASK],按10%概率将其替换为一个随机的token,按10%概率不做任何替换。

在这里插入图片描述

二是 Next Sentence Prediction (NSP),在将两个序列用特殊字符[SEP]拼接起来,然后在开头加上特殊字符[CLS]表示分类(classification),然后使用[CLS]对应的输出用于预测这两个序列是否是相邻的。

在这里插入图片描述

难题二

如何将得到的representation运用/迁移到下游任务中?目前尚无公认最好的方式,其中流行的有两种策略,分别是feature-basedfine-tuning.

feature-based: 固定预训练模型的参数,抽取预训练模型的hidden states作为下游任务的额外/辅助的特征(additional / auxiliary features),与下游任务的embedding拼接起来。优点在于非常灵活,几乎不必改动下游任务的网络架构,所以适用于所有下游任务。

fine-tuning: 在预训练模型的适当位置加上分类层(FFNN+Softmax),直接将其作为下游任务的网络架构,并将下游任务的数据集做适当的转换使其符合预训练模型的输入方式。优点在于需要train from scratch的参数非常少,所以需要的训练时间更少,也往往效果更好,特别是下游任务数据集较小时

feature-based示意图(ELMo):

feature-based示意图(图片来源(右边部分经修改):Improving a Sentiment Analyzer using ELMo

fine-tuning示意图(GPT与BERT):

GPT的fine-tuning

BERT的fine-tuning

下面表格是一个小结。

特征提取器 预训练阶段的任务 将得到的representation运用到下游任务的策略
ELMo 2个单向双层 LSTM biLM: forward LM + backward LM feature-based
GPT Transformer Decoder unidirectional LM fine-tuning
BERT Transformer Encoder Masked LM + Next Sentence Prediction fine-tuning

注意

  1. BERT的语言模型是MLM,并不是“用之前看到的词预测下一个词”这种语言模型任务,而是需要看到整句话(除了15%被mask的词),因此需要用Transformer Encoder。
  2. ELMo没有使用双向LSTM,原文指出:We tie the parameters for both the token represen-tation and Softmax layer in the forwardand backward direction while maintaining separate parameters for the LSTMs in each direction
  3. ELMo并非直接将预训练得到的biLM的参数固定,而是在应用到具体的任务之前,先用该任务的数据集(如果有label则忽略label)当做LM的语料来fine-tune参数(只需要训练一个epoch),然后再固定biLM的参数,用于抽取representation。
  4. GPT以及BERT运用到下游任务的策略是fine-tuning,这与平时所说的fine-tune是有区别的。一般的fine-tune可以译为“微调”,其含义参考:迁移学习与fine-tuning有什么区别?,例如ELMo在用于下游任务时也要fine-tune。而GPT和BERT的fine-tuning其实等价于GPT的论文中task-specific input transformation,专门用于指这种将得到预训练得到的representation运用到下游任务的策略。
  5. 在BERT的作者看来(见BERT论文的Introduction部分),ELMo的biLM本质上也是unidirectional language model(单向语言模型),称之为“a shallow concatenation of independently trained left-to-right and right-to-left LMs.”,而BERT才是“deeply bidirectional”的。

句子、文章的表示

BoW、TF-IDF

学习资料

  1. https://blog.rocuku.cc/bow-tfidf-vsm/

要点

Vector Space Model(VSM),即向量空间模型,使用一个向量表示一个文本。每一维都代表一个词。如果某个词出现在了文档中,那它在向量中的值就非零。有几种常见方法计算这个值:

  • 0 / 1(0 代表这个词没有出现,1 代表这个词出现了)
  • 词频(见后面 的BoW)
  • TF-IDF(见后面 TF-IDF )

BoW

Bag-of-Words(BoW)又叫词袋模型,用于文档特征表示。BoW 忽略文本的语法和语序,用一组无序的单词来表示这段文本。即 BoW 不会保留单词在句子里的顺序/位置信息。

TF-IDF

TF-IDF(term frequency–inverse document frequency)是一种统计方法,用以评估一个字词对于其所在的文档的重要程度。字词的重要性随着它在文档中出现的次数成正比,但同时会随着它在语料库(所有文档)中出现的频率成反比。为了反映这种思想,TF-IDF由TF与IDF相乘得到,TF表示词频,IDF表示逆文档频率。

在这里插入图片描述

LSA、pLSA、LDA

学习资料

  1. https://www.cnblogs.com/pinard/p/6805861.html (这篇博客其实参考了[2])
  2. Latent Semantic Indexing (LSI) A Fast Track Tutorial(介绍了LSI的具体计算过程, 包括如何对一篇新的文档计算其潜在语义空间内的座标)
  3. 短句归一化–LSI模型 Latent Semantic Analysis(LSA/ LSI)算法简介 对比了传统的VSM模型/词袋模型和LSI模型。
  4. https://blog.csdn.net/xpy870663266/article/details/102950268 (个人对于truncated SVD的笔记)

Latent Semantic Analysis/Indexing (LSA/ LSI) 对比VSM

常用的VSM文本表示模型中有两个主要的缺陷:

  1. 该模型假设所有特征词条之间是相互独立、互不影响的(朴素贝叶斯也是这个思想),即该模型还是基于“词袋”模型(应该说所有利用VSM模型没有进行潜在语义分析的算法都是基于“词袋”假设)。
  2. 没有进行特征降维,特征维数可能会很高,向量空间可能很大,对存储和计算资源要求会比较高。

LSI的基本思想是文本中的词与词之间不是孤立的,存在着某种潜在的语义关系,通过对样本数据的统计分析,让机器自动挖掘出这些潜在的语义关系,并把这些关系表示成计算机可以”理解”的模型。它可以消除词匹配过程中的同义和多义现象。它可以将传统的VSM降秩到一个低维的语义空间中,在该语义空间中计算文档的相似度等。总的说来,LSI就是利用词的语义关系对VSM模型进行降维,并提高分类的效果。

其他学习资料

  1. 从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史
  2. 史上最全词向量讲解(LSA/word2vec/Glove/FastText/ELMo/BERT)
  3. nlp中的词向量对比:word2vec/glove/fastText/elmo/GPT/bert
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章