斯坦福cs224w图机器学习课程colab2

斯坦福cs224w图机器学习课程colab2

参考 github.com/hdvvip/CS224

环境

python3.9.7 , PyTorch has version 1.10.2

遇到了问题undefined symbol, 可以参考下面.

github.com/pyg-team/pyt

# 激活环境后
conda install ogb
PackagesNotFoundError: The following packages are not available from current channels
#在anaconda 的官网尝试
conda install -c conda-forge ogb
#可以了

有两种类, 一个是datasets, 有一些常用数据集 一个是data, 可以把图变成tensor.

PyG dataset 是一个list,存储 torch_geometric.data.Data 对象

pyg_dataset.num_classes # 标签数量
num_features = pyg_dataset.num_features # Node的特征维数
label = pyg_dataset[idx] # 获取graph
num_edges = pyg_dataset[idx].edge_index.shape[1] // 2

统计无向图的edge数量需要 //2 edge_index 是二维tensor数组,第一行是start node,第二行是end node

600个图在ENZYMES数据集 ENZYMES dataset has 6 classes ENZYMES dataset has 3 features

Graph with index 100 has label Data(edge_index=[2, 176], x=[45, 3], y=[1])

Graph with index 200 has 53 edges

OGB

一个benchmark 数据集, 大量的开源Graph数据集,使用OGB Data Loader 可以自动下载,处理,划分数据集,还可以用OGB Evaluator进行校验

OGB也支持PyG dataset 和 Data

The ogbn-arxiv dataset has 1 graph Data(x=[169343, 128], node_year=[169343, 1], y=[169343, 1], adj_t=[169343, 169343, nnz=1166243])

nn和 nn.Functional的区别?

nn.Xxx 需要先实例化并传入参数,然后以函数调用的方式调用实例化的对象并传入输入数据。

nn.Xxx 继承于 nn.Module , 能够很好的与 nn.Sequential 结合使用, 而 nn.functional.xxx 无法与 nn.Sequential 结合使用。

nn.Xxx 不需要你自己定义和管理weight;而 nn.functional.xxx 需要你自己定义weight,每次调用的时候都需要手动传入weight, 不利于代码复用。

PyTorch官方推荐:具有学习参数的(例如,conv2d, linear, batch_norm)采用 nn.Xxx 方式,没有学习参数的(例如,maxpool, loss func, activation func)等根据个人选择使用 nn.functional.xxx 或者 nn.Xxx 方式。但关于dropout,个人强烈推荐使用 nn.Xxx 方式,因为一般情况下只有训练阶段才进行dropout,在eval阶段都不会进行dropout。在 nn.Xxx 不能满足你的功能需求时, nn.functional.xxx 是更佳的选择,因为 nn.functional.xxx 更加的灵活(更加接近底层),你可以在其基础上定义出自己想要的功能。

dropout

防止过拟合的一种方法 ,随机把一些参数设置为0 , 减少参数数量, 降低模型复杂度.

x = F.dropout(x, p=self.dropout, training=self.training)

GCN网络

首先在init函数里定义好每一层的参数,并且使用torch.nn.ModuleList保存Conv和bn对象。

对于GCNConv来说,由于网络的输入,输出和隐藏层维度不同,所以需要分别定义第一层,中间层和最后一层,它们的in_channels 和 out_channels 不同。

BN层使用torch.nn.BatchNorm1d, 只需要num_features 作为输入, 也就是当前层的特征维度 (hidden_dim)

Softmax函数使用了torch.nn.LogSoftmax,并定义dropout的概率

data 128 torch.Size([169343, 128])

data是一个图, 表示为一个tensor, 有16w个节点,每个节点128个feature. x就是二维的tensor 16w* 128 , adj_t 也是tensor 16w * 16w.

forward不会写, edge_index tensor adj_t 有什么用?

GCNConv需要邻接矩阵. forward一层层连起来就可以了。

示意图中间这三个点是啥?

就是每一层都和第一层一样

BN是啥?

有时一个向量里的元素值太大或者太小。就把一个batch中的每个tensor的第一个元素都归一化, 然后对每个tensor的第二个元素都归一化, 以此类推。

BN num_features 是多少呢?

是hidden dim , 为什么呢? 因为BN 连在 GCNconv的后面.

TypeError: append() missing 1 required positional argument: 'module'?

应该 self.convs = torch.nn.ModuleList() , 没有括号就是一个类。

train函数

out = model(data.x, data.adj_t) 为什么model是传这两个?

会自动执行forward

因为 PyTorch 中的大部分方法都继承自 torch.nn.Module,而 torch.nn.Module 的__call__(self)函数中会返回 forward()函数 的结果,因此PyTroch中的 forward()函数等于是被嵌套在了__call__(self)函数中;因此forward()函数可以直接通过类名被调用,而不用实例化对象

x是啥?

x是节点的特征向量 ,y是标签

为什么要squeeze?

pytorch.org/docs/stable 去掉维度为1 的维度, 在给定的维度进行一个挤压操作. 你可以把这个squeeze去掉看看会报什么错

y = x.squeeze(1) 等价于 y = torch.squeeze(x, 1)

报错: RuntimeError: 0D or 1D target tensor expected, multi-target not supported. 需要变成1维

val是训练过程中的测试集,是为了让你在边训练边看到训练的结果,及时判断学习状态。 test 就是训练模型结束后,用于评价模型结果的测试

Epoch: 01, Loss: 4.1908, Train: 25.46%, Valid: 28.79% Test: 25.75%
Epoch: 02, Loss: 2.3507, Train: 22.43%, Valid: 21.17% Test: 26.66%
Epoch: 03, Loss: 1.9348, Train: 32.51%, Valid: 26.68% Test: 31.12%
Epoch: 04, Loss: 1.7861, Train: 33.88%, Valid: 21.63% Test: 18.61%
Epoch: 05, Loss: 1.6681, Train: 35.50%, Valid: 24.05% Test: 21.02%
Epoch: 06, Loss: 1.5779, Train: 36.02%, Valid: 26.58% Test: 25.52%
Epoch: 07, Loss: 1.5019, Train: 36.38%, Valid: 30.07% Test: 31.83%
Epoch: 08, Loss: 1.4513, Train: 37.16%, Valid: 34.15% Test: 38.13%
Epoch: 09, Loss: 1.4104, Train: 38.04%, Valid: 36.17% Test: 41.44%
Epoch: 10, Loss: 1.3717, Train: 38.18%, Valid: 35.10% Test: 41.04%
Epoch: 11, Loss: 1.3339, Train: 38.92%, Valid: 34.80% Test: 40.79%
Epoch: 12, Loss: 1.3157, Train: 40.44%, Valid: 36.50% Test: 42.53%
Epoch: 13, Loss: 1.2892, Train: 42.95%, Valid: 40.94% Test: 46.42%

图属性预测

ogbg-molhiv是个较小的分子属性预测数据集,用于图分类任务(二元分类)。有41,127个无向图,平均每个图有25.5个节点、13.75个边。任务目标是二元分类。评估指标是ROC-AUC。节点有9维特征

Task type: binary classification

加载dataset , 设置好device , 设置好split, dataset有一个属性是任务类型.

然后加载dataset到pyG.data 的DataLoader中, 有train, 验证, 测试三种dataloader. 这时候要设置一个batch 32个graph, 训练的时候要shuffle 图的顺序.

torch_geometric.data.Batch 有一个属性是batch, 标出每个节点属于哪个batch

0 0 0 1 n-2

比如第一个0是指第一个节点属于第0个batch

首先使用AtomEncoder, 将节点属性和边属性分别映射到一个新的空间,在这个新的空间中,就可以对节点和边进行信息融合。这里只需要hidden_dim,会把输入x处理成hidden_dim的维度,不需要input_dim

然后用前面GCN的框架做Node embedding

关键用global mean pooling, 对输出的所有node_feature 做平均,得到graph的特征

self.pool = global_mean_pool(hidden_dim,)
# 这个参数应该填写啥? 
其实啥也不用填, 就直接
self.pool = global_mean_pool

ImportError: IProgress not found. Please update jupyter and ipywidgets?

我尝试安装一下. conda install -c conda-forge ipywidgets

out = model(batch) 这个该填什么参数?

看forward的参数设计即可.

t = t.float()    #'float32'
t = t.double()   #'float64'

Iteration: 0%| | 0/1029 [00:00<?, ?it/s]

为啥不是30个epoch?

因为是minibatch 1029个.

为啥迭代不动?

试试把batch size变小

if step % 100 ==0:
    print(loss)# 常用的输出.
    #loss 不变小. 为啥呢?