对抗鲁棒异质图神经网络

本文针对异质图神经网络的两个主要问题——扰动放大效应和SoftAttention机制的不足,提出RoHe模型以增强模型的防御能力。RoHe模型通过优先过渡策略减少远距离邻居的影响力,并采用净化面罩选择高置信度的邻居,有效过滤噪声。实验表明,该模型在对抗攻击下表现出更好的稳定性。
摘要由CSDN通过智能技术生成

来源:AAAI 2022
作者:张梦玟 北邮博士
石川老师团队
北邮和蚂蚁金服合作



一.文章部分

1.背景

图数据无处不在,例如社交网络、论文引用。图数据分为同质图和异质图,后者包含丰富的高阶的语义关系。
而图神经网络是现在的分析图数据的好的手段之一,本质上来讲就是逐层聚合邻居。
在这里插入图片描述
在这里插入图片描述
考虑到图神经网络应用的广泛性,则其安全性则变得愈加重要。
对抗攻击是挖掘模型漏洞,研究模型安全性、鲁棒性的重要手段。来源于计算机视觉。
在这里插入图片描述
攻击者设计一层肉眼不可见的扰动叠加进照片中,模型就很容易被它欺骗,现有的一些工作发现深度学习模型大概率会把蝴蝶识别为猫,原因可能是模型设计上存在一些漏洞,或者捕捉了与人识别过程中不同的特征。
扰动方式:增、删边,扰动结点特征、反转结点的标签。
现有的对抗工作主要是在同质图上进行,异质图非常脆弱,所以本文的价值便得以体现。
在这里插入图片描述


2.模型

Ps:在图中加入a3这个邻居
异质图神经网络普遍存在两个漏洞:

  1. 扰动放大效应
    (1) 同质图:加入a3邻居之后,P4-P66要先融合到a3上(逐层融合),a3的嵌入再融合到P1上,但影响不会超过1/3。
    (2) 异质图:因为模型经常是基于元路径直接聚合远距离的邻居,例如P4-P66,现有的很多工作往往不考虑转移的概率。结果就是P4-P66会占据主导地位,最后会使得p1被误分类为红色。

  2. Soft Attention机制的问题
    现有的异质图神经网络往往会设计一套Soft Attention机制,利用P1与它的邻居算特征相似度。但Soft Attention机制是让p1的每一个邻居对p1的影响都是正数,即注意力值都是大于0的,但P4-P66的注意力值应该为0才对。所以Soft Attention机制就没有起到过滤邻居的目的,不够鲁棒。

针对上述两个问题,设计了RoHe模型
在这里插入图片描述
(1) 首先给定一张异质图,现有的方法会抽出基于给定的不同元路径的邻居,例如PAP,PSP.
(2) 结点级聚合。对于不同的元路径做基于结点级的聚合。
(3) 语义级聚合。将(2)中所有结果再进行语义级的聚合。
防御就主要集中在结点级聚合部分。
选择confidence最高的Top T个邻居保留,剩下的都mask,目的是得到一个比较clean的attention,这p4-p66对比结果的影响就很小。

Node-level聚合具体流程
1.投影到同一个空间
在这里插入图片描述
2.计算特征的相似性
在这里插入图片描述
3. Transiting prior
在此处本文设计了一个“优先过渡”,思想类似与随机游走,例如图中从a1到p66的概率就会很小,从而p66对a1的影响就会减小,即解决了扰动放大问题。
在这里插入图片描述
在这里插入图片描述

4.Confidence Socre
把基于feature的相似性(e)与基于Transiting prior的相似性§结合起来,通过激活函数,为v结点的每个邻居u得到一个confidence score(固定了元路径)。

5.Purification mask(净化面罩)
设计了一种方法选择Top T个confidence score,即如果u不在前Top T个,其m的值就为负无穷,丢入softmax后其值就会无限趋近于0。
再把mask矩阵和原始的attention矩阵做一个结合得到pure attention。
6.最后再做结点的集合
在这里插入图片描述

语义级聚合
因为元路径具有多样性,所以要聚合不同的元路径。
在这里插入图片描述

3.实验部分

数据设置
在这里插入图片描述
基线方法(同质图防御模型,前三个)
在这里插入图片描述
Δ:扰动边的数目
在这里插入图片描述
对抗噪音
在这里插入图片描述

4.贡献

在这里插入图片描述

二.部分代码

import torch
import torch.nn as nn
import torch.nn.functional as F
import dgl
from dgl.nn.pytorch import GATConv

class SemanticAttention(nn.Module):
    def __init__(self, in_size, hidden_size=128):
        super(SemanticAttention, self).__init__()

        self.project = nn.Sequential(
            nn.Linear(in_size, hidden_size),
            nn.Tanh(),
            nn.Linear(hidden_size, 1, bias=False)
        )

    def forward(self, z):
        w = self.project(z).mean(0)                    # (M, 1)
        beta = torch.softmax(w, dim=0)                 # (M, 1)
        beta = beta.expand((z.shape[0],) + beta.shape) # (N, M, 1)

        return (beta * z).sum(1)                       # (N, D * K)

class HANLayer(nn.Module):
    def __init__(self, meta_paths, in_size, out_size, layer_num_heads, dropout):
        super(HANLayer, self).__init__()
        
        # One GAT layer for each meta path based adjacency matrix
        self.gat_layers = nn.ModuleList()
        for i in range(len(meta_paths)):
            self.gat_layers.append(GATConv(in_size, out_size, layer_num_heads,
                                           dropout, dropout, activation=F.elu))
        self.semantic_attention = SemanticAttention(in_size=out_size * layer_num_heads)
        self.meta_paths = list(tuple(meta_path) for meta_path in meta_paths)

        self._cached_graph = None
        self._cached_coalesced_graph = {}

    def forward(self, g, h):
        semantic_embeddings = []

        if self._cached_graph is None or self._cached_graph is not g:
            self._cached_graph = g
            self._cached_coalesced_graph.clear()
            for meta_path in self.meta_paths:
                self._cached_coalesced_graph[meta_path] = dgl.metapath_reachable_graph(
                        g, meta_path)

        for i, meta_path in enumerate(self.meta_paths):
            new_g = self._cached_coalesced_graph[meta_path]
            semantic_embeddings.append(self.gat_layers[i](new_g, h).flatten(1))
        semantic_embeddings = torch.stack(semantic_embeddings, dim=1)                  # (N, M, D * K)

        return self.semantic_attention(semantic_embeddings)                            # (N, D * K)

class HAN(nn.Module):
    def __init__(self, meta_paths, in_size, hidden_size, out_size, num_heads, dropout):
        super(HAN, self).__init__()
        self.layers = nn.ModuleList()
        self.layers.append(HANLayer(meta_paths, in_size, hidden_size, num_heads[0], dropout))
        for l in range(1, len(num_heads)):
            self.layers.append(HANLayer(meta_paths, hidden_size * num_heads[l-1],
                                        hidden_size, num_heads[l], dropout))
        self.predict = nn.Linear(hidden_size * num_heads[-1], out_size)

    def forward(self, g, h):
        for gnn in self.layers:
            h = gnn(g, h)

        return self.predict(h)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值