GCN之邻接矩阵标准化
程序员文章站
2022-04-22 11:48:15
推导解释——GCN每一层的输入都是节点特征矩阵H和邻接矩阵A,直接将这两个做内积,再乘以一个参数矩阵W,用激活函数激活,就形成一个简单的神经网络层。import numpy as npimport scipy.sparse as spif FLAGS.model == 'gcn': support = [preprocess_adj(adj)] num_supports = 1 model_func = GCN对邻接矩阵的处理1但是因为邻接矩阵的对角都是0,和特征矩阵内...
GCN每一层的输入都是节点特征矩阵H和邻接矩阵A,直接将这两个做内积,再乘以一个参数矩阵W,用激活函数激活,就形成一个简单的神经网络层。
1. 邻接矩阵标准化
import numpy as np import scipy.sparse as sp if FLAGS.model == 'gcn': support = [preprocess_adj(adj)] num_supports = 1 model_func = GCN
1.1 邻接矩阵+单位矩阵
但是因为邻接矩阵的对角都是0,和特征矩阵内积相当于将邻接矩阵做了加权和,节点特征的值成为了邻接矩阵的权,自身的特征被忽略。为避免这种情况,可以先给A加上一个单位矩阵I,单位矩阵。它是个方阵,从左上角到右下角的对角线(称为主对角线)上的元素均为1。除此以外全都为0。这样,使得邻接矩阵的对角元素变成1。
def preprocess_adj(adj): """Preprocessing of adjacency matrix for simple GCN model and conversion to tuple representation.""" adj_normalized = normalize_adj(adj + sp.eye(adj.shape[0])) # 给A加上一个单位矩阵 return sparse_to_tuple(adj_normalized)
1.2 归一化处理
就算如此,因为邻接矩阵A没有经过归一化处理,这样难以将数据限制在我们需要的范围内。通过归一化处理,可以将数据变得具有可比性,但又相对保持数据之间的关系。使得原来很难在一张纸上做出的图更方便给出图上的相对位置。因此,为了避免邻接矩阵和特征矩阵内积相乘改变特征原本的分布,需要我们对A做一个标准化处理。首先,给A乘以度矩阵,进一步将其拆为两个,得到对称且归一化的矩阵——()*(对称矩阵A) *()。
通过以上处理后,即使不训练,完全用随机初始化的参数W,GCN提取出来的特征就十分优秀了。
def normalize_adj(adj): """Symmetrically normalize adjacency matrix.""" adj = sp.coo_matrix(adj) # 采用三元组(row, col, data)的形式存储稀疏邻接矩阵 rowsum = np.array(adj.sum(1)) # 按行求和得到rowsum, 即每个节点的度 d_inv_sqrt = np.power(rowsum, -0.5).flatten() # (行和rowsum)^(-1/2) d_inv_sqrt[np.isinf(d_inv_sqrt)] = 0. # isinf部分赋值为0 d_mat_inv_sqrt = sp.diags(d_inv_sqrt) # 对角化; 将d_inv_sqrt 赋值到对角线元素上, 得到度矩阵^-1/2 return adj.dot(d_mat_inv_sqrt).transpose().dot(d_mat_inv_sqrt).tocoo() # (度矩阵^-1/2)*邻接矩阵*(度矩阵^-1/2)
2. 切比雪夫多项式近似
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 # L=I-D^{-1/2} A D^{-1/2} largest_eigval, _ = eigsh(laplacian, 1, which='LM') # 得到laplacian矩阵的最大特征值 scaled_laplacian = (2. / largest_eigval[0]) * laplacian - sp.eye(adj.shape[0]) # 对laplacian矩阵进行scale处理 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)
3. 一阶近似
参考博客:https://blog.csdn.net/u012856866/article/details/108258564
上一篇: python爬虫实例,股票数据定向爬虫
下一篇: 馒头要蒸多久才会熟?馒头的种类有哪些?
推荐阅读
-
使用sklearn之LabelEncoder将Label标准化的方法
-
rancher下的kubernetes之构建标准化vmware镜像的方法步骤
-
Sklearn学习之:(1)数据标准化与归一化
-
数据预处理之标准化和归一化
-
机器学习——SVM之python实现数据样本标准化和归一化
-
【python数据挖掘课程】二十九.数据预处理之字符型转换数值型、标准化、归一化处理
-
GCN之邻接矩阵标准化
-
数据结构之---C语言实现图的数组(邻接矩阵)存储表示
-
数据结构之图:邻接矩阵和邻接表、深度优先遍历和广度优先遍历
-
[SDUT](2141)数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 ---BFS(图)