GNN日常学习

获取图的相关结构:

from torch_geometric.datasets import KarateClub

# 数据集对象操作
dataset = MyOwnDataset('./data/waterloop') # 创建数据集对象
data_loader = DataLoader(dataset, batch_size=100, shuffle=False) # 加载数据进行处理;每批次数据的数量为1
print(f'Number of graphs: {len(dataset)}')#该dataset中graph的数量
print(f'Number of features: {dataset.num_features}')#node数量
print(f'Number of classes: {dataset.num_classes}')#标类别签数量
###
data = dataset[0]  # Get the first graph object.


## Gather some statistics about the graph.
print(f'Number of nodes: {data.num_nodes}')#节点数量
print(f'Number of edges: {data.num_edges}')#边数量
print(f'Number of training nodes: {data.train_mask.sum()}') # 4个节点有标签
print(f'Has isolated nodes: {data.has_isolated_nodes()}') # 孤立节点
print(f'Is undirected: {data.is_undirected()}') # 无向图
print(type(data))


##打印节点的ID和特征
for node_id, feature in zip(range(data.num_nodes), data.x):
    print(f"Node ID: {node_id}, Feature: {feature}")

#获取val test train的节点数。
num_true = torch.sum(data.train_mask).item()
num_true1 = torch.sum(data.val_mask).item()
num_true2 = torch.sum(data.test_mask).item()
print(num_true,num_true1,num_true2)

Data(x=[34, 34], edge_index=[2, 156], y=[34], train_mask=[34]),其中train_mask为true or false,代表作为训练的节点。

划分train/test/val数据集的方法,未梳理(存在逻辑问题)。

from sklearn.model_selection import train_test_split


# 划分训练集和测试集
train1_features, test_features, train1_labels, test_labels = train_test_split(node_features, labels, test_size=0.1, shuffle=False, stratify=None, random_state=42)
# 划分训练集和验证集
train_features, val_features, train_labels, val_labels = train_test_split(train1_features, train1_labels, test_size=0.1, random_state=42)
#创建掩码
train_mask = torch.zeros(labels.shape[0], dtype=torch.bool)
val_mask = torch.zeros(labels.shape[0], dtype=torch.bool)
test_mask = torch.zeros(labels.shape[0], dtype=torch.bool)
# train_mask[:int(train_labels.shape[0])] = True
# val_mask[:int(val_labels.shape[0])] = True
# test_mask[:int(test_labels[0])] = True

train_mask[:int(train1_labels.shape[0]*0.9)] = True
val_mask[int(train1_labels.shape[0]*0.9): int(train1_labels.shape[0])] = True
test_mask[int(labels.shape[0]*0.9):] = True

可视化图

# 可视化图
%matplotlib inline
import networkx as nx
import matplotlib.pyplot as plt

def visualize_graph(G, color):
    plt.figure(figsize=(7,7)) # (7, 7)的画布
    plt.xticks([]) # x轴刻度
    plt.yticks([]) # y轴刻度
    nx.draw_networkx(G, pos=nx.spring_layout(G, seed=42), with_labels=True, node_color=color, cmap="Set2")
    
#     其中,G 是一个 NetworkX 图形对象,它可以是一个无向图或有向图。
#     pos 参数表示节点的布局位置,它可以是一个字典,指定每个节点的坐标位置,
#     也可以是一个函数,用于自动计算节点的坐标位置。
#     在这个例子中,使用 nx.spring_layout(G, seed=42) 函数自动计算节点的坐标位置,
#     其中 seed 参数用于指定随机数种子,以确保结果可重复。
#     with_labels 参数表示是否在节点上显示标签,默认为 False,即不显示标签。
#     node_color 参数表示节点的颜色,可以是一个单一的颜色值,也可以是一个颜色列表,指定每个节点的颜色。
#     在这个例子中,使用了一个颜色列表 color,它与节点数量相同,表示每个节点的颜色。
#     cmap 参数表示使用的颜色映射,用于将节点颜色映射到颜色列表中的颜色。在这个例子中,使用了颜色映射 "Set2"。

    plt.show()
    
from torch_geometric.utils import to_networkx

G = to_networkx(data, to_undirected=True)

# to_networkx(data, to_undirected=True) 是 NetworkX 库中用于将图形数据转换为 NetworkX 图形对象的函数之一。
# 其中,data 参数是要转换的数据,它可以是多种格式,如邻接矩阵、边列表、邻接列表等等。
# 具体来说,如果 data 是邻接矩阵,则需要使用 nx.from_numpy_matrix() 函数;
# 如果 data 是边列表或邻接列表,则可以使用 nx.from_edgelist() 或 nx.from_adjacency_list() 函数。

visualize_graph(G, color=data.y)

可视化node分类情况

def visualize_embedding(h, color, epoch=None, loss=None):
    plt.figure(figsize=(7,7))
    plt.xticks([])
    plt.yticks([])
    h = h.detach().cpu().numpy()
    
#     这行代码的作用是将张量h从计算图中分离(detach),并将其转换为NumPy数组(numpy()),最后将其从所在设备中移动到CPU上(cpu())。
#     分离操作是将张量从当前计算图中分离出来,使得该张量的计算不会对计算图中其他节点的梯度传播产生影响。
#     这通常用于获取模型的中间输出,以便进行后续的计算和处理,而不会影响模型的反向传播。
#     转换为NumPy数组则是将张量对象转换为NumPy数组对象,以便进行各种NumPy操作。
#     将其从设备上移动到CPU上,则是将张量从GPU等计算设备上转移到CPU上,以便进行后续的操作或输出。

    plt.scatter(h[:, 0], h[:, 1], s=140, c=color, cmap="Set2") # 散点图:取第0列;取第一列。散点大小140
    if epoch is not None and loss is not None:
        plt.xlabel(f'Epoch: {epoch}, Loss: {loss.item():.4f}', fontsize=16) # 字体大小16
    plt.show()
model = GCN()
criterion = torch.nn.CrossEntropyLoss()  # Define loss criterion.
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)  # Define optimizer.

def train(data):
    optimizer.zero_grad()  # Clear gradients.
    out, h = model(data.x, data.edge_index)  # Perform a single forward pass.
    loss = criterion(out[data.train_mask], data.y[data.train_mask])  # Compute the loss solely based on the training nodes.
    loss.backward()  # Derive gradients.
    optimizer.step()  # Update parameters based on gradients.
    return loss, h

for epoch in range(401):
    loss, h = train(data)
    if epoch % 40 == 0:
        visualize_embedding(h, color=data.y, epoch=epoch, loss=loss)

其他:
from torch.utils.tensorboard import SummaryWriter导入不成功问题

#由于pytorch本身不自带tensorboard包,一般这样报错都是由于未安装tensorboard包导致的。
#可以通过pip 加载清华镜像源进行安装
sudo pip install  -i https://mirrors.aliyun.com/pypi/simple/ tensorboard
 
如果正确安装tensorboard之后,重新运行代码,还是报错找不到在torch.utils.tensorboard中找不到SummaryWriter该怎么办。
别着急,因为SummaryWriter是存在于tensorboardX(其作为tensorboard的子模块)因此同样通过pip进行安装:
sudo pip install  -i https://mirrors.aliyun.com/pypi/simple/ tensorboardX
如果正确安装tensorboardX依旧找不到SummaryWriter
请将报错的:
        from torch.utils.tensorboard import SummaryWriter
改为:    
        from tensorboardX import SummaryWriter

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值