论文阅读04——《Attention-driven Graph Clustering Network》
作者:Zhihao Peng, Hui Liu, yuheng Jia, Junhui Hou 发表时间:2021年8月 论文地址:https://arxiv.org/pdf/2108.05499.pdf
目录
- 论文阅读04——《Attention-driven Graph Clustering Network》
- Ideas:
- Model:
- AGCN-H模块
- 注意力权重计算
- 特征融合——加权
- 图卷积操作
- AGCN-S模块
- 计算注意力权重
- 特征融合——乘以权重后拼接
- 图卷积操作
- 算法伪代码
- Pytorch实现代码
- AGCN-H模块
Ideas:
- 提出一种新型的深度聚类方法,通过注意力机制自适应地融合GCN特征和AE特征
- 通过多尺度特征融合模块,动态连接不同层的多尺度特征
Model:
该模型整体上和SDCN类似,与SDCN相比,AGCN对特征信息的利用更加充分,自编码器的属性特征与图卷积的结构特征通过注意力机制自适应地学习权重,而不需要手工指定。AGCN主要包含KNN模块、DNN模块、AGCN-H模块、AGCN-S模块、双重自监督模块。其中KNN模块、DNN模块以及双重自监督模块与SDCN一致,不再详细讲解,SDCN详细请看论文阅读03——《Structural Deep Clustering Network》。
AGCN-H模块
该模块分为三大步骤,分别是注意力权重计算、特征融合、图卷积。
注意力权重计算
将自编码器每一层的嵌入与卷积的结果进行拼接,通过一个线性变换层得到一个2维的矩阵,使用softmax得到权重然后进行l2正则化。
特征融合——加权
特征融合使用加权的方式,将AE的特征和GCN的特征分别乘以权重再相加。乘之前需要将权重矩阵分割,去除对应部分并变换尺寸,使之可以进行哈达玛乘积。
图卷积操作
将融合后的特征输入到图卷积神经网络中,得到新的特征表示。
AGCN-S模块
该模块主要是将前面各层的图卷积输出再做一次特征融合,所以整体思路与AGCN-H一致,只不过融合方式不再是加权而是拼接。先计算注意力权重,接着拼接加权后的特征得到新的特征,最后输入图卷积神经网络。
计算注意力权重
特征融合——乘以权重后拼接
图卷积操作
聚类方式与SDCN一致
算法伪代码
Pytorch实现代码
由于论文可能还在审核中,代码尚未公开,根据模型结构代码还是比较容易写出来的,博主在这里给出AGCN-H和AGCN-S的pytorch代码,其余部分可以参考SDCN的代码:
代码语言:javascript复制class AGCN_H(nn.Module):
def __init__(self, in_features, out_features, active=True):
super(AGCN_H, self).__init__()
self.active = active
# 同一层输入特征维度一致,拼接后翻倍所以乘以2
self.full_conn = Linear(in_features * 2, 2)
self.gcn = GNNLayer(in_features, out_features)
def forward(self, Z, H, adj):
# 拼接
N = torch.cat((Z, H), 1)
# 全连接线性变换
N = self.full_conn(N)
# LeakyReLU激活
N = F.leaky_relu(N, negative_slope=0.2)
# softmax分类
N = F.softmax(N, dim=1)
# l2正则化
M = F.normalize(N)
# 切片并转置
M_i_1 = M[:, 0].reshape(M.shape[0], 1)
M_i_2 = M[:, 1].reshape(M.shape[0], 1)
# 行向量1
ones = torch.ones(1, Z.shape[1])
ones = ones.cuda()
# 权重系数与行向量1相乘得到权重矩阵
w_1 = torch.mm(M_i_1, ones)
w_2 = torch.mm(M_i_2, ones)
# 加权融合
Z = w_1 * Z w_2 * H
# 图卷积
Z = self.gcn(Z, adj, active=self.active)
return Z
'''
AGCN-H 的代码由于我一开始粗心,理解有偏差,特征融合仍然用了加权,而不是论文中的拼接,
这里注意一下!!!
'''
class AGCN_S(nn.Module):
def __init__(self, z_dim, h1_dim, h2_dim, h3_dim, h4_dim, out_features):
super(AGCN_S, self).__init__()
self.transform_h1 = Linear(h1_dim, z_dim)
self.transform_h2 = Linear(h2_dim, z_dim)
self.transform_h3 = Linear(h3_dim, z_dim)
self.transform_h4 = Linear(h4_dim, z_dim)
self.full_conn = Linear(z_dim * 5, 5)
self.gcn = GNNLayer(z_dim, out_features)
def forward(self, z, h1, h2, h3, h4, adj):
# 维度转换
h1 = self.transform_h1(h1)
h2 = self.transform_h2(h2)
h3 = self.transform_h3(h3)
h4 = self.transform_h4(h4)
# 拼接
N = torch.cat((z, h1, h2, h3, h4), 1)
# 全连接线性变换
N = self.full_conn(N)
# LeakyReLU激活
N = F.leaky_relu(N, negative_slope=0.2)
# softmax分类
N = F.softmax(N, dim=1)
# l2正则化
M = F.normalize(N)
# 切片并转置
M_i_1 = M[:, 0].reshape(M.shape[0], 1)
M_i_2 = M[:, 1].reshape(M.shape[0], 1)
M_i_3 = M[:, 2].reshape(M.shape[0], 1)
M_i_4 = M[:, 3].reshape(M.shape[0], 1)
M_i_5 = M[:, 4].reshape(M.shape[0], 1)
# 行向量1
ones = torch.ones(1, z.shape[1])
ones = ones.cuda()
# 权重矩阵
w_1 = torch.mm(M_i_1, ones)
w_2 = torch.mm(M_i_2, ones)
w_3 = torch.mm(M_i_3, ones)
w_4 = torch.mm(M_i_4, ones)
w_5 = torch.mm(M_i_5, ones)
# 融合
Z = w_1 * z w_2 * h1 w_3 * h2 w_4 * h3 w_5 * h4
# 图卷积
Z = self.gcn(Z, adj, active=False)
return Z