GCN:基于切比雪夫多项式(chebyshev ploynomials)为核的图卷积推导与pytorch实现

本文介绍了图卷积神经网络(GCN)的基本概念,包括使用Chebyshev多项式近似的图卷积公式,并通过PyTorch展示了其实现过程,涉及邻接矩阵、度矩阵和拉普拉斯矩阵的计算。
部署运行你感兴趣的模型镜像

GCN图卷积神经网络

顾名思义,图卷积神经网络,是对图信息进行卷积,从而获取相邻节点的信息和特征,本文将介绍和推导目前较为流行的以chebyshev ploynomials 契比雪夫多项式为核的图卷积公式,同时通过pytorch代码实现。
在这里插入图片描述

图卷积的定义

通过表示图信息的矩阵及上一层特征输入,输出该层对图信息的特征,表示如下:
Hl=f(Hl−1,A)H_l = f(H_{l-1},A)Hl=f(Hl1,A)
A代表邻接矩阵,或关于图表示的矩阵。
常用数学传播表示方式如下:
Hl=σ(D~−12A~D~−12Hl−1Wl−1) H_l=\sigma(\widetilde{D}^{-\frac{1}{2}}\widetilde{A}\widetilde{D}^{-\frac{1}{2}}H_{l-1}W_{l-1}) Hl=σ(D21AD21Hl1Wl1)

其中D~\widetilde{D}D代表A~\widetilde{A}A的度矩阵

A~\widetilde{A}A代表邻接矩阵AAA与单位矩阵III的和:A~=A+I\widetilde{A}=A+IA=A+I

HHH代表卷积后的特征,初始输入H=XH=XH=X

σ\sigmaσ为激活函数

推导

  1. 图的表示方式:

    1)邻接矩阵AAA,表示节点与节点之间是否存在连接,若存在则为1,不存在为0,对角线均为0

    2)度矩阵DDD ,只有对角线有值,表示该节点所连接边的个数

    ​3) Laplacian 拉普拉斯矩阵:L=D−AL=D-AL=DA 1)对称 2)非负特征值 3)正交

    ​ 归一化Laplacian: Lsym=D−12LD−12=I−D−12AD−12L^{sym}=D^{-\frac{1}{2}}LD^{-\frac{1}{2}}=I-D^{-\frac{1}{2}}AD^{-\frac{1}{2}}Lsym=D21LD21=ID21AD21

  2. 卷积公式:其中F(X)F(X)F(X)表示傅里叶变换

    f∗g=F−1(F(f)∗F(g))f*g=F^{-1}(F(f)*F(g))fg=F1(F(f)F(g))

  3. 根据拉普拉斯矩阵正交特性,存在U,UTU,U^TU,UT使得L=UΛUTL=U\Lambda U^TL=UΛUT 其中Λ\LambdaΛ表示特征向量

    则Graph Fourier可对应表示如下:

    GF(x)=UTxGF(x)=U^TxGF(x)=UTx

    根据卷积公式,对应图卷积公式如下:

    g∗x=U(UTgUTx)g*x=U(U^TgU^Tx)gx=U(UTgUTx)

    每一次卷积操作作用域都希望在中心节点附近的区域,则我们可以将ggg看作关于拉普拉斯矩阵LLL的函数g(L)g(L)g(L),那么,每卷积一次则相当于传递一次相邻节点信息

    而由LLL特征值特性:UTL=ΛUTU^TL=\Lambda U^TUTL=ΛUT 可知,UTg(L)U^Tg(L)UTg(L) 可看作是关于拉普拉斯矩阵LLL的特征函数gθ(Λ)g_\theta(\Lambda)gθ(Λ)

    则图卷积表达式可写作:

    g∗x=U(UTgUTx)=UgθUTxg*x=U(U^TgU^Tx)=Ug_\theta U^Txgx=U(UTgUTx)=UgθUTx

  4. 运算简化

    由于计算gθg_\thetagθ需要计算拉普拉斯矩阵特征值,计算复杂,因而提出利用切比雪夫Chebyshev polynomials多项式来进行近似计算,这里并不影响特征值的计算属性,只是通过切比雪夫多项式作为核能够将特征值矩阵计算化简为L,从而跳过特征值计算的步骤,表示如下。

    gθ=∑k=0KθkTk(Λ~)g_\theta=\sum_{k=0}^{K}\theta_k T_k(\widetilde{\Lambda})gθ=k=0KθkTk(Λ)

    其中Λ~=2∗ΛΛmax−1\widetilde{\Lambda}=2*\frac{\Lambda}{\Lambda_{max}}-1Λ=2ΛmaxΛ1,只是因为Chebyshev polynomials要求xxx处于[−1,1][-1,1][1,1]

    Tk(x)=2xTk−1(x)−Tk−2(x)T_k(x)=2xT_{k-1}(x)-T_{k-2}(x)Tk(x)=2xTk1(x)Tk2(x),T0=0T_0=0T0=0,T1=1T_1=1T1=1

    那么将上式代入卷积表达式可以得到:

    g∗x=U∑k=0KθkTk(Λ~)UTx=∑k=0KθKTk(L~)xg*x=U\sum_{k=0}^{K}\theta_k T_k(\widetilde{\Lambda})U^Tx\\=\sum_{k=0}^K\theta_K T_k(\widetilde{L})xgx=Uk=0KθkTk(Λ)UTx=k=0KθKTk(L)x

pytorch代码实现

包需求:

import numpy as np
import torch
import torch.nn as nn

1.Laplacian 以及scaled_Laplacian:

'''D matrix 根据邻接矩阵获取度矩阵'''
def get_d_matrix(adj_matrix):
    d_matrix = np.zeros((adj_matrix.shape[0], adj_matrix.shape[1]))
    for i in range(adj_matrix.shape[0]):
        d_matrix[i, i] = np.sum(adj_matrix[i, :])
    return d_matrix

'''Laplace matrix'''
def get_laplace_matrix(adj, d):
    d_turn = np.zeros((adj.shape[0], adj.shape[0]))
    for i in range(adj.shape[0]):
        d_turn[i, i] = np.power(d[i, i], -0.5)
    res = np.eye(adj.shape[0]) - d_turn @ adj @ d_turn
    return res


'''
get the  rou of matrix 获取矩阵谱半径,即最大绝对值特征值
'''
def getRou(x):
    lambdas, features = np.linalg.eig(x)
    return np.max(np.abs(lambdas))

'''
get scaled laplacian for chebyshev ploynomials
'''
def scaled_laplacian(L):
    res = (2*L)/getRou(L)-np.identity(L.shape[0])
    return res
  1. 契比雪夫多项式的实现
'''
get chebyshev ploynomials 
'''
def chebyshev_ploynomials(scaled_laplacian, K):
    '''
    :param scaled_laplacian: [-1,1]的拉普拉斯矩阵
    :param K: 多项式项数
    :return: list
    '''
    res = [np.identity(scaled_laplacian.shape[0]), scaled_laplacian]
    if K>=2:
        for i in range(2, K+1):
            res.append(2*scaled_laplacian*res[i-1]-res[i-2])
    return res
  1. pytorch 实现图卷积
'''
take chebyshev ploynomials as kernal for graph conv
'''
class Cheb_conv(nn.Module):
    def __init__(self, chebyshev_ploynomials, K, in_channel, out_channel):
        super(Cheb_conv, self).__init__()
        self.K = K
        self.chebyshev_ploynomials = chebyshev_ploynomials
        self.device = chebyshev_ploynomials[0].device
        self.thetaList = nn.ParameterList([nn.Parameter(torch.FloatTensor(in_channel, out_channel).to(self.device)) for _ in range(K)])
        self.relu = nn.ReLU()

    def forward(self, x):
        '''

        :param x: (batch, nodes_num, features(in_channel), seq_len)
        :return:
        '''
        batch_size, nodes_num, in_channel, seq_len = x.shape
        #(batch, seq_len, nodes_num, in_channel)
        x = x.permute(0,3,1,2)
        output = torch.zeros(batch_size, nodes_num, self.out_channels, seq_len).to(self.DEVICE)
        for i in range(self.K):
            cheb = self.chebyshev_ploynomials[i]
            #(batch, seq_len, nodes_num, in_channel)
            cash = cheb.matmul(x)
            # (batch, seq_len, nodes_num, out_channel)
            cash = self.cash.matmul(self.thetaList[i])
            #(batch, nodes_num, out_channel, seq_len)
            cash = cash.permute(0,2,3,1)
            output += cash

        return self.relu(output)

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx_Mike

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值