我正在 Cora 数据集上训练 GCN(图卷积网络)。
Cora 数据集具有以下属性:
Number of graphs: 1
Number of features: 1433
Number of classes: 7
Number of nodes: 2708
Number of edges: 10556
Number of training nodes: 140
Training node label rate: 0.05
Is undirected: True
Data(edge_index=[2, 10556], test_mask=[2708], train_mask=[2708], val_mask=[2708], x=[2708, 1433], y=[2708])
由于我的代码很长,我只把代码的相关部分放在这里。首先,我将 Cora 数据集拆分如下:
def to_mask(index, size):
mask = torch.zeros(size, dtype=torch.bool)
mask[index] = 1
return mask
def cora_splits(data, num_classes):
indices = []
for i in range(num_classes):
# returns all indices of the elements = i from data.y tensor
index = (data.y == i).nonzero().view(-1)
# returns a random permutation of integers from 0 to index.size(0).
index = index[torch.randperm(index.size(0))]
# indices is a list of tensors and it has a length of 7
indices.append(index)
# select 20 nodes from each class for training
train_index = torch.cat([i[:20] for i in indices], dim=0)
rest_index = torch.cat([i[20:] for i in indices], dim=0)
rest_index = rest_index[torch.randperm(len(rest_index))]
data.train_mask = to_mask(train_index, size=data.num_nodes)
data.val_mask = to_mask(rest_index[:500], size=data.num_nodes)
data.test_mask = to_mask(rest_index[500:], size=data.num_nodes)
return data
train
如下(取自 here,稍作修改):
def train(model, optimizer, data, epoch):
t = time.time()
model.train()
optimizer.zero_grad()
output = model(data)
loss_train = F.nll_loss(output[data.train_mask], data.y[data.train_mask])
acc_train = accuracy(output[data.train_mask], data.y[data.train_mask])
loss_train.backward()
optimizer.step()
loss_val = F.nll_loss(output[data.val_mask], data.y[data.val_mask])
acc_val = accuracy(output[data.val_mask], data.y[data.val_mask])
def accuracy(output, labels):
preds = output.max(1)[1].type_as(labels)
correct = preds.eq(labels).double()
correct = correct.sum()
return correct / len(labels)
当我在 10 次运行中以 200 个 epoch 运行我的代码时,我获得了:
tensor([0.7690, 0.8030, 0.8530, 0.8760, 0.8600, 0.8550, 0.8850, 0.8580, 0.8940, 0.8830])
Val Loss: 0.5974, Test Accuracy: 0.854 ± 0.039
其中张量中的每个值都属于每次运行的模型精度,所有这 10 次运行的平均精度为 0.854,标准差为 0.039。
可以观察到,从第一次运行到第 10 次的准确率大幅提高。因此,我认为该模型过度拟合。过拟合的一个原因是在代码中,测试数据已经在训练时间被模型看到了,因为在train
函数中,有一条线output = model(data)
,所以模型在整个过程中被训练数据。我打算做的是仅在部分数据上训练我的模型(类似于 data[data.train_mask]
),但问题是我无法通过 data[data.train_mask]
,因为 forward
GCN
模型(来自 this repository):
def forward(self, data):
x, edge_index = data.x, data.edge_index
x = F.relu(self.conv1(x, edge_index))
for conv in self.convs:
x = F.relu(conv(x, edge_index))
x = F.relu(self.lin1(x))
x = F.dropout(x, p=0.5, training=self.training)
x = self.lin2(x)
return F.log_softmax(x, dim=-1)
如果我将 data[data.train_mask]
传递给 GCN 模型,那么在上面的 forward
函数中,x, edge_index = data.x, data.edge_index
行中的 x
和 edge_index
无法从 { {1}}。因此,我需要找到一种方法来拆分 Cora 数据集,以便我可以将其中的特定部分与节点、边缘索引和其他属性一起传递给模型。我的问题是怎么做?
此外,非常感谢有关 k 折交叉验证的任何建议。