关系图卷积⽹络(Relationalgraphconvolutionalnetwork,R 。。。
关系图卷积⽹络(R-GCN )
这⾥,我们将会了解如何实现⼀个关系图卷积⽹络(R-GCN),这种类型的⽹络旨在泛化GCN来处理知识库中实体之间的不同关系。如果想要学习更多R-GCN背后的东西,可以看
简单的图卷积⽹络(GCN)和DGL探索⼀个数据集的结构信息(即,图的连通性)来改善节点表⽰的提取。图的边被保留为⽆类型。知识图由主题,关系,对象形式的三元组集合组成。 因此,边对重要信息进⾏编码,并具有⾃⼰有待学习的嵌⼊。 此外,在任何给定对之间可能存在多个边。
R-GCN 的⼀个简单介绍在统计关系学习(statistical relational learning, SRL)中,有两类基本任务:实体分类——需要指定实体的类型和分类属性
链路预测——需要发现丢失的三元组
上⾯两种情况中,我们都期望可以从图的邻居结构中发现丢失的信息。例如,有⼀篇R-GCN的⽂章提供了下⾯的例⼦。在知道Mikhail Baryshnikov曾经在Vaganova Academy受教育,可以推断出Mikhail Baryshnikov是有标签的,⽽且我们也可以知道三元组(Mikhail Baryshnikov, lived in, Russia)⼀定属于这个知识图。R-GCN通过⼀个常见的图卷积⽹络来解决上⾯两个问题。它使⽤多边编码进⾏扩展来计算
实体的嵌⼊,但具有不同的下游处理。实体分类通过在实体(节点)嵌⼊的最后加⼀个softmax分类器来实现,训练是采⽤标准交叉熵的损失函数。
链路预测通过⼀个⾃编码器结构来重新构建⼀条边,参数化score函数来实现,训练采⽤负采样。
这⾥关注的是第⼀个任务,实体分类,并展⽰了如何去⽣成实体表⽰。
R-GCN 的关键点
回想⼀下GCN中,在每个节点
的隐层表⽰通过下⾯式⼦计算:
其中,为正则化常数。
the blind sideR-GCN和GCN不同的关键之处:在R-GCN中,边可以表⽰不同的关系。GCN中,等式(1)中的是
层中所有的边共享的。相反,R-GCN中,不同类型的边使⽤不同的权重,只有相同关系类型的边才使⽤相同的映射权重。
因此在R-GCN中,
层上实体隐藏层可以⽤下⾯的等式来表⽰:其中表⽰在满⾜关系下,节点的邻居节点集合,是正则化常数。在实体分类中,R-GCN使⽤。(l +1)th i c i W (1)l r W r (1)
(l +1)th N i r r ∈R i c ,r i c ,r =i ∣N ∣i r
直接使⽤上⾯的等式存在问题:参数数⽬增长迅速,尤其对于⾼度多关系的数据⽽⾔。为了减少模型的参数规模和防⽌过拟合,原始的论⽂
中提出使⽤基础分解。
因此,权重是基础转换和系数的线性组合。ba的数⽬远远⼩于知识库的关系数⽬。
DGL 中R-GCN 的实现
⼀个R-GCN模型由多个R-GCN层构成。第⼀个R-GCN层作为输⼊层,输⼊与节点实体相关的特征,并映射到隐层空间(如:描述⽂本)。这⾥,我们只使⽤实体ID作为实体特征。
R-GCN 层对于每个节点,⼀个R-GCN层执⾏下⾯的步骤:使⽤节点表⽰和与边类型(消息函数)相关的权重矩阵计算输出信息。
聚合输⼊的信息并⽣成新的节点表⽰(reduce和apply函数)。
下⾯定义R-GCN隐藏层的代码。
**!**每种关系类型对应于不同的权重,因此,整个权重矩阵维度为3:关系,输⼊特征,输出特征。
import torch
import torch .nn .functional as F
from dgl import DGLGraph
import dgl .function as fn
from functools import partial
class RGCNLayer (nn .Module ):
def __init__(lf , in_feat , out_feat , num_rels , num_bas =-1, bias =None , activation =None , is_input_layer =Fal ):
super (RGCNLayer , lf ).__init__()
lf .in_feat = in_fear
lf .out_feat = out_feat
lf .num_rels = num_rels
lf .num_bas = num_bas
lf .bias =bias
lf .activation = activation毛遂自荐翻译
lf .is_input_layer = is_input_layer
# sanity check(完整性检查)
if lf .num_bas <= 0 or lf .num_bas > lf .num_rels :
lf .num_bas = lf .num_rels
# weight bas in equation (3)
lf .weight = nn .Parameter (torch .Tensor (lf .num_bas , lf .in_feat , lf .out_feat ))
if lf .num_bas < lf .num_rels :novel是什么意思
# linear combination coefficients in equation (3)
lf .w_comp = nn .Parameter (torch .Tensor (lf .num_rels , lf .num_bas ))
# add bias
if lf .bias :
lf .bias = nn .Parameter (torch .Tensor (out_feat ))
# init trainable parameters
nn .init .xavier_uniform_(lf .weight , gain =nn .init .calculate_gain ('relu'))
if lf .num_bas < lf .num_rels :
nn .init .xavier_uniform_(lf .w_comp , gain =nn .init .calculate_gain ('relu'))
if lf .bias :W l )r (V l )b (
despite的用法
a b l )r (B
if lf.bias:
nn.init.xavier_uniform_(lf.bias, gain=nn.init.calculate_gain('relu'))
def forward(lf, g):
if lf.num_bas < lf.num_rels:
# generate all weights from bas (equation (3))
weight = lf.weight.view(lf.in_feat, lf.num_bas, lf.out_feat)
weight = torch.matmul(lf.w_comp, weight).view(lf.num_rels, lf.in_feat, lf.out_feat)
el:
weight = lf.weight
if lf.is_input_layer:
def meaasge_func(edges):
# for input layer, matrix multiply can be converted to be an embedding lookup using source node id embed = weight.view(-1, lf.out_feat)
index = edges.data['rel_type']* lf.in_feat + edges.src['id']
return{'msg': embed[index]* edges.data['norm']}
el:
def message_func(edges):
w = weight[deges.data['rel_type']]
msg = torch.bmm(edges.src['h'].unsqueeze(1), w).squeeze()
msg = msg * edges.data['norm']
return{'msg': msg}
def apply_func(nodes):
h = nodes.data['h']
if lf.bias:
h = h + lf.bias
if lf.activation:fingerprint nsor
h = lf.activation(h)
return{'h': h}
g.update_all(message_func, fn.sum(msg='msg', out='h', apply_func)
完整R-GCN模型定义
class Model(nn.Module):
def__init__(lf, num_nodes, h_dim, out_dim, num_rels, num_bas=-1, num_hidden_layers=1):
super(Model, lf).__init__()
lf.num_nodes = num_nodes
lf.h_dim = h_dim
lf.out_dim = out_dim
lf.num_rels = num_rels
lf.num_bas = num_bas
lf.num_hidden_layers = num_hidden_layers
# create rgcn layers
lf.features = lf.create_features()
def build_model(lf):
lf.layers = nn.ModuleList()
# input to hidden
i2h = lf.build_input_layer()
lf.layers.append(i2h)
# hidden to hidden
for _ in range(lf.num_hidden_layers):
h2h = lf.build_hidden_layer()
速成
lf.layers.append(h2h)
# hidden to output
h2o = lf.build_output_layer()
lf.layers.append(h2o)
# initialize feature for each node
def create_features(lf):
features = torch.arange(lf.num_nodes)
return features
def build_input_layer(lf):
return RGCNLayer(lf.num_nodes, lf.h_dim, lf.num_rels, lf.num_bas, lu, is_input_layer=True)
def build_hidden_layer(lf):
return RGCNLayer(lf.h_dim, lf.h_dim, lf.num_rels, lf.num_bas, lu)
def build_output_layer(lf):
return RGCNLayer(lf.h_dim, lf.out_dim, lf.num_rels, lf.num_bas, activation=partial(F.softmax, dim=1))
def forward(lf, g):
if lf.features is not None:
g.ndata['id']= lf.features
for layer in lf.layers:
layer(g)
return g.ndata.pop('h')
数据集的处理
这⾥使⽤R-GCN论⽂中的应⽤信息学和形式描述⽅法研究所(AIFB)数据集。
# load graph data
ib.data import load_data
import numpy as np
data = load_data(datat='aifb')
num_nodes = data.num_nodes
num_rels = data.num_rels
admire是什么意思
num_class = data.num_class
labels = data.labels
train_idx = ain_idx
# split training and validation t
val_idx = train_idx[:len(train_idx)//5]
train_idx = train_idx[len(train_idx)//5:]
# edge type and normalization factorsuis
edge_type = torch.form_numpy(data.edge_type)
edge_norm = torch.form_numpy(data.edge_norm).unsqueeze(1)
labels = torch.from_numpy(labels).view(-1)
Out:
Loading datat aifb
Number of nodes:8285
Number of edges:66371
missyou是什么意思
Number of relations:91
Number of class:4
removing nodes that are more than3hops away
marry chrismas
创建图和模型
# configurations
n_hidden =16# number of hidden units
n_bas =-1# u number of relations as number of bas
n_hidden_layers =0# u 1 input layer, 1 output layer, no hidden layer
n_epochs =25# epochs to train
lr =0.01# learning rate
l2norm =0# L2 norm coefficient
# create graph
g = DGLGraph()
g.add_nodes(num_nodes)
g.add_edges(data.edge_src, data.edge_dst)
g.edata.update({'rel_type': edge_type,'norm': edge_norm})
# create model
model = Model(len(g), n_hidden, num_class, num_rels, num_bas=n_bas, num_hidden_layers=n_hidden_layers)训练