Pytorch Geometric - Graph Classification Issue - Train loader mixes graphs

I am trying to run a graph classification problem. For testing purposes, I am using a list of data objects, each of which looks like:

dataset = produceDataset(directory_path,
                      embeddings_path,
                      user_features_path,
                      labels_path,
                      train_frac=0.6,
                      val_frac=0.2,
                      binary_classification=True)
dataset[0]
Data(edge_attr=[1306, 1], edge_index=[2, 1306], x=[1281, 768], y=[1])

The structure of my data is a set of N graphs and N binary labels for each. I am not sure if the above structure is correctly created.

Then I build the loaders and assign pieces of the list for training and testing:

train_dataset, test_dataset = dataset[:2], dataset[2:]

train_loader = DataLoader(train_dataset,
                         batch_size=2,
                         shuffle=True)
test_loader = DataLoader(test_dataset,
                         batch_size=1,
                         shuffle=False)

I define the model:

class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = GCNConv(768, 16)
        self.conv2 = GCNConv(16, 2)

    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.softmax(x, dim=1)

and try to train it:

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = Net().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

model = Net().to(device)

def train():
    model.train()
    for data in train_loader:
        data_cuda = data.to(device)
        optimizer.zero_grad()
        out = model(data_cuda)#.unsqueeze(0).type(torch.float).mean(1).type(torch.int32).type(torch.float)
        y = data_cuda.y.type(torch.long)
        loss = CrossEntropyLoss(out, y)
        optimizer.step()

def test(loader):
    correct = []
    for data in loader:
        model.eval()
        data_cuda = data.to(device)
        pred = model(data_cuda).unsqueeze(0).type(torch.int32)
        correct += [1 if pred.eq(data_cuda.y).item() else 0]
        
    acc = sum(correct) / len(data)
    print('Accuracy: {:.4f}'.format(acc))

for epoch in range(1, 21):
    train()
    
test(test_loader)

I don’t know if the output of my model is correct for my task, it’s most likely not, as if I print the shapes of
out and y from the train method, they look like:

torch.Size([1484, 2])
torch.Size([2])

So I see that, for a batch size of 2, the node feature matrix just gets stacked, lacking a batch dimension. This is the first time I’m using Pytorch Geometric, and I am trying to understand this code, since I need to work on it for a project. Can someone please help me in getting it running? :frowning:

EDIT

I tried transposing the output. Now out and y are of shapes:

torch.Size([2, 1484])
torch.Size([2])

but when I pass them to the CrossEntropyLoss, I get:

RuntimeError: bool value of Tensor with more than one value is ambiguous

However, if I test this code:

loss = CrossEntropyLoss()
input = torch.randn(3, 15, requires_grad=True)
target = torch.empty(3, dtype=torch.long).random_(5)
output = loss(input, target)

the shapes of input and target are:

torch.Size([3, 15])
torch.Size([3])

And it does work. I really don’t understand what’s wrong.

It looks like you need the readout phase to average node embeddings and have a single prediction for each graph