园春编程

from future import division from future import print_function

导入包

import argparse import numpy as np import scipy.sparse as sp import torch import torch.nn.functional as F

定义命令行参数

parser = argparse.ArgumentParser() parser.add_argument('--seed', type=int, default=42, help='Random seed.') parser.add_argument('--dataset', type=str, default='cora', help='type of dataset.') #parser.add_argument('--hops', type=int, default=20, help='number of hops') hops =20 r_list = [0, 0.1, 0.2, 0.3, 0.4, 0.5] args = parser.parse_args()

将稀疏矩阵转换成稀疏张量

def sparse_mx_to_torch_sparse_tensor(sparse_mx):

sparse_mx = sparse_mx.tocoo().astype(np.float32) # 将稀疏矩阵转换为coo格式,并转换为float32类型
indices = torch.from_numpy(
    np.vstack((sparse_mx.row, sparse_mx.col)).astype(np.int64)) # 将行索引和列索引合并,并转换为int64类型
values = torch.from_numpy(sparse_mx.data) # 将矩阵中的元素转换为张量类型
shape = torch.Size(sparse_mx.shape) # 获取矩阵的形状
return torch.sparse.FloatTensor(indices, values, shape) # 返回稀疏张量

对邻接矩阵进行归一化

def normalize_adj(mx, r): """Row-normalize sparse matrix""" mx = sp.coo_matrix(mx) + sp.eye(mx.shape[0])# 将邻接矩阵转换为coo格式,然后加上对角线元素 rowsum = np.array(mx.sum(1))# 按行求和 r_inv_sqrt_left = np.power(rowsum, r-1).flatten()# 求行向量的r-1次方,并将结果展平 r_inv_sqrt_left[np.isinf(r_inv_sqrt_left)] = 0.# 如果结果中有inf则赋值为0 r_mat_inv_sqrt_left = sp.diags(r_inv_sqrt_left)

r_inv_sqrt_right = np.power(rowsum, -r).flatten()# 求行向量的-r次方,并将结果展平
r_inv_sqrt_right[np.isinf(r_inv_sqrt_right)] = 0.# 如果结果中有inf则赋值为0
r_mat_inv_sqrt_right = sp.diags(r_inv_sqrt_right)
adj_normalized = mx.dot(r_mat_inv_sqrt_left).transpose().dot(r_mat_inv_sqrt_right).tocoo()# 计算D^ r_t-1 A^ ~  D^ -r_t,DAD
return sparse_mx_to_torch_sparse_tensor(adj_normalized) # 返回归一化后的稀疏张量

主函数

def run(args):

adj = torch.tensor([
    [1., 1., 0., 0., 0., 0., 0., 1., 0., 0.],
    [1., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
    [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
    [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
    [0., 0., 0., 1., 1., 0., 0., 0., 0., 0.],
    [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
    [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
    [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
    [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
    [0., 0., 0., 0., 0., 1., 0., 0., 0., 1.],
])
features=torch.tensor([
    [1., 1.2, 0., 0., 0., 0., 0., 1., 0.2, 0.],
    [1., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
    [0., 0., 1., 0., 0.5, 0., 0., 0., 0., 0.],
    [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
    [0., 0., 0., 1., 1., 0., 0., 0., 0., 0.],
    [0., 0., 2., 0., 0., 1., 0., 0., 0., 0.],
    [0., 0., 1., 0., 0., 0., 1., 0., 0., 0.],
    [0., 0., 0., 0.4, 0., 0., 0., 1., 0., 0.],
    [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
    [0., 0., 0., 0., 0., 1., 0., 0., 0., 1.],
])
n_nodes, feat_dim = features.shape

# 迭代hop次
for hop in range(hops, hops+1): # hop为迭代次数n
    # 设置
    input_features = 0.
    for r in r_list:
        adj_norm = normalize_adj(adj, r) # 对邻接矩阵进行归一化
        features_list = []
        features_list.append(features) # 将特征矩阵加入列表
        features_list.append(torch.spmm(adj_norm, features_list[-1]))  # 计算邻接矩阵与特征矩阵的乘积
        # 计算权重
        weight_list = []
        norm_fea = torch.norm(features, 2, 1).add(1e-10)  # 计算特征矩阵的L2范数
        for fea in features_list:
            norm_cur = torch.norm(fea, 2, 1).add(1e-10) # 计算当前特征矩阵的L2范数
            temp = torch.div((features*fea).sum(1), norm_fea) # 计算特征矩阵与当前特征矩阵的点积,并除以两个矩阵的L2范数
            temp = torch.div(temp, norm_cur) # 再除以当前特征矩阵的L2范数
            weight_list.append(temp.unsqueeze(-1)) # 将权重加入列表
        weight = F.softmax(torch.cat(weight_list, dim=1), dim=1) # 对权重进行softmax归一化

        input_feas = []
       
        for i in range(n_nodes):
            fea = 0.
            for j in range(hop+1):
                fea += (weight[i][j]*features_list[j][i]).unsqueeze(0) # 计算每个节点的输入特征向量
            input_feas.append(fea)
        input_feas = torch.cat(input_feas, dim=0) # 将所有节点的输入特征向量拼接起来

        if r == r_list[0]:
            input_features = input_feas
        else:
         
            temp = []
            temp.append(input_features.unsqueeze(0))
            temp.append(input_feas.unsqueeze(0))

            input_features = torch.cat(temp, dim=0).max(0)[0] # 将不同r值下的输入特征向量进行max池化

    sim = torch.sigmoid(torch.mm(input_features, input_features.T)) # 计算相似度矩阵

if name == 'main': run(args)

这段代码实现了基于邻接矩阵和特征矩阵的图卷积神经网络(GCN)模型,并计算了输入节点的相似度矩阵。具体实现步骤如下:

  1. 对邻接矩阵进行归一化,得到归一化后的稀疏张量。

  2. 迭代hop次,每次迭代分别计算不同r值下的输入特征向量,并对不同r值下的输入特征向量进行max池化,得到最终的输入特征向量。

  3. 计算输入特征向量之间的相似度矩阵


原文地址: https://www.cveoy.top/t/topic/cj2m 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录