Trying to change graph regression model for pair of graphs to classifier

I’m trying to adapt this code that currently works for regression to work for classification but I get multiple errors, thought it would be as simple as converting the loss functions and output size but I am getting multiple errors. This is my code.

Class GNN(torch.nn.Module):
    def __init__(self, gnn, n_layer, tfeature_len, dim, mlp_hidden_unit, feature_mode):
        super(GNN, self).__init__()
        self.gnn = gnn
        self.n_layer = n_layer
        self.tfeature_len = tfeature_len
        self.dim = dim
        self.gnn_layers = ModuleList([])
        if gnn in ['gcn', 'gat', 'sage', 'tag']:
            for i in range(n_layer):
                if gnn == 'gcn':
                    self.gnn_layers.append(GraphConv(in_feats=tfeature_len if i == 0 else dim,
                                                     out_feats=dim,
                                                     activation=None if i == n_layer - 1 else torch.relu))
                elif gnn == 'gat':
                    num_heads = 16  # make sure that dim is dividable by num_heads
                    self.gnn_layers.append(GATConv(in_feats=tfeature_len if i == 0 else dim,
                                                   out_feats=dim // num_heads,
                                                   activation=None if i == n_layer - 1 else torch.relu,
                                                   num_heads=num_heads))
                elif gnn == 'sage':
                    agg = 'pool'
                    self.gnn_layers.append(SAGEConv(in_feats=tfeature_len if i == 0 else dim,
                                                    out_feats=dim,
                                                    activation=None if i == n_layer - 1 else torch.relu,
                                                    aggregator_type=agg))
                elif gnn == 'tag':
                    hops = 2
                    self.gnn_layers.append(TAGConv(in_feats=tfeature_len if i == 0 else dim,
                                                   out_feats=dim,
                                                   activation=None if i == n_layer - 1 else torch.relu,
                                                   k=hops))
        elif gnn == 'sgc':
            self.gnn_layers.append(SGConv(in_feats=tfeature_len, out_feats=dim, k=n_layer))
        else:
            raise ValueError('unknown GNN model')
        self.factor = None
        self.pooling_layer = SumPooling()

        self.mlp_hidden_unit = mlp_hidden_unit
        self.feature_mode = feature_mode
        if self.feature_mode == 'concat':
            self.mlp_hidden_layer = torch.nn.Linear(2 * self.dim, self.mlp_hidden_unit)
        elif self.feature_mode == 'subtract':
            self.mlp_hidden_layer = torch.nn.Linear(self.dim, self.mlp_hidden_unit)
        else:
            raise ValueError('unknown feature mode')
        self.mlp_output_layer = torch.nn.Linear(self.mlp_hidden_unit, 2)

    def forward(self, graph1, graph2):
        graph1_embedding = self.calculate_embedding(graph1)
        graph2_embedding = self.calculate_embedding(graph2)
        if self.feature_mode == 'concat':
            hidden = relu(self.mlp_hidden_layer(torch.concat([graph1_embedding, graph2_embedding], dim=-1)))
        elif self.feature_mode == 'subtract':
            hidden = relu(self.mlp_hidden_layer(graph1_embedding - graph2_embedding))
        else:
            raise ValueError('unknown feature mode')
        output = self.mlp_output_layer(hidden)
        return output

    def calculate_embedding(self, graph):
        feature = graph.ndata['feature']
        h = one_hot(feature, num_classes=self.tfeature_len)
        h = torch.sum(h, dim=1, dtype=torch.float)
        for layer in self.gnn_layers:
            h = layer(graph, h)
            if self.gnn == 'gat':
                h = torch.reshape(h, [h.size()[0], -1])
        if self.factor is None:
            self.factor = math.sqrt(self.dim) / float(torch.mean(torch.linalg.norm(h, dim=1)))
        h *= self.factor
        graph_embedding = self.pooling_layer(graph, h)
        return graph_embedding

def train(data,model,optimizer):
    train_loader, val_loader, test_loader, tfeature_len = data
    
    loss_fn = torch.nn.CrossEntropyLoss()
    epoch = 23
    model = model.to(device)

    print('start training\n')
    
    #evaluate(model, 'train', train_loader)
    evaluate(model, 'val', val_loader)
    evaluate(model, 'test', test_loader)

    epoch_losses = []

    for i in range(epoch):
        print('epoch %d:' % i)
        epoch_loss = 0
        model.train()
        for graph1, graph2, target in train_loader:
            pred = torch.squeeze(model(graph1, graph2))
            loss = loss_fn(pred, target)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            epoch_loss += loss.detach().item()
        epoch_loss /= (iter + 1)
        print('Epoch {}, loss {:.4f}'.format(epoch, epoch_loss))
        epoch_losses.append(epoch_loss)

        
        #evaluate(model, 'train', train_loader)
        evaluate(model, 'val', val_loader)
        evaluate(model, 'test', test_loader) 
        print()

def evaluate(model, mode, data):
    pred_list = []
    target_list = []
    model.eval()
    with torch.no_grad():
        for graph1, graph2, target in data:
            outputs = torch.softmax(model(graph1, graph2), 1)
            _, predicted = torch.max(outputs.data, 1)
            pred_list.append(predicted)
            target_list.append(target)

            #torch.sum(preds == targets).detach().cpu().numpy().
      
    pred_list = torch.concat(pred_list)
    target_list = torch.concat(target_list)
    
    #print('%s  Acc: %.4f' % (mode (sklearn.metrics.accuracy_score(target_list, pred_list, normalize=False)) / len(pred_list) * 100))

The accuracy is commented out at the moment because that too gave me an error. My first error however was the following:

start training

epoch 0:
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-84-9de6c6dbd2ee> in <module>
----> 1 train(data,model,optimizer)

3 frames
/usr/local/lib/python3.7/dist-packages/torch/nn/functional.py in cross_entropy(input, target, weight, size_average, ignore_index, reduce, reduction, label_smoothing)
   3012     if size_average is not None or reduce is not None:
   3013         reduction = _Reduction.legacy_get_string(size_average, reduce)
-> 3014     return torch._C._nn.cross_entropy_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index, label_smoothing)
   3015 
   3016 

RuntimeError: "nll_loss_forward_reduce_cuda_kernel_2d_index" not implemented for 'Float'

My targets are as follows:

targets = training_data['Class'].tolist()
targets = torch.Tensor(targets)
targets = targets.to(device)

And is just a list of 1s and 0s.

I call my model as follows:

model = GNN('sage', 3, tfeature_len, 2048, 100, 'subtract')
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)

Anyone know how I can fix this? Real bummer

Looks like the error is thrown in the loss function. Could you check the shape and data type of pred and target? I suspect your target is a float one-hot matrix, and CrossEntropyLoss should take in integers representing the class ID as target instead.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.