GitHub
  
  
    

rusty1s/pytorch_geometric 1

Geometric Deep Learning Extension Library for PyTorch - rusty1s/pytorch_geometric


  
  
    
    
  
  


Dear all,  i intend to replicated the example by using GCN model for IMDB-Binary. however, i am not able to print the accuracy and epoch loop at the end, some guidance pls
Loading data:
import argparse

import torch

import torch.nn.functional as F

from torch.nn import Linear as Lin

from torch_geometric.nn import XConv, fps, global_mean_pool

from points.datasets import get_dataset

from points.train_eval import run

parser = argparse.ArgumentParser()

parser.add_argument('--epochs', type=int, default=200)

parser.add_argument('--batch_size', type=int, default=32)

parser.add_argument('--lr', type=float, default=0.001)

parser.add_argument('--lr_decay_factor', type=float, default=0.5)

parser.add_argument('--lr_decay_step_size', type=int, default=50)

parser.add_argument('--weight_decay', type=float, default=0)

args = parser.parse_args()

class Net(torch.nn.Module):

    def __init__(self, num_classes):

        super(Net, self).__init__()

        self.conv1 = XConv(0, 48, dim=3, kernel_size=8, hidden_channels=32)

        self.conv2 = XConv(

            48, 96, dim=3, kernel_size=12, hidden_channels=64, dilation=2)

        self.conv3 = XConv(

            96, 192, dim=3, kernel_size=16, hidden_channels=128, dilation=2)

        self.conv4 = XConv(

            192, 384, dim=3, kernel_size=16, hidden_channels=256, dilation=2)

        self.lin1 = Lin(384, 256)

        self.lin2 = Lin(256, 128)

        self.lin3 = Lin(128, num_classes)

    def forward(self, pos, batch):

        x = F.relu(self.conv1(None, pos, batch))

        idx = fps(pos, batch, ratio=0.375)

        x, pos, batch = x[idx], pos[idx], batch[idx]

        x = F.relu(self.conv2(x, pos, batch))

        idx = fps(pos, batch, ratio=0.334)

        x, pos, batch = x[idx], pos[idx], batch[idx]

        x = F.relu(self.conv3(x, pos, batch))

        x = F.relu(self.conv4(x, pos, batch))

        x = global_mean_pool(x, batch)

        x = F.relu(self.lin1(x))

        x = F.relu(self.lin2(x))

        x = F.dropout(x, p=0.5, training=self.training)

        x = self.lin3(x)

        return F.log_softmax(x, dim=-1)

train_dataset, test_dataset = get_dataset(num_points=1024)

model = Net(train_dataset.num_classes)

run(train_dataset, test_dataset, model, args.epochs, args.batch_size, args.lr,

    args.lr_decay_factor, args.lr_decay_step_size, args.weight_decay)

GCN: 
import torch

import torch.nn.functional as F

from torch.nn import Linear

from torch_geometric.nn import GCNConv, global_mean_pool, JumpingKnowledge

class GCN(torch.nn.Module):

    def __init__(self, dataset, num_layers, hidden):

        super(GCN, self).__init__()

        self.conv1 = GCNConv(dataset.num_features, hidden)

        self.convs = torch.nn.ModuleList()

        for i in range(num_layers - 1):

            self.convs.append(GCNConv(hidden, hidden))

        self.lin1 = Linear(hidden, hidden)

        self.lin2 = Linear(hidden, dataset.num_classes)

    def reset_parameters(self):

        self.conv1.reset_parameters()

        for conv in self.convs:

            conv.reset_parameters()

        self.lin1.reset_parameters()

        self.lin2.reset_parameters()

    def forward(self, data):

        x, edge_index, batch = data.x, data.edge_index, data.batch

        x = F.relu(self.conv1(x, edge_index))

        for conv in self.convs:

            x = F.relu(conv(x, edge_index))

        x = global_mean_pool(x, batch)

        x = F.relu(self.lin1(x))

        x = F.dropout(x, p=0.5, training=self.training)

        x = self.lin2(x)

        return F.log_softmax(x, dim=-1)

    def __repr__(self):

        return self.__class__.__name__

class GCNWithJK(torch.nn.Module):

    def __init__(self, dataset, num_layers, hidden, mode='cat'):

        super(GCNWithJK, self).__init__()

        self.conv1 = GCNConv(dataset.num_features, hidden)

        self.convs = torch.nn.ModuleList()

        for i in range(num_layers - 1):

            self.convs.append(GCNConv(hidden, hidden))

        self.jump = JumpingKnowledge(mode)

        if mode == 'cat':

            self.lin1 = Linear(num_layers * hidden, hidden)

        else:

            self.lin1 = Linear(hidden, hidden)

        self.lin2 = Linear(hidden, dataset.num_classes)

    def reset_parameters(self):

        self.conv1.reset_parameters()

        for conv in self.convs:

            conv.reset_parameters()

        self.jump.reset_parameters()

        self.lin1.reset_parameters()

        self.lin2.reset_parameters()

    def forward(self, data):

        x, edge_index, batch = data.x, data.edge_index, data.batch

        x = F.relu(self.conv1(x, edge_index))

        xs = [x]

        for conv in self.convs:

            x = F.relu(conv(x, edge_index))

            xs += [x]

        x = self.jump(xs)

        x = global_mean_pool(x, batch)

        x = F.relu(self.lin1(x))

        x = F.dropout(x, p=0.5, training=self.training)

        x = self.lin2(x)

        return F.log_softmax(x, dim=-1)

    def __repr__(self):

        return self.__class__.__name__

Validation:
import time

import torch

import torch.nn.functional as F

from torch import tensor

from torch.optim import Adam

from sklearn.model_selection import StratifiedKFold

from torch_geometric.data import DataLoader, DenseDataLoader as DenseLoader

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

def cross_validation_with_val_set(dataset, model, folds, epochs, batch_size,

                                  lr, lr_decay_factor, lr_decay_step_size,

                                  weight_decay, logger=None):

    val_losses, accs, durations = [], [], []

    for fold, (train_idx, test_idx,

               val_idx) in enumerate(zip(*k_fold(dataset, folds))):

        train_dataset = dataset[train_idx]

        test_dataset = dataset[test_idx]

        val_dataset = dataset[val_idx]

        if 'adj' in train_dataset[0]:

            train_loader = DenseLoader(train_dataset, batch_size, shuffle=True)

            val_loader = DenseLoader(val_dataset, batch_size, shuffle=False)

            test_loader = DenseLoader(test_dataset, batch_size, shuffle=False)

        else:

            train_loader = DataLoader(train_dataset, batch_size, shuffle=True)

            val_loader = DataLoader(val_dataset, batch_size, shuffle=False)

            test_loader = DataLoader(test_dataset, batch_size, shuffle=False)

        model.to(device).reset_parameters()

        optimizer = Adam(model.parameters(), lr=lr, weight_decay=weight_decay)

        if torch.cuda.is_available():

            torch.cuda.synchronize()

        t_start = time.perf_counter()

        for epoch in range(1, epochs + 1):

            train_loss = train(model, optimizer, train_loader)

            val_losses.append(eval_loss(model, val_loader))

            accs.append(eval_acc(model, test_loader))

            eval_info = {

                'fold': fold,

                'epoch': epoch,

                'train_loss': train_loss,

                'val_loss': val_losses[-1],

                'test_acc': accs[-1],

            }

            if logger is not None:

                logger(eval_info)

            if epoch % lr_decay_step_size == 0:

                for param_group in optimizer.param_groups:

                    param_group['lr'] = lr_decay_factor * param_group['lr']

        if torch.cuda.is_available():

            torch.cuda.synchronize()

        t_end = time.perf_counter()

        durations.append(t_end - t_start)

    loss, acc, duration = tensor(val_losses), tensor(accs), tensor(durations)

    loss, acc = loss.view(folds, epochs), acc.view(folds, epochs)

    loss, argmin = loss.min(dim=1)

    acc = acc[torch.arange(folds, dtype=torch.long), argmin]

    loss_mean = loss.mean().item()

    acc_mean = acc.mean().item()

    acc_std = acc.std().item()

    duration_mean = duration.mean().item()

    print('Val Loss: {:.4f}, Test Accuracy: {:.3f} ± {:.3f}, Duration: {:.3f}'.

          format(loss_mean, acc_mean, acc_std, duration_mean))

    return loss_mean, acc_mean, acc_std

def k_fold(dataset, folds):

    skf = StratifiedKFold(folds, shuffle=True, random_state=12345)

    test_indices, train_indices = [], []

    for _, idx in skf.split(torch.zeros(len(dataset)), dataset.data.y):

        test_indices.append(torch.from_numpy(idx))

    val_indices = [test_indices[i - 1] for i in range(folds)]

    for i in range(folds):

        train_mask = torch.ones(len(dataset), dtype=torch.bool)

        train_mask[test_indices[i]] = 0

        train_mask[val_indices[i]] = 0

        train_indices.append(train_mask.nonzero().view(-1))

    return train_indices, test_indices, val_indices

def num_graphs(data):

    if data.batch is not None:

        return data.num_graphs

    else:

        return data.x.size(0)

def train(model, optimizer, loader):

    model.train()

    total_loss = 0

    for data in loader:

        optimizer.zero_grad()

        data = data.to(device)

        out = model(data)

        loss = F.nll_loss(out, data.y.view(-1))

        loss.backward()

        total_loss += loss.item() * num_graphs(data)

        optimizer.step()

    return total_loss / len(loader.dataset)

def eval_acc(model, loader):

    model.eval()

    correct = 0

    for data in loader:

        data = data.to(device)

        with torch.no_grad():

            pred = model(data).max(1)[1]

        correct += pred.eq(data.y.view(-1)).sum().item()

    return correct / len(loader.dataset)

def eval_loss(model, loader):

    model.eval()

    loss = 0

    for data in loader:

        data = data.to(device)

        with torch.no_grad():

            out = model(data)

        loss += F.nll_loss(out, data.y.view(-1), reduction='sum').item()

    return loss / len(loader.dataset)