深度学习(四十二)word2vec词向量学习笔记
word2vec词向量学习笔记
原文地址:http://blog.csdn.net/hjimce/article/details/51564783
个人微博:黄锦池-hjimce
一、使用原版word2vec工具训练
1、英文编译测试
(1)到官网到下载:https://code.google.com/archive/p/word2vec/,然后选择export 到github,也可以直接到我的github克隆:
git clone https://github.com/hjimce/word2vec.git
(2)编译:make
(3)下载测试数据http://mattmahoney.net/dc/text8.zip,并解压
(4)输入命令train起来:
time ./word2vec -train text8 -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-4 -threads 20 -binary 1 -iter 15
(5)测试距离功能:
./distance vectors.bin
2、中文训练测试
(1)中文词向量:下载数据msr_training.utf8,这个数据已经做好分词工作,如果想要直接使用自己的数据,就需要先做好分词工作
(2)输入命令train起来:
time ./word2vec -train msr_training.utf8 -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-4 -threads 20 -binary 1 -iter 15
(3)启动相似度距离测试:
./distance vectors.bin
(4)输入相关中文词:中国,查看结果:
hjimce@hjimcepc:~/workspace/word2vec$ ./distance vectors.bin
Enter word or sentence (EXIT to break): 中国Word: 中国 Position in vocabulary: 35Word Cosine distance
------------------------------------------------------------------------中国人民 0.502711美国 0.480650中国政府 0.463177我国 0.447327亚太地区 0.444878加勒比 0.418471两国 0.408678各国 0.392190独立自主 0.391517世界 0.387604国际 0.382578中美 0.382208欧美 0.379807古巴 0.378412
二、算法学习阶段
因为这个算法是半年前所学的算法,最近只是简单复习一下,所以不打算写详细的算法流程笔记,原理等也不打算啰嗦。word2vec网络结构可以分成两种:CBOW、Skip-Gram,其实网络结构都非常简单,不过是一个三层神经网络罢了。本文只讲解CBOW网络结构算法、算法流程。
CBOW又有两种方案,一种叫层次softmax,另一种叫:negative sample。这两种方法如果看不懂也没关系,你完全可以用原始的softmax替代网络的最后一层,进行训练,只是训练速度比较慢。
1、CBOW+层次softmax算法总体流程
先讲解层次softmax的算法实现过程:
(1)根据训练语料库,创建词典,并对词典每个单词进行二叉树霍夫曼编码。
如下图所示,比如经过编码后,可能汉语词典中的“自”就被编码成了:110,“我”对应的编码就是:001。这个算法与word2vec的实现过程关系不大,具体霍夫曼编码过程代码怎么写,不懂也没关系。我们只需要记住,字典中的每个单词都会被编码,每个单词对应二叉树的叶节点,每个单词的编码结果对应于:从跟节点到达当前单词,所经过的节点路径。编码中的1、0表示右节点、左节点。
这边需要知道的是每一位编码的用处,因为每位的编码节点刚好可以对应到0、1输出标签,而且这颗二叉树节点就是神经网络的输出层神经元,具体可以看下面的图。假如在训练的时候,最后一层训练数据的输出是“自”,那么其实我们只需要训练节点root、node1、node3使得这三个节点的激活值分别为:1、1、0,这样就可以了。
因此对于层次softmax来说,神经网络的隐藏层其实是连接到二叉树的每个非叶子节点上(如果是原始的sotfmax,是直接连接到叶子节点上),然后对这些非叶子节点,根据输出单词的编码路径,对路径上的每个节点,根据对应的编码进行训练。
(2)根据定义窗口大小,截取出一个窗口内的单词作为一个样本,进行训练
这一步在word2vec里面,其实我们给出的参数值是一个max window size,然后word2vec底层生成一个随机大小的窗口,只要满足其范围在max window size 即可,这个可能是为了数据扩充吧。
(3)输入层-》隐藏层:对窗口内的左右单词(不包含自己)对应的词向量,进行累加,并求取平均向量Vavg。
(4)隐藏层-》非叶子节点:每个二叉树非叶子节点,链接到Vavg都有一个可学习的参数W,然后通过sigmoid可以得到每个非叶子节点的激活值(也表示概率值):
也就是说网络的参数除了词向量之外,还有隐藏层链接到二叉树结点的参数向量(从word2vec代码上看,我没有看到偏置参数b)。
(5)反向求导:根据输出文字的节点路径,更新路径上的每个非叶子节点链接到隐藏层的参数值w;并更新窗口内各个单词的词向量。
具体网络结构图如下所示:
采用层次softmax的优点在于加快训练速度,参数个数、预测速度没啥差别。
2、CBOW+Negative Sample
这个比较简单,所谓的Negative Sample,就是除了正样本标签之外,还需要随机抽取出词典中的其它单词作为负样本(以前是把整个词典的其它单词都当成负样本),这个还是具体看源码实现吧。
三、源码阅读阶段
word = sen[sentence_position];//当前单词if (word == -1) continue;for (c = 0; c < layer1_size; c++) neu1[c] = 0;//隐藏层神经元激活值初始化为0for (c = 0; c < layer1_size; c++) neu1e[c] = 0;//隐藏层反向求导的误差值next_random = next_random * (unsigned long long)25214903917 + 11;b = next_random % window;//b是一个介于0~window size之间的随机数值//cbow算法,网络第一层:直接把左右窗口内的单词相加起来//sentence_position是当前单词if (cbow) {cw = 0;//算法第一步:除了当前单词之外,把上下文窗口单词的词向量相加起来for (a = b; a < window * 2 + 1 - b; a++)if (a != window){c = sentence_position - window + a;//遍历sentence_position窗口内的上下文单词if (c < 0) continue;//边界越界处理,因为一个文档的长度是0~sentence_lengthif (c >= sentence_length) continue;last_word = sen[c];if (last_word == -1) continue;for (c = 0; c < layer1_size; c++)//把左右窗口内的单词的词向量全部相加,其中layer1_size表示词向量的维度{neu1[c] += syn0[c + last_word * layer1_size];//syn0是词向量表}cw++;}if (cw){//算法第二步:平均,把上面左右单词的词向量加起来后再平均for (c = 0; c < layer1_size; c++){neu1[c] /= cw;}if (hs)//vocab[word].codelen表示当前单词的霍夫曼编码长度,下面也就遍历当前词的路径节点for (d = 0; d < vocab[word].codelen; d++){//算法第三步:启用了层次sorfmax模式,计算每个节点的概率//f是二叉树节点的输出值,下面是计算f,f是每个节点的逻辑回归概率值f = 0;l2 = vocab[word].point[d] * layer1_size;for (c = 0; c < layer1_size; c++) f += neu1[c] * syn1[c + l2];//syn1是从隐藏层到二叉树节点连接参数矩阵(可以把二叉树节点看成是神经元)//节点的label被定义为:1-code,而不是code,这个可能是为了方便计算吧// 那么节点损失函数为-[(1-code)*log(f)+code*log(1-f)]if (f <= -MAX_EXP) continue;else if (f >= MAX_EXP) continue;else f = expTable[(int)((f + MAX_EXP) * (EXP_TABLE_SIZE / MAX_EXP / 2))];//算法第四步:反向求导// 'g' is the gradient multiplied by the learning rateg = (1 - vocab[word].code[d] - f) * alpha;//梯度×学习率// Propagate errors output -> hiddenfor (c = 0; c < layer1_size; c++) neu1e[c] += g * syn1[c + l2];// Learn weights hidden -> outputfor (c = 0; c < layer1_size; c++) syn1[c + l2] += g * neu1[c];}//如果采用了negative sampleif (negative > 0)for (d = 0; d < negative + 1; d++){//正样本if (d == 0){target = word;label = 1;}//随机采样出负样本else{next_random = next_random * (unsigned long long)25214903917 + 11;target = table[(next_random >> 16) % table_size];if (target == 0) target = next_random % (vocab_size - 1) + 1;if (target == word) continue;label = 0;}l2 = target * layer1_size;f = 0;for (c = 0; c < layer1_size; c++) f += neu1[c] * syn1neg[c + l2];//同样计算输出单词,逻辑回归概率值//似然函数为-[label*log(f)+(1-label)*log(1-f)]//更新链接到当前类别(单词)节点的权值向量if (f > MAX_EXP) g = (label - 1) * alpha;else if (f < -MAX_EXP) g = (label - 0) * alpha;else g = (label - expTable[(int)((f + MAX_EXP) * (EXP_TABLE_SIZE / MAX_EXP / 2))]) * alpha;for (c = 0; c < layer1_size; c++) neu1e[c] += g * syn1neg[c + l2];for (c = 0; c < layer1_size; c++) syn1neg[c + l2] += g * neu1[c];}//从隐藏层到词向量层反向传播,更新词向量层for (a = b; a < window * 2 + 1 - b; a++) if (a != window){c = sentence_position - window + a;if (c < 0) continue;if (c >= sentence_length) continue;last_word = sen[c];if (last_word == -1) continue;for (c = 0; c < layer1_size; c++) syn0[c + last_word * layer1_size] += neu1e[c];}}}
参考文献:
1、《Efficient Estimation of Word Representations in Vector Space》
2、《word2vec Explained: Deriving Mikolov et al.'s Negative-Sampling Word-Embedding Method》
3、https://code.google.com/archive/p/word2vec/
深度学习(四十二)word2vec词向量学习笔记相关推荐
- Java多线程学习四十二:有哪些解决死锁问题的策略和哲学家就餐问题
线上发生死锁应该怎么办 如果线上环境发生了死锁,那么其实不良后果就已经造成了,修复死锁的最好时机在于"防患于未然",而不是事后补救.就好比发生火灾时,一旦着了大火,想要不造成损失去 ...
- MATLAB强化学习实战(十二) 创建自定义强化学习算法的智能体
创建自定义强化学习算法的智能体 创建环境 定义策略 自定义智能体类 智能体属性 构造函数 相关函数 可选功能 创建自定义智能体 训练自定义智能体 自定义智能体仿真 本示例说明如何为您自己的自定义强化学 ...
- Caffe学习记录(十二) ICNet分割网络学习二
在ICNet分割网络训练的过程中,发生了很郁闷的事情, 首先ICNet的训练数据准备,和segnet一样,需要准备原始数据,mask 已经对应的txt文件,格式为pathofdata 空格 patho ...
- OpenCV学习笔记(四十一)——再看基础数据结构core OpenCV学习笔记(四十二)——Mat数据操作之普通青年、文艺青年、暴力青年 OpenCV学习笔记(四十三)——存取像素值操作汇总co
OpenCV学习笔记(四十一)--再看基础数据结构core 记得我在OpenCV学习笔记(四)--新版本的数据结构core里面讲过新版本的数据结构了,可是我再看这部分的时候,我发现我当时实在是看得太马 ...
- 词向量学习笔记(一)Word2vec
词向量学习笔记(一)Word2vec 文章目录 词向量学习笔记(一)Word2vec 一.概述 二.词向量 2.1词的独热表示one-hot 2.2 词的分布式表示 三.原理--Skip-gram和C ...
- 花书+吴恩达深度学习(十二)卷积神经网络 CNN 之全连接层
目录 0. 前言 1. 全连接层(fully connected layer) 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常开心的~ 花书+吴恩达深度学习(十)卷积神经网络 CNN ...
- 系统学习NLP(十三)--词向量(word2vec原理)
词向量简介 自然语言是一套用来表达含义的复杂系统.在这套系统中,词是表义的基本单元.在机器学习中,如何使用向量表示词? 顾名思义,词向量是用来表示词的向量,通常也被认为是词的特征向量.近年来,词向量已 ...
- Tensorflow深度学习之十二:基础图像处理之二
Tensorflow深度学习之十二:基础图像处理之二 from:https://blog.csdn.net/davincil/article/details/76598474 首先放出原始图像: ...
- 前几帧预测 深度学习_使用深度学习从十二导联心电图预测心律失常
上集讲到 使用深度学习 从单导联预测房颤 这一集 将继续讨论该问题 单导联心电图 对心律失常的预测作用 非常有限 因为 单导联的信号很有限 临床上需要结合 多导联心电图 判断 心律失常的类型 这一集的 ...
最新文章
- shardingjdbc全局表_Sharding-JDBC 分库分表概述
- 地址总线是单向还是双向_三端双向交流开关(TRIAC)
- vuex登录后设置token
- css注释_CSS注释示例–如何注释CSS
- 优秀小程序demo 源码
- 今日SGU 5.20
- IEEE期刊论文模板的查找,下载方法--
- 微信API接口访问慢
- 【初等概率论】 01
- 第二章:HLK-7621开发板介绍
- SQL Server 2008 下载及版本说明
- Unity中录制VR全景视频(可录制UGUI)
- 5G学习之路——认识CU、DU
- C语言编程-7_4 字符统计
- 微信小程序图书管理系统
- Microsemi Libero系列教程(全网首发)
- IDEA 类中找不到main方法请将main方法定义为public static void main. 否则 JavaFX 应用程序类必须扩展javafx.application.Applicati
- Python初学者:元组数据操作,输出元组内7的倍数以及个位是7的数
- C语言低配版扫雷游戏
- win2003 由于可用空间计算失败_幼儿编程启蒙怎么做?智能家居+ai 玩空间是最佳教具...
热门文章
- aspjpeg已过期_Persits.Jpeg.1错误’800a0004′ AspJpeg组件过期解决方法 - YangJunwei
- neostrack服务器无响应,捷安特GPS码表NeosTrack试用评测
- Java程序中fix time_Java Position.setFixTime方法代码示例
- 复制release文件到另一台电脑.exe文件无法运行_电脑技巧:电脑版微信双开(或微信多开)?用start指令可以解决...
- system volume information是什么文件_如何扩展Unity URP的后处理Volume组件
- [crypto][ipsec] 简述ESP协议的sequence number机制
- CodeForces - 868F Yet Another Minimization Problem
- vmware工具克隆linux系统步骤及配置
- avast从隔离区恢复后,仍无法打开被误杀文件的解决方案
- spring Mvc 执行原理 及 xml注解配置说明 (六)