最近由于要做一个工程性的近义词的工程,因此接触到了Word2Vec这个工具。

Word2Vec是 Google 在 2013 年年中开源的一款将词表征为实数值向量的高效工具, 其利用深度学习的思想,可以通过训练,把对文本内容的处理简化为 K 维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似度。Word2vec输出的词向量可以被用来做很多 NLP 相关的工作,比如聚类、找同义词、词性分析等等。如果换个思路,把词当作特征,那么Word2vec就可以把特征映射到 K 维向量空间,可以为文本数据寻求更加深层次的特征表示

由于目前水平有限,对于真正的训练的过程还并未有真的吃透,所以这里就不详细介绍其原理,等后期看懂后,再补上。这里只介绍工程性用例。

http://word2vec.googlecode.com/svn/trunk/这里是谷歌官方给出的是它的C语言版本,最好的话是要在Linux系统下,进入系统后,直接使用Make编译即可。

使用时,

/word2vec-train input.txt -output output.model -cbow 0 -size 200 -window 5 -negative 0 -hs1 -sample 1e-3 -threads 12 -binary 1

-train 是输入语料

-oupput 是输出模型

-cbow 0表示不使用cbow模型,默认为Skip-Gram模型

-size 表示词向量维数:一般取100-300左右,经验是不超过1000。

-window cbow一般都是5,如果是Skip-Gram的话,最好是10

-sample 表示采样参数,是一个经验忽视掉频率过高的词的参数,一般为1e-3,最小一般为1e-5。

-sampe指的是采样的阈值,如果一个词语在训练样本中出现的频率越大,那么就越会被采样。

-negative表示负采样参数,每有一个正样本,选择几个负样本的参数,一般也是用默认(0)。

-binary为1指的是结果二进制存储,为0以文本形式进行存储。

-hs 做不做层次的softmax,是1的时候效果比较好,但是训练会慢一点.

-min-count控制词典的最低频率,默认是5,如果只想要高频词的话就设置高一点。

-threads使用线程数,一般都是12。

-classes设置聚类个数。

-alpha设置学习速率,默认的为0.025

不过一般除了训练的时候使用一下命令,其他调用的时候,建议使用JAVA版本的输出和应用。

JAVA版本的网上有很多,有些都没有办法打开或者使用。https://github.com/liuxuan320/Word2Vec这是在我的Github上的,这个版本有我标注了部分注释,直接eclipse里Import即可,包括所需要的JAR包,都已经在Extend里包含,重新导入即可。后续还会继续完善,也欢迎各位一同补充指正。

这里来解释一下网上常见的这个项目的错误,例如总是会提醒java heap memory错误。这个错误我追踪了很久,终于发现的问题了。

整个过程大概是这样的:

首先把整个语料读入内存中。

然后做一个HashMap的副本在内存中,其次根据HashMap建立一个Huffman树副本,其次再根据Huffman副本,使用回溯路径,建立隐节点副本。一切都准备就绪了,最后再开始正式训练。

首先,是语料库大小的问题,一般1G的语料库,有250万词,100维度,所需要的内存应该是超过4G,200维度的加载到160万左右就爆了。对于PC来讲,通常是会报错了,最好的话可以找台服务器跑。

那么解决办法就是让它慢下来,看过源码后,发现它里面的副本极多,具体的我在项目的注释里写了。这就需要JVM的垃圾回收,但是如果速度太快,JVM来不及回收,那么内存会很快被填满。

慢下来以后,仍然会报错,不过这次和上面那个位置不一样了,后来发现是在回溯路径的时候,因为神经元太多,导致回溯不到其父节点了,一直在计算,GC时间低于2%,JVM又开始进行保护机制,认为你是死循环或者其他情况,直接就产生中断了。

后来,使用了10维的向量,最后成功训练出来,不过其模型的实用性太差,只是为了证明java版本是可用的。例如,狗,通常相似的有猫,鼠等,但是这个训练出来的模型,会和仔队等无关的词相近。

另外要说的一点,利用C语言版本训练出的模型,需要用载入谷歌模型的方法,而java版本训练出来的要用载入java模型的方法。

以上就是最近使用的心得。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐