Facebook词向量工具FastText

标签: 数据 NLP 词向量 | 发表时间:2019-11-18 10:48 | 作者:标点符
出处:https://www.biaodianfu.com

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的架构

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

fastText模型架构

其中 x_1,x_2,...,x_{N-1},x_N表示一个文本中的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个被标注的样本: \{(x^{(1)}, y^{(1)}), \ldots, (x^{(m)}, y^{(m)}) \},其中 x^{(i)}\in R^n。因为类标是二元的,所以我们有 y^{(i)}\in \{0,1\}。我们的假设(hypothesis)有如下形式: h_{\theta}(x)=\frac{1}{1+e^{-\theta^{T} x}}

代价函数(cost function)如下:

    \[J(\theta)=-[\sum_{i=1}^{m} y^{(i)} \log h_{\theta}(x^{(i)})+(1-y^{(i)}) \log (1-h_{\theta}(x^{(i)}))]\]

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

    \[h_{\theta}(x)=[\begin{array}{c}{P(y=1 | x ; \theta)} \\ {P(y=2 | x ; \theta)} \\ {\vdots} \\ {P(y=K | x ; \theta)}\end{array}]=\frac{1}{\sum_{j=1}^{K} e^{\theta(j)^{T} x}}[\begin{array}{c}{e^{\theta^{(1)} x} x} \\ {e^{\theta(2)^{T} x}} \\ {\vdots} \\ {e^{\theta^{(K)^{T}} x}}\end{array}]\]

代价函数如下:

    \[J(\theta)=-[\sum_{i=1}^{m} \sum_{k=1}^{K} 1\{y^{(i)}=k\} \log \frac{e^{\theta^{(k) T} x^{(i)}}}{\sum_{j=1}^{K} e^{\theta(j) T_{x^{(i)}}}}]\]

其中 1\{\cdot \}是指示函数,即 1\{true\}=1,1\{false\}=0

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

    \[\begin{aligned} J(\theta) &=-[\sum_{i=1}^{m} y^{(i)} \log h_{\theta}(x^{(i)})+(1-y^{(i)}) \log (1-h_{\theta}(x^{(i)}))] \\ &=-\sum_{i=1}^{m} \sum_{k=0}^{1} 1\{y^{(i)}=k\} \log P(y^{(i)}=k | x^{(i)} ; \theta) \\ &=-\sum_{i=1}^{m} \sum_{k=0}^{1} 1\{y^{(i)}=k\} \log \frac{e^{\theta^{(k) T} x^{(i)}}}{\sum_{j=1}^{K} e^{\theta(j) T_{x}(i)}} \end{aligned}\]

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

下图是一个分层Softmax示例:

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

    \[\mathrm{P}(y_{j})=\prod_{i=1}^{L(y_{j})-1} \sigma(\left \| n(y_{j}, l+1)=L C(n(y_{j}, l))\right \| \cdot \theta_{n(y_{j}, l)}^{T} X)\]

其中: \sigma (\cdot )表示sigmoid函数; LC(n)表示n节点的左孩子; \left \| x \right \|是一个特殊的函数,被定义为: \left \| x \right \| =\{\begin{aligned} 1 & \text { if } x==\text { true } \\-1 & \text { otherwise } \end{aligned}\theta_{n(y_{j}, l)}是中间节点 n(y_{j}, l)的参数;X是Softmax层的输入。

上图中,高亮的节点和边是从根节点到 y_2的路径,路径长度 L(y_2)=4P(y_2)可以被表示为:

    \[\begin{aligned} \mathrm{P}(y_{2}) &=\mathrm{P}(n(y_{2}, 1), \text { left }) \cdot \mathrm{P}(n(y_{2}, 2), \text { left }) \cdot \mathrm{P}(n(y_{2}, 3), \text { right }) \\ &=\sigma(\theta_{n(y_{2}, 1)}^{T} X) \cdot \sigma(\theta_{n(y_{2}, 2)}^{T} X) \cdot \sigma(-\theta_{n(y_{2}, 3)}^{T} X) \end{aligned}\]

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

N-gram

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

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

“<ap”, “app”, “ppl”, “ple”, “le>”

其中,<表示前缀,>表示后缀。于是,我们可以用这些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 的优化能够在不影响分类其表现的情况下,将分类模型压缩为原大小的 \frac{1}{10}

裁剪字典内容

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

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 < 10000:
                    train_f.write(outline)
                    train_f.flush()
                    continue
                elif count < 20000:
                    test_f.write(outline)
                    test_f.flush()
                    continue
                else:
                    break


def train_model():
    model = fasttext.train_supervised("news_fasttext_train.txt", label_prefix="__label__")
    model.save_model("news_fasttext.model.bin")


def test_model():
    model = fasttext.load_model('news_fasttext.model.bin')
    result = model.test("news_fasttext_test.txt")
    print('precision:', result[1])
    # fasttext只提供全部结果的p值和r值,想要统计不同分类的结果,就需要自己写代码来实现了。
    labels_right = []
    texts = []
    with open("news_fasttext_test.txt", encoding='utf-8') as fr:
        for line in fr:
            line = line.rstrip()
            labels_right.append(line.split("\t")[1].replace("__label__", ""))
            texts.append(line.split("\t")[0])
    labels_predict = [term[0] for term in model.predict(texts)[0]]  # 预测输出结果为二维形式
    text_labels = list(set(labels_right))
    text_predict_labels = list(set(labels_predict))

    A = dict.fromkeys(text_labels, 0)  # 预测正确的各个类的数目
    B = dict.fromkeys(text_labels, 0)  # 测试数据集中各个类的数目
    C = dict.fromkeys(text_predict_labels, 0)  # 预测结果中各个类的数目
    for i in range(0, len(labels_right)):
        B[labels_right[i]] += 1
        C[labels_predict[i]] += 1
        if labels_right[i] == labels_predict[i].replace('__label__', ''):
            A[labels_right[i]] += 1

    # 计算准确率,召回率,F值
    for key in B:
        try:
            r = float(A[key]) / float(B[key])
            p = float(A[key]) / float(C['__label__' + key])
            f = p * r * 2 / (p + r)
            print("%s:\t p:%f\t r:%f\t f:%f" % (key, p, r, f))
        except:
            print("error:", key, "right:", A.get(key, 0), "real:", B.get(key, 0), "predict:", C.get(key, 0))


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

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

from gensim.models import FastText

参考链接:

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

相关 [facebook 向量 工具] 推荐:

Facebook词向量工具FastText

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

Phabricator —— Facebook 的代码评审工具

- - 开源中国社区最新新闻
在代码审查(Code Review)方面,Facebook做了一个可视化的工具,现已开源,叫Phabricator;工程师可以在页面上非常方便的针对每一段(单行或者多 行)代码进行交互讨论;负责审查的工程师可以接受代码改变,可以提出疑问要求原作者继续修改,可以提出自己不适合以推出该代码审查,等等.

Google+是工具,Facebook是玩具_互联网_比特网

- Yi - net.chinabyte.com
Google+是工具,Facebook是玩具. 2011-09-26 11:13腾讯网Kathy. 关键字:Google+ 谷歌 时间轴 Facebook.   北京时间9月26日消息,据国外媒体报道,美国科技博客TechCrunch编辑约翰·比格斯(John Biggs)今天撰文称,Google+是工具,Facebook是玩具.

Sean Lynch谈Facebook Claspin监控工具的由来

- - InfoQ cn
InfoQ中文站曾经报道过 Facebook的工具文化,Claspin就是该文化的产物,形象来说,Claspin就是Cache的健康热图. 该工具的创始人Sean Lynch在一篇博客中分析了它的由来. Sean Lynch在Facebook担任应用运维工程师,他加入的是产品工程部门新成立的缓存性能团队.

Facebook推社交搜索工具 挑战谷歌威胁Yelp

- - 互联网的那点事
Facebook今日面向其逾10亿用户,推出了社交搜索工具Graph Search( 发布会实录),向用户提供了另一个选择,来替代谷歌、LinkedIn及Yelp等企业所提供的服务. Facebook在位于加州门洛帕克市的总部举办了产品发布会,该公司CEO马克·扎克伯格(Mark Zuckerberg)在会上表示,用户可以通过Graph Search寻找用户、照片、地点及用户兴趣等.

Facebook 发布无梯度优化开源工具 Nevergrad

- - 开源中国社区最新新闻
大多数机器学习任务——从自然语言处理、图像分类到翻译以及大量其他任务,都依赖于无梯度优化来调整模型中的参数和/或超参数. 为了使得参数/超参数的调整更快、更简单,Facebook 创建了一个名叫 Nevergrad( https://github.com/facebookresearch/nevergrad) 的 Python 3 库,并将它开源发布.

Facebook 开源首个全卷积语音识别工具包 wav2letter++

- - 雷锋网
雷锋网 AI 科技评论按:近日,Facebook 人工智能研究院 ( FAIR ) 宣布开源首个全卷积语音识别工具包 wav2letter++. 系统基于全卷积方法进行语音识别,训练语音识别端到端神经网络的速度是其他框架的 2 倍多. 他们在博客中对此次开源进行了详细介绍. 由于端到端语音识别技术能够轻易扩展至多种语言,同时能在多变的环境下保证识别质量,因此被普遍认为是一种高效且稳定的语音识别技术.

FBI希望Facebook和Twitter开发威胁预警工具

- - PingWest品玩
PingWest品玩8月13日讯, 据Gizmodo报道,美国联邦调查局(FBI)希望Facebook和Twitter等科技公司开发一种工具,可以监控其社交平台上的各种威胁. 近日,FBI发布了一份“征求建议书”,称该机构希望拥有一款“社交媒体早期预警工具”,帮助他们追踪恐怖分子、犯罪组织等对平台的使用情况.

词向量工具word2vec的学习

- - 标点符
word2vec是Google在2013年开源的一款将词表征为实数值向量(word vector)的高效工具,采用的模型有CBOW(Continuous Bag-Of-Words,即连续的词袋模型)和Skip-Gram两种. word2vec通过训练,可以把对文本内容的处理简化为K维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似度.

Facebook 推出 App Links 开发者工具意在解决什么问题?

- - 知乎每日精选
App Links 并不是用来取代 URL Scheme 的,所以也谈不上「有何本质不同」. 它并不是某一种技术,而是一项协议(或者像他们说的,一种「解决方案」). 我们想像一下这样一个常见的场景:A 在大众点评上看到了一家餐厅并想通过微信把这家餐厅分享给 B——此时问题出现了——B 会如何处理这个链接是未知的.