GCN代码阅读


load_data方法,该工程数据源有3套,每套有8个数据文件,以文件后缀作为标识,以默认的croa数据集为例,包含以下数据文件:

    x:numpy的稀疏矩阵格式,size=(140, 1433),代表训练集140个节点的特征向量,用稀疏矩阵的原因是特征向量以onehot形式展开;

  y:numpy array格式,size=(140, 7),代表训练集140个节点的y值,以onehot的形式展开,有7个类别;

  tx:numpy的稀疏矩阵格式,size=(1000, 1433),代表测试集1000个节点的特征向量;

  ty:numpy array格式,size=(1000, 7),代表测试集1000个节点的y值;

  features: lil_matrix稀疏格式,size=(2708, 1433), 代表全部节点的特征向量;

  graph:图关系,字典格式,key为节点,value为邻居列表;

  y_train: 保留0-140,其余部份设置为0;

  y_val: 保留141-639,其余部份设置为0;

  y_test: 保留1708-2707,其余部份设置为0;

def sparse_to_tuple方法,mx.row, mx.col表示非0元素在稀疏矩阵中的坐标,非0元素通过以下三个变量进行描述:coords,values和shape,sparse_mx(coords, values, shape)为tuple。

直接定位到sparse_mx = to_tuple(sparse_mx)这一行再看to_tuple,实际上是将原来的feature从csr_matrix转化为coo_matrix,并且输出特征向量coords, values, shape(有值位置的坐标,值,特征向量的shape)三要素作为元组。这里有两个矩阵,分别是近接矩阵节点特性向量矩阵,由于这两个都是1,0稀疏格式因此采用scipy的稀疏矩阵格式,其中邻接矩阵采用csr_matrix方便计算对称归一化,而特征矩阵采用的是先lil_matrix方便做行切片,最后转化为coo_matrix,原因是特征矩阵需要使用占位符placeholder传入模型内部,而邻接矩阵是全局共享不变的不需要占位符,而稀疏站位符tf.sparse_placeholder的格式是(行列索引,值,shape)和coo_matrix对应,因此代码中最后转化为coo_matrix。

scipy.sparse的多种稀疏矩阵的区别:csr_matrixlil_matrixcoo_matri

csr_matrix:压缩稀疏行矩阵,该种格式常用于稀疏矩阵的运算,以及高效的行切片操作。

lil_matrix:基于行连接存储的稀疏矩阵,该种格式用于高效地添加、删除、查找元素,同时高效的行切片操作。

coo_matrix:坐标格式的矩阵,不同稀疏格式间转换效率高,coo_matrix不支持元素的存取和增删,一旦创建之后,除了将之转换成其它格式的矩阵,几乎无法对其做任何操作和矩阵运算。

def preprocess_features(features)对节点的特征向量做行L1归一化,每一行的和是1,具体实现是创建了一个每一行和的倒数的对角矩阵乘以特征向量,sparse_to_tuple(features)最终数据类型与sparse_mx相同。

利用Chebyshev多项式拟合卷积核是GCN论文中广泛应用的方法,切比雪夫多项式数学解释参考:https://zhuanlan.zhihu.com/p/106687580

def chebyshev_polynomials(adj, k):
"""Calculate Chebyshev polynomials up to order k. Return a list of sparse matrices (tuple representation)."""
    print("Calculating Chebyshev polynomials up to order {}...".format(k))

  adj_normalized = normalize_adj(adj)

  laplacian = sp.eye(adj.shape[0]) - adj_normalized

  largest_eigval, _ = eigsh(laplacian, 1, which = 'LM')

  scaled_laplacian = (2. / largest_eigval[0]) * laplacian - sp.eye(adj.shape[0])

  t_k = list()
  t_k.append(sp.eye(adj.shape[0]))
  t_k.append(scaled_laplacian)

  def chebyshev_recurrence(t_k_minus_one, t_k_minus_two, scaled_lap):

      s_lap = sp.csr_matrix(scaled_lap, copy = True)

    return 2 * s_lap.dot(t_k_minus_one) - t_k_minus_two

    for i in range(2, k+1):

        t_k.append(chebyshev_recurrence(t_k[-1], t_k[-2], scaled_laplacian))

    return sparse_to_tuple(t_k)

t_k为list类型,size为4。t_k[0]为单位矩阵I,t_k[1]为经过变换的拉普拉斯矩阵,t_k[2]与t_k[3]分别为卷积核。

转自:https://www.jianshu.com/p/bb38e9ca6347

GCN