信息是指外部客观存在的内容,知识是对外部客观规律的归纳和总结。知识图谱于2012年5月17日被Google正式提出,初衷是为了提高搜索引擎的能力,增强用户的搜索质量以及搜索体验。
知识图谱的定义
知识图谱是一种解释实体之间关系的语义网络,可以实现对现实世界的事物以及相互关系进行形式化地描述。现在的知识图谱已被用来泛指各种大规模的知识库。
知识图谱中存的是什么
三元组是知识图谱的一种通用表示方式,具有三种基本形态:
- 实体-关系-实体
- 实体-属性-属性值
- 实体-标签-标签值
知识图谱的构建
如何决定哪些是实体,哪些是属性,哪些是关系?取决于图谱的使用方式和想要完成的任务。
关系查找:xx的老婆的父亲是谁?
属性对比:xx的身高比xx高多少?
数据类型和存储方式
结构化数据(Structed Data): 如关系数据库
半结构化数据(Semi-Structed Data): 如XML、JSON、百科
非结构化数据(UNStructed Data): 如图片、音频、视频、文本
知识图谱的架构
逻辑架构
知识图谱在逻辑上分为模式层和数据层两个层次。
模式层构建在数据层之上,是知识图谱的核心,通常采用本体库来管理知识图谱的模式层。本体是结构化知识库的概念模板,通过本体库而形成的知识库不仅层次结构较强,并且冗余程度较小。
模式层:实体-关系-实体、实体-属性-属性值
数据层主要是由一系列的事实组成,而知识将以事实为单位进行存储。如果用(实体1,关系,实体2)、(实体、属性,属性值)这样的三元组来表达事实,可选择图数据库作为存储介质,例如开源的Neo4j、Twitter的FlockDB、sones的GraphDB等。
数据层:比尔盖茨-妻子-梅琳达·盖茨,比尔盖茨-总裁-微软
技术架构
知识图谱的构建
关键技术
知识抽取:非结构化->结构化
知识融合:消歧提升数据质量
知识推理:挖掘扩充或补全数据
知识表达:为应用做准备
知识抽取
面向非结构化数据,通过自动化的技术抽取出可用的知识单元
- 实体抽取
- 关系抽取
- 属性抽取
实体抽取
实体是知识图谱中的最基本的元素,其抽取的完整性、准确性、召回率等将直接影响到知识库的质量,命名实体识别通常采用:1.基于规则和词典的方法;2.基于机器学习的模型预测方法(序列标注问题)
关系抽取
判断实体之间关联关系
- 限定领域关系抽取
从预设好的数个关系中判断,给定的实体对是否满足某一个关系:
F(实体1,实体2,文本)——>关系
属于有监督分类任务
pipeline vs 联合训练
pipeline
先用一个模型抽取出实体,再用一个模型根据实体抽取出属性。
B-Bert用[CLS]token作为整个句子信息的输出,用实体的输出的加权和作为实体信息的向量,然后将它们拼接在一起。
联合训练
在一个模型中抽取实体和属性,一般模型中具有两个loss。
# -*- coding: utf-8 -*-
import torch
import torch.nn as nn
from torch.optim import Adam, SGD
#from torchcrf import CRF
#from transformers import T5Model
"""
建立网络模型结构
"""
class TorchModel(nn.Module):
def __init__(self, config):
super(TorchModel, self).__init__()
hidden_size = config["hidden_size"]
vocab_size = config["vocab_size"] + 1
self.embedding = nn.Embedding(vocab_size, hidden_size, padding_idx=0)
self.layer = nn.LSTM(hidden_size, hidden_size, batch_first=True, bidirectional=True, num_layers=1)# 此为双向LSTM
self.bio_classifier = nn.Linear(hidden_size * 2, config["bio_count"]) # 因为前面经过了双向LSTM,所以输入维度为hidden_size*2,此层用来找出实体
self.attribute_classifier = nn.Linear(hidden_size * 2, config["attribute_count"]) # 此层用来找出属性
self.attribute_loss_ratio = config["attribute_loss_ratio"]
self.loss = torch.nn.CrossEntropyLoss(ignore_index=-100) #loss采用交叉熵损失
#当输入真实标签,返回loss值;无真实标签,返回预测值
def forward(self, x, attribute_target=None, bio_target=None):
x = self.embedding(x)
x, _ = self.layer(x)
#序列标注
bio_predict = self.bio_classifier(x)
#文本分类
self.pooling_layer = nn.AvgPool1d(x.shape[1]) #inpt:(batch, sen_len, hidden_size) -> (batch, hidden_size)
x = self.pooling_layer(x.transpose(1, 2)).squeeze()
attribute_predict = self.attribute_classifier(x)
#multi-task训练
if bio_target is not None:
bio_loss = self.loss(bio_predict.view(-1, bio_predict.shape[-1]), bio_target.view(-1))
attribute_loss = self.loss(attribute_predict.view(x.shape[0], -1), attribute_target.view(-1))
return bio_loss + attribute_loss * self.attribute_loss_ratio # 计算复合loss,这是联合训练的关键
else:
return attribute_predict, bio_predict
def choose_optimizer(config, model):
optimizer = config["optimizer"]
learning_rate = config["learning_rate"]
if optimizer == "adam":
return Adam(model.parameters(), lr=learning_rate)
elif optimizer == "sgd":
return SGD(model.parameters(), lr=learning_rate)
if __name__ == "__main__":
from config import Config
model = TorchModel(Config)
- 开方领域关系抽取
- 基于依存句法分析+规则
比如:主谓宾关系 - 基于序列标注
属性抽取
实体的属性可以看成是实体与属性值之间的一种名称性关系,因此可以将实体属性的抽取问题转换为关系抽取问题。可以借鉴大部分关系抽取的方法。
知识融合
由于知识图谱中的知识来源广泛,存在知识质量良莠不齐、来自不同数据库的知识重复、知识间的关联不够明确等问题,所以必须要进行知识融合。具体方法包括:
- 实体对齐
- 实体消歧
- 属性对齐
实体对齐
将不同来源的知识认定为真实世界的同一。
可以依据不同实体所包含的属性之间的相似度来判断实体是否为同一实体:
实体消歧
将同一名称但指代不同事物的实体区分开:
属性对齐
不同数据源对于实体属性的记录可能使用不同的语言:
- 百度:姚明-生日-1980年9月12日
- 搜狗:姚明-出生日期-1980年9月12日
- 维基:姚明-出生年月-1980年9月12日
使用属性和属性值做相似度计算
知识推理
在已知的知识库基础上进一步挖掘隐含的知识,从而丰富、扩展知识库。
传递性:A-儿子-B,B-儿子-C,A-?-C
实例性:A-是-B,B属于C,A-?-C
基于模型的知识补全
给出两个实体,推断其关系:
h+r->t,h+t->r,(h,r,t)->{0,1}
相关论文:KG-Bert
KG-Bert
将三元组放入Bert模型中,让模型给三元组打分。
知识表示
将知识图谱中的实体,关系,属性等转化为向量,利用向量间的计算关系,反映实体间的关联性。
TransE:对于三元组(h,r,t),学习其向量表示\(I_h,I_r,I_t\),使其满足\(I_h+I_r\approx I_t\)
融合文本
融合文本的知识表示,将文本表示和知识图谱中的实体关系表示放入同一个空间,使得学习到的实体表示可以在文本相关的任务中使用。
优势:发掘实体之间的语义相关性,精确的语义表述能够提升三元组的可区分性。当一些实体对于现有的知识图谱来说是新的,并且仅仅带有描述性信息的时候,传统知识图谱表示学习方法不能够表示这些新实体,但融入了文本描述的模型,能通过描述信息构建实体表示。