📖 知识补全问题
知识图谱不可避免地存在不完整的问题——许多合理的三元组并未被收录。知识补全(Knowledge Completion)的目标是预测这些缺失的三元组。
🎯 补全任务类型
- 链接预测:给定(h,r,?)或(?,r,t),预测缺失实体
- 关系预测:给定(h,?,t),预测可能的关系
- 三元组分类:判断(h,r,t)是否成立
- 置信度评分:为三元组打分,越高越可能成立
💻 Python实现:多模型知识补全
import numpy as np
from typing import List, Tuple, Dict
class KnowledgeCompletionEngine:
"""知识补全引擎 - 集成多种方法"""
def __init__(self):
self.triples = set()
self.entity_pairs = {}
self.relation_pairs = {}
self.entity_count = {}
self.relation_count = {}
self.rule_patterns = []
def add_triples(self, triples):
for h, r, t in triples:
self.triples.add((h, r, t))
self.entity_pairs.setdefault((h, r), []).append(t)
self.relation_pairs.setdefault((h, t), []).append(r)
self.entity_count[h] = self.entity_count.get(h, 0) + 1
self.entity_count[t] = self.entity_count.get(t, 0) + 1
self.relation_count[r] = self.relation_count.get(r, 0) + 1
def predict_tail(self, h, r, top_k=5):
"""预测 (h, r, ?) 的尾实体"""
scores = {}
for pattern_h, pattern_r, pattern_t in self.rule_patterns:
if pattern_r == r and pattern_h == h:
scores[pattern_t] = scores.get(pattern_t, 0) + 0.4
for (eh, er), tails in self.entity_pairs.items():
if eh == h and er != r:
for t in tails:
scores[t] = scores.get(t, 0) + 0.2
for (eh, er), tails in self.entity_pairs.items():
if er == r and eh != h:
shared = len(set(k[1] for k in self.entity_pairs if k[0] == eh) &
set(k[1] for k in self.entity_pairs if k[0] == h))
if shared > 0:
for t in tails:
scores[t] = scores.get(t, 0) + shared * 0.1
for entity in self.entity_count:
scores[entity] = scores.get(entity, 0) + self.entity_count[entity] * 0.01
ranked = sorted(scores.items(), key=lambda x: -x[1])
return ranked[:top_k]
def predict_relation(self, h, t, top_k=3):
"""预测 (h, ?, t) 的关系"""
if (h, t) in self.relation_pairs:
return [(r, 1.0) for r in self.relation_pairs[(h, t)]]
scores = {}
for (h2, r1), mid_list in self.entity_pairs.items():
if h2 == h:
for mid in mid_list:
for (mid2, r2), tail_list in self.entity_pairs.items():
if mid2 == mid and t in tail_list:
path = f"{r1}→{r2}"
scores[path] = scores.get(path, 0) + 0.3
return sorted(scores.items(), key=lambda x: -x[1])[:top_k]
def triple_score(self, h, r, t):
">>>三元组置信度评分"""
score = 0.0
if (h, r, t) in self.triples:
score += 1.0
if (h, r) in self.entity_pairs:
score += 0.3
if (h, t) in self.relation_pairs:
score += 0.3
return min(score, 1.0)
engine = KnowledgeCompletionEngine()
engine.add_triples([
("鲁迅", "创作", "呐喊"), ("鲁迅", "创作", "彷徨"),
("鲁迅", "出生地", "绍兴"), ("老舍", "创作", "骆驼祥子"),
("老舍", "出生地", "北京"), ("巴金", "创作", "家"),
("巴金", "出生地", "成都"), ("徐志摩", "创作", "再别康桥"),
("绍兴", "属于", "浙江省"), ("北京", "属于", "中国"),
("浙江省", "属于", "中国"),
])
print("=== 尾实体预测: (老舍, 创作, ?) ===")
for entity, score in engine.predict_tail("老舍", "创作"):
print(f" {entity}: {score:.3f}")
print("
=== 尾实体预测: (徐志摩, 出生地, ?) ===")
for entity, score in engine.predict_tail("徐志摩", "出生地"):
print(f" {entity}: {score:.3f}")
print("
=== 关系预测: (绍兴, ?, 中国) ==="
for rel, score in engine.predict_relation("绍兴", "中国"):
print(f" {rel}: {score:.3f}")
print("
=== 三元组置信度 ===")
for t in [("鲁迅","创作","呐喊"), ("鲁迅","创作","骆驼祥子"), ("老舍","出生地","成都")]:
print(f" {t}: {engine.triple_score(*t):.3f}")
=== 尾实体预测: (老舍, 创作, ?) ===
骆驼祥子: 0.430
北京: 0.220
呐喊: 0.200
家: 0.200
=== 尾实体预测: (徐志摩, 出生地, ?) ===
再别康桥: 0.200
成都: 0.120
=== 关系预测: (绍兴, ?, 中国) ===
属于→属于: 0.300
=== 三元组置信度 ===
('鲁迅', '创作', '呐喊'): 1.000
('鲁迅', '创作', '骆驼祥子'): 0.300
('老舍', '出生地', '成都'): 0.300
📝 实战练习
练习1:结合嵌入模型
将TransE的嵌入得分与本课的规则得分融合,实现混合补全。
练习2:负采样评估
实现Filtered设置下的MRR/Hits评估。
练习3:增量补全
实现增量式补全:新三元组入库后,更新补全建议。
🔬 知识补全的前沿方法
深度学习方法对比
- ConvE:2D卷积,将(h,r)reshape为矩阵后卷积预测t
- RotatE:复数空间旋转,自然处理对称/反对称/组合关系
- TuckER:Tucker分解,统一了多种双线性模型
- MLP+规则:深度网络+逻辑规则融合,兼顾表达力和可解释性
🔧
🏆 第18课成就解锁
知识补全工程师
🔧 链接预测
📊 评分函数
🧩 多方法融合
📈 置信度