본문 바로가기
추천 시스템 논문

code로 보는 TransR 논문

by 블쭌 2021. 5. 19.
728x90
  • Abstract

지식그래프는 entitiy사이의 link를 예측을 완벽하게 수행하는것을 목표로 하고있다.

기존 TransE나 TransH의 경우, 동일한 semantic 공간에 entity와 relation이 존재했다.

그러나 entitiy들은 다양한 aspect를 가지고 있고 다양한 relation들은 entity의 다른 aspect를 집중하기때문에 동일한 공간에 mapping하는것이 옳지않다고 생각했고 entity와 relation을 분리된 공간에 mapping시킴으로써 TransR이라는 알고리즘을 제안했다.

 

 

 예를 들어, r1 측면에서는 h1, t1이 비슷했지만, r2 측면에서는 h1, t1이 비슷하지 않다고 볼 수 있기 때문입니다.

이런 한계를 극복하기 위해 TransR은 entity와 relation을 구분된 공간(entity space, multiple relation spaces)에 embedding하자는 아이디어를 제안했습니다. 또한, entity의 translation을 위해 TransR은 relation-specific projection을 수행하는 "projection matrix(M_r)"를 사용함으로써 entity를 entity space에서 각 relation space로 embedding 시킵니다.

 

왼쪽이미지 entitiy space에서 각각의 (h, r, t)의 triple이 operation(M_r) Projecion matrix를 통해 r-relation space에 mapping이 됩니다.

entity space에 h(head), t(tail) 뿐만 아니라, 여러 삼각형이 있습니다. 여기서 r(relation)이 존재하는 entity는 단지 h, t뿐입니다. 해당 entity들을 relation r이라는 r-relation space으로 투영시키기 위해 M_r이라는 projection matrix를 활용합니다. 그 결과는 오른쪽 이미지 r-relation space입니다. 왼쪽의 h, t에 비해서 오른쪽 h, t는 r이라는 relation 관계를 바탕으로 서로 가까운 공간에 위치시킴과 동시에 관계없는 삼각형 모양의 entitiy들은 멀어졌습니다. 즉 relation 마다 다른 공간에 찍히면서 보다 정확한 link prediction이 가능하게 만들어줄 수 있다는 것입니다.


  • code
import tensorflow as tf
import numpy as np

from kge_model.model import BaseModel

class TransR(BaseModel):
    def __init__(self, iterator, params):
        super(TransR, self).__init__(iterator, params)
        self.d = params.relation_embedding_dim

    def _score_func(self, h, r, t):
        """ f_r(h,t) = |M_r*h+r-M_r*t| """

        self.Mr = tf.get_variable("Mr", [self.k, self.d], initializer=tf.initializers.identity(gain=0.1))
        self.Mr = tf.tile(tf.expand_dims(self.Mr, 0), [self.batch_size, 1, 1]) # b, k, d
        h = tf.expand_dims(h, axis=1) # b, 1, k
        t = tf.expand_dims(t, axis=1) # b, 1, k
        h_r = tf.squeeze(tf.matmul(h, self.Mr), axis=1)
        t_r = tf.squeeze(tf.matmul(t, self.Mr), axis=1)
        distance = h_r + r - t_r

        if self.params.score_func.lower() == 'l1':  # L1 score
            score = tf.reduce_sum(tf.abs(distance), axis=1)
        elif self.params.score_func.lower() == 'l2':  # L2 score
            score = tf.sqrt(tf.reduce_sum(tf.square(distance), axis=1))
            
        return score

더욱더 자세한 코드는 아래 깃허브를 참고해주세요.

https://github.com/bladejun/Knowledge_graph_tensorflow

 

bladejun/Knowledge_graph_tensorflow

Knowledge Graph Embedding Model collections implemented by TensorFlow - bladejun/Knowledge_graph_tensorflow

github.com

 

728x90

댓글