让我用一个生动的比喻来解释NTN:
一、核心思想:从"相亲匹配"到"关系深度分析"
想象你是一个婚恋平台的AI:
传统方法(简单匹配):
小明(28岁,程序员) + 小红(26岁,设计师) → 匹配度:72%
-
做法:把两人的特征向量拼接或相加,算一个相似度
-
问题 :只知道"配不配",不知道"为什么配"(是因为年龄相近?还是职业互补?)
NTN方法(深度关系分析):
小明(28岁,程序员) + “同事关系” + 小红(26岁,设计师) → 可能性:15%
小明(28岁,程序员) + “夫妻关系” + 小红(26岁,设计师) → 可能性:85%
小明(28岁,程序员) + “师生关系” + 小红(26岁,设计师) → 可能性:2%
-
做法:对每种关系类型,学习一个专门的"关系分析器"
-
洞见 :能判断特定类型的关系是否存在,并解释关系性质
二、NTN要解决的根本问题
知识图谱补全任务 :
给定:(头实体,关系,尾实体),判断这个三元组是否成立
例如:
-
(姚明,出生于,上海)→ 成立 -
(姚明,执教于,火箭队)→ 不成立(姚明是球员,不是教练) -
(北京,是首都,中国)→ 成立
挑战 :如何建模实体间的复杂非线性关系?
三、NTN的核心创新:张量层
这是NTN最精髓的部分!让我分步解释:
1. 传统方法的局限
平移模型(如TransE):
向量(姚明) ≈ 向量(上海) + 向量(出生于)
问题:只能处理简单关系,对"一对多"等复杂关系失效
简单神经网络:
score = σ(W·[e₁; e₂] + b) # 简单拼接+线性变换
问题:表达能力有限,无法捕捉实体间的复杂交互
2. NTN的"三维打分器"
关键思想 :为每种关系类型r ,学习一个三维张量 Wᵣ
想象一个"关系分析矩阵"
头实体特征向量 e₁ (d维)
↓
关系张量Wᵣ → [三维分析网格] → 打分
↑
尾实体特征向量 e₂ (d维)
数学形式简化理解:
score = uᵣᵀ·tanh( e₁ᵀ·Wᵣ·e₂ + Vᵣ·[e₁; e₂] + bᵣ )
其中:
-
e₁ᵀ·Wᵣ·e₂:双线性张量积(核心!) -
Vᵣ·[e₁; e₂]:线性部分 -
uᵣ:关系特定的权重向量
3. 双线性张量积的直观理解
比喻 :有一个k×d×d的三维张量Wᵣ,其中k是"关系视角"的数量
# 假设d=3(实体特征维度),k=2(两个关系视角)
e₁ = [身高, 体重, 年龄] # 姚明的特征
e₂ = [面积, 人口, GDP] # 上海的特征
W_出生于 = [
[[...], [...], [...]], # 视角1:地理归属分析器
[[...], [...], [...]] # 视角2:时间线分析器
]
# 计算过程:
视角1得分 = e₁·Wᵣ[0]·e₂ᵀ # 分析“人的属性”与“城市属性”在地理上的匹配度
视角2得分 = e₁·Wᵣ[1]·e₂ᵀ # 分析时间线上的合理性
最终得分 = 综合两个视角
核心优势 :e₁和e₂不是简单相加,而是通过Wᵣ进行全方位的交互比较!
四、完整NTN架构详解
# NTN的完整计算流程(伪代码)
def NTN_layer(head_entity, relation, tail_entity):
# 输入:头实体e₁,关系r,尾实体e₂(都是d维向量)
# 1. 双线性张量积(核心!)
# Wᵣ形状:[k, d, d],k是超参数(切片数量)
bilinear = 0
for i in range(k): # 每个关系视角
# e₁ᵀ·Wᵣ[i]·e₂ ← 这是关键!
slice_i = W_r[i] # 第i个d×d矩阵
interaction = head_entity @ slice_i @ tail_entity.T
bilinear.append(interaction)
# 现在bilinear是k维向量
# 2. 线性部分(传统交互)
linear = V_r @ concatenate([head_entity, tail_entity]) + b_r
# 3. 组合并通过激活函数
combined = tanh(bilinear + linear) # k维向量
# 4. 关系特定的最终打分
score = u_r @ combined # 标量分数
return sigmoid(score) # 转化为概率
可视化理解:
头实体e₁ → | |
| Wᵣ | → 交互特征 → 全连接 → 打分
尾实体e₂ → |______| (k维) ↑
uᵣ(关系权重)
五、NTN为什么强大?(技术优势)
1. 极强的表达能力
-
传统方法 :
f(e₁, e₂) = similarity(e₁, e₂)只能建模对称关系 -
NTN :
fᵣ(e₁, e₂) = e₁ᵀ·Wᵣ·e₂可以建模:-
非对称关系(如"父亲"≠"儿子")
-
一对多关系(如"首都"关系:北京对中国,但反过来不成立)
-
复杂模式关系(需要多视角分析)
-
2. 关系特定的深度建模
每种关系有自己的参数{Wᵣ, Vᵣ, uᵣ, bᵣ}:
-
W_夫妻:学习夫妻间的匹配模式(年龄、兴趣等) -
W_上下级:学习职场层级关系 -
W_地理位置:学习空间包含关系
3. 实体交互的细粒度分析
通过k个不同的"关系切片",从多个角度分析实体对:
关系“合作”可能有k=4个视角:
视角1:行业匹配度(IT公司与广告公司合作?)
视角2:规模匹配度(大公司与小公司合作?)
视角3:地理匹配度(跨国合作?)
视角4:历史合作记录
六、应用场景示例
1. 知识图谱补全
已知:(苹果,创始人,乔布斯)
(微软,创始人,比尔盖茨)
预测:(特斯拉,创始人,?) → 输出:埃隆·马斯克
2. 社交网络关系推断
用户A特征:[科技宅, 爱编程, 硅谷]
用户B特征:[投资人, 爱高尔夫, 华尔街]
关系“可能有业务往来”? → 高概率
关系“是亲密朋友”? → 低概率
3. 药物相互作用预测
药物A特征:[化学成分X, 副作用Y]
药物B特征:[化学成分Z, 副作用W]
关系“同时服用危险”? → NTN分析化学交互
4. 推荐系统
用户特征:[喜欢科幻, 20岁, 男性]
商品特征:[《三体》书, 科幻类, 价格中等]
关系“可能购买”? → 高概率
七、NTN的局限性
1. 参数爆炸问题
-
每个关系需要一个
k×d×d的张量 -
如果有1000种关系,d=100,k=10:
-
参数量:
1000×10×100×100 = 1亿参数 -
训练困难,容易过拟合
-
2. 计算复杂度高
-
双线性张量积:
O(k×d²)复杂度 -
相比TransE的
O(d)复杂很多
3. 对简单关系"杀鸡用牛刀"
-
"首都"这种简单关系,用TransE就足够
-
NTN的复杂模型可能浪费计算资源
八、NTN的后续演进
1. 简化版:DistMult
-
将
Wᵣ简化为对角矩阵 -
score = Σᵢ e₁[i]·wᵣ[i]·e₂[i] -
只能处理对称关系,但计算量大减
2. 折衷版:ComplEx
-
引入复数空间
-
能处理非对称关系,复杂度适中
3. 现代替代:图神经网络(GNN)
-
直接在图结构上传播信息
-
更自然地建模多跳关系
-
如RGCN、GAT等
九、代码实现思路
import torch
import torch.nn as nn
class NeuralTensorNetwork(nn.Module):
def __init__(self, num_entities, num_relations, embedding_dim, k=10):
super().__init__()
self.k = k # 张量切片数
# 实体嵌入
self.entity_emb = nn.Embedding(num_entities, embedding_dim)
# 关系参数
self.W = nn.Parameter(torch.randn(num_relations, k, embedding_dim, embedding_dim))
self.V = nn.Parameter(torch.randn(num_relations, k, 2*embedding_dim))
self.b = nn.Parameter(torch.randn(num_relations, k))
self.u = nn.Parameter(torch.randn(num_relations, k))
def forward(self, head_idx, relation_idx, tail_idx):
# 获取嵌入
e1 = self.entity_emb(head_idx) # [batch, d]
e2 = self.entity_emb(tail_idx) # [batch, d]
r = relation_idx # [batch]
# 双线性张量积
# e1ᵀ·Wᵣ·e2
W_r = self.W[r] # [batch, k, d, d]
# 高效计算方式
bilinear = torch.einsum('bi,bkij,bj->bk', e1, W_r, e2)
# 线性部分
e_concat = torch.cat([e1, e2], dim=1) # [batch, 2d]
V_r = self.V[r] # [batch, k, 2d]
linear = torch.einsum('bi,bki->bk', e_concat, V_r) + self.b[r]
# 组合
combined = torch.tanh(bilinear + linear)
# 最终打分
u_r = self.u[r] # [batch, k]
scores = torch.einsum('bk,bk->b', combined, u_r)
return torch.sigmoid(scores)
十、总结:NTN的历史地位
NTN的核心贡献:
-
引入了关系特定的深度交互建模
-
证明了双线性形式对关系推理的有效性
-
启发了后续大量研究工作
现代视角:
-
NTN像是"关系推理领域的CNN"
-
它证明了:不同关系需要不同的交互模式
-
虽然现在有更高效的模型,但NTN的思想仍在影响:
-
推荐系统中的用户-物品交互建模
-
多模态关系学习
-
分子相互作用预测
-
一句话记住NTN:
它不是把实体特征简单相加,而是为每种关系准备了专用的"关系显微镜",从多个角度深度检验两个实体是否真的存在这种关系。
NTN标志着知识表示学习从"浅层相似度"走向"深度关系推理"的重要一步,尽管已被更高效的模型超越,但它的核心思想至今仍在发光发热。