来源:https://mydoc.myencyclopedia.top/pub-html/01_plot_cora.html
B站链接:https://www.bilibili.com/video/BV1f3411i7MQ?p=1

内置 Cora 数据集

下一步,我们会通过 geometric 类库加载 cora 数据集。这一步通常来说需要从网上下载,但是预制的 docker image 已经为大家下载好了 planetoid 图数据集。Planetoid 包含了 Cora,Pubmed 和 Citeseer。
因此,加载数据集这一步执行非常快

  1. import numpy as np
  2. import torch
  3. import torch.nn as nn
  4. import torch.nn.functional as F
  5. from torch_geometric.data import Data
  6. from torch_geometric.nn import GATConv
  7. from torch_geometric.datasets import Planetoid
  8. import torch_geometric.transforms as T
  9. name_data = 'Cora'
  10. dataset = Planetoid(root='./data/', name=name_data)

数据集说明

样本特征,标签,邻接矩阵 该数据集共2708个样本点,每个样本点都是一篇科学论文,所有样本点被分为8个类别,类别分别是1)基于案例;2)遗传算法;3)神经网络;4)概率方法;5)强化学习;6)规则学习;7)理论

每篇论文都由一个1433维的词向量表示,所以,每个样本点具有1433个特征。词向量的每个元素都对应一个词,且该元素只有0或1两个取值。取0表示该元素对应的词不在论文中,取1表示在论文中。所有的词来源于一个具有1433个词的字典。

每篇论文都至少引用了一篇其他论文,或者被其他论文引用,也就是样本点之间存在联系,没有任何一个样本点与其他样本点完全没联系。如果将样本点看做图中的点,则这是一个连通的图,不存在孤立点。[

](https://blog.csdn.net/yeziand01/article/details/93374216)

  1. dataset.data
  2. #Data(x=[2708, 1433], edge_index=[2, 10556], y=[2708], train_mask=[2708], val_mask=[2708], test_mask=[2708])
  3. np.unique(dataset[0].y)
  4. #array([0, 1, 2, 3, 4, 5, 6]) 一共有7个类别

y表示论文的标签。(因为有2708个结点,所以相应的有2708个y)
image.png

可视化

然后我们将 cora 转换成 networkx 格式。networkx 是 python 中一个比较流行的图类库。我们在后面 visualization 中也会利用networkx 的功能。
Cora 有 7 种节点类型,我们将每种节点类型赋予不同颜色,有助于更好 visualization。

  1. from torch_geometric.utils import to_networkx
  2. cora = to_networkx(dataset.data)
  3. print(cora.is_directed()) #True
  4. node_classes = dataset.data.y.data.numpy()
  5. print(node_classes) #[3 4 4 ... 3 3 3]
  6. node_color = ["red","blue","green","yellow","peru","violet","cyan"]
  7. node_label = np.array(list(cora.nodes))

image.png

接着,调用 networkx 的 spring_layout 计算每个节点的弹簧布局下的位置,这一步执行会比较耗时。

  1. import matplotlib.pyplot as plt
  2. import networkx as nx
  3. pos = nx.layout.spring_layout(cora)

我们首先来看一下 matplotlib 的渲染效果。

  1. plt.figure(figsize=(16,12))
  2. for i in np.arange(len(np.unique(node_classes))):
  3. node_list = node_label[node_classes == i] #将class为i的node组成 node_list
  4. nx.draw_networkx_nodes(cora, pos, nodelist=list(node_list),
  5. node_size=50,
  6. node_color=node_color[i],
  7. alpha=0.8)
  8. nx.draw_networkx_edges(cora, pos,width=1,edge_color="black")
  9. plt.show()

len(np.unique(node_classes)) =7

这里我不懂为什么**node_list = node_label[node_classes == i] **可以筛选出想要的条件,所以就有了如下的操作
以i=0时,node_list为例子
当i=0时,node_list的输出
image.png
可以看到,输出的是class为0的节点的下标

node_label是一个0-2707的数组(相当于下标)
node_classes是结点的类别
node_classes==0 是有True,False构成的数组
node_label[node_classes == 0]就返回了所以True的下标
image.png
image.png

绘图的结果
image.png
因为 matplotlib 只能画出一张静态图片, 无法做 interaction,也无法动态缩放。因此渲染效果不是特别好,尤其是对于 cora 这种数据量比较大的 graph 尤为显著。
我们看到图片种尽管有七种颜色的节点,但是当中存在的这块密集的点,我们很难看出节点和节点之间的关系。

我们换一个类库 hvplot,它的渲染和交换效果如下。

代码和 matplotlib 大致一致。注意渲染的时候 hvplot 需要将多个图片数据以乘法形式返回,借助 reduce 函数我们将 7 种节点的图相乘,再乘以描绘边的图,呈现出叠加的完整图片。

  1. import hvplot.networkx as hvnx
  2. options = {
  3. 'width': 800,
  4. 'height': 1000
  5. }
  6. plt_nodes = []
  7. for i in np.arange(len(np.unique(node_classes))):
  8. nodelist = node_label[node_classes == i]
  9. plt = hvnx.draw_networkx_nodes(cora, pos, nodelist=list(nodelist), node_color=node_color[i], **options)
  10. plt_nodes.append(plt)
  11. plt_edges = hvnx.draw_networkx_edges(cora, pos, arrowstyle='->', edge_width=2, colorbar=True, **options)
  12. import functools
  13. import operator
  14. plt_edges * functools.reduce(operator.mul, plt_nodes)

(虽然还是特别丑,但可以交互)
image.png