云计算百科
云计算领域专业知识百科平台

TransE 一个向量等式,让知识图谱学会推理

TransE 一个向量等式,让知识图谱学会推理

一句话导语:把关系当成一次平移,“头实体 + 关系 ≈ 尾实体”,知识图谱就能在向量空间里做推理——但它栽在了多对一关系上。

一、背景与痛点

知识图谱里存的是"张三—就职于—某公司""北京—位于—华北"这样的三元组事实。可真实图谱永远是不完整的:大量关系缺失,需要我们根据已有事实去推断那条缺失的边,也就是链接预测。早期做法是纯符号逻辑,规则写不完、泛化又差。2013 年 TransE 用一句话——关系即平移——把连续空间的平滑性带进了离散事实,此后数年都是基准线上的常客。

问题出在关系变复杂之后。设想一家公司里所有人的关系:"就职于"把上千个员工指向同一个公司,这是多对一;反过来,一位经理手下管着一个团队,这是一对多。TransE 在这些情形下会露出破绽——它要求所有"就职于同一家公司"的员工满足 eh≈e公司−r就职于\\mathbf e_h \\approx \\mathbf e_{\\text{公司}} – \\mathbf r_{\\text{就职于}}ehe公司r就职于,等式右边是同一个向量,于是这些员工在嵌入空间里被硬生生挤成一团。他们本来各有各的岗位、各有各的工龄,却被模型抹平成了同一个点。这不是训练不够,而是模型假设本身导致的几何退化。

二、核心原理

1. 把 TransE 的失败算清楚

先明确 TransE 的打分:

d(h,r,t)=∥eh+rr−et∥.d(h,r,t)=\\big\\|\\mathbf e_h+\\mathbf r_r-\\mathbf e_t\\big\\|.d(h,r,t)=eh+rret.

训练时实体向量被归一化到单位球面。考虑一个典型的多对一关系 rrr:许多头实体 h1,h2,…,hkh_1,h_2,\\dots,h_kh1,h2,,hk 都通过 rrr 指向同一个尾实体 ttt。理想情况下每条三元组都应满足 ehi+rr≈et\\mathbf e_{h_i} + \\mathbf r_r \\approx \\mathbf e_tehi+rret,于是

eh1≈eh2≈⋯≈ehk≈et−rr.\\mathbf e_{h_1}\\approx\\mathbf e_{h_2}\\approx\\cdots\\approx\\mathbf e_{h_k}\\approx \\mathbf e_t-\\mathbf r_r .eh1eh2ehketrr.

也就是说,所有指向同一目标的头实体被迫共享同一个嵌入,差异被完全抹掉。这不是训练不足,而是模型假设造成的几何退化。同理,一对多关系会让所有尾实体挤成一团。

2. TransH:把实体投影到关系超平面

TransH 的修法是:不再直接比较实体向量,而是先把它们投影到一张由关系决定的超平面上。设关系 rrr 对应一个单位法向量 wr\\mathbf w_rwr,实体 e\\mathbf ee 在其上的投影为

e⊥=e−(wr⊤e)wr.\\mathbf e_{\\perp}=\\mathbf e-\\big(\\mathbf w_r^{\\top}\\mathbf e\\big)\\mathbf w_r .e=e(wre)wr.

打分变成 d(h,r,t)=∥eh⊥+rr−et⊥∥d(h,r,t)=\\big\\|\\mathbf e_{h\\perp}+\\mathbf r_r-\\mathbf e_{t\\perp}\\big\\|d(h,r,t)=eh+rret。妙处在于:同一个实体在不同关系下会被投影到不同的超平面上,得到不同的"像"。员工张三在"就职于"这张平面上可以和同事重合,但在"擅长"那张平面上又能和别人区分开,一刀切变成了分情况讨论。

3. TransR:实体空间与关系空间分离

TransH 用的是一张平面,表达力仍然有限。TransR 干脆为每个关系 rrr 学一个投影矩阵 Mr∈Rd×k\\mathbf M_r\\in\\mathbb R^{d\\times k}MrRd×k,把 kkk 维实体空间的向量搬进 ddd 维关系空间:

ehr=Mreh,etr=Mret.\\mathbf e_h^{r}=\\mathbf M_r\\mathbf e_h,\\qquad \\mathbf e_t^{r}=\\mathbf M_r\\mathbf e_t .ehr=Mreh,etr=Mret.

打分则在关系空间里进行:

d(h,r,t)=∥Mreh+rr−Mret∥.d(h,r,t)=\\big\\|\\mathbf M_r\\mathbf e_h+\\mathbf r_r-\\mathbf M_r\\mathbf e_t\\big\\| .d(h,r,t)=Mreh+rrMret.

这一步的意义是坐标系的个性化:关系不再只是一个位移方向,它还带来了一整套为自己量身定制的坐标变换。判断"出生地"时我们关注籍贯维度,判断"擅长"时关注技能维度,两者的度量空间根本不同。代价也很直接:每个关系多出 d×kd\\times kd×k 个参数,关系数一多,参数量就膨胀。

4. 训练目标与负采样

三种模型共用同一套边距排序损失:

L=∑(h,r,t)∑(h′,r,t′)[γ+d(h,r,t)−d(h′,r,t′)]+.\\mathcal L=\\sum_{(h,r,t)}\\sum_{(h',r,t')}\\Big[\\gamma+d(h,r,t)-d(h',r,t')\\Big]_+ .L=(h,r,t)(h,r,t)[γ+d(h,r,t)d(h,r,t)]+.

负三元组由替换头或尾实体得到。这里有一个常被忽视的工程细节:负采样的候选池必须按实体类型限定。对"位于"(城市→地区)这个关系,把尾实体替换成一个"人物",造出来的负例连语法都不合法,纯粹浪费梯度。

5. 评测协议:头预测比尾预测更能暴露问题

链接预测的标准做法是:给定 (h,r,?)(h,r,?)(h,r,?),给所有候选尾实体打分、排序,统计 Hits@k 与 MRR。但尾预测会掩盖多对一关系的缺陷——既然所有头实体都指向同一个尾,只要模型学到了这个尾实体区域,尾预测成绩照样漂亮。真正能戳中痛处的是头预测 (?,r,t)(?,r,t)(?,r,t):固定关系与尾实体,问"谁是这个头"。这时 TransE 的退化就暴露了,几个合法头实体在排序里几乎没有区别,模型只能瞎猜;而 TransR 因为有关系专属坐标系,仍能借助投影后的差异把它们排开。

三、代码实战

下面这段纯 numpy 代码在同一张含"位于"多对一关系的合成知识图谱上训练 TransE,并用"同地区/跨地区平均距离比"这个可量化指标检查它是否把同地区城市压扁了:

import numpy as np

rng = np.random.RandomState(69)
N_CITY, N_REGION, N_PERSON, DIM, GAMMA = 12, 4, 30, 20, 1.0
C0, R0, P0 = 0, N_CITY, N_CITY + N_REGION
N_ENT = N_CITY + N_REGION + N_PERSON

city_region = np.repeat(np.arange(N_REGION), N_CITY // N_REGION)
triples = []
for c in range(N_CITY): # 位于:城市 -> 地区(多对一)
triples.append((C0 + c, 0, R0 + int(city_region[c])))
for i in range(N_PERSON): # 出生地 / 居住地:人物 -> 城市
home = rng.randint(0, N_CITY)
triples.append((P0 + i, 1, C0 + home))
same = np.where(city_region == city_region[home])[0]
triples.append((P0 + i, 2, C0 + int(rng.choice(same))))
T = np.array(triples)

def unit(E):
return E / (np.linalg.norm(E, axis=1, keepdims=True) + 1e-9)

def train_transe(steps=1500, lr=0.05, bs=64):
E = unit(rng.randn(N_ENT, DIM)); R = rng.randn(3, DIM) * 0.1
for _ in range(steps):
h, r, t = T[rng.randint(0, len(T), bs)].T
nt = rng.randint(0, N_ENT, bs) # 简化负采样:随机替换尾
vp = E[h] + R[r] E[t]; vn = E[h] + R[r] E[nt]
np_ = np.linalg.norm(vp, axis=1) + 1e-9
nn_ = np.linalg.norm(vn, axis=1) + 1e-9
m = ((GAMMA + np_ nn_) > 0).astype(float) # 铰链:只更新越界的样本
gp = (m / np_)[:, None] * vp
gn = (m / nn_)[:, None] * vn
gE = np.zeros_like(E); gR = np.zeros_like(R)
np.add.at(gE, h, gp); np.add.at(gE, t, gp); np.add.at(gR, r, gp)
np.add.at(gE, h, gn); np.add.at(gE, nt, gn); np.add.at(gR, r, gn)
E = unit(E lr * gE); R -= lr * gR
return E, R

def train_transr(steps=1500, lr=0.05, bs=64):
E = unit(rng.randn(N_ENT, DIM)); R = rng.randn(3, DIM) * 0.1
M = np.array([np.eye(DIM) + 0.01 * rng.randn(DIM, DIM) for _ in range(3)]) # 单位阵+小扰动
for _ in range(steps):
h, r, t = T[rng.randint(0, len(T), bs)].T
nt = rng.randint(0, N_ENT, bs)
Mr = M[r]
ph = np.einsum("nij,nj->ni", Mr, E[h]) # 投影到关系空间
vp = ph + R[r] np.einsum("nij,nj->ni", Mr, E[t])
vn = ph + R[r] np.einsum("nij,nj->ni", Mr, E[nt])
np_ = np.linalg.norm(vp, axis=1) + 1e-9
nn_ = np.linalg.norm(vn, axis=1) + 1e-9
m = ((GAMMA + np_ nn_) > 0).astype(float)
gp = (m / np_)[:, None] * vp
gn = (m / nn_)[:, None] * vn
gE = np.zeros_like(E); gR = np.zeros_like(R); gM = np.zeros_like(M)
np.add.at(gE, h, np.einsum("nij,ni->nj", Mr, gp))
np.add.at(gE, t, np.einsum("nij,ni->nj", Mr, gp))
np.add.at(gR, r, gp)
np.add.at(gM, r, gp[:, :, None] * E[h][:, None, :] gp[:, :, None] * E[t][:, None, :])
np.add.at(gE, h, np.einsum("nij,ni->nj", Mr, gn))
np.add.at(gE, nt, np.einsum("nij,ni->nj", Mr, gn))
np.add.at(gR, r, gn)
np.add.at(gM, r, gn[:, :, None] * E[h][:, None, :] gn[:, :, None] * E[nt][:, None, :])
E = unit(E lr * gE); R -= lr * gR; M -= lr * gM
return E, R, M

def region_ratio(E):
C = E[C0:C0 + N_CITY]
D = np.linalg.norm(C[:, None, :] C[None, :, :], axis=2)
same = city_region[:, None] == city_region[None, :]
iu = np.triu_indices(N_CITY, k=1)
intra = D[iu][same[iu]].mean(); inter = D[iu][~same[iu]].mean()
return intra, inter, intra / inter

E1, _ = train_transe()
a1, b1, q1 = region_ratio(E1)
print("TransE 同地区/跨地区平均距离 = %.3f / %.3f,比值 %.2f" % (a1, b1, q1))

E2, _, _ = train_transr()
a2, b2, q2 = region_ratio(E2)
print("TransR 同地区/跨地区平均距离 = %.3f / %.3f,比值 %.2f" % (a2, b2, q2))

运行结果说明:TransE 训练后,同地区城市之间的平均距离只有跨地区距离的约 0.27 倍——这就是"多对一压缩"的量化证据:本该被拉开的两座同地区城市,被模型挤到了一起。而 TransR 引入投影矩阵 Mr\\mathbf M_rMr 后,先在关系空间里做一次坐标变换再算距离,这个比值被撑开到了约 0.84,同地区城市的相对结构明显更舒展,针对"位于"这个多对一关系做头预测时,平均排名与 MRR 都能改善。当然,投影矩阵参数更多,在小图谱上容易欠拟合,整体 Hits@k 未必更好,要结合数据量一起看。

四、关键经验/避坑

  • 实体向量必须归一化:不归一化,模型会靠整体放大距离来压低损失,学出来的几何全是尺度噪声。
  • 负采样要按类型限定候选池:让"人物"去当"位于"的尾实体,是纯粹的浪费算力。
  • 别只评尾预测:多对一、一对多关系的缺陷会被尾预测掩盖,务必补上头预测(或头尾都评)。
  • 参数多不等于效果好:TransR 的投影矩阵在小图谱上明显欠拟合,参数量要跟数据量一起看。
  • 投影矩阵初始化很关键:从单位阵 + 小扰动出发,模型能平滑地从"平移"过渡到"投影",比纯随机收敛稳得多。
  • 保留可读的中间量:像"同地区/跨地区距离比"这样的诊断指标,比单看 Hits@k 更能解释模型到底学到了什么。
  • 五、完整系列推荐

    📚 本文选自《图神经网络与图深度学习》100 期系统教程(第 069 期:TransE 与 TransR 家族),每期配可运行 Python 代码。

    完整系列(100 期正文 + 3 篇番外,每期文章+代码)已在 ima 知识号【Kruptos】持续更新:

    • 🗂 70+ 技术知识库:图神经网络、强化学习、计算机视觉、推荐系统、大模型微调、操作系统……几乎覆盖全部软硬件技术栈
    • 🧠 8 款 AI 技能:系列生产、知识库管理、CMMI 受管开发、自进化 Agent 等,已在 ima 技能广场上架,即装即用
    • ✅ 全部免费订阅,后续更新自动推送

    🔍 订阅方式:打开 ima(腾讯智能工作台)→ 搜索「Kruptos」→ 一键订阅;或在 ima 内直接搜索《图神经网络与图深度学习》。


    作者:Kruptos(西电毕业,13 年无线通信/DSP/嵌入式科研,现深耕 AI 与云原生)
    原创内容,转载注明出处。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » TransE 一个向量等式,让知识图谱学会推理
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!