目录
0、基本信息
- 作者:Yanqiao Zhu Yichen Xu
- 文章链接:Deep Graph Contrastive Representation Learning
- 代码链接:Deep Graph Contrastive Representation Learning
1、研究动机
-  现实世界中,图的标签数量较少,尽管GNNs蓬勃发展,但是训练模型时标签的可用性问题也越来越受到关心。 
-  传统的无监督图表征学习方法,例如DeepWalk和node2vec,以牺牲结构信息为代价过度强调邻近信息 
-  基于局部-全局互信息最大化框架的[[DGI]]模型,要求readout函数是单射的具有局限性,并且对节点特征随机排列,当特征矩阵稀疏时,不足以生成不同的上下文信息,导致难以学习对比目标 
本文提出的GRACE模型:首先,通过移除边和掩盖特征生成两个视图,然后最大化两个视图中结点嵌入的一致性。
2、创新点
- 结点级图对比学习框架
- 提出新的Corruption Function:删除边和特征掩盖
3、方法论
3.1、整体框架及算法流程
- 首先,通过Corruption函数在原始图 G G G的基础上生成两个视图 G ~ 1 \tilde{G}_1 G~1和 G ~ 2 \tilde{G}_2 G~2;
- 其次,通过编码器函数 f f f,生成两个视图的结点嵌入表征, U = f ( G ~ 1 ) U=f(\tilde{G}_1) U=f(G~1)和 V = f ( G ~ 2 ) V=f(\tilde{G}_2) V=f(G~2);
- 计算对比目标函数 J \mathcal{J} J;
- 通过随机梯度下降更新参数;
GRACE的整体框架如下图所示:
 
3.2、Corruption函数的具体实现
视图的生成是对比学习方法的关键组成部分,不同视图为每个节点提供不同的上下文,本文依赖不同视图中结点嵌入之间对比的对比方法,作者在结构和属性两个层次上破坏原始图,这为模型构建了不同的节点上下文,分别是删除边和掩蔽结点特征。
3.2.1、删除边(RE)
 随机删除原图中的部分边。
  首先,采样一个随机掩盖矩阵 
     
      
       
        
        
          R 
         
        
          ~ 
         
        
       
         ∈ 
        
       
         { 
        
       
         0 
        
       
         , 
        
       
         1 
        
        
        
          } 
         
         
         
           N 
          
         
           × 
          
         
           N 
          
         
        
       
      
        \tilde{R}\in \{0,1\}^{N \times N} 
       
      
    R~∈{0,1}N×N,矩阵中的每个元素服从伯努利分布,即 
     
      
       
        
        
          R 
         
        
          ~ 
         
        
       
         ∼ 
        
       
         B 
        
       
         ( 
        
       
         1 
        
       
         − 
        
        
        
          p 
         
        
          r 
         
        
       
         ) 
        
       
      
        \tilde{R}\sim \mathcal{B}(1-p_r) 
       
      
    R~∼B(1−pr), 
     
      
       
        
        
          p 
         
        
          r 
         
        
       
      
        p_r 
       
      
    pr是每条边被移除的概率;其次,用得到地掩盖矩阵与原始邻接矩阵做Hadamard积,最终得到的邻接矩阵为:
  
      
       
        
         
         
           A 
          
         
           ~ 
          
         
        
          = 
         
        
          A 
         
        
          ∘ 
         
         
         
           R 
          
         
           ~ 
          
         
        
       
         \tilde{A}=A\circ \tilde{R} 
        
       
     A~=A∘R~
 注意,上式为Hadamard积。
3.2.2、特征掩盖(MF)
 再结点特征中用零随机地掩盖部分特征。
  首先,采样一个随机向量 
     
      
       
        
        
          m 
         
        
          ~ 
         
        
       
         ∈ 
        
       
         { 
        
       
         0 
        
       
         , 
        
       
         1 
        
        
        
          } 
         
        
          F 
         
        
       
      
        \tilde{m}\in\{0,1\}^F 
       
      
    m~∈{0,1}F,向量的每个元素来自于伯努利分布,即 
     
      
       
        
        
          m 
         
        
          ~ 
         
        
       
         ∼ 
        
       
         B 
        
       
         ( 
        
       
         1 
        
       
         − 
        
        
        
          p 
         
        
          m 
         
        
       
         ) 
        
       
      
        \tilde{m}\sim \mathcal{B}(1-p_m) 
       
      
    m~∼B(1−pm), 
     
      
       
        
        
          p 
         
        
          r 
         
        
       
      
        p_r 
       
      
    pr是元素被掩盖的概率;其次,用得到地掩盖向量与原始特征做Hadamard积,最终得到的特征矩阵为:
  
      
       
        
         
         
           X 
          
         
           ~ 
          
         
        
          = 
         
        
          [ 
         
         
         
           x 
          
         
           1 
          
         
        
          ∘ 
         
         
         
           m 
          
         
           ~ 
          
         
        
          ; 
         
         
         
           x 
          
         
           2 
          
         
        
          ∘ 
         
         
         
           m 
          
         
           ~ 
          
         
        
          ; 
         
        
          . 
         
        
          . 
         
        
          . 
         
        
          ; 
         
         
         
           x 
          
         
           N 
          
         
        
          ∘ 
         
         
         
           m 
          
         
           ~ 
          
         
        
          ; 
         
        
          ] 
         
        
       
         \tilde{X}=[x_1 \circ\tilde{m};x_2 \circ\tilde{m};...;x_N \circ\tilde{m};] 
        
       
     X~=[x1∘m~;x2∘m~;...;xN∘m~;]
 注意, 
     
      
       
       
         [ 
        
       
         . 
        
       
         ; 
        
       
         . 
        
       
         ] 
        
       
      
        [.;.] 
       
      
    [.;.]是连接运算符。
3.3、编码器的设计
针对不同任务,transductive learning、inductive learning on large graphs和inductive learning on multiple graphs,设计不同的编码器。这里仅仅列出transductive learning的编码器设计,其他任务编码器的设计请阅读原文4.2节实验设置。
3.3.1、直推式学习
 直推式学习采用了一个两层的GCN作为编码器。编码器 
     
      
       
       
         f 
        
       
      
        f 
       
      
    f的形式如下:
  
      
       
        
        
          G 
         
         
         
           C 
          
         
           i 
          
         
        
          ( 
         
        
          X 
         
        
          , 
         
        
          A 
         
        
          ) 
         
        
          = 
         
        
          σ 
         
        
          ( 
         
         
          
          
            D 
           
          
            ^ 
           
          
          
          
            1 
           
          
            2 
           
          
         
         
         
           A 
          
         
           ^ 
          
         
         
          
          
            D 
           
          
            ^ 
           
          
          
          
            1 
           
          
            2 
           
          
         
        
          X 
         
         
         
           W 
          
         
           i 
          
         
        
          ) 
         
        
       
         GC_i(X,A)=\sigma(\hat{D}^{\frac{1}{2}}\hat{A}\hat{D}^{\frac{1}{2}}XW_i) 
        
       
     GCi(X,A)=σ(D^21A^D^21XWi)
  
      
       
        
        
          f 
         
        
          ( 
         
        
          X 
         
        
          , 
         
        
          A 
         
        
          ) 
         
        
          = 
         
        
          G 
         
         
         
           C 
          
         
           2 
          
         
        
          ( 
         
        
          G 
         
         
         
           C 
          
         
           1 
          
         
        
          ( 
         
        
          X 
         
        
          , 
         
        
          A 
         
        
          ) 
         
        
          , 
         
        
          A 
         
        
          ) 
         
        
       
         f(X,A)=GC_2(GC_1(X,A),A) 
        
       
     f(X,A)=GC2(GC1(X,A),A)
 其中, 
     
      
       
        
        
          A 
         
        
          ^ 
         
        
       
         = 
        
       
         A 
        
       
         + 
        
       
         I 
        
       
      
        \hat{A}=A+I 
       
      
    A^=A+I, 
     
      
       
        
        
          D 
         
        
          ^ 
         
        
       
      
        \hat{D} 
       
      
    D^为 
     
      
       
        
        
          A 
         
        
          ^ 
         
        
       
      
        \hat{A} 
       
      
    A^的度矩阵, 
     
      
       
       
         σ 
        
       
         ( 
        
       
         . 
        
       
         ) 
        
       
      
        \sigma(.) 
       
      
    σ(.)为激活函数,例如 
     
      
       
        
        
          R 
         
        
          e 
         
        
          L 
         
        
          U 
         
        
       
         ( 
        
       
         . 
        
       
         ) 
        
       
         = 
        
       
         m 
        
       
         a 
        
       
         x 
        
       
         ( 
        
       
         0 
        
       
         , 
        
       
         . 
        
       
         ) 
        
       
      
        \mathrm{ReLU}(.)=max(0,.) 
       
      
    ReLU(.)=max(0,.), 
     
      
       
        
        
          W 
         
        
          i 
         
        
       
      
        W_i 
       
      
    Wi为可训练的权重矩阵。
3.4、损失函数的定义
对比目标,即判别器,是将两个来自不同视图相同结点的嵌入与其他结点区分开来,最大化嵌入之间的结点级的一致性。
对于任意一个结点 v i v_i vi,在第一个视图中的嵌入为 u i \mathbf{u}_i ui,被视作锚;在另外一个视图中的嵌入为 v i \mathbf{v}_i vi,形成正样本,两个视图中出 v i v_i vi之外的结点嵌入被视为负样本。
简单而言,正样本:同一结点在不同视图的嵌入被视作正样本对;负样本包含两类:(1)intra-view:同一视图中的不同结点对(2)inter-view:不同视图中的不同结点对。
判别函数定义为 θ ( u , v ) = s ( g ( u ) , g ( v ) ) \theta(u,v)=s(g(u),g(v)) θ(u,v)=s(g(u),g(v)), s s s为cosine相似度,g为非线性映射,例如两层的MLP。
综上所述,目标函数定义为:
ℓ ( u i , v i ) = log  e θ ( u i , v i ) / τ e θ ( u i , v i ) / τ ⏟ the positive pair + ∑ k = 1 N 1 [ k ≠ i ] e θ ( u i , v k ) / τ ⏟ inter-view negaive pairs + ∑ k = 1 N 1 [ k ≠ i ] e θ ( u i , u k ) / τ ⏟ intra-view negative pairs \ell(\boldsymbol{u}_i,\boldsymbol{v}_i)=\log\frac{e^{\theta(\boldsymbol{u}_i,\boldsymbol{v}_i)/\tau}}{\underbrace{e^{\theta(\boldsymbol{u}_i,\boldsymbol{v}_i)/\tau}}_{\text{the positive pair}}+\underbrace{\sum _ { k = 1 }^N\mathbb{1}_{[k\neq i]}e^{\theta(\boldsymbol{u}_i,\boldsymbol{v}_k)/\tau}}_{\text{inter-view negaive pairs}}+\underbrace{\sum _ { k = 1 }^N\mathbb{1}_{[k\neq i]}e^{\theta(\boldsymbol{u}_i,\boldsymbol{u}_k)/\tau}}_{\text{intra-view negative pairs}}} ℓ(ui,vi)=logthe positive pair eθ(ui,vi)/τ+inter-view negaive pairs k=1∑N1[k=i]eθ(ui,vk)/τ+intra-view negative pairs k=1∑N1[k=i]eθ(ui,uk)/τeθ(ui,vi)/τ
其中, 1 [ k ≠ i ] ∈ { 0 , 1 } \mathbb{1}_{[k\neq i]}\in\{0,1\} 1[k=i]∈{0,1}是一个指示函数,当且仅当 k ≠ i k \neq i k=i时定于1。两个视图是对称的,另一个视图定义类似 ℓ ( v i , u i ) \ell(\boldsymbol{v}_i,\boldsymbol{u}_i) ℓ(vi,ui),最后,要最大化的总体目标被定义为:
J = 1 2 N ∑ i = 1 N [ ℓ ( u i , v i ) + ℓ ( v i , u i ) ] \mathcal{J}=\dfrac{1}{2N}\sum_{i=1}^N\left[\ell(\boldsymbol{u}_i,\boldsymbol{v}_i)+\ell(\boldsymbol{v}_i,\boldsymbol{u}_i)\right] J=2N1i=1∑N[ℓ(ui,vi)+ℓ(vi,ui)]
3.5、评估
类似于DGI中的线性评估方案,模型首先以无监督的方式训练,得到的嵌入被用来训练逻辑回归分类器并做测试。
3.6、理论动机
3.6.1、最大化目标函数等价于最大化互信息的下界
 定理1说明了目标函数 
     
      
       
       
         J 
        
       
      
        \mathcal{J} 
       
      
    J是InfoNCE目标函数的一个下界,而InfoNCE评估器是MI(即互信息)的下界,所以 
     
      
       
       
         J 
        
       
         ≤ 
        
       
         I 
        
       
         ( 
        
       
         X 
        
       
         ; 
        
       
         U 
        
       
         , 
        
       
         V 
        
       
         ) 
        
       
      
        \mathcal{J} \le I(X;U,V) 
       
      
    J≤I(X;U,V)。
 所以,最大化目标函数 
     
      
       
       
         J 
        
       
      
        \mathcal{J} 
       
      
    J等价于最大化输入节点特征和学习节点表示之间的互信息 
     
      
       
       
         I 
        
       
         ( 
        
       
         X 
        
       
         ; 
        
       
         U 
        
       
         , 
        
       
         V 
        
       
         ) 
        
       
      
        I(X;U,V) 
       
      
    I(X;U,V)的下界
3.6.2、三重损失
定理2说明了最小化目标函数与最大化三重损失一致。更详细的证明请看原文。
3.7、实验参数设置
| Dataset | p m , 1 p_{m,1} pm,1 | p m , 2 p_{m,2} pm,2 | p r , 1 p_{r,1} pr,1 | p r , 2 p_{r,2} pr,2 | lr | wd | epoch | hidfeat | activation | 
|---|---|---|---|---|---|---|---|---|---|
| Cora | 0.3 | 0.4 | 0.2 | 0.4 | 0.005 | 1e-5 | 200 | 128 | ReLU | 
| Citeseer | 0.3 | 0.2 | 0.2 | 0.0 | 0.001 | 1e-5 | 200 | 256 | PReLU | 
| Pubmed | 0.0 | 0.2 | 0.4 | 0.1 | 0.001 | 1e-5 | 1500 | 256 | ReLU | 
4、代码实现
4.1、RE and MF
from dgl.transforms import DropEdge
#RE
#随机删除边——使用dgl内建库DropEdge
#MF
#随机掩盖特征
def drop_feature(x, drop_prob):
    drop_masks=[]
    for i in range(x.shape[0]):
        drop_mask = torch.empty(
            size= (x.size(1),) ,
            dtype=torch.float32,
            device=x.device).uniform_(0, 1) < drop_prob
        drop_masks.append(drop_mask)
    x = x.clone()
    for i,e in enumerate(drop_masks):
        x[i,e] = 0
    return x
4.2、encorder
import dgl
import torch.nn as nn
from dgl.nn.pytorch import GraphConv
from model.GCNLayer import GCNLayer
class Encoder(nn.Module):
    def __init__(self, infeat: int, outfeat: int, act_func,base_model=GraphConv, k: int = 2):
        super(Encoder, self).__init__()
        self.base_model = base_model
        assert k >= 2
        self.k = k
        self.convs = nn.ModuleList()
        self.convs.append(base_model(infeat, 2 * outfeat))
        for _ in range(1, k-1):
            self.convs.append(base_model(2 * outfeat, 2 * outfeat))
        self.convs.append(base_model(2 * outfeat, outfeat))
        self.act_func = act_func
    def forward(self, g, x ):
        #g = dgl.add_self_loop(g)
        for i in range(self.k):
            x = self.act_func(self.convs[i](g,x))
        return x
4.3、GRACE
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from dgl.nn.pytorch import GraphConv
from model.encoder import Encoder
class GRACE(nn.Module):
   def __init__(self,infeat,hidfeat,act_func,k=2) -> None:
      super(GRACE,self).__init__()
      self.encoder = Encoder(infeat,hidfeat,act_func,base_model=GraphConv,k=k)
   def forward(self,g,x):
      z =self.encoder(g,x)
      return z
4.4、loss
import torch
import torch.nn as nn
import torch.nn.functional as F
class LossFunc(nn.Module):
    def __init__(self, infeat,hidfeat,outfeat,tau) -> None:
        super(LossFunc,self).__init__()
        self.tau = tau
        self.layer1 = nn.Linear(infeat,hidfeat)
        self.layer2 = nn.Linear(hidfeat,outfeat)
    def projection(self,x):
        x = F.elu(self.layer1(x))
        x = self.layer2(x)
        return x
    def sim(self,x,y):
        x = F.normalize(x)
        y = F.normalize(y)
        return torch.mm(x, y.t())
    def sim_loss(self,h1,h2):
        f = lambda x : torch.exp(x/self.tau)
        #exp(\theta(u_i,u_j)/tau)
        intra_sim = f(self.sim(h1,h1))
        #exp(\theta(u_i,v_j)/tau)
        inter_sim = f(self.sim(h1,h2))
        return -torch.log(
            inter_sim.diag() / (intra_sim.sum(1) + inter_sim.sum(1) - intra_sim.diag())
            )
    def forward(self,u,v):
        h1 = self.projection(u)
        h2 = self.projection(v)
        loss1 = self.sim_loss(h1,h2)
        loss2 = self.sim_loss(h2,h1)
        loss_sum = (loss1 + loss2) * 0.5
        res = loss_sum.mean()
        return res










