精华内容
下载资源
问答
  • TransE

    2019-07-17 20:15:59
    一、TransE提出了一种将实体与关系嵌入到低维向量空间中的简单模型 二、具体算法

    一、TransE提出了一种将实体与关系嵌入到低维向量空间中的简单模型
    二、具体算法
    1、相关环境和参数

    import tensorflow as tf
    import numpy as np
    import pandas as pd
    import random
    import time
    dim = 87  #最终习得的entity_embedding和relation_embedding的维度
    margin = 1  
    leanring_rate = 0.01
    nepoch = 2000
    batchs = 8
    method = 0  #影响在sample中随机选取neg项时候不同选项的概率
    norm = 1   #指定规范化的方法,一范数还二范数
    enconding = 'utf-8-sig'
    entityfile='./data/entity2id.csv'
    trainfile="./data/train2id.csv"
    relation2idfile='./data/relation2id.csv'
    

    在这里插入图片描述
    2、导入实体,字典id2entity的每一个key,value对应实体id和实体名

    id2entity = {}
    count = 0
    entity_num = 0
    for line in open(entityfile, encoding=enconding):
        if (count == 0):
            entity_num = int(line.strip(',\n'))
            count += 1
            continue
        array = line.strip().split(",")
        id2entity[int(array[1])] = array[0].strip()  #id和实体
        count += 1
    print("实体数:", entity_num)            #实体数: 1852
    

    3、导入当前各个实体之间所有的关系
    {0: ‘不相关’, 1: ‘正相关’, 2: ‘负相关’}

    id2relation = {}
    count = 0
    relation_num = 0
    for line in open(relation2idfile, encoding=enconding):
        if (count == 0):
            relation_num = int(line.strip(',\n'))
            count += 1
            continue
        array = line.strip().split(",")
        id2relation[int(array[1])] = array[0]    #id和联系
        count += 1
    print("关系数:", relation_num)   #关系数: 3
    

    4、map形如{‘1:1’:(2,3,5,6,8,9), ‘1:0’ : (10,11,26) ,‘2:0’:(5,9,6)},将于id为1的实体的关系为0、1、2的实体的id分别存在到集合里面。
    train_list 则是形如[ h , r , t ] (首实体,关系,尾实体)的三元组列表
    left_entity 和right_entity分别有三行,entity_num个维度,left_entity第i行的第j列代表着与id为j首实体关系为i的实体的数量
    left_num代表将left_entity求各个关系上(此处三个关系)首实体对应的尾实体的平均数量(不计关系数量为0的尾实体,即除去left_entity中每一个零值)

    count = 0
    train_num = 0
    map = {}   #len=5436
    train_list = list()   #(71536,)
    left_entity = np.zeros(shape=[relation_num, entity_num])    #(3,1852)
    right_entity = np.zeros(shape=[relation_num, entity_num])
    for line in open(trainfile, encoding=enconding):
        if(count == 0):
            train_num = int(line.strip(',\n'))
            count += 1
            continue  #首行存放训练数据数量值
        array = line.strip().split(",")    
        train_list.append([int(array[0]), int(array[2]), int(array[1])])   #array[2]代表着相关性,0、1、2
        if(not ((array[0] + ":" + array[2]) in map)):
            map[array[0] + ":" + array[2]] = set()
        map[array[0] + ":" + array[2]].add(int(array[1]))   #将与各个实体(每个实体独立放)关系为 0的实体存放到一个集合,为1的存放到一个集合,2的存放一个
        left_entity[int(array[2])][int(array[0])] += 1  #与左实体关系为0、1、2的实体数量累加存放在矩阵中,array【0】为左实体id
        right_entity[int(array[2])][int(array[1])] += 1   #与有实体关系为0、1、2的实体数量存放在
        count += 1
    print("关系对数:",train_num)   #每次训练包 8942
    
    left_num=np.sum(left_entity,axis=1)/np.sum(left_entity>0,axis=1)
    right_num=np.sum(right_entity,axis=1)/np.sum(right_entity>0,axis=1)
    print(left_num,right_num)
    #(array([14.74454148,  4.85811966, 19.46890211]),
    # array([14.74454148,  4.85811966, 19.46890211]))
    

    5、模型搭建训练embdding矩阵
    (1)、定义一个计算首尾实体以及关系的特征函数

    def _calc(h, t, r):
        if(norm == 1):
            return abs(h + r - t)    #首实体+关系-尾实体   #一范数
        else:
            return (h + r - t) * (h + r - t) / 2   #二范数
    

    (2)、初始化定义好相关参数,通过计算最小化loss来优化更新ent_embeddings,rel_embeddings两个矩阵
    pos代表好的三元组里面的首实体尾实体和关系,neg则代表不相关的(会根据下面的sample随机生成)。
    embedding_lookup则是pos_h中的id值(d,)去对应ent_embeddings(shape=(a,b))中第一维度的每一个下标进行嵌入,生成的矩阵shape=(d,b),pos_h中的每一id值必须小于嵌入矩阵的长度a(否则爆出找不到对应)

    initializer1 = tf.contrib.layers.xavier_initializer(uniform=False, dtype=tf.float32,seed=2019)
    initializer2 = tf.contrib.layers.xavier_initializer(uniform=False, dtype=tf.float32,seed=2019)
    #该函数返回一个用于初始化权重的初始化程序 “Xavier” 。
    #这个初始化器是用来保持每一层的梯度大小都差不多相同。
    
    ent_embeddings = tf.Variable(initializer1([entity_num, dim]), name="ent_embedding", dtype=tf.float32)
    rel_embeddings = tf.Variable(initializer2([relation_num, dim]), name="rel_embedding", dtype=tf.float32)
    pos_h = tf.placeholder(tf.int32)
    pos_t = tf.placeholder(tf.int32)
    pos_r = tf.placeholder(tf.int32)
    neg_h = tf.placeholder(tf.int32)
    neg_t = tf.placeholder(tf.int32)
    neg_r = tf.placeholder(tf.int32)
    p_h = tf.nn.embedding_lookup(ent_embeddings, pos_h)  #  (params,ids)The returned tensor has shape `shape(ids) + shape(params)[1:]`.
    p_t = tf.nn.embedding_lookup(ent_embeddings, pos_t)  #pos_t去ent_embeddings矩阵中查找行,pos_t中的id值去对应矩阵ent_embeddings的第一维度为相应id值的一行(如果是三维embding矩阵那就是将pos_t二维矩阵了了)
    p_r = tf.nn.embedding_lookup(rel_embeddings, pos_r)
    n_h = tf.nn.embedding_lookup(ent_embeddings, neg_h)
    n_t = tf.nn.embedding_lookup(ent_embeddings, neg_t)
    n_r = tf.nn.embedding_lookup(rel_embeddings, neg_r)
    _p_score = _calc(p_h, p_t, p_r)
    _n_score = _calc(n_h, n_t, n_r)
    p_score = tf.reduce_sum(tf.reduce_mean(_p_score, reduction_indices=1,keepdims=False), reduction_indices=1, keepdims=True)
    n_score = tf.reduce_sum(tf.reduce_mean(_n_score, reduction_indices=1, keepdims=False), reduction_indices=1, keepdims=True)
    loss = tf.reduce_sum(tf.maximum(p_score - n_score + margin, 0))   #margin对应公式中的‘甘码’,边缘
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=leanring_rate)
    grads_and_vars = optimizer.compute_gradients(loss)  #返回梯度和相关的变量 列表
    train_op = optimizer.apply_gradients(grads_and_vars) #这两步骤可以和为一起 的,minimize(loss)即可
    ipos_h = np.zeros(shape=[batch_size, 1], dtype=np.int32)
    ipos_t = np.zeros(shape=[batch_size, 1], dtype=np.int32)
    ipos_r = np.zeros(shape=[batch_size, 1], dtype=np.int32)
    ineg_h = np.zeros(shape=[batch_size, 1], dtype=np.int32)  #neg表示不相关的,用来说生成不相关 的元组集合
    ineg_t = np.zeros(shape=[batch_size, 1], dtype=np.int32)
    ineg_r = np.zeros(shape=[batch_size, 1], dtype=np.int32)
    

    此处的loss函数与论文中的loss相对应,对好的三元组关系和坏的三元组关系进行计算,最小化 h+r-t 的值,使得h+r 接近于 t,此处计算loss时设置有一个边缘值‘甘码’(y表示),代码中用margin表示。
    则y表示三元集合中正负样本之间的间距,对于一个正确的三元组(pos_h,pos_r,pos_t),d(pos_h+pos_r,pos_t)是越小越好,对于一个错误的三元组(ipos_h,ipos_r,ipos_t),d(ipos_h+ipos_r,ipos_t)则是越大越好,所以可以导导目标函数
    在这里插入图片描述

    在此更新使其最小化。

    (3)、生成坏的三元组和初始化正确的三元组列表,此处核心在与生成坏的三元组,分别生成坏的首实体三元组和坏的尾实体三元组。对应论文中的将首尾坏实体并起来的公式。
    首先,随机生成一个neg代表实体的id,然后遍历map字典,寻找neg作为首实体或者尾实体不存在关系的那个坏三元组,如neg=1 ,而此随机找到的一个三元组 tri=(2,1,5)
    则判断 ’ neg:1 ( tri [ 1 ] )’ 是否在字典map的keys里面以及其对应的值(为一个集合)中有没有 5 (即 tri [ 2 ] ) ,如果这里map {‘1:1’:(5,6,8)},则说明有,这是一个正确的三元组,那么持续循环直到找到一个 neg 能够组成不相关的三元组,则退出循环。
    坏的尾实体三元组同理。
    所谓坏即是生成的元组对应的两个实体间的这种关系是不存在已知实体联系表中的,此处生成并非负相关或者不相关,而是在实体联系中找不到的未知关系。(简称错误的三元组)

    def sampling(k, train_list, map, ipos_h, ipos_t, ipos_r, ineg_h, ineg_t, ineg_r, train_num, entity_num):  #生成一个坏的三元组
        rand = random.randint(0, train_num - 1)   #这里减一貌似有问题,减少一项了
        tri = train_list[rand]   #随机取出训练数据中的一项三元组
        neg = random.randint(0, entity_num - 1)
        ipos_h[k] = tri[0]    #好的正确三元组
        ipos_t[k] = tri[2]
        ipos_r[k] = tri[1]
        pr = 500
        if(method == 1):
            pr = 1000 * right_num[tri[1]] / (right_num[tri[1]] + left_num[tri[1]])
            #right_num[tri[1]] 表示关系为tri[1]的平均实体数量,由于建设的关系矩阵是对称矩阵,而且饱满的,故,left和right的平均应该一样
        if (random.random() * 1000 < pr):
            while (str(neg) + ":" + str(tri[1]) in map and tri[2] in map[str(neg) + ":" + str(tri[1])]):
                #tri[1]是tri[0]与tri[2]的关系
                #判断随机的一个实体是否在map里面是否有对应的关系存在,有的话就一直循环直到找不到{'0:1':(1,2,3,5,9)....}
                #(与id为0的实体关系为1有(1,2,3,5,9)) 此处即为了判断tri[2]是否在(1,2,3,5,9)
                neg = random.randint(0, entity_num - 1)
            ineg_h[k] = neg    #负h设置为这个找不到关系的实体对应的id,id=neg,坏的三元组首实体
            ineg_t[k] = tri[2]  #t设置为这个找不到id为neg(找不到对应关系的实体的id)的尾实体
            ineg_r[k] = tri[1]  #找不到的对应关系是 tri[i]
        else:
            while (str(tri[0]) + ":" + str(tri[1]) in map and neg in map[str(tri[0]) + ":" + str(tri[1])]):
                neg = random.randint(0, entity_num - 1)
            ineg_h[k] = tri[0]  #坏的三元组
            ineg_t[k] = neg  ##坏的三元组尾实体
            ineg_r[k] = tri[1]
    

    在这里插入图片描述

    (4)、调动训练优化embdding矩阵

    batch_size = int(train_num / batchs)   #batchs=8,batch_size=8942,train_num=71536
    with tf.Session() as sess:
        sess.run(tf.initialize_all_variables())
        for epoch in range(nepoch):   #nepoch=2000
            res = 0.0
            tmp = time.time()
            for batch in range(batchs):   #batchs=8     保证每个实体都有相等概率遍历到
                tmp2 = time.time()
                for k in range(batch_size):   #8942
                    sampling(k, train_list, map, ipos_h, ipos_t, ipos_r, ineg_h,
                             ineg_t, ineg_r, train_num, entity_num) 
                    #通过batch_size次将好的三元组和坏的三元组填满
                    #train_list是(h,l,r)三元组列表,长度为71536,map存放与各个实体到有相应关系的实体集合
       
                tmp3 = time.time()
                feed_dict = {pos_h: ipos_h, pos_t: ipos_t, pos_r: ipos_r, neg_h: ineg_h, neg_t: ineg_t, neg_r: ineg_r}
                res += sess.run([train_op, loss], feed_dict=feed_dict)[1]
            print(str(epoch) + ":" + str(res) + ", time: " + str(time.time() - tmp))
        ent_embedding = sess.run([ent_embeddings], feed_dict=feed_dict)[0]
        rel_embedding = sess.run([rel_embeddings], feed_dict=feed_dict)[0] 
        np.save('ent_emb', ent_embedding)
        np.save('rel_emb', rel_embedding)
        # saver = tf.train.Saver()
        # saver_path = saver.save(sess, "company_TransE_unif_l1")
        # print("Model saved in file:", saver_path)
        np.savetxt('ent_embedding.txt',ent_embedding,delimiter=',')
        np.savetxt('rel_embedding.txt',rel_embedding,delimiter=',')
    

    6、局部异常识别模型

    def lof2(data,predict=None,k=5,cont=0.05):  ##基于密度的局部异常因子
        from sklearn.neighbors import LocalOutlierFactor
        try:
            if predict == None:
                predict = data.copy()
        except Exception:
            pass
        predict = pd.DataFrame(predict)
        clf = LocalOutlierFactor(n_neighbors=k, algorithm='auto', contamination=cont)
        y_pred = clf.fit_predict(predict)
        print('y_pre shape:',y_pred.shape)
        print('y_pre:',y_pred)
        outliers = predict[y_pred == -1].index   #y_pre后值为-1的那一行即为对应的污点结果,取出在dataframe中对应的index下表即为实体的id,返回这些脱离的实体
        return outliers
    

    此处输入的时候的predict=data 即是对应的train_data为一个dataframe形式的数据。
    contamination:数据集的污染量的占比

    下面train_data的操作类似于从实体id通过embeddings矩阵映射成相应的训练数据矩阵(这里相当于手工lookup,通过dataframe的下标索取函数)

    import re
    allxm = ['未分配利润', '长期借款', '净利润', '经营活动产生的现金流量净额']
    k=1
    con=0.03
    data=pd.DataFrame(ent_embedding)
    print('data shape:',data.shape)
    namedict={v:k for k,v in id2entity.items()}  #id,entity
    for xm in allxm:
        tolxm = []
        for key, value in namedict.items():
            pattern = re.compile(r'_')
            xmlst = re.split(pattern, key)
            if xm == xmlst[1]:
                tolxm.append(int(namedict[key]))  #中牧实业股份有限公司_未分配利润,华润双鹤药业股份有限公司_未分配利润 等这些实体的id就被add进来
        #print('entity id:',tolxm)
        train_data = pd.DataFrame(data, index=tolxm)  #抽取出游相应后缀(eg‘未分配利润’)的行出来作为训练数据
        
        #print('train_data shape:',train_data.shape)
        tolrecord = train_data.index.size  ##
        #print('train_data_size:',tolrecord)
        result = lof2(train_data, k=k, cont=con)  ##异常点分析
       # print('result: ',result)
        for i in result: 
            print(id2entity[int(i)])   #输出相应的污点实体(即异常实体)
    

    相应的一次输出:
    data shape: (1852, 87)
    entity id: [27, 64, 104, 141, 180, 220, 258, 296, 336, 375, 412, 451, 490, 529, 565, 604, 641, 679, 718, 756, 795, 834, 874, 908, 947, 986, 1024, 1062, 1102, 1141, 1180, 1220, 1258, 1297, 1336, 1374, 1412, 1452, 1491, 1529, 1567, 1607, 1645, 1683, 1723, 1762, 1801, 1840]
    train_data shape: (48, 87)
    train_data_size: 48
    y_pre shape: (48,)
    y_pre: [ 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
    result: Int64Index([296, 1180], dtype=‘int64’)
    中牧实业股份有限公司_未分配利润
    康美药业股份有限公司_未分配利润

    展开全文
  • transE

    千次阅读 2018-10-31 17:18:45
    刚才我们简单介绍了TransE很有意思的性能,但是TransE也有自身的缺陷,这里我们简单总结TransE面临的若干挑战,以及在这些方面的最新研究进展。 首先,很多情况下TransE关于h + r=t的假设其实本身并不符合实际。为...

    文章来源:http://chuansong.me/n/2553541
    我们为什么要关注表示学习这个问题呢?我们可以看关于机器学习的一个重要公式,这个公式有三个部分组成,第一部分是关于数据或者问题的表示,在表示的基础上我们要去设计或者构建一个目标,也就是说我们要实现一个什么样的目标。在设定了目标之后,开始看怎么实现这个目标,这就是优化的过程。对于机器学习来讲,表示是这三个环节中最基础的部分,也是我们为什么会关注它的重要原因。对于自然语言处理和多媒体处理而言,所处理的数据是典型的无结构数据。为了让计算机更好地对这些数据进行智能处理,如何很好地表示它们是一个至关重要的问题。

    什么是表示学习呢?在自然语言处理中,常用的表示方式是1-hot Representation,每一个词都可以表示成一个非常长的向量,这个向量的长度就是词汇的数量,例如汉语常用词有6000个,我们就把每个词表示成6000维的向量。每个词对应的向量中有一维设置为1,其他维度设置为0,这样很自然地就把人类语言中的所有词都独一无二地表示成一个向量,这样计算机就可以很好的区分某个词跟另外一个词是不一样的。这种方法非常简单,应用也非常广泛,例如搜索引擎中的百度、谷歌,当输入一个查询词,基本思路就是匹配哪些文档里面出现了这些查询词。其实背后本质就是把每一个词都表示成一个独一无二的符号。但是这种方法面临一个很大的问题,大家可以看到,其实很多的词互相之间有非常丰富的语义联系,比如说star和sun,一个是星星,一个是太阳,它们虽然是不同的词,但有密切的语义关联。但是计算机把它们表示成了两个独立的向量,忽略了它们之间的语义关系。这就是我们希望用表示学习解决的问题。

    表示学习的基本思想是提出一种所谓的Distributed Representation,或者是Embedding,用一个低维的向量空间,把每个词都表示到空间里面的某一个位置。这样,我们就可以利用词和词之间在这个空间中的距离来衡量词与词之间的语义关系,这就是表示学习的基本目标。

    表示学习的基础是什么?我为什么能够做这件事情?其实刚才蔡老师讲到了,这与人脑有非常密切联系。人脑有什么样的特点?第一个特点就是,人脑中的信号都是通过生物电或化学电传递的,这是一个非常低速的过程。但是我们又知道,人脑与计算机相比,虽然信号速度很慢,但认知能力却非常强,比如我们人可以快速地识别一张图片中哪个部分是老虎,哪个部分是草坪等等。但是对于计算机来讲,要实现这种认知能力却非常难。第二个,与计算机相比,人脑是一个非常低功耗的装置。也就是说对于人脑来讲,我们每天只需要吃几顿饭就可以让人脑一天到晚一直工作,但是对于计算机来讲,一台普通计算机每天消耗的能量比人脑要多得多。因此,人脑的工作原理非常值得我们学习。那么,人脑有什么样重要的工作机制呢?

    我们现实世界是一个离散的世界,这个世界里面每个物体相互之间都是独立的,有比较明确的界限,因此可以称为离散的世界。但是人脑表示这些物体的时候,都是表示为很多神经元上抑制和激活的状态。也就是说,我们用神经元上不同的抑制和激活状态来表示不同的物体。因此,虽然现实世界是离散的世界,但是在人脑的认知世界中,都被表示到连续的空间中。从这个角度来看,我们刚才所说的那种低维向量表示,其中每一维都可以看成是人脑的神经元。

    现实世界带有非常强的层次性,比如人有头、四肢和躯体,头又可以分成头发、眉毛、五官等等。在认知世界里面也会对应存在这种层次性,即神经网络的层次结构。现在非常流行的深度学习技术就是由于引入了“深度”的层次性结构,带来了很多任务性能的革命性提升。

    所以我们来看,人脑的这两个特点,对应到表示学习的两个特点,这两个特点就是:第一,采用分布式表示来表征现实世界的对象,即采用连续的空间表示对象。第二,采用深度的多层神经网络实现对现实世界的层次性建模,这也是表示学习的重要思想。

    可以说,表示学习有非常强的认知基础。而同时,对于自然语言处理而言,也有着非常重要的现实意义,主要体现在两个方面,第一个方面,大规模自然语言处理面临非常强的数据稀疏难题,传统方法无法很好解决。而通过构建低维向量表示空间,我们把所有对象映射到这个空间里面,就可以利用这个空间的连续性较好地处理数据稀疏问题。另外一个好处是,可以实现不同领域以及不同对象之间的知识迁移。在自然语言处理中,我们关心的对象非常多,从最基础的词到句子,到文档,以及知识,我们如何更好地计算它们之间的语义关联呢?比如说给你一个句子、一个文档,怎么判断他们之间的语义关系?对传统的自然语言处理而言,这是非常难的事情。通过将这些对象映射到统一的空间中,我们将能够非常容易地计算它们之间的语义关系。因此,我们认为对于自然语言处理来讲,表示学习是非常重要的技术,也是近年来自然语言处理领域非常关心的方向。深度学习技术则是这个方面的重要代表。今天由于时间关系,不可能介绍表示学习在自然语言处理所有方面的应用。这里将以知识表示学习为例,向大家简单介绍最新的进展。

    知识图谱是一种特殊网络,其中每个节点代表现实世界中的实体,而节点间的边表示实体之间的关系。知识图谱一般用三元组形式组织知识,每个三元组包括一个头实体、一个尾实体以及它们之间的关系。这是知识图谱的基本表示形式。有两种代表性的知识图谱,一个是语言知识图谱WordNet,包含了英语中词与词之间的同义、反义、上下位等关系。Wordnet是自然语言处理常用的语言知识库。另外一种知识图谱Freebace是世界知识图谱,包含了现实世界中人、地点、机构等实体以及它们之间的关系,例如,乔布斯是苹果公司的创始人等。

    传统的知识图谱表示方式是基于RDF的三元组,相当于把每一个实体和关系都表示成独一无二的符号。这种方法与one-hot representation类似无法很好地利用或计算实体之间的语义关系。例如,乔布斯和比尔盖茨都是IT里面非常有名的人物,但是在知识图谱中用两个独一无二的符号表示,因此无法很好地计算它们之间的语义关系。因此我们希望通过表示学习来解决这个问题。如果能做到这一点,将能够更好地利用知识图谱中的知识。

    现在主要介绍知识表示学习的一个最简单也是最有效的方案,叫TransE。在这个模型中,每个实体和关系都表示成低维向量。那么如何怎么学习这些低维向量呢?我们需要设计一个学习目标,这个目标就是,给定任何一个三元组,我们都将中间的relation看成是从head到tail的一个翻译过程,也就是说把head的向量加上relation的向量,要让它尽可能地等于tail向量。在学习过程中,通过不断调整、更新实体和关系向量的取值,使这些等式尽可能实现。这里面会有非常多技术实现细节,这里面就不作太多讲解,大家如果感兴趣可以去阅读相关论文。

    这些实体和关系的表示可以用来做什么呢?一个直观的应用就是Entity Prediction(实体预测)。就是说,如果给一个head entity,再给一个relation,那么可以利用刚才学到的向量表示,去预测它的tail entity可能是什么。思想非常简单,直接把h + r,然后去找跟h + r向量最相近的tail向量就可以了。实际上,我们也用这个任务来判断不同表示模型的效果。我们可以看到,以TransE为代表的翻译模型,需要学习的参数数量要小很多,但同时能够达到非常好的预测准确率。

    这里举一些例子。首先,利用TransE学到的实体表示,我们可以很容易地计算出跟某个实体最相似的实体。大家可以看到,关于中国、奥巴马、苹果,通过TransE向量得到的相似实体能够非常好地反映这些实体的关联。

    如果已知head entity和relation,我们可以用TransE模型判断对应的tail entity是什么。比如说与中国相邻的国家或者地区,可以看到比较靠前的实体均比较相关。比如说奥巴马曾经入学的学校,虽然前面的有些并不准确,但是基本上也都是大学或教育机构。

    如果同时知道heat entity和tail entity,我们也可以用TransE模型判断它们之间的关系。例如奥巴马和哥伦比亚大学之间就是一个入学学校的关系。这表明 TransE能够得到比较好的预测效果。

    刚才我们简单介绍了TransE很有意思的性能,但是TransE也有自身的缺陷,这里我们简单总结TransE面临的若干挑战,以及在这些方面的最新研究进展。

    首先,很多情况下TransE关于h + r=t的假设其实本身并不符合实际。为什么呢?假如头实体是美国,关系是总统,而美国总统其实有非常多,我们拿出任意两个实体来,比如奥巴马和布什,这两个人都可以跟USA构成同样的关系。在这种情况下,对这两个三元组学习TransE模型,就会发现,它倾向于让奥巴马和布什在空间中变得非常接近。而这其实不太符合常理,因为奥巴马和布什虽然都是美国总统,但是在其他方面有千差万别。这其实就是涉及到复杂关系的处理问题,即所谓的1对N,N对1、N对N这些关系。刚才例子就是典型的1对N关系,就是一个USA可能会对应多个tail entity。为了解决TransE在处理复杂关系时的不足,研究者提出很多扩展模型,基本思想是,首先把实体按照关系进行映射,然后与该关系构建翻译等式。

    TransH和TransR均为代表扩展模型之一,其中TransH由MSRA研究者提出,TransR由我们实验室提出。可以看到,TransE在实体预测任务能够达到47.1的准确率,而采用TransH和TransR,特别是TransR可以达到20%的提升。对于知识图谱复杂关系的处理,还有很多工作需要做。这里只是简介了一些初步尝试。

    对于TransH和TransR的效果我们给出一些例子。比如对于《泰坦尼克号》电影,想看它的电影风格是什么,TransE得到的效果比TransH和TransR都要差一些。再如剑桥大学的杰出校友有哪些?我们可以看到对这种典型的1对N关系,TransR和TransH均做得更好一些。

    人类知识除了在知识图谱中,更多地蕴藏在大量的互联网文本中。如何把文本信息与知识图谱信息结合起来,更好地实现知识表示,是一个重要的挑战问题。其实如何从文本中抽取知识,是自然语言处理的重要研究任务,其基本思想是寻找两个实体共同出现的文本,然后从这些文本中抽取特征,用来判断实体间的关系。

    我们来看知识表示与文本结合的重要意义。通过上图可以发现,如果单独利用文本信息进行关系抽取,效果如蓝线所示。而如果将知识表示信息结合进来,效果会有明显跃迁。这说明,如果能够将文本和知识图谱信息有效融合在一起,将有助于表示学习等任务的性能提升。另外一个非常重要的挑战是,实体在知识图谱中还有丰富的描述信息,这些信息也是文本形式的,怎么把它融合进来呢?我们尝试了采用卷积神经网络对文本建模。由于时间关系就不作详细介绍,如果大家感兴趣可以私下交流。

    总之,有非常多的知识是蕴藏在无结构的文本里面的,如何把无结构的文本和有结构的知识结合在一起,是非常重要的研究方向,也是不断扩充知识图谱的重要技术手段,值得深入研究。

    最后我想介绍的是,如何充分利用知识图谱中的关系路径进行表示学习。我们可以看到,任意两个实体之间的关系,其实跟它们之间的关系路径有非常强的联系。比如说《阿甘正传》的电影语言其实与导演的语言有密切联系。如何充分利用关系路径,对于知识表示学习有重要意义。

    过去就有人利用关系路径判断两个实体之间的关系,取得了非常好的效果。我们现在想说,在知识表示学习中,不只考虑直接的关联关系,还应当考虑两个实体之间的关系路径。这里有个重要问题,任给两个实体,如何把它们之间的关系路径也表示成向量,这就涉及到组合语义问题。

    我们提出利用相加、相乘、循环神经网络的形式来实现组合语义,利用关系路径中每个关系的表示,得到关系路径的表示。这样我们就得到一个扩展的TransE模型,把关系路径表示成向量,然后构建h + r = t等式。

    可以看一下扩展版TransE的性能。通过这些表格我们可以看到,考虑关系路径的模型在实体预测有超过35%的提升,这个提升是非常显著的。而在关系预测上,也有10%的提升,这个提升也非常明显。

    由于时间关系这里就只举一个例子。如果我们能够很好地考虑关系路径,任给两个关系,假如它们形成一个路径的话,我们可以得到这个路径对应的关系,比如说某个关系路径是:“出生地点”和“地点所在国家”,通过模型可以推测出这个路径对应着关系“国籍”。

    以上就是我们今天着重介绍的,如何在知识表示学习中考虑复杂关系,如何把文本和知识图谱信息相结合,以及如何考虑关系路径等等。当然,知识图谱的表示学习还有非常多值得研究的课题。

    知识表示学习与深度学习在自然语言处理中的应用密切相关,最近两年正处在爆发期,今年自然语言处理会议的大部分论文都是关于深度学习的。这表明,表示学习是非常重要的研究方向。

    最后想再强调一点,面向知识图谱的表示学习,对于更好地表示和利用知识图谱中的信息具有非常重要的意义。

    这个方向仍然处于探索阶段,有非常多的工作值得去做。其有很多开放性的问题没有得到答案。比如人类认知的举一反三的能力,这代表了人的泛化能力以及抽象能力,目前深度学习和表示学习对此还做得不够好。2015年《科学》杂志上发表了一篇重要工作,就探索了只给一个样例来学习分类的问题,这对于人来讲很容易,但是对于机器则很难做到,特别是深度学习在这方面的能力非常差。实际上,深度学习领域在2014年发布过一个非常有名的成果,能够利用大规模无标注的图片自动学习和识别猫脸。其实这个过程有非常多的限制,包括使用了非常大量的猫的图片,而且都是标准的正脸。采用非常规范的数据学习得到猫脸,与人脑相比没什么了不起,因为人脑根本不需要这么多图片才能学到猫的样子。人只需要根据有限个样例,就能总结出猫的特点。这是深度学习和表示学习需要继续努力的方向。

    展开全文
  • transE by Python Train transE.py and test test.py. If shut down during training, also can run reTrans.py to continue. Finally, also can use pca.py to dimensionality reduction, and plot in .png THANKS...
  • 该工程代码主要是实现自己阅读过的和知识图谱相关的经典算法的代码:1.TransE是知识图谱中知识表示的经典算法,工程实现了训练代码(多进程通信版)和测试代码后续如继续进行论文阅读会补充相应的代码2.TransE论文地址...

    该工程代码主要是实现自己阅读过的和知识图谱相关的经典算法的代码:

    1.TransE是知识图谱中知识表示的经典算法,工程实现了训练代码(多进程通信版)和测试代码

    后续如继续进行论文阅读会补充相应的代码

    2.TransE论文地址: https://www.utc.fr/~bordesan/dokuwiki/_media/en/transe_nips13.pdf

    3.TransE SGD解释与代码简单解释: https://blog.csdn.net/weixin_42348333/article/details/89598144

    环境配置与前置技术要求:

    环境配置

    CPU 24 Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz

    内存 128G

    系统 CentOS Linux release 7.5.1804 (Core)

    涉及到的技术点

    Linux基本操作与shell脚本简单语法 利用shell脚本去进行训练,避免使用Python文件中的main函数去训练

    git基本操作

    Python的多进程 可以参考https://blog.csdn.net/weixin_42348333/article/details/105126470

    TensorFlow 常用API

    Pycharm debug与pdb debug

    对论文的训练和评估细节的深刻理解

    训练部分

    Simple版本

    ./train_fb15k.sh 0

    仅仅使用Python完成对应的训练代码

    Manager版本

    ./train_fb15k.sh 1

    将TransE类的实例在多进程之间传递

    Queue版本

    ./train_fb15k.sh 2

    将TransE类的训练数据传入队列,减小进程开销,加快训练速度

    注意事项

    当训练完成之后,再进行测试。

    测试代码需要在Linux环境执行,Windows环境多进程速度慢,且多进程有bug!!!

    测试部分

    TestMainTF

    python TestMainTF.py

    tf与多进程测试加速,效果显著,Linux环境128G服务器,测试结束仅需要8min左右。

    最终测试结果

    THANKS

    展开全文
  • transE编译失败

    2020-12-26 07:11:12
    transE.cpp -o transE -pthread -O3 -march=native 进行编译,然后系统报错 <p>transE.cpp: 在函数‘void<em> train(void)’中: transE.cpp:407:1: 警告:在有返回值的函数中未发现 return 语句 ...
  • TransE算法解析

    2020-12-04 21:17:54
    transE(Translating Embedding)详解+简单python实现 概念 transE算法是一个非常经典的知识表示学习,用分布式表示(distributed representation)来描述知识库中的三元组。 原理 transE算法利用了word2vec的平移不变...

    transE(Translating Embedding)详解+简单python实现

    概念

    transE算法是一个非常经典的知识表示学习,用分布式表示(distributed representation)来描述知识库中的三元组。

    原理

    transE算法利用了word2vec的平移不变性,TransE的直观含义,就是TransE基于实体和关系的分布式向量表示,将每个三元组实例(head,relation,tail)中的关系relation看做从实体head到实体tail的翻译(其实就是向量相加),通过不断调整h、r和t(head、relation和tail的向量),使(h + r) 尽可能与 t 相等,即,实体向量 + 关系向量 = 实体向量 (h+l = t)

    损失函数

    img

    1️⃣ ( h ′ , l , t ′ )称为corrupted triplet,通过随机替换头或尾实体得到的

    2️⃣ 正样本 - 即原有样本,公式中的d(h+l, t)

    3️⃣ 负样本 - 随机替换h或者l, 不同时替换,公式中的d(h’+l, t’)

    4️⃣ γ>0为 margin(一个边际参数),表示正负样本之间的间距

    5️⃣ transE针对给定三元组进行二分类任务

    ​ 其中的负例是通过替换自行构造的,目标是使得最相近的正负例样本距离最大化。

    6️⃣ 距离度量方式

    ​ L1和L2范数

    7️⃣ 关系向量 (l)需要归一化,避免训练时带来实体向量的尺度变化

    8️⃣ 让正样本的距离最小,也就是m i n ( d i s t a n c e ( h + r , t ) ),让负样本的相反数最小也就是min(-distance(h’+r’,t’)),对于每一个正样本和负样本求和,再增加一个常数的间距margin,就是整体距离的最小值。也就是我们的目标函数。

    9️⃣ 如何产生负样本
    通过随机替换头实体的方式来实现一个错误的三元组,或者采用随机替换一个错误的尾实体的方式来形成一个错误的三 元组。

    在这里插入图片描述

    同时,为了避免出现生成的负例其实存在于知识库中的情况,我们在替换形成的三元组也存在于知识图谱中,我们需要在替换之后进行过滤

    训练方式采用SGD训练法
    SGD的收敛没有GD好,但是,这反而是优点,因为在机器学习领域,过于best的结果反而是害处,因为用于过拟合(overfitting)。也就是,尽管叫做D(下降),但整个过程我们难保一直D下去。只能保证在forever可以做到D。

    通常为了方便训练并避免过拟合,会加上约束条件
    ∣ ∣ h ∣ ∣ ≤ 1 , ∣ ∣ r ∣ ∣ ≤ 1 , ∣ ∣ t ∣ ∣ ≤ 1 ,

    具体的优化过程

    1️⃣ 所有实体和关系的嵌入首先按照随机过程进行初始化;
    2️⃣ 在算法的每次主要迭代中,对实体的嵌入向量进行归一化;
    3️⃣ 从训练集中采样一个小的三元组集合,作为小批的训练三元组;
    4️⃣ 对于每一个这样的三元组,我们取样一个损坏的三元组;
    5️⃣ 然后以恒定的学习速率梯度更新参数。

    下图是论文里的算法描述:
    在这里插入图片描述

    代码从网上下载即可。
    运行的部分结果:
    在这里插入图片描述

    论文:Translating Embeddings for Modeling Multi-relational Data

    展开全文
  • TransE系列源码

    2017-12-29 11:03:36
    TransE的直观含义,就是TransE基于实体和关系的分布式向量表示,将每个三元组实例(head,relation,tail)中的关系relation看做从实体head到实体tail的翻译(其实我一直很纳闷为什么叫做translating,其实就是向量...
  • TransE算法详解

    千次阅读 多人点赞 2018-12-25 20:31:31
    TransE 算法详解 @(机器学习)[知识图谱|知识表示|TransE] 文章目录TransE 算法详解算法背景知识图谱是什么知识表示是什么基本思想算法描述梯度参考文献 算法背景 知识图谱是什么 一条知识图谱可以表示为一个三元组...
  • 简单了解TransE

    2020-10-07 19:17:41
    接触TransE算法也有半年多了,从一开始的一脸懵逼到现在满脸懵逼,也算是有点收获。。。 于是,,,献丑了~ 关于算法的具体实现,网上有很多,也不过多赘述,推荐几篇比较好的(不保证是原创,因为同款文章太多...
  • TransE算法

    千次阅读 2018-04-11 18:35:59
    TransE算法中存在一个设定,它将关系看作是实体间的平移向量,也就是说对于一个三元组(h,r,t)对应的向量lh,lr,lt,希望 lh+lr =lt 这源于Mikolov等人在2013年提出的word2vec词表示学习模型,他们发现词向量...
  • TransE模型的基本思想是使head向量和relation向量的和尽可能靠近tail向量。这里我们用L1或L2范数来衡量它们的靠近程度。 损失函数是使用了负抽样的max-margin函数。 L(y, y’) = max(0, margin - y + y’) y是正...
  • <p>So this means I need to perform some hyperparameter search for TransE. Would you like to provide some search range or rule of thumb? Such as which hyperparameter are important ones? <p>Thank you!...
  • Update transe.py

    2020-12-08 19:58:02
    <div><p>Missing a return statement in the else clause of the TransE embedding scorer.</p><p>该提问来源于开源项目:uma-pi1/kge</p></div>
  • 关于知识图谱的trans系列一:transE 论文链接 https://www.utc.fr/~bordesan/dokuwiki/_media/en/transe_nips13.pdf 参考链接 https://zhuanlan.zhihu.com/p/32993044 abstract: Hence, we propose TransE, a method...
  • TransE算法的整理

    2019-12-10 21:24:52
    TransE 1 TransE的作用 TransE 作用就是把三元组翻译成embedding词向量的方法 三元组,也就是(头实体,关系,尾实体)的形式,头实体和尾实体统称为实体。为了简化起见,我们用(h,r,t)来表示三元组。其中 h表示头...
  • 知识图谱——TransE模型原理

    千次阅读 2020-02-12 16:27:20
    知识图谱——TransE模型原理 1 TransE模型介绍 1.1 TransE模型引入 在我们之前的文章中,提到了知识图谱补全任务的前提任务是知识表示学习,在知识表示学习中,最为经典的模型就是TransE模型,TransE模型的核心作用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,061
精华内容 824
关键字:

transe