Understanding Information Aggregation by applying SAGE convolution layer on Cora dataset
# torch geometric
try:
import torch_geometric
except ModuleNotFoundError:
# Installing torch geometric packages with specific CUDA+PyTorch version.
# See https://pytorch-geometric.readthedocs.io/en/latest/notes/installation.html for details
import torch
TORCH = torch.__version__.split('+')[0]
CUDA = 'cu' + torch.version.cuda.replace('.','')
!pip install torch-scatter -f https://pytorch-geometric.com/whl/torch-{TORCH}+{CUDA}.html
!pip install torch-sparse -f https://pytorch-geometric.com/whl/torch-{TORCH}+{CUDA}.html
!pip install torch-cluster -f https://pytorch-geometric.com/whl/torch-{TORCH}+{CUDA}.html
!pip install torch-spline-conv -f https://pytorch-geometric.com/whl/torch-{TORCH}+{CUDA}.html
!pip install torch-geometric
import torch_geometric
import torch_geometric.nn as geom_nn
import torch_geometric.data as geom_data
import os.path as osp
import torch
import torch.nn.functional as F
import torch_geometric
from torch_geometric.datasets import Planetoid
from torch_geometric.nn import SAGEConv
use_cuda_if_available = False
dataset = Planetoid(root="/content/cora", name= "Cora")
Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.cora.x Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.cora.tx Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.cora.allx Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.cora.y Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.cora.ty Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.cora.ally Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.cora.graph Downloading https://github.com/kimiyoung/planetoid/raw/master/data/ind.cora.test.index Processing... Done!
print(dataset)
print("number of graphs:\t\t",len(dataset))
print("number of classes:\t\t",dataset.num_classes)
print("number of node features:\t",dataset.num_node_features)
print("number of edge features:\t",dataset.num_edge_features)
Cora() number of graphs: 1 number of classes: 7 number of node features: 1433 number of edge features: 0
print(dataset.data)
Data(x=[2708, 1433], edge_index=[2, 10556], y=[2708], train_mask=[2708], val_mask=[2708], test_mask=[2708])
print("edge_index:\t\t",dataset.data.edge_index.shape)
print(dataset.data.edge_index)
print("\n")
print("train_mask:\t\t",dataset.data.train_mask.shape)
print(dataset.data.train_mask)
print("\n")
print("x:\t\t",dataset.data.x.shape)
print(dataset.data.x)
print("\n")
print("y:\t\t",dataset.data.y.shape)
print(dataset.data.y)
edge_index: torch.Size([2, 10556]) tensor([[ 0, 0, 0, ..., 2707, 2707, 2707], [ 633, 1862, 2582, ..., 598, 1473, 2706]]) train_mask: torch.Size([2708]) tensor([ True, True, True, ..., False, False, False]) x: torch.Size([2708, 1433]) tensor([[0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], ..., [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]) y: torch.Size([2708]) tensor([3, 4, 4, ..., 3, 3, 3])
data = dataset[0]
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv = SAGEConv(dataset.num_features,
dataset.num_classes,
aggr="max") # max, mean, add ...)
def forward(self):
x = self.conv(data.x, data.edge_index)
return F.log_softmax(x, dim=1)
device = torch.device('cuda' if torch.cuda.is_available() and use_cuda_if_available else 'cpu')
model, data = Net().to(device), data.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
device
device(type='cpu')
def train():
model.train()
optimizer.zero_grad()
F.nll_loss(model()[data.train_mask], data.y[data.train_mask]).backward()
optimizer.step()
def test():
model.eval()
logits, accs = model(), []
for _, mask in data('train_mask', 'val_mask', 'test_mask'):
pred = logits[mask].max(1)[1]
acc = pred.eq(data.y[mask]).sum().item() / mask.sum().item()
accs.append(acc)
return accs
best_val_acc = test_acc = 0
for epoch in range(1,100):
train()
_, val_acc, tmp_test_acc = test()
if val_acc > best_val_acc:
best_val_acc = val_acc
test_acc = tmp_test_acc
log = 'Epoch: {:03d}, Val: {:.4f}, Test: {:.4f}'
if epoch % 10 == 0:
print(log.format(epoch, best_val_acc, test_acc))
Epoch: 010, Val: 0.7220, Test: 0.7220 Epoch: 020, Val: 0.7220, Test: 0.7220 Epoch: 030, Val: 0.7220, Test: 0.7220 Epoch: 040, Val: 0.7220, Test: 0.7220 Epoch: 050, Val: 0.7220, Test: 0.7220 Epoch: 060, Val: 0.7220, Test: 0.7220 Epoch: 070, Val: 0.7280, Test: 0.7130 Epoch: 080, Val: 0.7300, Test: 0.7150 Epoch: 090, Val: 0.7300, Test: 0.7150
%%writefile src/datasets/vectorial.py
import torch.nn as nn
import torch
#%% Dataset to manage vector to vector data
class VectorialDataset(torch.utils.data.Dataset):
def __init__(self, input_data, output_data):
super(VectorialDataset, self).__init__()
self.input_data = torch.tensor(input_data.astype('f'))
self.output_data = torch.tensor(output_data.astype('f'))
def __len__(self):
return self.input_data.shape[0]
def __getitem__(self, idx):
if torch.is_tensor(idx):
idx = idx.tolist()
sample = (self.input_data[idx, :],
self.output_data[idx, :])
return sample
Writing src/datasets/vectorial.py
%%writefile src/datasets/__init__.py
from .vectorial import VectorialDataset
Writing src/datasets/__init__.py
%%writefile src/models/linear.py
import torch.nn as nn
import torch
#%% Linear layer
class LinearModel(nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearModel, self).__init__()
self.input_dim = input_dim
self.output_dim = output_dim
self.linear = nn.Linear(self.input_dim, self.output_dim, bias=True)
def forward(self, x):
out = self.linear(x)
return out
def reset(self):
self.linear.reset_parameters()
Writing src/models/linear.py
%%writefile src/models/__init__.py
from .linear import LinearModel
Writing src/models/__init__.py
!pip install -q watermark
%reload_ext watermark
%watermark -a "Sparsh A." -m -iv -u -t -d
Author: Sparsh A. Last updated: 2021-12-05 18:58:56 Compiler : GCC 7.5.0 OS : Linux Release : 5.4.104+ Machine : x86_64 Processor : x86_64 CPU cores : 2 Architecture: 64bit IPython : 5.5.0 torch_geometric: 2.0.2 torch : 1.10.0+cu111
END