文章说明:
1)参考资料:PYG的文档。文档超链。
2)博主水平不高,如有错误,还望批评指正。
3)我在百度网盘上传这篇文章的jupyter notebook以及有关文献。提取码8488。
文献阅读:
参考文献:SEMI-SUPERVISED CLASSIFICATION WITH GRAPH CONVOLUTIONAL NETWORKS
中文翻译:用图神经网络进行半监督的分类
文献首先:介绍了其他前辈的工作。在损失函数中使用拉普拉斯正则化项。公式如下(打这个公式真费劲,还的学Latex):
L
=
L
0
+
λ
L
r
e
g
\mathcal{L}=\mathcal{L}_{0}+\lambda\mathcal{L}_{reg}
L=L0+λLreg with
L
r
e
g
=
∑
i
,
j
A
i
,
j
∣
∣
f
(
X
i
)
−
f
(
X
j
)
∣
∣
2
=
f
(
X
)
T
Δ
f
(
X
)
\mathcal{L}_{reg}=\sum_{i,j}{A}_{i,j}||\mathcal{f}({X}_{i})-\mathcal{f}({X}_{j})||^{2}=\mathcal{f}(X)^{T}\Delta\mathcal{f}(X)
Lreg=∑i,jAi,j∣∣f(Xi)−f(Xj)∣∣2=f(X)TΔf(X)
符号说明:
L
\mathcal{L}
L表示为损失函数。
L
0
\mathcal{{L}_{0}}
L0表示为有标签的损失(还有没标签的毕竟是半监督)。
λ
\lambda
λ表示为权重系数。
A
i
,
j
{A_{i,j}}
Ai,j表示为图边。
f
(
⋅
)
\mathcal{f}(\cdot)
f(⋅)表示为像神经网络的可微函数。
X
X
X表示为特征矩阵。
Δ
=
D
−
A
\Delta=D-A
Δ=D−A表示为非规范化的拉普拉斯算子。
D
D
D表示为度的矩阵,
D
i
,
i
=
∑
j
A
i
,
j
D_{i,i}=\sum_{j}A_{i,j}
Di,i=∑jAi,j。
文章然后:简单说明使用上述公式需要有个假设:图中连接节点共享相同标签。于是作者这篇文章便就来了,为了解决这个问题,使用神经网络模型
f
(
X
,
A
)
f(X,A)
f(X,A)编码图结构,避免使用显示基于图正则化。文章有两贡献,1.提出一种简单良好直接作用于图上的神经网络传播规则并且展示它是如何从谱图卷积的一阶逼近得到反馈。2.演示了基于图神经网络是如何分类的。
文章然后:具体开始阐述理论。
H
l
+
1
=
σ
(
D
~
−
1
2
A
~
D
~
−
1
2
H
l
W
l
)
H^{l+1}=\sigma(\tilde{D}^{-\frac{1}{2}}\tilde{A}\tilde{D}^{-\frac{1}{2}}H^{l}W^{l})
Hl+1=σ(D~−21A~D~−21HlWl)。(知道核心公式就好,其他细节跳过因为我看不懂)
符号说明:
D
i
,
i
=
∑
j
A
i
,
j
D_{i,i}=\sum_{j}A_{i,j}
Di,i=∑jAi,j表示为度的矩阵。
A
~
=
A
+
I
N
\tilde{A}=A+I_{N}
A~=A+IN表示为邻接矩阵加上一个单位矩阵。
W
l
W^{l}
Wl表示为权重系数。
σ
\sigma
σ表示为激活函数。
H
l
H^{l}
Hl为第
l
l
l层的特征矩阵。
H
0
H^{0}
H0即为
X
X
X。
文章然后:进行代码分类实操,他们这里搭建了两层GCN。所以最后的公式为
Z
=
f
(
X
,
A
)
=
s
o
f
t
m
a
x
(
A
^
R
e
l
u
(
A
^
X
W
0
)
W
1
)
Z=f(X,A)=softmax(\widehat{A}Relu(\widehat{A}XW^{0})W^{1})
Z=f(X,A)=softmax(A
Relu(A
XW0)W1)。这里
A
^
=
D
~
−
1
2
A
~
D
~
−
1
2
\widehat{A}=\tilde{D}^{-\frac{1}{2}}\tilde{A}\tilde{D}^{-\frac{1}{2}}
A
=D~−21A~D~−21。损失函数就使用交叉熵
L
=
−
∑
l
∈
Y
l
∑
f
=
1
F
Y
l
f
ln
Z
l
f
L=-\sum_{l \in \mathcal{Y}_{l}}\sum_{f=1}^FY_{lf}\ln{Z_{lf}}
L=−∑l∈Yl∑f=1FYlflnZlf吧。
文章然后:介绍图半监督学习领域以及图上运行神经网络领域两个领域相关工作。
文章然后:进行实验展示结果。
文章然后:进行讨论。1.作者模型可以克服Skip-gram方法难以优化多步流程限制同时时间以及效果表现更好。2.未来工作1)解决内存:作者证明对于无法使用GPU大型图,用CPU是可行的。用小批量随机梯度可以缓解这个问题。但是生成小批量时应该考虑GCN的层数,对于非常大且密集连接的图可能需要进一步地近似。2)不支持有向图,但是有解决方法的(具体是什么我没看懂)3)考虑一个权衡参数
λ
\lambda
λ可能会有益。具体来说就是修改生成自循环图时用的
λ
\lambda
λ。即
A
~
=
A
+
λ
I
\tilde{A}=A+\lambda I
A~=A+λI。
文章然后:得到结论。
文章最后:引用以及其他工作。1)WL-1算法2)深层的GCN。太深不好。
代码实操
导入依赖
import matplotlib.pyplot as plt
import networkx as nx
定义函数
def visualize_graph(G,color):
plt.figure(figsize=(7,7))
plt.xticks([])
plt.yticks([])
nx.draw_networkx(G,pos=nx.spring_layout(G,seed=42),with_labels=False,node_color=color,cmap="Set2")
plt.show()
#可视化图网络
def visualize_embedding(h,color,epoch=None,loss=None):
plt.figure(figsize=(7,7))
plt.xticks([])
plt.yticks([])
h=h.detach().cpu().numpy()
plt.scatter(h[:,0],h[:,1],s=140,c=color,cmap="Set2")
if epoch is not None and loss is not None:
plt.xlabel(f'Epoch: {epoch}, Loss: {loss.item():.4f}',fontsize=16)
plt.show()
#可视化图嵌入
导入数据
from torch_geometric.datasets import KarateClub
dataset=KarateClub()
KarateClub数据集简单说明:34个人的社交网络,如果在俱乐部之外两人认识连一条边。然后由于俱乐部的内部冲突,人们选择站队所以分成两派。
打印信息
print(len(dataset),dataset.num_features,dataset.num_classes)
#输出:1 34 4
简单说明:num_features:33加上1。33指,这个节点与其他的33个节点是否有边,有边为1,无边为0。1是指度。num_classes:按理应该为2,但是官方做了修改,所以这里为4。
data=dataset[0]
#具体到确定的图上
print(data.num_nodes,data.num_edges,data,data.train_mask.sum().item())
#输出:34 156 Data(x=[34, 34], edge_index=[2, 156], y=[34], train_mask=[34]) 4
print(data.has_isolated_nodes(),data.has_self_loops(),data.is_undirected())
#输出:False False True
edge_index=data.edge_index
print(edge_index.t())
#输出:不表
导入依赖
from torch_geometric.utils import to_networkx
可视网络
G=to_networkx(data,to_undirected=True)
visualize_graph(G,color=data.y)
搭建模型GCN的框架
from torch_geometric.nn import GCNConv
from torch.nn import Linear
import torch
class GCN(torch.nn.Module):
def __init__(self):
super().__init__()
self.conv1=GCNConv(dataset.num_features,4)
self.conv2=GCNConv(4,4)
self.conv3=GCNConv(4,2)
self.classifier=Linear(2,dataset.num_classes)
def forward(self,x,edge_index):
h=self.conv1(x,edge_index)
h=h.tanh()
h=self.conv2(h,edge_index)
h=h.tanh()
h=self.conv3(h,edge_index)
h=h.tanh()
out=self.classifier(h)
return out,h
model=GCN()
print(model)
#输出
#GCN(
# (conv1): GCNConv(34, 4)
# (conv2): GCNConv(4, 4)
# (conv3): GCNConv(4, 2)
# (classifier): Linear(in_features=2, out_features=4, bias=True)
#)
简单说明:
X
v
(
l
+
1
)
=
W
(
l
+
1
)
∑
w
∈
N
(
v
)
∪
{
v
}
1
c
w
,
v
⋅
X
w
(
l
)
X_{v}^{(l+1)}=W^{(l+1)}\sum_{w \in N(v)\cup{\{v\}}}\frac{1}{c_{w,v}}\cdot X_{w}^{(l)}
Xv(l+1)=W(l+1)∑w∈N(v)∪{v}cw,v1⋅Xw(l)
可视嵌入(未经训练)
model=GCN()
_,h=model(data.x,data.edge_index)
visualize_embedding(h,color=data.y)
进行训练得出结果文章来源:https://www.toymoban.com/news/detail-468857.html
model=GCN()
criterion=torch.nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(model.parameters(),lr=0.01)
def train(data):
optimizer.zero_grad()
out,h=model(data.x,data.edge_index)
loss=criterion(out[data.train_mask],data.y[data.train_mask])
loss.backward()
optimizer.step()
return loss,h
for epoch in range(401):
loss,h=train(data)
if epoch==400:
visualize_embedding(h,color=data.y,epoch=epoch,loss=loss)
文章来源地址https://www.toymoban.com/news/detail-468857.html
到了这里,关于图神经网络:(节点分类)在KarateClub数据集上动手实现图神经网络的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!