欢迎关注鄙人公众号,技术干货随时看!
one-hot表示法
词向量就是把一个词用向量的形式表示,以前的经典表示法是one-hot,这种表示法向量的维度是词汇量的大小。它的处理方式简单粗暴,一般就是统计词库包含的所有V个词,然后将这V个词固定好顺序,然后每个词就可以用一个V维的稀疏向量来表示,向量中只有在该词出现的位置的元素才为1,其它元素全为0。比如下面这几个词,第一个元素为1的表示中国,第六个元素为1的表示美国,第五个元素为1的表示日本。
中国[1,0,0,0,0,0,0,0,0,……,0,0,0,0,0,0,0]
美国[0,0,0,0,0,1,0,0,0,……,0,0,0,0,0,0,0]
日本[0,0,0,0,1,0,0,0,0,……,0,0,0,0,0,0,0]
按照目前汉语的词汇量20万左右,那么一个词就是20万维度的向量来表示,这对内存和计算效率都是灾难性的,优点是非常简单,只需过扫描一遍语料库好即可。
word2vec
google开源的word2vec得到的词的向量形式则可以自由控制维度,一般是100左右。google开源的是用c语言开发的,hanlp的作者移植了这套c代码并合并到了word2vec中。据说,每个线程每秒训练的词语稳定在180-190K,比原版C程序要快2.5倍左右;训练速度比C程序要快的原因是,原版C程序读取单词后需要去char数组里遍历查找id;而我的Java实现直接读取缓存文件中的id,当然开始训练前要先进行词->id的转换并输出到缓存文件,这个过程大约多花一两分钟时间,相较于训练时间,无疑是值得的。这样改进之后还可以直接读取类似text8那样的变态语料,一举多得。效率与c语言版的没有差别。
下面开始正式讨论hanlp中word2vec的源码。关计word2vec中用到的神经网络的模型和算法,这里不再赘述,请参考作者的文章http://www.hankcs.com/nlp/word2vec.html
语料库
训库词向量当然需要一个相对完整的语料库,目有可以采用人民日报、Sighan05分词语料 http://sighan.cs.uchicago.edu/bakeoff2005/,一般情况下首先对语料库分词,这里不再讨论分词,为了讨论源码的方更的,我们采用的语料库如下(生产环境语料库越大越向量模型越准确):
帕勒莫 VS 梅西纳 已经 无关紧要 初盘 显示 格局
雷吉纳 VS 尤文图斯 初盘 显示 客队 强大 关系到 客队 夺冠 问题 尤文图斯 任胆
特雷维索 VS 乌迪内斯 乌迪内斯 客场 连续 拿下 状态 开出 平手 想必 乌鸡 势头 就此 中断 足彩 王智 德甲 解盘
科隆 VS 比勒菲尔德 初盘 高开 意图 明显 庄家 筹码 上盘 嫌疑 极大 科隆 有望 不败
拜仁 慕尼黑 VS 多特蒙德 多特蒙德 客场 至多 连赢 极限 盘也 有意 冷落 主队
汉堡 VS 不莱梅 半球盘 本赛季 尚无 平局 记录 适合 选择
杜伊斯堡 VS 美因兹 初盘 极为 不符 庄家 利用 主队 已经 降级 题材 美因兹 嫌疑
沙尔克 VS 斯图加特 初盘 主队 水位 偏高 目前 斯图加特 客场 路有 反弹 迹象 排除 客队 可能
训练完成的词向量文件如下所示:第一行是词向量的条数和维度。
15 20
VS 0.020013 0.022097 -0.019151 -0.016390 0.006833 0.015105 0.004704 0.001057 -0.018018 0.011092 -0.021782 0.006248 -0.003757 -0.004786 -0.016579 -0.009411 0.012897 0.015127 0.014845 0.007987
初盘 0.007693 -0.018967 -0.020466 0.024825 0.019040 0.015461 -0.003025 0.020149 -0.002462 0.003626 -0.000768 -0.014950 0.006504 -0.006674 -0.019058 0.023742 0.021883 -0.005529 -0.001090 0.002513
客队 -0.018188 -0.020036 0.022774 0.000315 -0.012912 -0.015211 -0.015382 0.008485 0.001007 0.006655 -0.02106