I trying to convert a regression model to a classification model

username: BanAckerman
cooked: <p>I have a GNN that works well however I have changed the nature of the task from regression to classification. I thought it would be as simple as converting the loss functions and output size but I am getting multiple errors. This is my code</p>
<pre><code class="lang-auto">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
</code></pre>
<pre><code class="lang-auto">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) * 10
</code></pre>
<p>The accuracy is commented out at the moment because that too gave me an error. My first error however was the following:</p>
<pre><code class="lang-auto">start training

epoch 0:
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
&lt;ipython-input-84-9de6c6dbd2ee&gt; in &lt;module&gt;
----&gt; 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)
-&gt; 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'
</code></pre>
<p>My targets are as follows:</p>
<pre><code class="lang-auto">targets = training_data['Class'].tolist()
targets = torch.Tensor(targets)
targets = targets.to(device)
</code></pre>
<p>And are just 1s and 0s.<br>
I call my model as follows:</p>
<pre><code class="lang-auto">model = GNN('sage', 3, tfeature_len, 2048, 100, 'subtract')
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
</code></pre>
<p>Anyone know how I can fix this? Real bummer</p>

username: ptrblck
cooked: <p><code>nn.NLLLoss</code> expects class indices as a <code>LongTensor</code> as the target and based on the error message you are seeing I would guess you are trying to pass a target as a <code>FloatTensor</code> to it.</p>