简体   繁体   中英

Constant training and test accuracy in GCNConv

I am new to pytorch and I'm trying to write a classifier for graph data. I have a dataset of 91 adj matrices (two classes in ratio 50/41, correlation matrices obtained from fMRI data). Currently I am struggling with classification task: my training and test accuracy doesn't change, although loss looks normal (?). Here's some code of my model:

from torch.nn import Linear,Sigmoid
import torch.nn.functional as F
from torch_geometric.nn import GCNConv, BatchNorm, GraphConv
from torch_geometric.nn import global_mean_pool


class GCN(torch.nn.Module):
    def __init__(self, hidden_channels):
        super(GCN, self).__init__()
        torch.manual_seed(12345)
        self.conv1 = GCNConv(dataset.num_node_features, hidden_channels)
        self.conv2 = GCNConv(hidden_channels, hidden_channels)
        self.conv3 = GCNConv(hidden_channels, hidden_channels)
        self.lin = Linear(hidden_channels, 1)

    def forward(self, x, edge_index, edge_weight, batch):
        # 1. Obtain node embeddings 
        h = self.conv1(x, edge_index, edge_weight)
        h = h.relu()
        h = self.conv2(h, edge_index, edge_weight)
        h = h.relu()
        h = self.conv3(h, edge_index, edge_weight)
    
        # 2. Readout layer
        h = global_mean_pool(h, batch)  # [batch_size, hidden_channels]

        # 3. Apply a final classifier
        h = F.dropout(h, p=0.5, training=self.training)
        h = self.lin(h)
    
        return h

and training loop:

model = GCN(hidden_channels=32)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# criterion = torch.nn.CrossEntropyLoss()
criterion = torch.nn.BCELoss()
# criterion = torch.nn.MSELoss()

model = model.to(device)
def train():
    model.train()
    total_loss = 0
    batch_count = 0
    for data in train_loader:  # Iterate in batches over the training dataset.
        data = data.to(device)
        out = model(data.x, data.edge_index,  data.edge_weight, data.batch)  # Perform a single forward pass.
        target = data.y
        target = target.unsqueeze(1)
        target = target.float()
        loss = criterion(out, target)  # Compute the loss.
        loss.backward()  # Derive gradients.
        optimizer.step()  # Update parameters based on gradients.
        optimizer.zero_grad()  # Clear gradients.
        total_loss += loss.detach()
        batch_count += 1
    mean_loss = total_loss/batch_count
    return mean_loss

def test(loader):
    model.eval()
    correct = 0
    for data in loader:  # Iterate in batches over the training/test dataset.
    data = data.to(device)
    out = model(data.x, data.edge_index,  data.edge_weight, data.batch)  
    pred = out.argmax(dim=1)  # Use the class with highest probability.
    correct += int((pred == data.y).sum())  # Check against ground-truth labels.
    return correct / len(loader.dataset)  # Derive ratio of correct predictions.

test_acc_summ = []
train_acc_summ = []
loss_summ = []
for epoch in range(1, 100):
    loss = train()
    train_acc = test(train_loader)
    test_acc = test(test_loader)
    test_acc_summ.append(test_acc)
    train_acc_summ.append(train_acc)
    loss_summ.append(loss)
    print(f'Epoch: {epoch:03d}, Train Acc: {train_acc:.4f}, Test Acc: {test_acc:.4f}, Loss: {loss:.4f}')

The output I'm getting:

Epoch: 001, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 1.0981
Epoch: 002, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 1.0983
Epoch: 003, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 1.1312
Epoch: 004, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 1.0880
Epoch: 005, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 0.8857
Epoch: 006, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 0.9774
Epoch: 007, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 0.8917
Epoch: 008, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 0.8679
Epoch: 009, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 0.9000
Epoch: 010, Train Acc: 0.4568, Test Acc: 0.3000, Loss: 0.8371

Train and Test acc remains constant regardless of epochs number, but loss decreases. Is there some bug i don't see, or there's more complex problem?

Try to add nn.Sigmoid() on top of self.lin output and remove dropout

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM