当前工业界,主要使用的预训练模型包括两种,一种是以wordvec为代表的预训练词向量,另一种是以BERT为代表的预训练语言模型。前者通常作为词语表示输入的初始化,后接NN/CNN/LSTM等编码层,后者既可以同样后接,也可以直接接上softmax/crf/span-pointer等进行解码。
本文,主要围绕预训练词向量模型这一主题,对当前预训练词向量模型的常用方法、评估与应用方式、领域的迁移变体、当前开放的训练工具和词向量文件进行介绍,并以word2vec和fasttext为例,展示一个词向量训练的案例,做到理论与实践相结合。
自从进入2010年以来,神经语言模型就逐渐进入人们眼球,以NNLM为典型最初代表的神经网络模型,极大的推动了NLP这一领域的发展。
下面就选择其中三种典型进行介绍。
1、word2vec
word2vec是2013年Google开源的一款用于词向量计算的工具,通过内置的语言模型训练目标,可以将中间层得到的向量权重矩阵进行抽离,形成每个词对应的向量化表示,包括CBOW、Skip-gram两种方式,前者通过周围词来预测中心词,后者以中心词来预测上下文。
经典的wordvec结构包括输入层、隐藏层和输出层,其计算流程为:
1、输入层存储上下文单词的onehot。假设单词向量空间dim为V,上下文单词个数为C。
2、所有onehot分别乘以共享的输入权重矩阵W。V*N矩阵,N为自己设定的数,初始化权重矩阵W。
3、所得的向量相加求平均作为隐层向量,size为1*N。
4、乘以输出权重矩阵W'N*V。
5、得到向量1*V,经过激活函数处理得到V-dim概率分布。
6、HierarchicalSoftmax分类,概率最大的index所指示的单词为预测出的中间词与预测值的onehot做比较,根据误差更新权重矩阵。
这个W矩阵就是所有单词的wordembedding,任何一个单词的onehot乘以这个矩阵都将得到自己的词向量。
通常,在训练词向量时候,会根据语料的大小来选择相应的训练方法。例如,针对小型的数据集,可以用CBOW算法,该方法对于很多分布式信息进行了平滑处理,将一整段上下文信息视为一个单一观察量,对于小型的数据集,这一处理是有帮助的。相比之下,大型数据集,可以用Skip-Gram模型,该方法将每个“上下文-目标词汇”的组合视为一个新观察量,这种做法在大型数据集中会更为有效。
2、fasttext
fastText是Facebook于2016年开源的一个词向量计算和文本分类工具。将整篇文档的词及n-gram向量叠加平均得到文档向量,然后使用文档向量做softmax多分类。包括字符级n-gram特征的引入以及分层Softmax分类两种。
与CBOW一样,原本的fastText模型包括输入层、隐含层、输出层,输入都是多个经向量表示的单词,输出都是一个特定的目标,隐含层都是对多个词向量的叠加平均。不同的是,CBOW的输入是目标单词的上下文,fastText的输入是多个单词及其n-gram特征,这些特征用来表示单个文档,CBOW的输入单词被onehot编码过,fastText的输入特征是经embedding化的,CBOW的输出是目标词汇,fastText的输出是文档对应的类标。
而如果将该类标替换成中间目标词,那么就可以得到wordvec的升级版,即单纯的词向量模型。例如,word2vec把语料库中的每个单词当成原子的,它会为每个单词生成一个向量。这忽略了单词内部的形态特征。
fasttext使用了字符级别的n-grams来表示一个单词。对于单词“apple”,假设n的取值为3,则它的trigram有“
因此,因为它们的n-gram可以和其它词共享,对于训练词库之外的单词,能够解决或者oov词,这也是在当前很多文本分类、推荐场景中会优先选用fastText作为训练方法。
3、Glove
GloVe是斯坦福团队于2014年提出一个词向量方法,全名叫“GlobalVectors”,直接利用全局的统计信息进行训练。
与上述两种方式靠滑动窗口来制造局部上下文不同,GloVe会用到全局的词语之间共现的统计信息,即词的出现次数,词对之间的共现概率,形成共现概率矩阵,并试图生成词向量来毕竟共现概率,利用Word2Vec的skip-gram算法的高性能来解决LDA的计算量复杂问题。
因此,我们可以发现,Glove需要事先统计共现概率,这也让其通常被认为是无监督学习,实际上glove还是有label的,即共现次数。与wordvec还有一处不同的是,损失函数是最小平方损失函数,权重可以做映射变换。
词向量模型的超参数很多,不同的参数选择会取得不同的效果,并且,word2vec中有几个大家提的比较多的问题。以gensim-word2vec为例,包括以下参数:
sentences:可以是一个list,对于大语料集,可使用BrownCorpus,Text8Corpus或LineSentence构建;
sg:用于设置训练算法,默认为0,对应CBOW算法;sg=1则采用skip-gram算法;
size:特征向量的维度,默认为100。大的size需要更多的训练数据,但是效果会更好.推荐值为几十到几百;
window:表示当前词与预测词在一个句子中的最大距离是多少;
alpha:学习速率;
seed:用于随机数发生器。与初始化词向量有关;
min_count:可以对字典做截断.词频少于min_count次数的单词会被丢弃掉,默认值为5;
max_vocab_size:设置词向量构建期间的RAM限制。如果所有独立单词个数超过这个,则就消除掉其中最不频繁的一个。每一千万个单词需要大约1GB的RAM。设置成None则没有限制;
sample:高频词汇的随机降采样的配置阈值,默认为1e-3,范围是(0,1e-5);workers参数控制训练的并行数;
hs:如果为1则会采用hierarchicalsoftmax技巧。如果设置为0(defaut),则negativesampling会被使用;
negative:如果>0,则会采用negativesamping,用于设置多少个noisewords;
cbow_mean:如果为0,则采用上下文词向量的和,如果为1(defaut)则采用均值。只有使用CBOW的时候才起作用;
hashfxn:hash函数来初始化权重。默认使用python的hash函数;
iter:迭代次数,默认为5;
trim_rule:用于设置词汇表的整理规则,指定那些单词要留下,哪些要被删除。可以设置为None(min_count会被使用)或者一个接受()并返回RUE_DISCARD,utis.RUE_KEEP或者utis.RUE_DEFAUT的函数;
sorted_vocab:如果为1(defaut),则在分配wordindex的时候会先对单词基于频率降序排序;
batch_words:每一批的传递给线程的单词的数量,默认为10000。
预训练词向量生产出来,需要进行性能的评估。这方面的方法包括基于评测集,或者基于具体业务使用,用业务的指标来进行评估。
1,预训练词向量的评估
学术上,词向量的质量通常由类比问题任务进行评估。如CA-translated包含了三个语义问题和134个中文词。CA8是专门为中文语言设计的。它包含了17813个类比问题,覆盖了综合的词法和语义关联。
工业,则使用词向量来代替之前随机生成的词向量文件,来对自然语言处理中的文本/情感分类、实体识别、关系抽取等任务进行评估。
2、预训练词向量的应用
预训练词向量文件最大的价值在于解决了一个词语的初始化稠密表示,在解决当前以数值化为输入的深度或机器学习模型第一部的同时,还保留了一个词的区别性特征。
另一方面,词向量可以用于当前无监督文本表示的重要方法,通过对文本进行分词,然后找到词语对应的向量,通过向量叠加的方式可以快速得到一个文本的向量表示,这一表示在诸如情感分析、句子相似度计算等任务中是实际有效的,基于文本表示,也可以进一步提升文本分类、聚类、相似query召回等使用场景性能,甚至很形象的成为了当前业务模型的baseline或者兜底模型。
共现信息,是cbow以及skipgram的基础,其本质在于通过周围词来建模中心词或者用中心词来建模周围词。因此,通过构造不同的共现信息,可以得到不同类型的向量形式。这里取了个名字叫gramembedding,用于表示专指文本的一系列embedding变体。
例如,对于一个词来说,我们可以把词拆分为词word、n元序列ngram、汉字character,偏旁部首Radical,词性POS,依存关系dependency、拼音pinying。
单元的共现,我们同样可以进行组合,例如,构造word-word,word-ngram、ngran-ngram等,得到上下文特征(单词、n-gram、字符等)等不同粒度的词向量。
观察近几年的发展,词向量可以进一步分成偏旁部首向量、字符向量等。如香侬科技推出的glyce向量,引入汉字的字形特征。蚂蚁金服推出的cw2vec字符向量,将汉字拆解成偏旁、字件进行建模。
当ngram中的n为1时,可以得到字向量,n为2或者更多时,则可以得到词向量等。fasttext中,就是得到了ngram的向量,并进行加和,得到一个OOV词语的向量进行表示。
例如,基于skigram,分别设定词向量的维度及其他超参数,可以得到字向量,拼音向量,词向量,词性向量,通过上下文共现与PCA降维的方法可以得到依存向量。
从下面的结果可以看出,词和字向量的效果看起来还不错。
2)拼音向量,从wo,guo的拼音相似拼音来看,我们可以看到,这种相似的拼音更像是一种搭配,很有意思,(词性参照jieba分词词性对照表)。
3)词性向量,从a,n的相似词性来看,也似乎更像是一种搭配现象,或许有更好的解释。
2、DomainEmbedding
为了更好的适配不同领域的任务,当前也有很多的公司或者任务会选择使用领域性的领域进行训练,以得到不同领域的词向量文件,这与当前各种领域的bert模型做法是类似的。当前出现了金融领域bert、法律领域的bert等。
代表性的,2018年推出的Chinese-Word-Vectors中提供了包含经过数十种用各领域语料(百度百科、维基百科、人民日报1947-2017、知乎、微博、文学、金融、古汉语等)训练的词向量,涵盖各领域,且包含多种训练设置。
又如,当前PaddleNLP官方提供了61种可直接加载的预训练词向量,训练自多领域中英文语料、如百度百科、新闻语料、微博等,覆盖多种经典词向量模型(word2vec、glove、fastText)、涵盖不同维度、不同语料库大小。
3、GraphEmbdding
经典的deepwalk以及node2vec也是借鉴word2vec思想,学习图节点嵌入的方法。并且成为当前推荐系统中的一个重量级使用方法。
1、Deepwalk
通过对图中的节点进行随机游走(主要考虑深度优先遍历),形成节点之间的游走序列,并将其作为上下文,后面接入skipgram形成节点向量,从构造上来看,就是首先利用randomwalk来表示图结构,然后利用skip-gram模型来更新学习节点表示。
随机选取与其邻接的下一个结点,直至达到给定长度,这个长度作为一个参数进行指定,这个类似于word2vec中的window_size上下文窗口。
2、node2vec
node2vec综合考虑了广度优先遍历(用于捕捉局部信息)和深度优先遍历(用于捕捉全局信息)的游走,提出二阶随机游走思想,解决内容相似和结构相似的问题。
前者具有直接链接关系的两个节点,我们可以认为是内容相似的(例如两个灰色网站之间很有可能能够直接跳转,如图中的s1,s2等一阶邻居)、结构相似(例如周围邻居数量都很类似,如图中的s6和u节点,两个都有4个邻接,结构类似)。
具体实现思路也很简单:
我们从节点v转移到节点t,并且当前在节点t时,需要考虑下一个采样节点x。因此,可以设计一个节点到它的不同邻居的转移概率:
其中,每一步采样都会有三种状态,分别对应于上图的0,1,2三种情况:
1)0代表如果t和x相等,那么采样的概率为1/p;
2)1代表t与x相连,采样的概率为1;
3)2代表t与x不相连,采样的概率为1/q
式子中的参数p作为返回参数,控制重新采样上一步已访问节点的概率。参数q,作为出入参数,控制采样的方向。
其中:
1)当q>1时,接下来采样的节点倾向于节点t,偏向于广度优先;
2)当q<1时,接下来采样的节点倾向于远离t,偏向于深度优先遍历。
3)当p>max(q,1)时,接下来采样的节点很大概率不是之前已访问节点,这一方法使得采样偏向深度优先;
4)当p 此外,在推荐场景中也有item2vec的类似延伸,例如协同过滤算法是建立在一个user-item的co-occurrence矩阵的基础上,通过行向量或列向量的相似性进行推荐。如果将同一个user购买的item视为一个context,就可以建立一个item-context的矩阵。进一步的,可以在这个矩阵上借鉴CBoW模型或Skip-gram模型计算出item的向量表达。 下面以gemsim中的wordvec和fasttext为例进行实践,大家可以看出其中的一些具体的步骤和结果。 1、构造训练语料 3、增量数据预训练 增量训练,主要解决在新的文本上进行训练,也可以引入一些新的词,但这个时候,需要考虑到min_count这一过滤条件。 1、全量数据训练 4、fasttext是如何解决oov问题的 通过对其源码进行阅读,可以发现fasttext针对OOV词的原始计算方式包括三个步骤, 1)抽取出每个词的N-grams; 2)与预先存好的n-grams词库进行匹配; 3)将匹配到的n-gram向量进行平均,实现如下: 实际上,词向量的发展也在一定程度上验证了当前nlp的进步。 由最开始的基于one-hot、tf-idf、textrank等的bag-of-words,到LSA(SVD)、pLSA、LDA的主题模型词向量,再到word2vec、fastText、glove为代表的固定表征,最后到当前elmo、GPT、bert为代表的基于词向量的动态表征,都说明了语义建模中的动态属性和文本语境的多样性。 不过,我们需要认识的是,在此类词向量中,虽然其本质仍然是语言模型,但是它的目标不是语言模型本身,而是词向量,其所作的一系列优化,其专注于词向量本身,因此做了许多优化来提高计算效率。 例如,与NNLM相比,word2vec将词向量直接sum,不再拼接,并舍弃隐层;考虑到sofmax归一化需要遍历整个词汇表,采用hierarchicalsoftmax和negativesampling进行优化,前者生成一颗带权路径最小的哈夫曼树,让高频词搜索路劲变小;后者对每一个样本中每一个词都进行负例采样。 最后,以当前一个新的观点来结尾: 参考文献 就职于360人工智能研究院、曾就职于中国科学院软件研究所。