知识表示-TransE

Posted by Sunder on July 7, 2016

本文介绍知识库表示学习中的翻译模型:TransE

预备知识

知识库通常可以看作是三元组的集合,所谓三元组,也就是(头实体,关系,尾实体)的形式,头实体和尾实体统称为实体。下面是几个三元组的例子:

(姚明,出生于,上海)

(姚明,职业,篮球运动员)

(姚明,性别,男)

为了简化起见,我们用(h,r,t)来表示三元组。其中

  • h表示头实体
  • r表示关系
  • t表示尾实体

我们的目标是将知识库中所有的实体、关系表示成一个低维的向量。我们把三元组(h,r,t)对应的向量表示为\((h,r,t)\)。

  • \(h\) 表示头实体对应的向量
  • \(r\) 表示关系对应的向量
  • \(t\) 表示尾实体对应的向量

这样,“姚明”这个实体就不再是一个孤立的符号了,而是一个低维的稠密的向量。它看起来就像下面这样:

[0.01, 0.04, 0.8, 0.32, 0.09, 0.18]

上面这个向量的维度是6维,真实情况下向量的维度会比这个大,但具体取多大并没有一个统一的标准,一般取为50~200左右。

在知识表示中,这种向量有一个专门的名称:embedding。

下面我们就介绍一种将三元组表示成它对应的embedding的方法——TransE。

TransE的基本思想

TransE模型认为一个正确的三元组的embedding\((h,r,t)\)会满足下面的公式:\(h+r=t\)

也就是说,头实体embedding加上关系embedding会等于尾实体embedding。同理,如果是一个错误的三元组,那么它们的embedding之间就不满足这种关系。

这就是TransE的基本思想,其实非常的简单。但这却是一种很有效的方法。

TransE的目标函数

上面介绍了transE的基本思想,下面我们介绍如何实现这个想法。 既然我们的目标是学得所有实体和关系的embedding。

上面说了,理想情况下,一个正确的三元组的embedding之间会有\(h+r=t\)的关系,而错误的三元组之间不会有这个关系。因此我们定义如下的势能函数: \(f(h,r,t)=||h+r-t||_2\)

也就是说,我们通过\(h\)和\(t\)之和与\(t\)之差的二范数来表示这个三元组的势能。对于一个正确的三元组,我们希望势能越低越好,而对于一个错误的三元组,我们希望势能越高越好。这样我们就很容易给出目标函数了:

\[min\sum_{(h,r,t)\in\Delta}\sum_{(h',r',t')\in\Delta'}[\gamma+f(h,r,t)-f(h',r',t')]_+\]

其中

  • \(\Delta\) 表示正确的三元组集合
  • \(\Delta'\) 表示错误的三元组集合
  • \(\gamma\) 表示正负样本之间的间距,是一个常数
  • \([x]_+\) 表示\(max(0,x)\)

为了方便训练,避免过拟合,通常还会在上述目标函数后面增加约束条件 \(||h||\le1,||r||\le1,||t||\le1\)。

负样本(错误三元组)的产生

通常我们得到的知识库是三元组的集合,所有在知识库中出现了的三元组都被看作是正例,那我们如何产生负例呢?我们通常使用替换法来获取负例。

对于三元组\((h,r,t)\),我们随机用知识库中的某个实体\(h'\)来替换\(h\),或者用某个实体\(t'\)来替换\(t\),这样我们就得到了两个负例\((h',r,t)\)和\((h,r,t')\)。

为了避免出现生成的负例其实存在于知识库中的情况,我们可以对生成的负例进行过滤,如果它是知识库中的正例,那我们就不把它作为负例,而是重新生成一个负例。

还有人认为,生成负例的时候不应该在知识库中随机选择一个实体来替换,而是应该选择跟被替换实体类型相似的实体来替换。比如给三元组

(姚明,出生于,上海)

生成负例时,应当在于“上海”类型相似的实体,比如“北京”、“西安”等实体中随机抽取一个来生成负例。因为

(姚明,出生于,上海)

这样的负例比

(姚明,出生于,男)

这样的负例更加合理。

transE的主要内容就是这么多了,后续可能会添加如何编程实现transE的内容。 如何用TensorFlow实现transE可以看这里


Creative Commons License
This work is licensed under a CC A-S 4.0 International License.