关于fastText,有两篇paper需要看下,见下面的参考。如果你的目的是用来训练词向量,可以查看paper 1. 如果是用来进行文本分类,参考paper 2.
第1为《Enriching Word Vectors with Subword Information》:使用subword的信息来增强词向量。
对于常规的一些词向量模型,它们将词汇表中每个词表示成一个不同的向量,在训练中会忽略词形。这对于一些大词汇量、许多罕见字、且词形丰富的语言来说(比如:Turkish语 或 Finnish语),是个很大限制,很难使用这些模型训练到较好的词级别(word-level)的向量。fastText是一种基于skip-gram模型的新扩展,它会使用subword的信息,将每个词被表示成一个字符级n-gram词袋(a bag of character n-grams)。每个向量表示与每个字符级n-gram相关联,而词(word)则可以看成是这些n-gram向量表示的求和(sum)。fastText在大语料上训练很快。
1.介绍
在NLP领域学习词的连续表示(continuous representations)已经有一段历史了(rumelhart et al., 1988)。这些表示通常来自于大型无标记语料来使用共现统计获得(Deerwester et al., 1990)。大部分工作称为“分布式语义(distributional semantics)”,已经研究了这些方法的属性(turney et al.,2010..)。在神经网络社区,Collobert和Weston(2008)提出了使用一个前馈网络来学习word embeddings,它通过基于一个词的左前两词和右后两词来预测中心词。最近,Mikolov(2013b)提出了一种简单的log-bilinear模型来高效学习大规模语料的连续表示。
通过一个不同的向量(distinct vector)来表示词汇表中的每个词,不需要参数共享。特别的,它们忽略了词的内部结构,对于词型丰富的语言( morphologically rich languages)来说,比如Turkish语 和 Finnish语,这是个重要的限制。这些语言包含了许多罕见词,使得很难学习很好的word-level representations。在本paper中,我们提出了为character n-grams学习词表示,并将words表示成n-gram vectors的求和(sum)。我们的主要贡献是对Mikolov的skip-gram做了一个扩展,让它能解释subword information。我们在五种语言上(它们具有不同的词型)评估了该模型,展示了我们的方法的好处。
2.相关工作
形态学词表示(Morphological word representations): 最近几年提出了不少方法,将形态学信息插入到词向量中。为了更好地建模罕见字,Alexandrescu和Kirchhoff(2006)引入了因子化的自然语言模型,其中词被表示成关于特征的集合。这些特征可以包含形态学信息,该技术被成功应用于形态学丰富的语言中,比如:Turkish(Sak 2010)。最近,一些相关的工作提出了不同复合函数来从词素(morphemes)生成词表示。这些不同的方法依赖于词的一个形态学解耦,但我们的方法不会。相似的,Chen(2015)介绍了一个方法来联合学习中文词和字符的embeddings。Soricut(2015)提出了将形态相似的词限制到具有相似表示。Soricut(2015)描述了一个方法来学习形态学转移的向量表示,允许通过应用规则来获取对未登陆词的表示。Cotterell(2015)则在形态学标注的数据上学习词表示。与我们的方法最接近的是Schutze(1993),它通过SVD来学习字符级4-grams的表示,并通过对4-gram representations进行求和来生成词表示。
NLP的字符级特征(Character level features):与我们工作相关的另一个研究领域是,NLP的字符级模型,它直接从字符序列中学习表示。这种模型的最高级方法是RNN,应用到语言建模(Mikolov 2012)、文本归一化(Chrupala, 2014),、词性标注(Ling.2015)、parsing(Ballesterors.2015)。该模型的另一个家族是在字符上训练的CNN,它可以被应用到:词性标注(Santos,2014)、情感分析(dos Santos.2014)、文本分类(zhang.2015)、语言建模(Kim.2016)。(Sperr.2013)提出了基于受限波尔茨曼机的语言模型,其中词被编码成字符级别n-grams的一个集合。最后,在机器翻译中的最近工作也提出了使用subword units来获取罕见词的表示。(Sennrich.2016)
3.模型
本节中,我们提出了一个模型来学习representations来解释词形。
1.1 通用模型
先简单回顾下(Mikolov et al.,2013b)提出的continuous skip-gram模型,给定一个size=W的词汇表,其中词通过它的索引进行表示 \(w \in {1, ..., W}\),目标是为每个词w学习一个向量表示。受分布式假设的启发,这些表示被训练来预测在一个给定词的上下文中出现的词。更正式的,给定一个大型训练语料,一个词序列: \(w_1, ..., w_T\),它的skip-gram模型的目标函数是最大化log似然:
\[\sum_{t=1}^{T}\sum_{c \in {C_t}}log p(w_c|w_t)\]其中,上下文\(C_t\)表示在词\(w_t\)周围词的索引集合,给定\(w_t\),预测观察到\(w_c\)的概率。使用一个scoring函数s,可以将(word,context)pair映射到一个R空间的分值上:
\[p(w_c|w_t)=\frac{e^{s(w_t,w_c)}}{\sum_{j=1}^{W}e^{s(w_t,j)}}\]该问题也可分解为多个二分类问题,目标是预测对应的\(w_c\)是否出现。对于位置t的词,以及上下文c,我们可以得到negative log-likelihood:
\[log(1+e^{-s(w_t,w_c)})+\sum_{n \in {N_{t,c}}} log(1+e^{s(w_t,n)})\]其中\(N_{t,c}\)是一个从词汇表抽样出的负样本集合。logistic loss函数\(l:x \rightarrow log(1+e^{-x})\),我们可以获得相应的目标函数:
\[\sum_{t=1}^{T}\sum_{c \in C_t}l(s(w_t,w_c))+\sum_{n \in N_{t,c}}l(-s(w_t,n))\]\(w_t\)和上下文词\(w_c\)采用标量积:$ s(w_t,w_c)=u_{w_t}^{T}v_{w_c} $
1.2 Subword模型
由于每个词会使用一个不同的向量表示,skip-gram模型会忽视词的内部结构。在本部分,我们接着提出一个不同的scoring函数 s,将subword信息考虑进行。给定一个词w,我们定义在w上出现的n-gram集合为:$ G_w\subset{1,…,G} $.我们将一个向量表示\(z_g\)与每个n-gram g相关联。我们可以通过对这些n-gram的向量进行求和来表示一个词。我们获得一个scoring函数:
\[s(w,c)=\sum_{g \in {G_w}}z_g^Tv_c\]对于词w,它的n-gram集合中总是包含着它,也可以为每个词学到一个向量表示。n-gram集合也是词汇表的一个超集(superset)。需要注意的是,对于共享相同的字序列(sequence of characters)的一个词和一个n-gram,会分配不同的向量给它们。例如,单词”as”和出现在词”paste”中的bigram “as”,会分配给不同的向量。这种简单模型允许在不同的词之间共享representations,从而对一些罕见词学到可靠的向量表示。
1.3 n-gram字典
上述模型很简单,并在\(G_w\)的定义上留下了设计选择的空间。在本paper中,我们采用了一个非常简单的scheme:所有n-gram的长度在[3,6]范围内. 可以使用n-gram的不同集合,例如前缀和后缀。同时,也添加一个特殊字符做为词的开头和结尾,这样就可以区分前缀和后缀。
为了限定模型的内存,使用一个hashing函数,将n-gram映射到[1,K]上。下面,我们使用的K等于200w。在结尾处,一个词可以被表示成在词典中的索引,以及它的n-gram的hash值。为了提升模型效率,我们不会使用n-gram来表示在词汇表中最频繁的P个词。P的选择需要权衡,值越小表示计算代价越高,但性能越好。当P=W时,我们的模型就是skip-gram模型。
1.4 试验
数据集和baseline:将新模型与word2vec的cbow和skip-gram相比较。数据集:5种语言的Wikipedia数据。三种size:小(50M tokens),中(200M tokens),完整。训练使用的epoch为:5.
其它参数:negative-sample: 5, rejection threshold: $ 10^{-4} $, window-size: 5, min-count:5.
- 小数据集:100维, 中数据集:200维,完整数据集:300维.
- skip-gram baseline learning-rate: 0.025; CBOW: 0.05, 新模型:0.05
对于英文语料,新模型的训练速度比skip-gram慢1.5倍。
人肉相似度判断
评估向量的质量:计算人肉判断(human judgement)与向量表示之间的cosine相似度之间的Spearman rank相关系数。
使用的数据集:
- 英文:使用 WS353 (Finkelstein et al.2001)以及 RW (Luong et al.2013)
- 德文:Gur65, Gur350,ZG222(Gurevych, 2005; Zesch and Gurevych, 2006)
- 法文:RG65(Joubarne and Inkpen, 2011)
- 西班牙文:WS353(Hassan and Mihalcea, 2009)
这些数据集中的一些词不会在训练数据中出现,对于CBOW方法和skip-gram baseline方法,我们不能获取这些词的向量表示。因此,我们决定排序包含这些词的pairs进行评测。我们在表1中上报了OOV比率。需要注意,我们的方法和baseline共享着相同的词汇表,因此,在相同训练集中的不同方法的结果是可以比较的。另一方面,不同训练语料上的结果是不可比较的,因为词汇表并不相同(具有不同的OOV rates)。
表1:
我们注意到,使用subword信息的新模型的效果在大多数数据集上的效果要好。我们也观察到,字符n-grams的效果,在德文上远比英文、西班牙文上好。一点也不令人吃惊,因为德文的字形更丰富。数据集越小,区别越重要。在RW英文数据集(罕见词数据集)上,新方法效要比baseline要好。
词类比任务(Word analogy)
使用Mikolov et al.(2013a)提出的:句法:syntactic(en-syn),以及语义:semantic(en-sem)来评测,数据集使用cs-all(Svoboda and Brychcin (2016), for Czech, 捷克文)。一些包含words的questions不会在训练语料中出来,我们会排除这些questions,并上报oov rate。所有的方法在相同数据上进行训练,因此可比较。我们上报了表1中的不同模型。我们观察到,字形(morphological)信息对于syntactic任务有极大的帮助,新方法在en-syn上效果要比baseline好。相反的,它在小数据集的semantic任务上,效果有所下降。第二,对于捷克文,一个字形丰富的语言,使用subword信息可以很强地提升效果(对比baseline)。
2.高效文本分类tricks
Mikolov等在
对应paper的研究主要是基于:有名标签预测(namely tag prediction), 情感分析(sentiment analysis),这两个领域做出的。
2.1 模型架构
baseline: 对于句子分类,简单又有效的baseline为:BOW向量 + 一个线性分类器(LR或SVM)。
线性分类器不会共享特征和分类间的参数。对于输出空间很大,但某些类上的训练样本很少的上下文上,这种方法的泛化能力受限。常用的解决方法是,将线性分类器分解为低秩矩阵(Schutze, 1992; Mikolov et al., 2013),或者使用多层神经网络(Collobert and Weston, 2008;Zhang et al., 2015)
图3展示了简单线性模型的秩约束(rank constraint)。第一个权重矩阵A,是一个在words上的look-up table。词向量被平均成一个文本向量,然后输入(feed)到一个线性分类器。文本向量是一个隐变量,它可以尽可能被复用。该架构与Mikolov提出的CBOW模型相似,中间的word被一个label所取代。我们使用softmax函数f来计算在预定义分类上的概率分布。对于N个文档的集合,目标是在这些类上最小化负log-likelihood:
\[-\frac{1}{N}\sum_{n=1}^{N}y_nlog(f(BAx_n))\]其中xn是第n个文档的归一化的bag of features,yn是label,A和B是权重矩阵。该模型可以在多核CPU上使用SGD和一个线性衰减的learning_rate进行异步训练。
Hierarchical softmax
由于类的数目相当大,计算线性分类器的开销很大。计算复杂度是O(kh),其中k是类的个数,h是文本向量的维度。为了在运行时提升,可以使用基于Huffman树的Hierarchical softmax,具体可以详见另一篇。在训练期,它的计算复杂度下降到O(hlog2(k)).
当在测试阶段时,当查询最可能的分类时,Hierarchical softmax也很有优势。每个节点与一个概率相关,该概率表示从根节点到该节点上路径的概率。如果节点的深度为l+1,相应的父节点为:n1, n2, …, nl,概率为:
\[P(n_{l+1})=\prod_{i=1}^{l}P(n_i)\]这意味着一个节点的概率总是比它的父节点要低。搜索某一深度的该树时,以及在叶子间跟踪最大概率,允许我们抛弃掉所有小概率的分枝。实际上,我们观察到在测试时,复杂度降到O(hlog2(k))。该方法会进一步扩展到使用binary heap来计算top T个target,开销为O(log(T))。
N-gram features
BOW与词序无关,显式采用该顺序的计算开销通常很大。作为替代,我们使用bag-of-n-grams作为额外的特征来捕获一些关于局部词序的部分信息(partial information)。这在惯例上很有效(Wang and Manning, 2012).
我们使用hashing trick(Weinberger et al., 2009),以及Mikolov et al.(2011)中相同的hashing function,以及10M的bins(如果我们只使用bigrams,否则可能100M),来维持一个快速的、内存高效的n-gram映射。
2.2 实验评测
fastText在两个不同的任务上进行评测。首先,会比较在情感分析(sentiment analysis)问题上的文本分类器。模型的实现可以使用Vowpal Wabbit library,但实际上使用的定制版本要比它快2-5x倍。
情感分析(Sentiment analysis)
数据集与baseline。使用8份由Zhang et al. (2015)提供的相同的数据集以及评测约定。使用Zhang et al. (2015)提供的n-gram和TF-IDF做为baselines。以及Zhang and LeCun (2015)提出的字符级卷积模型(char-CNN), (Xiao and Cho, 2016)提出的字符级卷积RNN模型(char-CRNN), Conneau et al. (2016)提出的极深卷积网络(VDCNN)。我们另外采用了Tang et al. (2015)的评测约定,上报了我们的方法以及他们的两种方法 (Conv-GRNN 和 LSTM-GRNN).
结果:使用10个隐单元,fastText迭代5轮(epochs),learning_rate为{0.05, 0.1, 0.25, 0.5}。在该任务上,添加bigram信息可以提升1-4%的效果。整体的accuracy比char-CNN和char-CRNN稍好一些,比VDCNN略差些。注意,可以使用更多的n-gram可以(略微)提升accuracy,例如:使用trigrams,在Sogou语料上的效果可以提升到97.1%。最终,下图展示了我们的方法与Tang et al. (2015)的比较。在验证集上调整超参数,并观察到:使用n-gram为5-gram时,会达到最佳性能。不同于Tang的方法,fastText不会使用pre-trained word-embeddings,据说在accuarcy上可以有1%的提升。
在训练时间上: char-CNN 和 VDCNN在NVIDIA Tesla K40 GPU训练,fastText的模型在使用20线程的CPU上训练。对于char-CNN,使用最新的CUDA实现,可以有10x的速度提升。fastText则可以在1分钟内完成训练。。。
标签预测
数据集和baselines: 采用YFCC100M数据集(Thomee et al., 2016),包含了100M的图片,带说明(captions),标题(titles),以及标签(tags)。我们只关注title和caption(不使用图片)来预测tags。将出现次数少于100次的words/tags进行移除,将数据分割成训练集/验证集/测试集。训练集包含大于9000W的样本(1.5B的tokens),验证集93W的样本,测试集54W的样本。词汇表的size为30W左右,有31W左右是唯一的tags。我们发布了一个脚本来重新创建该数据集。
我们使用一个基于频率的方法作为baseline,来预测最频繁的标签。我们也比较了Tagspace(Weston et al.,2014)的方法,它与我们的模型相类似,但基于Wsabie model of Weston et al. (2011)。Tagspace模型使用卷积进行描述,我们使用它的线性版本作为baseline。
结果与训练时间:上表为fastText与baseline的比较。比较了fastText 5轮的迭代,与两种隐层size(50, 100)的Tagspace算法。两种模型的隐层size都是小值时,在accuracy上效果相似,但如果增加bigram,会有极大的提升。在测试时,tagspace需要为所有类计算分值,这会相当慢,当类数目很大时(本例中为:300K),fastText的inference则会很快!