TransE算法原理与代码解析(2021-06-22)

TransE算法原理与案例

文章目录

  • TransE
    • 知识图谱基础
    • 知识表示
    • 算法描述
    • 代码分析
    • 数据

TransE

知识图谱基础

三元组(h,r,t)

知识表示

即将实体和关系向量化,embedding

算法描述

思想:一个正确的三元组的embedding会满足:h+r=t
在这里插入图片描述

定义距离d表示向量之间的距离,一般取L1或者L2,期望正确的三元组的距离越小越好,而错误的三元组的距离越大越好。为此给出目标函数为:

在这里插入图片描述

在这里插入图片描述
梯度求解
在这里插入图片描述

代码分析

  • 定义类:
参数:
目标函数的常数——margin
学习率——learningRate
向量维度——dim
实体列表——entityList(读取文本文件,实体+id)
关系列表——relationList(读取文本文件,关系 + id)
三元关系列表——tripleList(读取文本文件,实体 + 实体 + 关系)
损失值——loss

距离公式——L1

  • 向量初始化

规定初始化维度和取值范围(TransE算法原理中的取值范围)
涉及的函数:

    init:随机生成值
    norm:归一化
  • 训练向量
    getSample——随机选取部分三元关系,Sbatch
    getCorruptedTriplet(sbatch)——随机替换三元组的实体,h、t中任意一个被替换,但不同时替换。
    update——更新

L2更新向量的推导过程:
[外链图片转存失败(img-ecjLQyc0-1567589870034)(en-resource://database/2941:0)]

python 函数
uniform(a, b)#随机生成a,b之间的数,左闭右开。
求向量的模,var = linalg.norm(list)

"""
@version: 3.7
@author: jiayalu
@file: trainTransE.py
@time: 22/08/2019 10:56
@description: 用于对知识图谱中的实体、关系基于TransE算法训练获取向量
数据:三元关系
实体id和关系id
结果为:两个文本文件,即entityVector.txt和relationVector.txt    实体 [array向量]

“”"
from random import uniform, sample
from numpy import *
from copy import deepcopy

class TransE:
def init(self, entityList, relationList, tripleList, margin = 1, learingRate = 0.00001, dim = 10, L1 = True):
self.margin = margin
self.learingRate = learingRate
self.dim = dim#向量维度
self.entityList = entityList#一开始,entityList是entity的list;初始化后,变为字典,key是entity,values是其向量(使用narray)。
self.relationList = relationList#理由同上
self.tripleList = tripleList#理由同上
self.loss = 0
self.L1 = L1

def initialize(self):
    '''
    初始化向量
    '''
    entityVectorList = {}
    relationVectorList = {}
    for entity in self.entityList:
        n = 0
        entityVector = []
        while n < self.dim:
            ram = init(self.dim)#初始化的范围
            entityVector.append(ram)
            n += 1
        entityVector = norm(entityVector)#归一化
        entityVectorList[entity] = entityVector
    print("entityVector初始化完成,数量是%d"%len(entityVectorList))
    for relation in self. relationList:
        n = 0
        relationVector = []
        while n < self.dim:
            ram = init(self.dim)#初始化的范围
            relationVector.append(ram)
            n += 1
        relationVector = norm(relationVector)#归一化
        relationVectorList[relation] = relationVector
    print("relationVectorList初始化完成,数量是%d"%len(relationVectorList))
    self.entityList = entityVectorList
    self.relationList = relationVectorList
def transE(self, cI = 20):
    print("训练开始")
    for cycleIndex in range(cI):
        Sbatch = self.getSample(3)
        Tbatch = []#元组对(原三元组,打碎的三元组)的列表 :{((h,r,t),(h',r,t'))}
        for sbatch in Sbatch:
            tripletWithCorruptedTriplet = (sbatch, self.getCorruptedTriplet(sbatch))
            # print(tripletWithCorruptedTriplet)
            if(tripletWithCorruptedTriplet not in Tbatch):
                Tbatch.append(tripletWithCorruptedTriplet)
        self.update(Tbatch)
        if cycleIndex % 100 == 0:
            print("第%d次循环"%cycleIndex)
            print(self.loss)
            self.writeRelationVector("E:\pythoncode\knownlageGraph\\transE-master\\relationVector.txt")
            self.writeEntilyVector("E:\pythoncode\knownlageGraph\\transE-master\\entityVector.txt")
            self.loss = 0
def getSample(self, size):
    return sample(self.tripleList, size)

def getCorruptedTriplet(self, triplet):
    '''
    training triplets with either the head or tail replaced by a random entity (but not both at the same time)
    :param triplet:
    :return corruptedTriplet:
    '''
    i = uniform(-1, 1)
    if i < 0:  # 小于0,打坏三元组的第一项
        while True:
            entityTemp = sample(self.entityList.keys(), 1)[0]
            if entityTemp != triplet[0]:
                break
        corruptedTriplet = (entityTemp, triplet[1], triplet[2])
    else:  # 大于等于0,打坏三元组的第二项
        while True:
            entityTemp = sample(self.entityList.keys(), 1)[0]
            if entityTemp != triplet[1]:
                break
        corruptedTriplet = (triplet[0], entityTemp, triplet[2])
    return corruptedTriplet

def update(self, Tbatch):
    copyEntityList = deepcopy(self.entityList)
    copyRelationList = deepcopy(self.relationList)

    for tripletWithCorruptedTriplet in Tbatch:
        headEntityVector = copyEntityList[
            tripletWithCorruptedTriplet[0][0]]  # tripletWithCorruptedTriplet是原三元组和打碎的三元组的元组tuple
        tailEntityVector = copyEntityList[tripletWithCorruptedTriplet[0][1]]
        relationVector = copyRelationList[tripletWithCorruptedTriplet[0][2]]
        headEntityVectorWithCorruptedTriplet = copyEntityList[tripletWithCorruptedTriplet[1][0]]
        tailEntityVectorWithCorruptedTriplet = copyEntityList[tripletWithCorruptedTriplet[1][1]]

        headEntityVectorBeforeBatch = self.entityList[
            tripletWithCorruptedTriplet[0][0]]  # tripletWithCorruptedTriplet是原三元组和打碎的三元组的元组tuple
        tailEntityVectorBeforeBatch = self.entityList[tripletWithCorruptedTriplet[0][1]]
        relationVectorBeforeBatch = self.relationList[tripletWithCorruptedTriplet[0][2]]
        headEntityVectorWithCorruptedTripletBeforeBatch = self.entityList[tripletWithCorruptedTriplet[1][0]]
        tailEntityVectorWithCorruptedTripletBeforeBatch = self.entityList[tripletWithCorruptedTriplet[1][1]]

        if self.L1:
            distTriplet = distanceL1(headEntityVectorBeforeBatch, tailEntityVectorBeforeBatch,
                                     relationVectorBeforeBatch)
            distCorruptedTriplet = distanceL1(headEntityVectorWithCorruptedTripletBeforeBatch,
                                              tailEntityVectorWithCorruptedTripletBeforeBatch,
                                              relationVectorBeforeBatch)
        else:
            distTriplet = distanceL2(headEntityVectorBeforeBatch, tailEntityVectorBeforeBatch,
                                     relationVectorBeforeBatch)
            distCorruptedTriplet = distanceL2(headEntityVectorWithCorruptedTripletBeforeBatch,
                                              tailEntityVectorWithCorruptedTripletBeforeBatch,
                                              relationVectorBeforeBatch)
        eg = self.margin + distTriplet - distCorruptedTriplet
        if eg > 0:  # [function]+ 是一个取正值的函数
            self.loss += eg
            if self.L1:
                tempPositive = 2 * self.learingRate * (
                            tailEntityVectorBeforeBatch - headEntityVectorBeforeBatch - relationVectorBeforeBatch)
                tempNegtative = 2 * self.learingRate * (
                            tailEntityVectorWithCorruptedTripletBeforeBatch - headEntityVectorWithCorruptedTripletBeforeBatch - relationVectorBeforeBatch)
                tempPositiveL1 = []
                tempNegtativeL1 = []
                for i in range(self.dim):  # 不知道有没有pythonic的写法(比如列表推倒或者numpy的函数)?
                    if tempPositive[i] >= 0:
                        tempPositiveL1.append(1)
                    else:
                        tempPositiveL1.append(-1)
                    if tempNegtative[i] >= 0:
                        tempNegtativeL1.append(1)
                    else:
                        tempNegtativeL1.append(-1)
                tempPositive = array(tempPositiveL1)
                tempNegtative = array(tempNegtativeL1)

            else:
                #根据损失函数的求梯度
                tempPositive = 2 * self.learingRate * (
                            tailEntityVectorBeforeBatch - headEntityVectorBeforeBatch - relationVectorBeforeBatch)
                tempNegtative = 2 * self.learingRate * (
                            tailEntityVectorWithCorruptedTripletBeforeBatch - headEntityVectorWithCorruptedTripletBeforeBatch - relationVectorBeforeBatch)

            headEntityVector = headEntityVector + tempPositive#更新向量
            tailEntityVector = tailEntityVector - tempPositive
            relationVector = relationVector + tempPositive - tempNegtative
            headEntityVectorWithCorruptedTriplet = headEntityVectorWithCorruptedTriplet - tempNegtative
            tailEntityVectorWithCorruptedTriplet = tailEntityVectorWithCorruptedTriplet + tempNegtative

            # 只归一化这几个刚更新的向量,而不是按原论文那些一口气全更新了
            copyEntityList[tripletWithCorruptedTriplet[0][0]] = norm(headEntityVector)
            copyEntityList[tripletWithCorruptedTriplet[0][1]] = norm(tailEntityVector)
            copyRelationList[tripletWithCorruptedTriplet[0][2]] = norm(relationVector)
            copyEntityList[tripletWithCorruptedTriplet[1][0]] = norm(headEntityVectorWithCorruptedTriplet)
            copyEntityList[tripletWithCorruptedTriplet[1][1]] = norm(tailEntityVectorWithCorruptedTriplet)

    self.entityList = copyEntityList
    self.relationList = copyRelationList
def writeEntilyVector(self, dir):
    print("写入实体")
    entityVectorFile = open(dir, 'w', encoding="utf-8")
    for entity in self.entityList.keys():
        entityVectorFile.write(entity + "    ")
        entityVectorFile.write(str(self.entityList[entity].tolist()))
        entityVectorFile.write("\n")
    entityVectorFile.close()

def writeRelationVector(self, dir):
    print("写入关系")
    relationVectorFile = open(dir, 'w', encoding="utf-8")
    for relation in self.relationList.keys():
        relationVectorFile.write(relation + "    ")
        relationVectorFile.write(str(self.relationList[relation].tolist()))
        relationVectorFile.write("\n")
    relationVectorFile.close()

def init(dim):
return uniform(-6/(dim0.5), 6/(dim0.5))

def norm(list):
‘’’
归一化
:param 向量
:return: 向量的平方和的开方后的向量
‘’’

var = linalg.norm(list)
i = 0
while i < len(list):
list[i] = list[i]/var
i += 1
return array(list)

def distanceL1(h, t ,r):
s = h + r - t
sum = fabs(s).sum()
return sum

def distanceL2(h, t, r):
s = h + r - t
sum = (s*s).sum()
return sum

def openDetailsAndId(dir,sp=" "):
idNum = 0
list = []
with open(dir,“r”, encoding=“utf-8”) as file:
lines = file.readlines()
for line in lines:
DetailsAndId = line.strip().split(sp)
list.append(DetailsAndId[0])
idNum += 1
return idNum, list

def openTrain(dir,sp=" "):
num = 0
list = []
with open(dir, “r”, encoding=“utf-8”) as file:
lines = file.readlines()
for line in lines:
triple = line.strip().split(sp)
if(len(triple)<3):
continue
list.append(tuple(triple))
num += 1
return num, list

if name == main:
dirEntity = “E:\pythoncode\ZXknownlageGraph\TransEgetvector\entity2id.txt”
entityIdNum, entityList = openDetailsAndId(dirEntity)
dirRelation = “E:\pythoncode\ZXknownlageGraph\TransEgetvector\relation2id.txt”
relationIdNum, relationList = openDetailsAndId(dirRelation)
dirTrain = “E:\pythoncode\ZXknownlageGraph\TransEgetvector\train.txt”
tripleNum, tripleList = openTrain(dirTrain)
# print(tripleNum, tripleList)
print(“打开TransE”)
transE = TransE(entityList,relationList,tripleList, margin=1, dim = 128)
print(“TranE初始化”)
transE.initialize()
transE.transE(1500)
transE.writeRelationVector(“E:\pythoncode\ZXknownlageGraph\TransEgetvector\relationVector.txt”)
transE.writeEntilyVector(“E:\pythoncode\ZXknownlageGraph\TransEgetvector\entityVector.txt”)

数据

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
结果向量在这里插入图片描述

  • 点赞 5
  • 评论 21
  • 分享
    x

    海报分享

    扫一扫,分享海报

  • 收藏 37
  • 打赏

    打赏

    jiayalu

    你的鼓励将是我创作的最大动力

    C币 余额
    2C币 4C币 6C币 10C币 20C币 50C币

    确定

  • 举报
  • 关注 关注
  • 一键三连

TranSE算法实现及测试
04-26
这是我自己的代码,主要用来存储,若能帮到其他人,我也很愿意。
表情包
插入表情
还能输入1000个字符
相关推荐
TransE算法(Translating Embedding)
u011274209的专栏
03-27 4万+
介绍 TransE 算法(Translating Embedding)
知识表示学习 TransE 代码逻辑梳理 超详细解析
南波兔不写bug
09-02 2536
知识表示学习 网络上已经存在了大量知识库(KBs),比如OpenCyc,WordNet,Freebase,Dbpedia等等。

这些知识库是为了各种各样的目的建立的,因此很难用到其他系统上面。为了发挥知识库的图(graph)性,也为了得到统计学习(包括机器学习和深度学习)的优势,我们需要将知识库嵌入(embedding)到一个低维空间里(比如10、20、50维)。我们都知道,获得了向量后,就可以运用各种数学工具进行分析。它为许多知识获取任务和下游应用铺平了道路。
总的来说,废话这么多,所谓知识表示学习,就


	
TransE如何进行向量更新?
暗焰之珩的博客
04-27 5088
目录

算法伪代码

SGD中的向量更新

代码实现

关于TransE,博客上各种博文漫天飞,对于原理我就不做重复性劳动,只多说一句,TransE是知识表示算法翻译算法系列中的最基础算法,此处还有TransH、TransD等等;个人觉得翻译算法的叫法是不太合适的,translating,叫做平移或者变换算法可能更加符合作者的原本意图,利用向量的平移不变性去做链路预测。了解原理个人觉得以下两篇足够…


TransE代码实践(很详细)
得克特
09-27 5663
TranE是一篇Bordes等人2013年发表在NIPS上的文章提出的 算法。它的提出,是为了解决多关系数据(multi-relational data)的处理问题。 TransE的直观含义,就是 TransE基于实体和关系的分布式向量表示,将每个三元组实例(head,relation,tail)中的关系relation看做从实体head到实体tail的翻译,通过不断调整h、r和t(head、relat...
transE(Translating Embedding)详解+简单python实现
yuanyue
05-15 1万+
表示学习旨在学习一系列低维稠密向量来表征语义信息,而知识表示学习是面向知识库中实体和关系的表示学习。当今大规模知识库(或称知识图谱)的构建为许多NLP任务提供了底层支持,但由于其规模庞大且不完备,如何高效存储和补全知识库成为了一项非常重要的任务,这就依托于知识表示学习。 transE 算法就是一个非常经典的知识表示学习,用分布式表示(distributed representation)来描述知识库...
TransE算法详解
MonkeyDSummer的博客
12-25 1万+
TransE 算法详解 @(机器学习)[知识图谱|知识表示| TransE]

文章目录TransE 算法详解算法背景知识图谱是什么知识表示是什么基本思想算法描述梯度参考文献
算法背景
知识图谱是什么
一条知识图谱可以表示为一个三元组(sub,rel,obj)。举个例子:小明的爸爸是大明,表示成三元组是(小明,爸爸,大明)。前者是主体,中间是关系,后者是客体。主体和客体统称为实体(entity)。关…


TransE算法解析
perfectzxiny的博客
12-04 511
transE(Translating Embedding)详解+简单python实现 概念 transE 算法是一个非常经典的知识表示学习,用分布式表示(distributed representation)来描述知识库中的三元组。 原理 transE 算法利用了word2vec的平移不变性, TransE的直观含义,就是 TransE基于实体和关系的分布式向量表示,将每个三元组实例(head,relation,tail)中的关系relation看做从实体head到实体tail的翻译(其实就是向量相加),通过不断调
【论文笔记】 知识图谱 之 TransE算法(Translating Embedding)
justlpf的专栏
10-31 1856
原文地址:https://blog.csdn.net/elaine_bao/article/details/52012537
TransE算法
dxk_093812的博客
04-11 5178
TransE 算法中存在一个设定,它将关系看作是实体间的平移向量,也就是说对于一个三元组(h,r,t)对应的向量lh,lr,lt,希望 lh+lr =lt 这源于Mikolov等人在2013年提出的word2vec词表示学习模型,他们发现词向量空间存在着平移不变现象,如 C(king)−C(queen)≈C(man...
TransE算法详解【代码学习系列】【知识图谱】【表示学习】
weixin_44023339的博客
08-27 3941
1 代码来源 本代码来源于github项目地址,项目实现了 TransE 算法。下面结合项目代码,对 TransE 算法 原理及实现进行详细说明。 2基本思想 TransE是一篇Bordes等人2013年发表在NIPS上的文章提出的 算法。它的提出,是为了解决多关系数据(multi-relational data)的处理问题。我们现在有很多很多的知识库数据knowledge bases (KBs),比如Fre...
Svm算法原理及实现
d__760的博客
05-21 10万+
      Svm(support Vector Mac)又称为支持向量机,是一种二分类的模型。当然如果进行修改之后也是可以用于多类别问题的分类。支持向量机可以分为线性核非线性两大类。其主要思想为找到空间中的一个更够将所有数据样本划开的超平面,并且使得本本集中所有数据到这个超平面的距离最短。一、基于最大间隔分隔数据1.1支持向量与超平面    在了解svm 算法之前,我们首先需要了解一下线性分类器这...
TransE的理解
机器学习 数据挖掘 搜索引擎 推荐系统
02-26 5048
github.com/thunlp/OpenKE

先看下train2id.txt,大概是这样子:

253 3643 35
438 10640 94
36 13172 18
8484 35 17
406 3869 38
6039 6038 384
5771 8658 50
7111 683 10
7293 9471 61
4312 2557 382

就只有head tail relatio…


TransE
weixin_43751558的博客
11-20 56
转自:http://blog.csdn.net/u011274209/article/details/50991385 一、引言 网络上已经存在了大量知识库(KBs),比如OpenCyc,WordNet,Freebase,Dbpedia等等。这些知识库是为了各种各样的目的建立的,因此很难用到其他系统上面。为了发挥知识库的图(graph)性,也为了得到统计学习(包括机器学习和深度学习)的优势,我们需要将知识库嵌入(embedding)到一个低维空间里(比如10、20、50维)。我们都知道,获得了向量后,就可以
CSDN开发者助手,常用网站自动整合,多种工具一键调用
CSDN开发者助手由CSDN官方开发,集成一键呼出搜索、万能快捷工具、个性化新标签页和官方免广告四大功能。帮助您提升10倍开发效率!
TransE模型:知识图谱的经典表示学习方法
ChihkAnchor的博客
10-24 1万+
传统的知识图谱表示方法是采用OWL、RDF等本体语言进行描述;随着深度学习的发展与应用,我们期望采用一种更为简单的方式表示,那就是【向量】,采用向量形式可以方便我们进行之后的各种工作,比如:推理,所以,我们现在的目标就是把每条简单的三元组< subject, relation, object > 编码为一个低维分布式向量。(有关【分布式表示】的概念请大家自行百度)

paper:Tra…


学习笔记(2)——TransE算法(Translating Embedding)
strivequeen的博客
08-26 1232
前言 目前网络上存在大量知识库(KBs):如OpenCyc、WordNet、Freebase、Dbpedia等等,它们因不同目的建成,因此很难用到其他系统上。为发挥知识库的图(graph)性,也为得到统计学习(包括机器学习和深度学习)的优势,需要将知识库嵌入(embedding)到一个低维空间里(比如10、20、50维)。获得向量后,就可以运用各种数学工具进行分析。 表示学习 :学习一系列低维稠密向量来表征语义信息,知识表示学习是面向知识库中实体和关系的表示学习。大规模知识库(知识图谱)的构建为许多NLP任
transE
qq_27374315的博客
10-31 3381
我们为什么要关注表示学习这个问题呢?我们可以看关于机器学习的一个重要公式,这个公式有三个部分组成,第一部分是关于数据或者问题的表示,在表示的基础上我们要去设计或者构建一个目标,也就是说我们要实现一个什么样的目标。在设定了目标之后,开始看怎么实现这个目标,这就是优化的过程。对于机器学习来讲,表示是这三个环节中最基础的部分,也是我们为什么会关注它的重要原因。对于自然语言处理和多媒体处理而言,所处理的数...
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页

热门文章

  • 知识图谱与推荐系统 12495
  • 主题模型 5345
  • TransE算法原理与案例 4593
  • AMBERT(李航)---- 多粒度预训练模型 918
  • HanLP环境搭建 755

分类专栏

  • 环境搭建 1篇
  • 算法模型 10篇

最新评论

  • TransE算法原理与案例

    onion: 我也是,我试了FB15K跟WN18都是几百,是因为数据集选的不合适吗,loss最后到多少算合适呢

  • 主题模型

    qq_39717003: drugdescrib1.csv 想要这个文件

  • TransE算法原理与案例

    firstelfin: 如博主所说,自己准备一些数据吧,我也没有数据集

  • TransE算法原理与案例

    Nothing can stop me 、: 你好 请问有咩有拿到数据集呀 [email protected]如果拿到的话 希望大佬可以分享给我

  • TransE算法原理与案例

    qq_37983076: 想问一下为什么2范数直接用(h+r-t)的平方表示

最新文章

  • 白板推导SVM--个人手推笔记
  • AMBERT(李航)---- 多粒度预训练模型
  • FM模型--推荐系统
2021年1篇
2020年1篇
2019年9篇

目录

你可能感兴趣的:(知识表示,神经网络,机器学习,大数据,算法模型)