word2vec能将文本中出现的词向量化,其原理建立在Mikolov的博士论文成果及其在谷歌的研究经验的基础上。与潜在语义分析(Latent Semantic Index, LSI)、潜在狄立克雷分配(Latent Dirichlet Allocation)的经典过程相比,word2vec利用了词的上下文,语义信息更加地丰富。word2vec并不是Mikolov某一天拍拍脑袋就给想出来的,也是站在牛人的肩膀上。大牛Bengio(NIPS 2001)借着深度学习的东风提出了一种可并行的神经网络模型;Morin(2005)为了加快神经网络语言模型(Neural Network Language Model,NNLM)的概率输出Softmax的计算,提出了Hierarchical Softmax;Mikolov同学慢慢地注意到神经网络在语言模型中的作用,早年的论文多在语音领域,其博士论文总结并优化了循环神经网络(Recurrent Neural Network),之后到了谷歌做研究,才总算提出了word2vec。这一段历史可进一步查看licstar的博客:词向量与语言模型。本文的重点在于描述word2vec是如何并行的,或者说是哪个部分并行的。相关实现代码在gitHub/siegfang/word2vec

并行前的准备

并行训练前需要遍历一遍所有的训练的语料,统计词频,并依据词频构建一颗哈夫曼树(Huffman Tree)。一般来说,在海量语料的情况下,词频非常小的词一般不予以考虑。这里面大概有两个原因:

  • 只出现一次或两次的词往往会非常之多,得到的词汇表非常庞大,后续所需的内存空间(包括哈夫曼树和词向量)也将非常庞大,训练时间也会相应地延长;
  • 词频极低的词由于出现次数少,在神经网络训练中往往得不到充分地训练,其词向量可能会与邻近词相近,这会降低训练效果。

一个例子就是“奥巴马与主席夫人彭丽...”中的“彭丽”。由于新闻抓取错误或人名缺失等问题,会产生很多莫名其妙的低频词。深度学习等一切机器学习都不是万能的,去掉或替换这些噪声,能使得训练更好地进行。

并行ing

并行的关键在于如何分割好并行的任务和如何达成任务之间的良好通信?具体到word2vec来说,需要做的是将训练的语料分成若干份,依次交给并行的线程、进程或分布式机器等并行运行载体进行Skip-Gram或CBow-Gram模型训练,在各个独立的并行空间中,语料是不相同的,但训练的神经网络、词向量和哈夫曼是共享的,训练中使用的学习率等参数需要更新,在结束训练后需要计算。

Hierarchical Softmax

Hierarchical Softmax使用以词作为叶子的二叉树(这里即为哈夫曼树)来计算每个词出现的概率。每个词都可以由根结点经过某一路径到达,设L(w)是这条路径的长度,n(w,j)是这条路径上的第j个结点。显然n(w,1)即为根结点(root),n(w,L(w))是词所在的叶子结点。除了叶子结点,对于整棵树中包括根在内的其它结点,ch(n)表示结点n所分支的某一子结点。以输入词向量$w_I$预测输出向量$w_O$的概率计算公式为:

$$p\left( w_O | w_I \right) = \prod_{j = 1}^{L(w) - 1} \sigma \left( [n(w,j+1) = ch(n(w,j))] \centerdot v_{n(w,j)}^{\top} v_{w_I} \right)$$

其中[x]为指示函数,当x为真时,[x]的值为1,否则为-1;$\sigma(x)=1/(1+exp(-x))$。拿Skip-Gram模型来说,就是要以一个词的向量去预测其上下文的词的向量,而CBow-Gram则是先将上下文的词的向量和来预测中间词的向量,如下图所示:

word2vec中通过最小化交叉熵来对哈夫曼树节点向量和词向量进行更新。从根结点到词结点的路径可以看作是不断地从父结点选择一个子结点的过程,要使得路径正确就必须使得每次子结点的选择正确,也就是选择正确子结点的概率比错误的高。哈夫曼树从根结点开始的边要么以0标记,要么以1标记,这里使用交叉熵来使得每次选择都能尽可能地正确,正确选择的概率p(c)及交叉熵H如下

$$\begin{align*} p(c) &= \frac{\exp(v_{n(w,j)} \cdot v_{w_I} )}{1 + \exp(v_{n(w,j)} \cdot v_{w_I})} \\ H(v_{n(w,j)},v_{w_I}) &= - c\log p(c) - (1-c)\log (1-p(c)) \\ \end{align*}$$

其中c为正确选择的标记。最小化交叉熵可以通过梯度下降法迭代实现,偏导如下式所示:

$$\begin{align*} \underset{v_{n(w,j)},v_{w_I}}{\min} &H(v_{n(w,j)},v_{w_I}) \\ \frac{\partial H}{\partial v_{w_I}} &= (c - p(c))v_{n(w,j)} \\ \frac{\partial H}{\partial v_{n(w,j)}} &= (c - p(c))v_{w_I} \\ \end{align*}$$

Mikolov在其实现中使用1-c,这其实是一样的。之前我不是很明白为什么这么做?直到我用CBow-Gram做了一次主客观分类和褒贬分类时,我发现使用1-c会比使用c,准确率、召回率都会高1%,算是个小经验(trick)吧~

站在巨人的肩膀上

参考了其它语言和大牛的实现方法,包括:

为啥不实现Negative Sampling

Negative Sampling在Mikolov自个儿的C代码中是有实现的,但ansj和piskvorky就没有,jdeng实现了但用宏(define)置代码无法执行。我挨个遍历了没有实现的大牛,问是不是因为词向量的质量在即使没Negative Sampling的情况下也足够好?

  • jdeng issue#2:Right. The performance improvement was not observed but I am not sure if my implementation is accurate.
  • piskvorky issue#156:See issue #130 : negative sampling is waiting for someone to implement it.
  • ansj issue#4:一直没有回复

内存

我使用ansj的串行实现对比我的并行实现,分别做了在77M网络小说数据和1G新闻数据的对比。内存变化图如下:

77M文本数据串行训练堆内存变化图

77M文本数据并行训练堆内存变化图

1G文本数据串行训练堆内存变化图

1G文本数据并行训练堆内存变化图

参考文献

  • Bengio Y, Ducharme R, Vincent P, et al. A Neural Probabilistic Language Model[J]. Journal of Machine Learning Research, 2003, 3: 1137-1155.
  • Morin F, Bengio Y. Hierarchical probabilistic neural network language model[C]//Proceedings of the international workshop on artificial intelligence and statistics. 2005: 246-252.
  • Mikolov T. Statistical Language Models Based on Neural Networks}[D]. Ph. D. thesis, Brno University of Technology, 2012.
  • Mikolov T, Sutskever I, Chen K, et al. Distributed representations of words and phrases and their compositionality[J]. arXiv preprint arXiv:1310.4546, 2013.
  • Mikolov T, Chen K, Corrado G, et al. Efficient Estimation of Word Representations in Vector Space[J]. arXiv preprint arXiv:1301.3781, 2013.
  • word2vec演示:http://thisplusthat.me/

word2vec并行实现小记的更多相关文章

  1. Word2vec多线程(tensorflow)

    workers = [] for _ in xrange(opts.concurrent_steps): t = threading.Thread(target=self._train_thread_ ...

  2. iOS多线程之GCD小记

    iOS多线程之GCD小记 iOS多线程方案简介 从各种资料中了解到,iOS中目前有4套多线程的方案,分别是下列4中: 1.Pthreads 这是一套可以在很多操作系统上通用的多线程API,是基于C语言 ...

  3. 【转载】word2vec原理推导与代码分析

    本文的理论部分大量参考<word2vec中的数学原理详解>,按照我这种初学者方便理解的顺序重新编排.重新叙述.题图来自siegfang的博客.我提出的Java方案基于kojisekig,我 ...

  4. NLP:Gensim库之word2vec

    Gensim是一款开源的第三方Python工具包,用于从原始的非结构化的文本中,无监督地学习到文本隐层的主题向量表达.它支持包括TF-IDF,LSA,LDA,和word2vec在内的多种主题模型算法, ...

  5. 利用python中的gensim模块训练和测试word2vec

    word2vec的基础知识介绍参考上一篇博客和列举的参考资料. 首先利用安装gensim模块,相关依赖如下,注意版本要一致: Python >= 2.7 (tested with version ...

  6. Python gensim库word2vec 基本用法

    ip install gensim安装好库后,即可导入使用: 1.训练模型定义 from gensim.models import Word2Vec   model = Word2Vec(senten ...

  7. word2vec参数理解

    之前写了对word2vec的一些简单理解,实践过程中需要对其参数有较深的了解: class gensim.models.word2vec.Word2Vec(sentences=None,size=10 ...

  8. word2vec模型评估方案

    1.word2vec参数详解 · sentences:可以是一个·ist,对于大语料集,建议使用BrownCorpus,Text8Corpus或·ineSentence构建.· sg: 用于设置训练算 ...

  9. 使用word2vec训练中文词向量

    https://www.jianshu.com/p/87798bccee48 一.文本处理流程 通常我们文本处理流程如下: 1 对文本数据进行预处理:数据预处理,包括简繁体转换,去除xml符号,将单词 ...

随机推荐

  1. Linux下批量管理工具pssh安装和使用

    Linux下批量管理工具pssh安装和使用 pssh工具包 安装:yum -y install pssh pssh:在多个主机上并行地运行命令 pscp:把文件并行地复制到多个主机上 prsync:通 ...

  2. <Android基础> (七)内容提供器

    第七章 内容提供器 7.1 内容提供器(Content Provider) 主要应用于在不同的应用程序之间实现数据共享功能.允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性. 7.2 ...

  3. jdbc 连接各种数据库 CRUD

    一,jdbc简介 SUN公司为了简化.统一对数据库的操作,定义了一套Java操作数据库的规范(接口),称之为JDBC.这套接口由数据库厂商去实现,这样,开发人员只需要学习jdbc接口,并通过jdbc加 ...

  4. STS搭建SpringBoot项目

    开发工具:推荐IDEA . Spring Tool Suit 虽然很简单,但还是记录一下,图个热闹. 开始 >>> 1. File --> New --> Spring ...

  5. Python机器学习第一章

    1. 机器学习 (Machine Learning, ML)            1.1 概念:多领域交叉学科,涉及概率论.统计学.逼近论.凸分析.算法复杂度理论等多门学科.专门研究计算机怎样模拟或 ...

  6. JavaEESpringMVC基础整理

    1.什么是 SpringMVC ? 在介绍什么是 SpringMVC 之前,我们先看看 Spring 的基本架构.如下图: 我们可以看到,在 Spring 的基本架构中,红色圈起来的 Spring W ...

  7. python3 动态import

    有些情况下,需要动态的替换引入的包 1.常用的import方法 import platform import os 2.__import__ 动态引用 loop_manager = __import_ ...

  8. Hibernate日志输出到SLF4J

    一,Hibernate日志问题 工程使用SLF4J,但日志文件一直没有看到Hibernate相关日志及showsql 二,Logback文件配置 修改Hibernate 日志输出指定为SLF4J,当修 ...

  9. 目前的.NET 主流的后端ORM框架

    转自:https://www.cnblogs.com/yeminglong/p/9518438.html  推荐一些常用的asp.net ORM框架 SqlSugar (国内) Dos.ORM (国内 ...

  10. spring boot项目能启动打包失败

    如题,项目本地可以正常启动.但是用 mvn clean package打包就失败! 事件原因如下: 一.pom.xml少packing元素 <groupId>com.sanyi</g ...