KG-BERT for Knowledge Graph Completion 笔记

Abstract

1、采用预训练的语言模型BERT来补全知识图谱

2、将知识图谱中的三元组视为文本序列,并提出新框架KG-BERT

3、方法:用三元组的实体描述和关系描述作为输入,利用KG-BERT语言模型计算三元组的评分函数

资料查阅:

预训练语言模型 PLMs:预训练模型就意味着先学习人类的语言知识,然后再代入到某个具体任务。

1)基于大规模文本,预训练得出通用的语言表示;2)通过微调的方式,将学习到的知识传递到不同的下游任务

预训练模型的三个关键技术:①Transformer ②自监督学习 ③微调

Introduction

1、KG通常是一个多关系图,KG通常是一个多关系图,包含实体作为节点,关系作为边。

每条边都表示为一个三元组(head entity, relation, tail entity)(简称(h, r, t)),表示两个实体的关系

例如(Steve Jobs, founded, Apple Inc.)

2、知识图谱补全的任务:评估知识图中未出现的三元组的合理性

3、知识图谱补全的常用方法:

”知识图嵌入“它将三元组中的实体和关系表示为实值向量,并用这些向量评估三元组的真实性(Wang et al. 2017)

缺陷:只观察到三元组的结构信息,存在知识图谱的稀疏性问题

BERT的优势:通过掩码语言建模和下一句预测对双向Transformer编码器进行预训练,它可以在预先训练的模型权重中获取丰富的语言知识。

本研究中,提出了一种利用预先训练的语言模型来完成知识图谱的新方法:

将实体、关系和三元组看成文本序列,并将知识图谱的补全问题转化为序列分类问题,然后在这些序列上面微调BERT模型,以预测一个三元组或一个关系的可信度。

1、该文提出了一种新的语言模型用于知识图谱的补全,这是第一个用预先训练过的语言模型来进行三元组的可信性研究。

2、实验结果表明,该方法在三元组分类、关系预测和链路预测等方面取得了较好的效果。

Method

Bert:Bidirectional Encoder Representations from Transformers(一种从Transformers模型得来的双向编码表征模型。)

《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》
在这里插入图片描述

每个序列的首个token总是一个特定的classification token([CLS])。这个token对应的最后的隐藏状态被用作分类任务的聚合序列表征。SEP是分隔符,用于区分句子,如Question/Answer

Pre-training:

1、Task 1:Masked LM:为了训练一个深度双向表征,作者简单的随机mask一些百分比的输入tokens,然后预测那些被mask掉的tokens。这一步称为“masked LM”(MLM),文献中它通常被称为完型填空任务(Cloze task)。在实验中,作者为每个序列随机mask掉了15%的WordPiece tokens。

2、Task 2:Next Sentence Prediction (NSP):当为每个预测样例选择一个句子对A和B,50%的时间B是A后面的下一个句子(标记为IsNext), 50%的时间B是语料库中的一个随机句子(标记为NotNext)。图1中,C用来预测下一个句子(NSP)。

Fine-tuning:

在这里插入图片描述

具体的做法是修改了BERT模型的输入使其适用于知识库三元组的形式。

首先是KG-BERT(a),输入为三元组( h , r , t )的形式,当然还有BERT自带的special tokens。例如,对于三元组(SteveJobs,founded,AppleInc),上图中的Head Entity输入可以表示为Steven Paul Jobs was an American business magnate, entrepreneur and investor或者Steve Jobs,而Tail Entity可以表示为Apple Inc. is an American multinational technology company headquartered in Cupertino, California或Apple Inc。也就是说,头尾实体的输入可以是实体描述句子或者实体名本身。

上述的KG-BERT(a)需要输入关系,对于预测关系任务不适用,于是作者又提出一种KG-BERT(b),如下图。

在这里插入图片描述

KG-BERT(b)采用CLS处的隐态输出C后接一个分类矩阵来预测两实体之间的关系:

在这里插入图片描述

其中W为关系的分类矩阵,多分类也将sigmoid换成了softmax.

Experiments

数据集:

在这里插入图片描述

作者微调的BERT参数

fine-tuning: batch size: 32, learning rate: 5e-5, dropout rate:0.1

Epochs:

3 for triple classification,

5 for link (entity) prediction

20 for relation prediction

三元组分类(3),实体预测(5),关系预测(20)

对于关系预测,epoch越多效果越好,三元组分类和实体预测不是这样。

关于深度学习中的三个概念:

(1)iteration:表示1次迭代(也叫training step),每次迭代更新1次网络结构的参数;

(2)batch-size:1次迭代所使用的样本量;

(3)epoch:1个epoch表示过了1遍训练集中的所有样本。

三元组分类任务

不同嵌入方法的三元组分类精确度:

在这里插入图片描述

KG-BERT表现良好的原因:

1)输入序列同时包含实体词序列和关系词序列

2)三元组分类任务与BERT预训练中的下一个句子预测任务非常相似,该任务捕获了大型自由文本中两个句子之间的关系,因此预先训练的BERT权值可以很好地定位到三元组分类任务中不同元素之间的关系

3)标记隐藏向量是上下文嵌入。同一个标记可以在不同的三元组中有不同的隐藏向量,因此可以显式地使用上下文信息。

4)自注意机制可以发现与三元组事实相关的最重要的词

链接(实体)预测任务

预测头部实体(?,r,t)或预测给定的尾部实体(h, r,?)

(?表示缺少的元素)

在这里插入图片描述

关系预测任务

该任务预测两个给定实体之间的关系,即(h,?,t)这个过程类似于链接(实体)预测。

KG-BERT的注意模式

在这里插入图片描述

输入序列使用实体描述“一张价值20美元的美钞”和“一张纸币”以及关系名称“hypernym”。一些重要的词,如“纸”和“钱”,与标签标记[CLS]相关的注意力得分更高,而一些不太相关的词,如“联合”和“国家”,获得的关注较少。

存在的不足

BERT模型的一个主要局限性是代价昂贵,使得链路(实体)预测评估非常耗时,链路(实体)预测评估需要用几乎所有的实体替换头或尾实体。

总结

本文提出了一种新的知识图补全方法,称为知识图BERT (KG-BERT)。我们将实体和关系表示为名称/描述文本序列,并将知识图补全问题转化为序列分类问题。KG-BERT可以利用丰富的语言信息在大量的自由文本和突出最重要的单词连接到一个三元组。

总结

本文提出了一种新的知识图补全方法,称为知识图BERT (KG-BERT)。我们将实体和关系表示为名称/描述文本序列,并将知识图补全问题转化为序列分类问题。KG-BERT可以利用丰富的语言信息在大量的自由文本和突出最重要的单词连接到一个三元组。

Molecular-graph-BERT 是一种基于图神经网络的化学分子表示方法,可用于分子性质预测、分子设计等应用。以下是 Molecular-graph-BERT 的代码实现。 1. 安装依赖 ```python !pip install torch !pip install dgl !pip install rdkit ``` 2. 数据预处理 ```python import dgl from rdkit import Chem from dgl.data.utils import load_graphs, save_graphs from dgl.data.chem.utils import smiles_to_bigraph, CanonicalAtomFeaturizer # 将 SMILES 序列转换为 DGLGraph def graph_from_smiles(smiles): mol = Chem.MolFromSmiles(smiles) return smiles_to_bigraph(smiles, atom_featurizer=CanonicalAtomFeaturizer()) # 读取数据,并将 SMILES 序列转换为 DGLGraph data = [] with open('data.txt', 'r') as f: for line in f: smiles, label = line.strip().split('\t') g = graph_from_smiles(smiles) label = int(label) data.append((g, label)) # 将 DGLGraph 序列化并保存为二进制文件 save_graphs('data.bin', data) ``` 3. 定义模型 ```python import torch import torch.nn as nn import dgl.function as fn # 定义 GraphConvLayer class GraphConvLayer(nn.Module): def __init__(self, in_feats, out_feats): super(GraphConvLayer, self).__init__() self.linear = nn.Linear(in_feats, out_feats) self.activation = nn.ReLU() def forward(self, g, features): with g.local_scope(): g.ndata['h'] = features g.update_all(fn.copy_u('h', 'm'), fn.sum('m', 'neigh')) h_neigh = g.ndata['neigh'] h = self.linear(features + h_neigh) h = self.activation(h) return h # 定义 MolecularGraphBERT 模型 class MolecularGraphBERT(nn.Module): def __init__(self, hidden_size, num_layers): super(MolecularGraphBERT, self).__init__() self.embed = nn.Embedding(100, hidden_size) self.layers = nn.ModuleList([GraphConvLayer(hidden_size, hidden_size) for _ in range(num_layers)]) self.pool = dgl.nn.pytorch.glob.max_pool def forward(self, g): h = self.embed(g.ndata['feat']) for layer in self.layers: h = layer(g, h) g.ndata['h'] = h hg = self.pool(g, g.ndata['h']) return hg ``` 4. 训练模型 ```python from torch.utils.data import DataLoader from dgl.data.utils import load_graphs # 加载数据 data, _ = load_graphs('data.bin') labels = torch.tensor([d[1] for d in data]) # 划分训练集和测试集 train_data, test_data = data[:80], data[80:] train_labels, test_labels = labels[:80], labels[80:] # 定义训练参数 lr = 0.01 num_epochs = 50 hidden_size = 128 num_layers = 3 # 定义模型和优化器 model = MolecularGraphBERT(hidden_size, num_layers) optimizer = torch.optim.Adam(model.parameters(), lr=lr) # 训练模型 for epoch in range(num_epochs): model.train() for i, (g, label) in enumerate(train_data): pred = model(g) loss = nn.functional.binary_cross_entropy_with_logits(pred, label.unsqueeze(0).float()) optimizer.zero_grad() loss.backward() optimizer.step() model.eval() with torch.no_grad(): train_acc = 0 for g, label in train_data: pred = model(g) train_acc += ((pred > 0).long() == label).sum().item() train_acc /= len(train_data) test_acc = 0 for g, label in test_data: pred = model(g) test_acc += ((pred > 0).long() == label).sum().item() test_acc /= len(test_data) print('Epoch {:d} | Train Acc {:.4f} | Test Acc {:.4f}'.format(epoch, train_acc, test_acc)) ``` 以上就是 Molecular-graph-BERT 的代码实现。需要注意的是,由于 Molecular-graph-BERT 是基于图神经网络的方法,需要使用 DGL 库来构建和操作图数据,因此需要先安装 DGL 库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chaser_Hc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>