TransE如何进行向量更新?
目录
算法伪代码
SGD中的向量更新
代码实现
关于TransE,博客上各种博文漫天飞,对于原理我就不做重复性劳动,只多说一句,TransE是知识表示算法翻译算法系列中的最基础算法,此处还有TransH、TransD等等;个人觉得翻译算法的叫法是不太合适的,translating,叫做平移或者变换算法可能更加符合作者的原本意图,利用向量的平移不变性去做链路预测。了解原理个人觉得以下两篇足够了:
TransE Embedding
TransE论文知识总结
算法伪代码
合页损失函数
SGD中的向量更新
前辈们的博文中对原理已经说的比较清楚了,但是对于SGD(stochastic gradient descent)随机梯度下降中的向量更新,都几乎没有过多讲解,简单的说一下我的理解。
随机梯度下降我们首先可以简化成梯度下降,随机是体现在sample时的。根据吴恩达老师机器学习的课程梯度下降可知,每一次对θ的更新如下(α是学习率):
线性回归的损失函数如下:
损失函数可以推广到更一般的形式,在TransE中我们的损失函数如下:
对于一般的数学表达式,不管是导数和偏导数我们都比较熟悉。以导数为例
对于一般函数,例如,则
对于TransE中的损失函数,首先进行简化,去掉前面的两个sigma求和,将Relu神经元用R函数代替,简化成如下形式。
走到这一步我们发现,和上面的线性回归的损失函数已经对应起来了,只不过吴恩达老师课程里的变量名是,在这里的变量名是'
,而且这里的变量实际上是一个dim维向量,这个dim是TransE算法中的一个超参数。ok,那么类比于这一个公式
,我们来试着推导TransE的梯度下降:
以其中第一个公式为例进行推导:
首先来看公式7里面的,这里的d函数实际上是第一范数,d的取值一定会大于等于0。对于Relu函数,具备如下的函数图像,可以认为在TransE中,
=1:
再来看,因为d和h相关的式子是
,所以这里
。这里的的d函数是第一范数L1,一般情况下我们使用第二范数L2(L1范数:向量中各个元素绝对值之和;L2范数:向量中各个元素平方和的开二次方根;Lp范数:向量中各个元素绝对值的p次方和的开p次方根)。这里L2范数是可导的,L1范数并不是处处可导的,因为L1范数简单的来说就是f(x)=|x|,在x=0处是不可导的。但是存在次梯度,拥有次微分,这里的次微分就是我们的
,详细可见常用的范数求导。
所以我们由789 10四个公式得到,最后的偏导数向量要等于类似[1,1,1,-1,1,-1,...,-1]这样的一个dim维向量。特别说一下,更新的时候一定要乘上学习率,否则很有可能会不收敛,形成z字形震荡。
wuxiyu前辈的梯度更新代码如下所示:
self.loss += eg
temp_positive = 2 * self.learning_rate * (t - h - r)
temp_negative = 2 * self.learning_rate * (t2 - h2 - r)
if self.normal_form == "L1":temp_positive_L1 = [1 if temp_positive[i] >= 0 else -1 for i in range(self.dim)]temp_negative_L1 = [1 if temp_negative[i] >= 0 else -1 for i in range(self.dim)]temp_positive = np.array(temp_positive_L1) * self.learning_ratetemp_negative = np.array(temp_negative_L1) * self.learning_rate# 对损失函数的5个参数进行梯度下降, 随机体现在sample函数上
h += temp_positive
t -= temp_positive
r = r + temp_positive - temp_negative
h2 -= temp_negative
t2 += temp_negative
他的代码是先推L2的导数,根据L2来推L1,也可以写成这样的形式,更好理解一些:
if self.normal_form == "L2":temp_positive = 2 * (h + r - t)temp_negative = 2 * (h2 + r - t2)
else: # 此处表示使用L1范数d_positive = h + r - td_negative = h2 + r - t2temp_positive = [1 if d_positive[i] >= 0 else -1 for i in range(self.dim)]temp_negative = [1 if d_negative[i] >= 0 else -1 for i in range(self.dim)]# 对损失函数的5个参数进行梯度下降, 随机体现在sample函数上
# 命名表示严格的偏导乘上学习率
der_h_times_lr = np.array(temp_positive) * self.learning_rate
der_t_times_lr = -1 * np.array(temp_positive) * self.learning_rate
der_r_times_lr = (np.array(temp_positive) - np.array(temp_negative)) * self.learning_rate
der_h2_times_lr = -1 * np.array(temp_negative) * self.learning_rate
der_t2_times_lr = np.array(temp_negative) * self.learning_rateh -= der_h_times_lr
t -= der_t_times_lr
r -= der_r_times_lr
h2 -= der_h2_times_lr
t2 -= der_t2_times_lr
看梯度更新也是下降的:
代码实现
https://github.com/haidfs/TransE
代码简要分析
case1:TrainTransESimple
先实现基本的功能,各项模型内参数与超参如截图所示,可见单进程单线程一次训练一个batch_size为10000的batch,速度非常慢,接近11s(这是在内存128G的Linux服务器上,个人PC会更慢),
case2:TrainTransEMpManager
11s一轮实在说不上快。。在不考虑物理外挂(gpu)的情况下,先考虑使用多进程,最开始不太理解多进程的使用方法,最初的思路是多进程共享变量,将TransE类的变量在多个子进程间传递,于是有了TrainTransEMpManager.py(不建议在个人PC上运行,会非常卡),在这里面将TransE类的实例通过Manager共享。这个速度相比于之前的for循环存在一定的提升,但是不如multiprocessing.Queue()带来的性能提升大。个人理解:如果类比于多线程,每次线程的切入切出总是需要记录上下文信息,大量的线程会造成线程颠簸,带来不必要的开销;Python的多进程应该也是类似,当进程间共享的类的对象存在很多属性,即占用很大的内存空间时,切入和切出同样会带来很大的开销。这样的多进程反而降低了性能,多进程,应该尽可能精简共享的内存大小。在Linux服务器上,同样的batch_size,manger多进程一轮的时间为4.7s,如下:
case3:TrainTransEMpQueue
再看多进程实现同样的参数配置,通过multiprocessing的Queue(),每次仅仅共享[batch_size,dim]维大小的向量,和同样的case1相比:速度还是提升了不少,每一轮仅耗时4.3s。运行到1000轮之后,每轮运行时间接近2s。
初步训练与测试结果:
可以发现初步结果与论文结果较接近,但是还有一定的差距,等待后续调参再训练。
FB15k | ||||
---|---|---|---|---|
epochs:2000 | MeanRank | Hits@10 | ||
raw | filter | raw | filter | |
head | 320.743 | 192.152 | 29.7 | 41.2 |
tail | 236.984 | 153.431 | 36.1 | 46.2 |
average | 278.863 | 172.792 | 32.9 | 43.7 |
paper | 243 | 125 | 34.9 | 47.1 |
疑问:
进行测试时由于单个测试例需要利用整个测试集的所有测试例替换头尾实体,在代码里面写了TestTransEMpQueue和TestMainTF两个版本的测试代码,但是使用Queue()的多进程效果并不理想,几乎没有提升,单个测试例0.4s左右,接近5w个测试例约为5.5小时,速度实在太慢。。。但是不明确为什么,希望有明白的大神可以多多指教。
TestMainTF进行一次测试的耗时为420s左右,约7min。
参考:
https://blog.csdn.net/oBrightLamp/article/details/84326978
https://blog.csdn.net/raby_gyl/article/details/53635459
TransE如何进行向量更新?相关推荐
- 论文解读:Question Answering over Knowledge Base with Neural Attention Combining Global Knowledge Info...
论文解读:Question Answering over Knowledge Base with Neural Attention Combining Global Knowledge Informa ...
- BERT 词向量理解及训练更新
1.BERT 词向量理解 在预训练阶段中,词向量是在不断更新的,而在fine-tuning阶段中,词向量是固定不变的.在fine-tuning阶段中,我们使用预训练好的模型参数来对新的数据进行训练. ...
- [Trans 系列之一]TransE算法(Translating Embedding)
TransE算法(Translating Embedding) 一.引言 网络上已经存在了大量知识库(KBs),比如OpenCyc,WordNet,Freebase,Dbpedia等等.这些知识库是为 ...
- 【论文笔记】 知识图谱 之 TransE算法(Translating Embedding)
最近对知识图谱比较感兴趣,觉得这会是未来整个人工智能领域的发展方向.知识图谱是对人类知识的结构化总结,试想以后所有我们知道的不知道的事情都能通过知识图谱串在一起,形成一个云图书馆.那么知识图谱是如何建 ...
- TransE,知识图谱嵌入(KGE)源码阅读(一)
TransE,知识图谱嵌入(KGE)源码阅读(一) Paper: Antoine Bordes等人在2013年发表于NIPS上的文章 Paper Understanding:TransE,知识图谱嵌入 ...
- word2vec原理_Word2vec详细整理(1)—权重更新原理
在做graph embedding的过程中,产生了对w2v几个疑问,索性重新回顾了一下w2v,做此总结.其中忽略了成吨的梯度更新推导,抓住主干,结论即可. 先按时间顺序附上w2v的几篇论文: 2013 ...
- lstm数学推导_如何在训练LSTM的同时训练词向量?
你本来也不用自己手动进行词向量更新啊,你搞这么一出最后收敛到0那不是必然的么? @霍华德 老师的答案已经给你推导出来了. 实际上你问的这个问题很简单--只要把Embedding层本身也当成模型参数的一 ...
- 词嵌入、句向量等方法汇总
在cips2016出来之前,笔者也总结多类似词向量的内容,自然语言处理︱简述四大类文本分析中的"词向量"(文本词特征提取)事实证明,笔者当时所写的基本跟CIPS2016一章中总结的 ...
- 【CS224W】(task4/5)图嵌入表示学习(Deepwalk、Node2vec)更新中
note Node embedding的基本框架:encoder+decoder 最简单encoder是embedding-lookup表:ENC(v)=zv=Z⋅v\mathrm{ENC}(v)=z ...
- 词向量、句子向量、篇章向量的一些理解(转)
2019独角兽企业重金招聘Python工程师标准>>> 词向量.句子向量.篇章向量的一些理解(转) (转自)http://blog.csdn.net/sinat_26917383/a ...
最新文章
- C++ 笔记(20)— 异常处理(抛出异常、捕获异常)
- jps命令(Java Virtual Machine Process Status Tool)(转)
- (2014年2月7日升级)Ubuntu-14.04-Alpha2-32位简体中文优化封装版
- python Celery 分布式任务队列快速入门
- Pycharm运行时找不到文件问题
- unityios开发--Scorll View控件 .
- java 创建水果_简单的java水果商店后台
- JavaWeb篇-谷歌验证码的使用
- 【Web安全从入门到放弃】06_文件包含漏洞
- vue项目设置ip访问
- python如何赚外快 淘宝_Python如何爬取淘宝MM呢?教你一招
- 没项目实战经验?分享自学练手的软件测试项目实战+数据库+接口,部署超级简单
- c 截取字符串函数代码实现
- Codeforces Round #727 div.2 A-F题解
- android硬解码x265,Android 设置硬解码 h265 失败
- 【人物专访】FreeICQ的CTO龙云飞[1001]访谈
- uestudio 14 注册机 绿色免费版
- 使用FullCalendar做一个自己的日程管理(一)- 基础篇
- 盘企lcms php开发框架,LCMS操作 · 盘企LCMS PHP开发框架文档 · 看云
- iOS 各视频播放器评价~总结