2017年11月9日星期四

不到一年英伟达股价又翻番了,CFO说:感谢中国、感谢AI

夏乙 问耕 发自 凹非寺

量子位 出品 | 公众号 QbitAI

2016年1月初,英伟达股价不到30美元。

2017年1月初,英伟达股价刚过100美元。

今年还剩两个月没过完,英伟达的股价已经超过200美元。

而且英伟达股价今早盘后又上涨超过3%。原因很直接,英伟达发布了第三季度的财报,业绩表现超过此前分析师预期。

财报发布后的电话会议上,英伟达CFO进一步讲述了业绩表现,量子位听来听去,总结起来就是一句话:感谢中国、感谢AI。

另外,英伟达CEO黄仁勋在电话会议上,再次强调了对无人车的坚定看好。

黄仁勋预计明年自动驾驶的模拟和开发系统会成熟,2019年自动驾驶的出租车会出现,2020年完全的自动驾驶汽车会上路行驶。

对于英特尔从AMD挖来高手开发GPU一事,黄仁勋不以为意。

26.4亿美元

先来看看英伟达刚交出一份怎样的成绩单。

今年第三季度,英伟达营收26.4亿美元(约175亿人民币),同比增长32%;净利润8.3亿美元(约55亿人民币),同比增长55%。

有两个维度可以进一步详解英伟达的营收。第一个是产品维度,GPU业务第三季度贡献营收22.1亿美元,同比增长31%;Tegra处理器业务贡献营收4.2亿美元,同比增长74%。

基于Pascal架构的GeForce GTX系列产品,驱动着GPU业务的增长。而Tegra业务的增长仍然是受益于任天堂Switch游戏掌机的畅销。

如果从行业维度看,游戏业务贡献营收15.6亿美元,同比增长25%;专业可视化业务贡献营收2.4亿美元,同比增长15%;数据中心业务贡献营收5亿美元,同比增长109%;汽车业务贡献营收1.4亿美元,同比增长13%。

数据中心仍然是增长最快的业务,毕竟深度学习的训练和加速都需要GPU的支持,DGX等产品还是处于供不应求的状况。汽车业务的主打产品还是DRIVE PX平台。

截至目前,英伟达持有的现金、现金等价物、短期证券总价值已达63.2亿美元。第三季度英伟达的自由现金流为10.9亿美元,上一季度是6.5亿美元。

中国动力

上述种种业务中,很多都与中国公司有关。这也难怪英伟达CFO会重点提到中国。这里我们概要的摘录下英伟达第三季度都干了什么。

数据中心业务

随着越来越多的公司将人工智能视为下一步战略核心,对于英伟达GPU的需求也越来越来强烈,也就是英伟达GPU在数据中心服务器上的应用。

用老黄的话说,就是"每一家主要的互联网公司、云服务提供商、计算机制造商都在拥抱我们的Volta系列GPU,我们的新TensorRT推断加速平台为我们带来了超大规模数据中心的增长。"

具体来说:

  • 在北京、慕尼黑、特拉维夫、台北和华盛顿召开GTC大会。
  • 今年新推出的Volta GPU,阿里巴巴、百度、腾讯,都将用它来速面向企业和消费者的AI应用,紧随亚马逊、Facebook、Google和微软之后。
  • 华为、浪潮、联想都使用英伟达Volta HGX架构为数据中心构建AI系统;戴尔EMC、惠普、IBM和Supermicro推出基于Tesla V100 GPU的服务器。
  • 英伟达最新推出的TensorRT 3人工智能推理加速平台,也带来了一大批数据中心客户。英伟达CFO在电话会议上说,有1200多家公司在使用英伟达推理平台,包括亚马逊、微软、Facebook、谷歌、百度、阿里巴巴、京东、讯飞、海康威视和腾讯。

游戏业务

  • 发布GeForce GTX 1070 Ti GPU。
  • 将GameWorks技术引入《最终幻想XV》等游戏新作。

汽车业务

  • 发布DRIVE PX Pegasus,计算能力强大AI电脑,意在帮助构建一个没有司机、没有方向盘、没有踏板、没有后视镜的无人出租车。
  • DRIVE PX Pegasus迄今它已被超过200家硬件公司和汽车制造商采用,120家初创公司正在使用这一平台。

"我们正在制造的处理器可谓世界上最难的东西。必须放手一搏",黄仁勋表示未来所有的东西都将实现自主化,"汽车、卡车、航天飞机、送货车。还会有机器人在仓库里走来走去,或者给你送披萨"。

黄仁勋预计明年开始,汽车业务的收入会有更快的增长。

正如开头我们提到的,黄仁勋预计2019年,机器人出租车将飞速发展;2020-2021年底,第一辆全自动的L4级自动驾驶汽车上路。

自主机器/AI边缘计算

  • 成为阿里巴巴、华为的合作伙伴使用Metropolis打造AI智慧城市
  • 宣布与京东X实验室合作,使用Jetson创建自动化机器,将AI引入物流行业。

One More Thing

这一季度,英伟达的游戏业务也出现了大幅增长。量子位在上一季度提到过,推动这项业务增长的一个重要推手,是比特币挖矿。

当时,华尔街普遍认为比特币带来的需求无法持续,不过,老黄却认定这个趋势不会停止。

截至目前,老黄是对的。不信看图。

想要查看英伟达的业绩详情,可以在量子位微信公众号(QbitAI)后台回复:"NQ3",我们会发给你美国证监会(SEC)的相关地址。

— 完 —

诚挚招聘

量子位正在招募编辑/记者,工作地点在北京中关村。期待有才气、有热情的同学加入我们!相关细节,请在量子位公众号(QbitAI)对话界面,回复"招聘"两个字。

量子位 QbitAI · 头条号签约作者

վ'ᴗ' ի 追踪AI技术和产品新动态



via 量子位 - 知乎专栏 http://ift.tt/2zw6sbi
RSS Feed

RSS5

IFTTT

随机计算图:在随机结点中执行反向传播的新方法

本文作者曾介绍一些现代变分推理理论。这些方法经常可用于深度神经网络并构造深度生成模型(例如 VAE 等),或者使用便于探索的随机控制来丰富确定性模型。本文介绍了一种随机计算图,它将随机变量分解为其它随机变量的组合以避免 BP 算法的随机性。


所有的这些变分推理的案例都会把计算图转换成随机计算图,即之前确定的那些结点会变成随机的。不过在这些结点中做反向传播的方式并不是简单与直观的,本文将介绍一些可能的方法。这次我们会注意到,为什么通用的方法会如此糟糕,并且会看到我们在连续的例子中能够做什么。

首先,要更加正式的描述一下这个问题。假设近似推理(approximate inference)的学习目标如下:


或者是一个强化学习的目标函数:


在后面的内容中,我会使用以下标记来表示目标函数:


在该情况下,随机计算图(SCG)可以被表示成下面的形式 [1]:


这里双层圆环内的θ是可调参数的集合,蓝色的菱形是可以取随机值的随机点,但是它们的分布会依赖于θ(或许是通过一些复杂的已知函数来得到,例如神经网络),橙色的圆圈内的函数 f(x) 是我们要最大化的值。为了使用这种随即图估计得到 F(θ),你只需要使用θ去计算 x 的分布,我们可能需要尽可能多的样本为每一个 x 计算出 f(x),然后再求 f(x) 的均值。

那么如何最大化它呢?现代深度学习使用的方法是随机梯度下降(或者是我们例子中使用的梯度上升方法),如果想在我们的例子中应用这种方法,我们所需要做的就是估计(最好具有无偏性和有效性)目标函数关于θ的梯度∇F(θ)。这对任何一个有一定的微积分基础的人来说是不太难的:


在上式中,我们先采集一些 x 的样本(x∼p(x∣θ)),并用这些样本计算得到 f(x),然后将结果和对数密度的梯度相乘,这就是真实梯度的无偏估计了。然而,在实际中人们发现这种估计(被称作得分函数估计,或者在强化学习文献中被称作 REINFORCE)会有较大的方差,会使得对高维的 x 而言不太现实。

注意一下估计器,它并没有使用 f 的梯度信息,所以它不能给出任何关于如何移动 p(x|θ) 使得 F(θ) 有更高期望的指导。此外,它还使用了很多随机的 x,对每一个都选择了应该使得它更有可能的方向,并通过 f(x) 的大小来衡量这些方向。当求取平均值之后,这就会给出一个能够最大化目标函数的方向,但是很难仅仅使用较少的样本就能随机碰到好的 x(尤其是在训练的早期,或者是在高维空间里),所以方差会比较大。

这就表现出了对能够改善这个估计器方差的其他方法的需求,或者是不同的更加有效的估计方法。在下面的内容中我们会给出这两方面的解释。

参数重新设置的技巧

当意识到前面提及的局限性后,Kingm 等人在变分自编码器的论文中使用了一个聪明的小技巧(http://ift.tt/2iKgNqq

结果是肯定的。也就是说,对于任何高斯随机变量 x∼N(μ,σ^2),我们都能够将它分解成一些其他标准高斯噪声(x=μ+σε,其中 ε∼N(0,1))的仿射变换。我们在这里重新设定了参数,所以这个技巧就以此命名了。然后随机计算图(SCG)就可以表示为以下形式:


此处红色的箭头代表的是反向传播的「流」:注意我们没有遇到任何采样点,所以我们不需要使用高方差得分函数(score-function)估计器。我们甚至可以有很多由随机单元组成的层级,在参数重设之后我们不需要对所有的样本做微分,我们只需将它们混合在一起。可以看一下下面的公式:


请注意,我们在这里使用了 f 的梯度!这是这个估计器与得分函数估计器之间最关键的不同之处:在后者中,我们利用「分数」随机的方向进行了平均,同时我们还通过学习得到了一个独立噪声的仿射变换,因此经过变换的样本所在的区域具有较大的 f(x) 值。f 的梯度信息会告诉我们朝着哪里移动样本 x,然后我们通过调整 μ 和 δ 来进行这种移动。

这看起来貌似是一个不错的方法,那么为何不在每个地方都是用它呢?问题在于,即使你总能够将一个均匀分布的随机变量变换为任何其他一个,然而涉及的计算并不总是很容易实现的 [3]。对于某些分布(例如狄利克雷分布 [4]),我们甚至不知道任何把无参数随机变量变换成这种分布的转换方法。

泛化的参数重设技巧

参数重设(reparametrization)技巧可以被看成是一种将某些独立噪声变成所期望随机变量的变换 T(ε|θ)。反过来,如果 T 是可逆的,那么 T(x|θ) 逆就是一个「白噪声」/「标准噪声」的变换:它使用一些依赖于参数 θ 的随机变量,并将它们变成参数独立的随机变量。

倘若我们找到的变换方法可能无法将 x 完全变成白噪声(whiten noise),但是仍然能够减少它对 θ 的依赖性,那该怎么办呢?这就是这篇论文的思想:泛化的参数重设技巧。在那种情况下,ε 仍然依赖于 θ,但是会「弱一些」。


这里 g^rep 就是我们通常重设参数得到的梯度,g^corr 是得分函数得到的梯度。容易看到,改变变换 T 可以让你在完全重设参数梯度和完全得分函数梯度之间进行插值(interpolate)。事实上,如果 T 完全将 x 变成白噪声,那么 p(ε|θ) 就会独立于 θ,并且∇logp(ε|θ)=0,我们只能得到 g_rep。但是,如果 T 是一个恒等映射,那么∇f(T(ε∣θ))=∇f(ε)=0,我们又会恢复到得分函数估计器。

这个公式看起来很棒,但是为了从中给 ε 进行采样,我们需要了解 T(x∣θ) 逆的分布。根据从 p(x|θ) 中的采样重新用公式表达梯度会更加方便,这个我们可以通过一些代数运算完成:


在这个公式中,我们像平常一样对 x 进行采样,并把它传递到「白化噪声」变换 T(x|θ) 的逆中,来得到样本 ε,并在梯度的组成部分中替代这些变量。除了 f(x)∇logp(x∣θ),其他的所有都可以被视为一个控制变量(我们在后面会讨论这个),这个控制变量(control variate)使用 f 的梯度信息,所以它是相当强大的。

最后一个问题是,应该选择哪个变换?公式的作者建议使用常用的标准变换,即求出平均值,然后再除以标准差。这个选择是受以下几点驱动的:a) 计算方便,因为我们要使用 T 和 T 的逆 [5]; b) 这使得最先的两个时刻与θ独立,并从某种程度上导致变量会依赖于 θ。

拒绝采样(Rejection sampling)的观点 [6]

另外一个关于泛化参数重设的观点源于下面的想法:很多分布都有有效的取样器,我们能不能在采样过程中进行反向传播呢?这正是论文 Reparameterization Gradients through Acceptance-Rejection Sampling Algorithms(通过接受-拒绝算法来进行梯度的参数重设)的作者决定要解决的问题。

你想要对一些分布 p(x|θ) 进行采样,但是却不能计算并翻转(invert)它的累积分布函数(CDF),那么给怎么办呢?你可以使用拒绝采样过程。基本而言,你有一些容易从中采样的参考分布 r(x∣θ),然后找到一个缩放因子 M_θ,通过缩放之后,对于所有的 x,参考分布都要比目标参考的概率密度函数大: M_θr(x|θ)≥p(x|θ)∀x。然后你生成的点都随机地分布在 M_θr(x|θ) 曲线的下面,只需要保留(接受)那些同样分布在 p(x|θ) 曲线下面的点作为样本即可。

1. 生成 x∼r(x|θ)

2. 生成 u∼U[0,M_θr(x|θ)]

3. 如果 u>p(x|θ),从步骤 1 开始重复。否则,返回 x。

此外,我们还对样本 ε∼r(ε) 使用一些变换 T(ε|θ)(经过缩放的变换变量密度函数会大一些)。这就是 numpy 中生成 Gamma 变量的过程:如果 ε 是标准高斯分布中的样本,则通过一些 x=T(ε|θ) 的函数来对样本进行变换,然后接受服从 a(x|θ) 分布的样本即可。[7]

为了搜索导致接受与 x 对应的 ε 密度函数,我们的变换过程如下:


注意,这个概率密度是比较容易计算的,如果我们将生成的样本 ε 进行参数重设,那么我们将得到我们所寻找的 x,即 x=T(ε|θ),所以目标函数就可以表示为:


F(θ) 求关于 θ 的梯度,则:


现在我们把后面附加的这一块与前一部分的 grep 和 gcorr 做一下对比。你会看到它们是完全一样的!

在前一部分中我们选择的变换是 T 的逆,因此它一直在试图去除样本 x 对θ的依赖。这一部分允许我们从另一方面来观察同样的方法:如果你有一些独立的噪声 ε 以及一个能让样本看起来像是服从目标分布 p(x|θ) 的变换 T,那么你可以在上面加一些拒绝采样来弥补误采样,这样同样可以得到小方差的梯度估计。

一个非常简单的例子

让我们来看一下参数重设的技巧实际上让方差减小了多少,以一个简单的问题为例。我们尝试将高斯随机变量平方(x^2)的期望最小化 [8](再加上一些正的常数 c 作为偏移量,我们会在后面看到它们所起的作用):


首先,重设参数的目标函数是:


然后它的随机梯度为:


基于得分函数的梯度如下:


两个估计器都是无偏估计,但是它们的方差会怎么样呢?WolframAlpha 表明:


你能够发现,基于得分函数的梯度不仅方差总是比较大,而且随着 μ=0、σ=0(除非 c=0,μ足够小),梯度的方差还会趋于无穷大。这是因为:随着方差的变小,采样点远离均值的概率会非常小,所以基于得分函数的梯度认为应该多尝试让它们变得更加符合概率分布。

你也许会好奇,泛化重设参数是如何工作的?如果我们考虑到 [T(x|μ,σ)]^-1=x−μ的逆变换(它仅仅在一阶矩进行「白噪声化处理」),我们将得到以下的梯度估计:


这就是与 μ 对应的参数重设梯度和与 σ 对应的得分函数梯度(这里 ε∼N(0,σ^2))。我并不认为这是一个有趣的场景,所以我们会考虑看起来很奇怪的二阶矩白噪声化处理变换 [T(x|μ,σ)]^-1=x−μσ+μ,其中 T(ε|μ,σ)=σ(ϵ−μ)+μ。这种变换下的梯度可以表示如下:


你可以发现,当 σ 接近 0 的时候,梯度的幅值不在趋近于无穷大。让我们检查一下这些变量:


首先,我们可以看到,与 σ 对应的梯度的方差与重设参数的情况下的梯度方差是一样的。其次,我们可以确定,在接近最优解的时候,梯度的方差不会「爆炸」(趋于无穷大)。


  • Gen Rep 1 是只进行了一阶矩白噪声化处理的泛化参数重设。
  • Gen Rep 2 是只在二阶矩进行了白噪声化变换处理的泛化参数重设。

模拟曲线清楚地展示:基于得分函数的梯度和第一个泛化参数重设都没能成功地收敛,这和我们的方差分析是一致的。然而,第二个泛化参数重设则表现得和全参数重设一样好,即便它的方差还是比较大。

我这篇博文中涉及的工作的源代码可以在这里找到(http://ift.tt/2zz5k53

总结

我们讨论了让随机变分推理在连续性隐藏变量中变得可计算的技巧。然而,我们往常都是只对连续的潜在变量模型感兴趣。例如,我们可能会对动态选择一个计算路径或另一个计算路径的模型感兴趣,这往往要控制在一个给定样本上花费的计算时间。也许在文本上训练 GAN 时,我们需要一种在鉴别器的输入上进行反向传播的新方式。


]]> 原文: http://ift.tt/2iKgP1w
RSS Feed

机器知心

IFTTT

面向无监督任务:DeepMind提出神经离散表示学习生成模型VQ-VAE

DeepMind 最近提出的 VQ-VAE 是一种简单而强大的生成模型,结合向量量化和变分自编码器学习离散表示,实现在图像识别、语音和对话等任务上的无监督学习。


近期,图像、音频、视频领域生成模型的发展产生了惊人的案例与应用。同时,few-shot 学习、域适应或强化学习这样具有挑战性的任务也极为依赖从原始数据学习到的表征。但以无监督方式训练的通用表征的有效性仍无法成为该领域的主流方法。


最大似然和重构误差(reconstruction error)是在像素域中训练无监督模型常用的两种目标函数,但是它们的有效性取决于使用特征的特定应用。DeepMind 的目标是构建一个模型,在其潜在空间(latent space)中保存数据的重要特征,同时优化最大似然。正如 [7] 中的研究,最好的生成模型(以最大似然来衡量)是那些没有隐变量但是具备强大解码器的模型(如 PixelCNN)。在这篇论文中,DeepMind 提出学习离散、有用的隐变量也是一种很好的方法,并在多个领域中进行证实。


使用连续特征学习表示是之前很多研究的重点,但是 DeepMind 把目光放在离散表示上,离散表示有可能更适合 DeepMind 感兴趣的很多模态(modality)。语言是内在离散的,类似地,语音通常表示为符号序列。图像通常可以通过语言进行精确描述 [40]。此外,离散表示适合复杂的推理、规划和预测性学习(如,如果下雨了,我就打伞)。在深度学习中使用离散隐变量证明,已经开发出难度高、强大的自回归模型,可用于对离散变量的分布进行建模 [37]。


这篇论文中,DeepMind 介绍了一族新的生成模型,通过对(离散)隐变量的后验分布进行新型参数化,成功地将变分自编码器(VAE)框架和离散隐变量表示结合起来。该模型依赖于向量量化(vector quantization,VQ),易于训练,不会出现大的变量,避免「后验崩溃」(posterior collapse)问题,该问题通常由被忽略的隐变量引起,对很多具有强大解码器的 VAE 模型来说都是个难题。此外,该模型也是首个离散隐变量 VAE 模型,其性能和连续隐变量 VAE 模型类似,同时还具备离散分布的灵活性。DeepMind 将这种模型命名为 VQ-VAE。


因为 VQ-VAE 可以有效利用潜在空间,它可以有效地对通常跨越数据空间多个维度的重要特征进行建模(例如对象跨越图像中的多个像素、语音对话中的音素、文本片段中的信息等等),而非把注意力集中在噪声或其他细微之处——这些细节往往是局部的。


最后,当 VQ-VAE 发现了一种模态的优秀离散隐变量结构,我们就可以在这些离散随机变量上训练强大的先验,得到有意义的样本和有用的应用。例如,在语音任务中,我们可以在没有任何监督或单词音素先验知识的情况下发现语言的潜在结构。此外,我们可以给解码器赋予说话者的角色,让它展开对话,如让语音在两个说话者之间传递,但不改变说话内容。DeepMind 还在论文中展示了利用此方法在强化学习环境中学习长期结构的高性能。


这篇论文的贡献可概括为:


  • 介绍 VQ-VAE 模型,这是一个简单模型,使用离散隐变量,不会出现「后验崩溃」和变量问题。
  • 证明离散隐变量模型(VQ-VAE)和它在 log 似然中的连续隐变量模型的性能一样好。
  • 当和强大的先验一起出现时,DeepMind 的样本在大量应用(比如语音和视频生成)上都是连贯且高质量的。
  • 证明可以在无监督的情况下,通过原材料学习语言,并展示了无监督说话者对话的应用。


VQ-VAE


或许和 DeepMind 的方法联系最紧密的就是 VAE。VAE 包括以下几个部分:1)一个编码器网络,对后验分布 q(z|x) 进行参数化,z 是离散隐随机变量,x 为输入数据;2)先验分布 p(z);3)一个解码器,它的输入数据分布是 p(x|z)。


通常,VAE 中的后验分布和先验分布呈对角协方差分布,允许使用高斯重参数化 [32, 23]。其扩展包括自回归先验和后验模型 [14]、常规流(normalising flow)[31, 10],和逆自回归后验模型 [22]。


这篇论文介绍了 VQ-VAE,该模型使用离散隐变量,受向量量化的启发用一种新的方式进行训练。后验和先验分布是明确分类的,从这些分布中提取的样本可通过嵌入表进行索引。然后将这些嵌入作为解码器网络的输入。



图 1. 左:VQ-VAE 图示。右:嵌入空间可视化。编码器 z(x) 的输出映射到最近点 e_2。梯度∇zL(红色)使编码器改变输出,从而改变下一个前向传输的配置。



图 2. 左:ImageNet 128x128x3 图像,右:潜在空间为 32x32x1、K=512 的 VQ-VAE 输出的重构结果。



图 5. 上方:原始图像,下方:两阶段 VQ-VAE 的重构结果,使用 3 个隐变量对整个图像(27 bits)进行建模,这样的模型仍然不能对图像进行完美重构。重构结果是由第一阶 VQ-VAE 的 21×21 潜在域中的第二个 PixelCNN 先验采样而来,随后被标准 VQ-VAE 解码器解码为 84×84。很多原始场景,包括纹理、房间布局和附近的墙壁都保留原状,但模型没有试图去储存像素值,这意味着纹理是由 PixelCNN 生成的。


论文:Neural Discrete Representation Learning




论文链接:http://ift.tt/2ziC1Dw


论文第一作者 Aaron van den Oord 也在 GitHub 上展示了新模型的一些结果:http://ift.tt/2zkL3SB


摘要:在无监督情况下学习有意义的表示是机器学习的一个核心挑战。在本论文中,我们提出了一个简单却强大的生成模型,该模型可以学习此类离散表示。我们提出了向量量化-变分自编码器(Vector Quantised-Variational AutoEncoder,VQ-VAE),它与 VAE 在两个关键的方面存在不同:1. 编码器网络输出离散而不是连续的代码;2. 先验是学习的,而非静止的。为了学习离散隐变量表示,我们吸收了向量量化(VQ)的思路。使用 VQ 方法可以让模型绕过「后期崩溃」的问题——隐变量在遇到强大的自回归解码器时被忽略,这种问题通常会在 VAE 框架中出现。通过让这些表示和自回归先验配对,模型可以生成高质量的图像、视频、语音,以及高质量对话,也可以在无监督的情况下学习音素,本研究进一步证明了已学得表示的实用性。

]]> 原文: http://ift.tt/2hhPpPW
RSS Feed

机器知心

IFTTT

FastText:语料库数据快速清理利器

数据清理是很多机器学习任务上我们遇到的首要问题。本文介绍的 FastText 是一个开源 Python 库,可用于快速进行大规模语料库的文本搜索与替换。该项目的作者表示,使用正则表达式(Regex)需要 5 天的任务在新的方法中只需要 15 分钟即可完成。


项目链接:http://ift.tt/2guItlC


自然语言处理领域的开发者在处理文本之前必须对数据进行清理。有些时候,此类工作是由关键词替换完成的,就像吧「Javascript」替换成「JavaScript」。另一些时候,我们只需要知道文档中是否提到了「JavaScript」。


这类数据清理任务是大多数处理文本的数据科学项目必须要做的。


数据科学从清理数据开始


本文作者是 Belong.co 的一名数据科学家,需要从事有关自然语言处理的工作,于是遇到了这个问题。当我在自己的文档语料库中开始训练 Word2Vec 模型时,它开始将同义词归为同类项,「Javascripting」被归类为「JavaScript」的同类项。


为了解决这个问题,我写了一个正则表达式(Regex),用标准化命名来替换所有已知的同义词。Regex 会将「Javascripting」替换为「JavaScript」,这解决了一个问题,却又带来了另一个问题。


有些人遇到问题时会想:「没关系,我们有正则表达式。」现在问题变成了两个。


上文所述引自 Stack-exchange question,现在让我遇到了。


事实证明,正则表达式的速度很快——如果要搜索和替换的关键词数量是一百多个的话。但是面对超过 20k 个关键词,300 万个文件的语料库,事情就会变得很糟。当我测试我的代码时,我发现完全运行需要 5 天之久。




通常,面对这种情况我们的解决方案是并行运算。但在面对上千万个文件中成百上千出现频次的关键词,并行的性能提升有限,我们必须找到更好的方法!


幸好,在 Stack Overflow 上我的疑问获得了大家的关注,网友们和公司同事 Vinay Pandey、Suresh Lakshmanan 等人提到了一个名叫 Aho-Corasick 算法的神奇工具,以及前缀树数据结构(Trie Data Structure)。然而目前网络上还缺乏相关资源。


  • Aho-Corasick 算法:http://ift.tt/1RYwS9M
  • Trie Data Structure:http://ift.tt/1ezUKqz


所以我开始自己动手,FlashText 诞生了。


在介绍 FlashText 的结构和工作原理之前,先看看它的搜索性能表现:



下面的红线是 FlashText 的搜索耗时


如上图所示,Regex 算法和 FlashText 搜索同一篇文档的耗时相差很大。随着关键词数量的增加,Regex 的耗时呈线性增长,而对于 FlashText 来说并没有影响。


FlashText 可以把 5 天的工作缩短到 15 分钟!




这是 FlashText 替换的速度:



同样,下面的红线是 FlashText 的替换速度。


所以,FlashText 是什么?


FlashText 是我在 GitHub 上开源的一个 Python 库,它能高效地提取和替换关键词。


使用 FlashText 时,首先你需要发送一系列关键词,这个列表将被用于在内部建立一个前缀树字典。随后你需要传递一个字符串,告诉它你需要执行替换还是搜索。


在替换时,它会创建一个新字符串来替换关键词。在搜索时,它会返回一个关键词列表。这一切都将在输入字符串上进行。


有的用户是这样评价FastText的:



Radim Řehůřek 是著名 Python 库 Gensim 的作者


FlashText 为什么那么快?


我们用一个例子来尝试和理解这一部分。假设我们有一个包含三个单词的句子 I like Python,和一个有四个单词的语料库 {Python,Java,J2ee,Ruby}。


如果每次取出语料库中的一个单词,并检查其在句子中是否出现,这需要四次操作。


  1. is 'Python' in sentence?

  2. is 'Java' in sentence?

  3. ...


如果语料库有 n 个单词,意味着需要做 n 次的循环操作,并且每一个时间步的搜索都是 isin sentence ? 这有点像正则表示式相配(Regex match)中的过程。


还有另一种和第一种相反的方法。对于句子中的每一个单词,检查其是否在语料库中出现。


  1. is 'I' in corpus?

  2. is 'like' in corpus?

  3. is 'python' in corpus?


如果句子 m 个单词,意味着需要做 m 次的循环操作。在这个例子中所需的时间步取决于句子中的单词数。而使用字典查询进行 isin corpus ? 会快得多。


FlashText 基于第二种方法,由 Aho-Corasick 算法和前缀树(Trie)数据结构所启发。


它的工作方式为:


首先由语料库创建一个如下图所示的前缀树字典:



语料库的前缀树字典


Start 和 EOT(End Of Term,期末)表示单词的边界比如 space、period 和 new_line。只有两侧都有边界的关键词才能得到匹配,这可以防止把 apple 匹配到 pineapple。


下一步我们将取输入字符串为 I like Python,并按字符逐个对齐进行搜索。


  1. Step 1: is Iin dictionary? No

  2. Step 2: is likein dictionary? No

  3. Step 3: is Pythonin dictionary? Yes



Python出现在字典中。


由于这是一个字符匹配过程,我们可以轻易地在进行到l 的时候跳过整个like,因为 start 并没有和 l 相连。这使得跳过缺失单词的过程变得非常快。


FlashText 算法只需要遍历输入字符串『I like Python』的每一个字符。即使字典有上百万个关键词,对运行时间也没有任何影响。这是 FlashText 算法的真正威力。


什么时候需要使用 FlashText?


简单的回答是:当关键词数量>500 的时候




当关键词数量>500 的时候,FlashText 的搜索速度开始超过 Regex


完整的回答是:Regex 可以搜索基于特殊字符比如^、$、*、\d 等的关键词,而 FlashText 不支持这种搜索。


所以如果想要匹配部分单词比如『word\dvec』,使用 FlashText 并没有好处,但其非常善于提取完整的单词比如『word2vec』。


用于寻找关键词的代码


  1. # pip install flashtext

  2. from flashtext.keyword import KeywordProcessor

  3. keyword_processor = KeywordProcessor()

  4. keyword_processor.add_keyword('Big Apple', 'New York')

  5. keyword_processor.add_keyword('Bay Area')

  6. keywords_found = keyword_processor.extract_keywords('I love Big Apple and Bay Area.')

  7. keywords_found

  8. # ['New York', 'Bay Area']


使用 FlashText 提取关键词的简单例子


用于替换关键词的代码


FlashText 不仅可以提取句子中的关键词还可以对其进行替换。我们将此作为数据处理管道的数据清理步骤。 


  1. from flashtext.keyword import KeywordProcessor

  2. keyword_processor = KeywordProcessor()

  3. keyword_processor.add_keyword('Big Apple', 'New York')

  4. keyword_processor.add_keyword('New Delhi', 'NCR region')

  5. new_sentence = keyword_processor.replace_keywords('I love Big Apple and new delhi.')

  6. new_sentence

  7. # 'I love New York and NCR region.'


使用 FlashText 替换关键词的简单例子

]]> 原文: http://ift.tt/2zqJpPJ
RSS Feed

机器知心

IFTTT