为什么我的pytorch几何GCNN将所有节点分类为0?

问题描述 投票:0回答:1

我是 pytorch 和 pytorch 几何的新手,我正在尝试进行节点分类。大约 5-10% 的节点应该被归类为

violates
(因为它们违反了我想要预测的条件),而其余的则不应该。违规节点依赖于距离大约 5-10 个边的节点,我不知道这个 GCN 是否可以跟踪它(如果可以,请也回答这个问题)。我使用了文档中的示例并对其进行了调整以适合我的数据。我的问题是模型只输出 0。我哪里出错了?我该从哪里开始呢?我尝试调整一些参数,但没有改变任何东西,所以我认为我使用了错误的 GCN 设置。预先感谢!

import pandas as pd
import torch
import torch.nn.functional as F
from torch_geometric.data import Data
from torch_geometric.nn import GCNConv

TOTAL_TRAINING_DATA_SIZE = 10
VALIDATION_FACTOR = 0.2
TRAINING_DATA_SIZE = int(TOTAL_TRAINING_DATA_SIZE * (1 - VALIDATION_FACTOR))


def read_graph_data(amount):
    graphs = []
    for i in range(amount):
        with pd.ExcelFile(f'training_data/test_{i}_graph_matrices.xlsx') as graph_file:
            nodes = pd.read_excel(graph_file, 'nodes', usecols=[1, 2, 3, 4, 5])
            edges = pd.read_excel(graph_file, 'edges', usecols=[1, 2])
            node_classifications = pd.read_excel(graph_file, 'classifications',
                                                 dtype={'violates': bool}, usecols=[1])

            graphs.append([nodes, edges, node_classifications])

    return graphs


def create_dataset(graphs):
    dataset = []
    for i in range(TOTAL_TRAINING_DATA_SIZE):
        nodes, edges, node_classifications = graphs[i]
        edge_index = torch.tensor(edges.values, dtype=torch.long)
        node_features = torch.tensor(nodes.values, dtype=torch.float)
        node_classifications_ = torch.tensor(node_classifications.values, dtype=torch.long).flatten()

        data = Data(x=node_features, y=node_classifications_, edge_index=edge_index.t().contiguous())

        data.validate(raise_on_error=True)
        dataset.append(data)
    return dataset


class GCN(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = GCNConv(5, 16)
        self.conv2 = GCNConv(16, 1)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index

        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)
        x = self.conv2(x, edge_index)

        return F.log_softmax(x, dim=1)


print('reading training data')
graphs = read_graph_data(TOTAL_TRAINING_DATA_SIZE)
dataset = create_dataset(graphs)

print('starting training')
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = GCN().to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, weight_decay=5e-4)

model.train()
for index in range(TRAINING_DATA_SIZE):
    data = dataset[index].to(device)
    for epoch in range(200):
        optimizer.zero_grad()
        out = model(data)
        loss = F.nll_loss(out.flatten(), data.y)
        loss.backward()
        optimizer.step()

print('starting eval')
model.eval()
all_correct = 0
eval_test_case_amount = 0
for index in range(TRAINING_DATA_SIZE, TOTAL_TRAINING_DATA_SIZE):
    data = dataset[index].to(device)
    pred = model(data).argmax(dim=1)

    print(pred.sum())  # compare the outputs (accumulated sum is enough because this line always prints 0)
    print(data.y.sum())

    comparison_correct = (pred == data.y)

    correct = comparison_correct.sum()
    all_correct += correct

    eval_test_case_amount += len(pred)
    assert (correct <= len(pred)), f'{correct} {len(pred)}'

acc = int(all_correct) / int(eval_test_case_amount)
print(f'Accuracy: {acc:.4f}')

python pytorch-geometric gnn
1个回答
0
投票

我发现了问题:

pred = model(data).argmax(dim=1)

始终输出 0,因为输出向量只有一个元素。我改变了数据的结构,现在它可以工作了。

一个有趣的评论:

F.nll_loss
无法处理目标向量中的多个维度,所以我不得不切换到
L1Loss

© www.soinside.com 2019 - 2024. All rights reserved.