Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Facebook词向量工具FastText

FastText简介

fastText是Facebook于2016年开源的一个词向量计算和文本分类工具,在文本分类任务中,fastText(浅层网络)往往能取得和深度网络相媲美的精度,却在训练时间上比深度网络快许多数量级。在标准的多核CPU上, 能够训练10亿词级别语料库的词向量在10分钟之内,能够分类有着30万多类别的50多万句子在1分钟之内。

FastText与Word2Vec

fastText的其中的一个作者是Thomas Mikolov。也正是这个人在谷歌的时候,带领团队在2012年提出了 word2vec代替了one-hot编码,将词表示为一个低维连续嵌入,极大促进了NLP的发展。14年她去了脸书,然后提出了word2vec的改进版:fasttext。所以fastText和word2vec在结构上很相似。

相同之处:

  • 图模型结构很像,都是采用 embedding 向量的形式,得到 word 的隐向量表达。
  • 采用很多相似的优化方法,比如使用 Hierarchical softmax 优化训练和预测中的打分速度。
  • 训练词向量时,两者都是无监督算法。输入层是 context window 内的 term。输出层对应的是每一个 term,计算某 term 的概率最大;
  • 在使用层次softmax的时候,huffman 树叶子节点处是训练语料里所有词的向量。

不同之处:

  • 模型的输出层:word2vec的输出层,对应的是每一个term,计算某term的概率最大;而fasttext的输出层对应的是分类的label。不过不管输出层对应的是什么内容,其对应的vector都不会被保留和使用;
  • 模型的输入层:word2vec的输入层,是 context window 内的term;而fasttext 对应的整个sentence的内容,包括term,也包括 n-gram的内容;
  • 两者本质的不同,体现在 Hierarchical softmax的使用。
    • Wordvec的目的是得到词向量,该词向量 最终是在输入层得到,输出层对应的Hierarchical softmax也会生成一系列的向量,但最终都被抛弃,不会使用。
    • fasttext则充分利用了Hierarchical softmax的分类功能,遍历分类树的所有叶节点,找到概率最大的label(一个或者N个)

FastText的优点:

  • 适合大型数据+高效的训练速度:能够训练模型“在使用标准多核CPU的情况下10分钟内处理超过10亿个词汇”,特别是与深度模型对比,fastText能将训练时间由数天缩短到几秒钟。使用一个标准多核 CPU,得到了在10分钟内训练完超过10亿词汇量模型的结果。此外, fastText还能在五分钟内将50万个句子分成超过30万个类别。
  • 支持多语言表达:利用其语言形态结构,fastText能够被设计用来支持包括英语、德语、西班牙语、法语以及捷克语等多种语言。它还使用了一种简单高效的纳入子字信息的方式,在用于像捷克语这样词态丰富的语言时,这种方式表现得非常好,这也证明了精心设计的字符 n-gram 特征是丰富词汇表征的重要来源。FastText的性能要比时下流行的word2vec工具明显好上不少,也比其他目前最先进的词态词汇表征要好。
  • fastText专注于文本分类,在许多标准问题上实现当下最好的表现(例如文本倾向性分析或标签预测)。
  • 比word2vec更考虑了相似性,比如 fastText 的词嵌入学习能够考虑 english-born 和 british-born 之间有相同的后缀,但 word2vec 却不能。

模型架构

fastText的架构和word2vec中的CBOW的架构类似,因为它们的作者Tomas Mikolov,而且确实fastText也算是word2vec所衍生出来的。

CBOW的架构

输入的是 的上下文2d个词,经过隐藏层后,输出的是 。word2vec将上下文关系转化为多分类任务,进而训练逻辑回归模型,这里的类别数量是 词库大小。通常的文本数据中,词库少则数万,多则百万,在训练中直接训练多分类逻辑回归并不现实。word2vec中提供了两种针对大规模多分类问题的优化手段,negative sampling 和 hierarchical softmax。在优化中,negative sampling 只更新少量负面类,从而减轻了计算量。hierarchical softmax 将词库表示成前缀树,从树根到叶子的路径可以表示为一系列二分类器,一次多分类计算的复杂度从 降低到了树的高度。

fastText模型架构

其中 表示一个文本中的n-gram向量,每个特征是词向量的平均值。这和前文中提到的cbow相似,cbow用上下文去预测中心词,而此处用全部的n-gram去预测指定类别。注意:此架构图没有展示词向量的训练过程。可以看到,和CBOW一样,fastText模型也只有三层:输入层、隐含层、输出层(Hierarchical Softmax),输入都是多个经向量表示的单词,输出都是一个特定的target,隐含层都是对多个词向量的叠加平均。

fastText与CBOW的不同点:

  • CBOW的输入是目标单词的上下文,fastText的输入是多个单词及其n-gram特征,这些特征用来表示单个文档
  • CBOW的输入单词被one-hot编码过,fastText的输入特征是被embedding过
  • CBOW的输出是目标词汇,fastText的输出是文档对应的类标

值得注意的是,fastText在输入时,将单词的字符级别的n-gram向量作为额外的特征;在输出时,fastText采用了分层Softmax,大大降低了模型训练时间。

Hierarchical softmax

Softmax回归(Softmax Regression)又被称作多项逻辑回归(multinomial logistic regression),它是逻辑回归在处理多类别任务上的推广。

在逻辑回归中,我们有m个被标注的样本: ,其中 。因为类标是二元的,所以我们有 。我们的假设(hypothesis)有如下形式:

代价函数(cost function)如下:

   

在Softmax回归中,类标是大于2的,因此在我们的训练集 中,。给定一个测试输入x,我们的假设应该输出一个K维的向量,向量内每个元素的值表示x属于当前类别的概率。具体地,假设 形式如下:

   

代价函数如下:

   

其中 是指示函数,即

既然我们说Softmax回归是逻辑回归的推广,那我们是否能够在代价函数上推导出它们的一致性呢?当然可以,于是:

   

可以看到,逻辑回归是softmax回归在K=2时的特例。你可能也发现了,标准的Softmax回归中,要计算y=j时的Softmax概率: ,我们需要对所有的K个概率做归一化,这在 很大时非常耗时。于是,分层Softmax诞生了,它的基本思想是使用树的层级结构替代扁平化的标准Softmax,使得在计算 时,只需计算一条路径上的所有节点的概率值,无需在意其它的节点。

下图是一个分层Softmax示例:

树的结构是根据类标的频数构造的霍夫曼树。K个不同的类标组成所有的叶子节点,K-1个内部节点作为内部参数,从根节点到某个叶子节点经过的节点和边形成一条路径,路径长度被表示为 。于是 就可以被写成:

   

其中: 表示sigmoid函数; 表示n节点的左孩子; 是一个特殊的函数,被定义为: ; 是中间节点 的参数;X是Softmax层的输入。

上图中,高亮的节点和边是从根节点到 的路径,路径长度 , 可以被表示为:

   

于是,从根节点走到叶子节点 ,实际上是在做了3次二分类的逻辑回归。通过分层的Softmax,计算复杂度一下从 降低到 。

N-gram

word2vec把语料库中的每个单词当成原子的,它会为每个单词生成一个向量。这忽略了单词内部的形态特征,比如:“book” 和“books”, “apple” 和“apples”,这两个例子中,两个单词都有较多公共字符,即它们的内部形态类似,但是在传统的word2vec中,这种单词内部形态信息因为它们被转换成不同的id丢失了。

为了克服这个问题,fastText使用了字符级别的n-grams来表示一个单词。对于单词“apple”,假设n的取值为3,则它的trigram有

“”

其中,表示后缀。于是,我们可以用这些trigram来表示“apple”这个单词,进一步,我们可以用这5个trigram的向量叠加来表示“apple”的词向量。

这带来两点好处:

  • 对于低频词生成的词向量效果会更好。因为它们的n-gram可以和其它词共享。
  • 对于训练词库之外的单词,仍然可以构建它们的词向量。我们可以叠加它们的字符级n-gram向量。

fastText的优化

子空间量化

product quantization是一种保存数据间距离的压缩技术。PQ 用一个码本来近似数据,与传统的 keams 训练码本不同的是, PQ 将数据空间划分为 k 个子空间,并分别用 kmeans 学习子空间码本。数据的近似和重建均在子空间完成,最终拼接成结果。在 fasttext 中,子空间码本大小为 256,可以用 1 byte 表示。子空间的数量在 [2, d/2] 间取值。除了用 PQ 对数据进行量化压缩,fasttext 还提供了对分类系数的 PQ 量化选项。PQ 的优化能够在不影响分类其表现的情况下,将分类模型压缩为原大小的 。

裁剪字典内容

fasttext 提供了一个诱导式裁剪字典的算法,保证裁剪后的字典内容覆盖了所有的文章。具体而言,fasttext 存有一个保留字典,并在线处理文章,如果新的文章没有被保留字典涵盖,则从该文章中提取一个 norm 最大的词和其子串加入字典中。字典裁剪能够有效将模型的数量减少,甚至到原有的 。

FastText的使用

使用FastText训练词向量

# -*- coding: utf-8 -*-
import jieba
import os
import fasttext


def get_data():
    # 清华大学的新闻分类文本数据集下载:https://thunlp.oss-cn-qingdao.aliyuncs.com/THUCNews.zip
    data_dir = 'D:\\迅雷下载\\THUCNews\\THUCNews\\财经'

    with open("finance_news_cut.txt", "w", encoding='utf-8') as f:
        for file_name in os.listdir(data_dir):
            print(file_name)
            file_path = data_dir + os.sep + file_name
            with open(file_path, 'r', encoding='utf-8') as fr:
                text = fr.read()
                seg_text = jieba.cut(text.replace("\t", " ").replace("\n", " "))
                outline = " ".join(seg_text)
                f.write(outline)
                f.flush()


def train_model():
    model = fasttext.train_unsupervised('finance_news_cut.txt')
    model.save_model("news_fasttext.model.bin")


def test_model():
    model = fasttext.load_model('news_fasttext.model.bin')
    print(model.words)
    print(model.get_word_vector("股票"))
    print(model.get_nearest_neighbors('股票'))


if __name__ == "__main__":
    pass
    # get_data()
    # train_model()
    test_model()

备注:不要使用

pip install FastText
 进行安装,否则会出现如下报错:
AttributeError: '_FastText' object has no attribute 'get_nearest_neighbors'

安装流程:

git clone https://github.com/facebookresearch/fastText.git
cd fastText
pip install .

使用FastText进行文本分类

# -*- coding: utf-8 -*-
import jieba
import os
import fasttext


def get_data():
    # 清华大学的新闻分类文本数据集下载:https://thunlp.oss-cn-qingdao.aliyuncs.com/THUCNews.zip
    data_dir = 'D:\\迅雷下载\\THUCNews\\THUCNews'

    # 生成训练数据&测试数据
    with open("news_fasttext_train.txt", "w", encoding='utf-8') as train_f, open("news_fasttext_test.txt", "w",
                                                                                 encoding='utf-8') as test_f:
        for category in os.listdir(data_dir):
            print(category)
            category_path = data_dir + os.sep + category
            count = 0
            for file_name in os.listdir(category_path):
                file_path = data_dir + os.sep + category + os.sep + file_name
                with open(file_path, 'r', encoding='utf-8') as fr:
                    count += 1
                    text = fr.read()
                    seg_text = jieba.cut(text.replace("\t", " ").replace("\n", " "))
                    outline = " ".join(seg_text)
                    outline = outline + "\t__label__" + category + "\n"
                print(count)
                if count  

另外,还可以使用gensim来使用FastText,如:

from gensim.models import FastText

参考链接:

  • https://fasttext.cc/
  • https://github.com/facebookresearch/fastText
  • https://heleifz.github.io/14732610572844.html

The post Facebook词向量工具FastText appeared first on 标点符.

Related posts:

  1. 使用Python下载文件的几种方法
  2. 使用Python来检查统计代码是否布置到位
  3. 情感分析的现代方法(修复代码问题)


This post first appeared on IT瘾 | IT社区推荐资讯, please read the originial post: here

Share the post

Facebook词向量工具FastText

×

Subscribe to It瘾 | It社区推荐资讯

Get updates delivered right to your inbox!

Thank you for your subscription

×