RGCN:record:

RGCN:record:_第1张图片

  • 这里的每一个实体的嵌入 X i X_i Xi更新公式是把每一个关系 r r r下的所有邻居节点的嵌入 X j X_j Xj乘以该关系矩阵 Θ r \Theta_r Θr的正则化拿出来全部求和,然后与该实体本身的嵌入 X i X_i Xi相加:
  • 文章公式:
    变换公式:
    RGCN:record:_第2张图片
  • 基分解:
    RGCN:record:_第3张图片
class RGCNConv(MessagePassing):

        in_channels (int): Size of each input sample.
        out_channels (int): Size of each output sample.
        num_relations (int): Number of relations.
        num_bases (int): Number of bases used for basis-decomposition.
        bias (bool, optional): If set to :obj:`False`, the layer will not learn an additive bias. (default: :obj:`True`)


    def __init__(self,
                 in_channels,
                 out_channels,
                 num_relations,
                 num_bases,
                 bias=True):
        super(RGCNConv, self).__init__('add')

        self.in_channels = in_channels
        self.out_channels = out_channels
        self.num_relations = num_relations
        self.num_bases = num_bases
	# 基分解:多这个矩阵来过渡关系数目少的数据集,防止过拟合
        self.basis = Param(torch.Tensor(num_bases, in_channels, out_channels))
        self.att = Param(torch.Tensor(num_relations, num_bases))
        self.root = Param(torch.Tensor(in_channels, out_channels))

        if bias:
            self.bias = Param(torch.Tensor(out_channels))
        else:
            self.register_parameter('bias', None)

        self.reset_parameters()

    def reset_parameters(self):
        size = self.num_bases * self.in_channels
        uniform(size, self.basis)
        uniform(size, self.att)
        uniform(size, self.root)
        uniform(size, self.bias)

    def forward(self, x, edge_index, edge_type, edge_norm=None):
        """"""
        return self.propagate(
            edge_index, x=x, edge_type=edge_type, edge_norm=edge_norm)

    def message(self, x_j, edge_index_j, edge_type, edge_norm):
    # 基分解得到大小为【关系类别数目,输入,输出】的权值矩阵,对应公式(2)中的W
        w = torch.matmul(self.att, self.basis.view(self.num_bases, -1))

        # If no node features are given, we implement a simple embedding
        # loopkup based on the target node index and its edge type.
        if x_j is None:
            w = w.view(-1, self.out_channels)
            # 第一层的时候没有每一个实体的特征,则用出边的向量表示。
            # edge_type是【0~边大小】列表,数据集有多少边, edge_type就是多少,乘上输入大小,表示对应边类型的矩阵位置,
            # 加上出边的索引edge_index_j,表示取出这个实体的出边向量位置。
            index = edge_type * self.in_channels + edge_index_j
            #取出这个实体的出边向量位置
            out = torch.index_select(w, 0, index)
        else:
        # 第二层及以后,
            w = w.view(self.num_relations, self.in_channels, self.out_channels)
            # 取出对应边的矩阵
            w = torch.index_select(w, 0, edge_type)
            # batch 矩阵相乘,【边的数目,1,hiddensize】* 【边的数目,hiddensize,out】--->>>> 【边的数目,out】
            out = torch.bmm(x_j.unsqueeze(1), w).squeeze(-2)

        return out if edge_norm is None else out * edge_norm.view(-1, 1)

    def update(self, aggr_out, x):
    # aggr_out 就是message 的输出
        if x is None:
        # 第一层:加上自己的嵌入
            out = aggr_out + self.root
        else:
        # 加上特征变换之后加上自己的out
            out = aggr_out + torch.matmul(x, self.root)

        if self.bias is not None:
            out = out + self.bias
        return out

你可能感兴趣的:(神经网络)