Unverified Commit 117dd252 authored by Quan (Andy) Gan's avatar Quan (Andy) Gan Committed by GitHub
Browse files

[Doc] Fix inconsistencies and GPU code (#2642)

* fix inconsistencies and GPu

* bug fixes

* fix

* trigger new tutorials
parent 8ccb8206
......@@ -182,7 +182,7 @@ optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
for epoch in range(20):
for batched_graph, labels in train_dataloader:
pred = model(batched_graph, batched_graph.ndata['attr'])
pred = model(batched_graph, batched_graph.ndata['attr'].float())
loss = F.cross_entropy(pred, labels)
optimizer.zero_grad()
loss.backward()
......@@ -191,7 +191,7 @@ for epoch in range(20):
num_correct = 0
num_tests = 0
for batched_graph, labels in test_dataloader:
pred = model(batched_graph, batched_graph.ndata['attr'])
pred = model(batched_graph, batched_graph.ndata['attr'].float())
num_correct += (pred.argmax(1) == labels).sum().item()
num_tests += len(labels)
......
......@@ -3,9 +3,9 @@ Training GNN with Neighbor Sampling for Node Classification
===========================================================
This tutorial shows how to train a multi-layer GraphSAGE for node
classification on Amazon Co-purchase Network provided by `Open Graph
Benchmark (OGB) <https://ogb.stanford.edu/>`__. The dataset contains 2.4
million nodes and 61 million edges.
classification on ``ogbn-arxiv`` provided by `Open Graph
Benchmark (OGB) <https://ogb.stanford.edu/>`__. The dataset contains around
170 thousand nodes and 1 million edges.
By the end of this tutorial, you will be able to
......@@ -30,16 +30,19 @@ import torch
import numpy as np
from ogb.nodeproppred import DglNodePropPredDataset
dataset = DglNodePropPredDataset('ogbn-products')
dataset = DglNodePropPredDataset('ogbn-arxiv')
device = 'cpu' # change to 'cuda' for GPU
######################################################################
# OGB dataset is a collection of graphs and their labels. The Amazon
# Co-purchase Network dataset only contains a single graph. So you can
# OGB dataset is a collection of graphs and their labels. ``ogbn-arxiv``
# dataset only contains a single graph. So you can
# simply get the graph and its node labels like this:
#
graph, node_labels = dataset[0]
# Add reverse edges since ogbn-arxiv is unidirectional.
graph = dgl.add_reverse_edges(graph)
graph.ndata['label'] = node_labels[:, 0]
print(graph)
print(node_labels)
......@@ -110,7 +113,7 @@ train_dataloader = dgl.dataloading.NodeDataLoader(
graph, # The graph
train_nids, # The node IDs to iterate over in minibatches
sampler, # The neighbor sampler
device='cuda', # Put the sampled bipartite graphs to GPU
device=device, # Put the sampled bipartite graphs on CPU or GPU
# The following arguments are inherited from PyTorch DataLoader.
batch_size=1024, # Batch size
shuffle=True, # Whether to shuffle the nodes for every epoch
......@@ -184,7 +187,7 @@ class Model(nn.Module):
h = self.conv2(bipartites[1], (h, h_dst)) # <---
return h
model = Model(num_features, 128, num_classes).cuda()
model = Model(num_features, 128, num_classes).to(device)
######################################################################
......@@ -255,7 +258,8 @@ valid_dataloader = dgl.dataloading.NodeDataLoader(
batch_size=1024,
shuffle=False,
drop_last=False,
num_workers=0
num_workers=0,
device=device
)
......@@ -295,9 +299,8 @@ for epoch in range(10):
labels = []
with tqdm.tqdm(valid_dataloader) as tq, torch.no_grad():
for input_nodes, output_nodes, bipartites in tq:
bipartites = [b.to(torch.device('cuda')) for b in bipartites]
inputs = node_features[input_nodes].cuda()
labels.append(node_labels[output_nodes].numpy())
inputs = bipartites[0].srcdata['feat']
labels.append(bipartites[-1].dstdata['label'].cpu().numpy())
predictions.append(model(bipartites, inputs).argmax(1).cpu().numpy())
predictions = np.concatenate(predictions)
labels = np.concatenate(labels)
......
......@@ -3,9 +3,9 @@ Stochastic Training of GNN for Link Prediction
==============================================
This tutorial will show how to train a multi-layer GraphSAGE for link
prediction on Amazon Co-purchase Network provided by `Open Graph Benchmark
prediction on ``ogbn-arxiv`` provided by `Open Graph Benchmark
(OGB) <https://ogb.stanford.edu/>`__. The dataset
contains 2.4 million nodes and 61 million edges.
contains around 170 thousand nodes and 1 million edges.
By the end of this tutorial, you will be able to
......@@ -57,9 +57,12 @@ import torch
import numpy as np
from ogb.nodeproppred import DglNodePropPredDataset
dataset = DglNodePropPredDataset('ogbn-products')
dataset = DglNodePropPredDataset('ogbn-arxiv')
device = 'cpu' # change to 'cuda' for GPU
graph, node_labels = dataset[0]
# Add reverse edges since ogbn-arxiv is unidirectional.
graph = dgl.add_reverse_edges(graph)
print(graph)
print(node_labels)
......@@ -114,7 +117,7 @@ train_dataloader = dgl.dataloading.EdgeDataLoader(
torch.arange(graph.number_of_edges()), # The edges to iterate over
sampler, # The neighbor sampler
negative_sampler=negative_sampler, # The negative sampler
device='cuda', # Put the bipartite graphs on GPU
device=device, # Put the bipartite graphs on CPU or GPU
# The following arguments are inherited from PyTorch DataLoader.
batch_size=1024, # Batch size
shuffle=True, # Whether to shuffle the nodes for every epoch
......@@ -185,7 +188,7 @@ class Model(nn.Module):
h = self.conv2(bipartites[1], (h, h_dst))
return h
model = Model(num_features, 128).cuda()
model = Model(num_features, 128).to(device)
######################################################################
......@@ -250,7 +253,7 @@ def inference(model, graph, node_features):
shuffle=False,
drop_last=False,
num_workers=4,
device='cuda')
device=device)
result = []
for input_nodes, output_nodes, bipartites in train_dataloader:
......@@ -263,12 +266,12 @@ def inference(model, graph, node_features):
import sklearn.metrics
def evaluate(emb, label, train_nids, valid_nids, test_nids):
classifier = nn.Linear(emb.shape[1], label.max().item()).cuda()
classifier = nn.Linear(emb.shape[1], num_classes).to(device)
opt = torch.optim.LBFGS(classifier.parameters())
def compute_loss():
pred = classifier(emb[train_nids].cuda())
loss = F.cross_entropy(pred, label[train_nids].cuda())
pred = classifier(emb[train_nids].to(device))
loss = F.cross_entropy(pred, label[train_nids].to(device))
return loss
def closure():
......@@ -289,7 +292,7 @@ def evaluate(emb, label, train_nids, valid_nids, test_nids):
prev_loss = loss
with torch.no_grad():
pred = classifier(emb.cuda()).cpu()
pred = classifier(emb.to(device)).cpu()
label = label
valid_acc = sklearn.metrics.accuracy_score(label[valid_nids].numpy(), pred[valid_nids].numpy().argmax(1))
test_acc = sklearn.metrics.accuracy_score(label[test_nids].numpy(), pred[test_nids].numpy().argmax(1))
......@@ -303,8 +306,8 @@ def evaluate(emb, label, train_nids, valid_nids, test_nids):
# The following initializes the model and defines the optimizer.
#
model = Model(node_features.shape[1], 128).cuda()
predictor = DotPredictor().cuda()
model = Model(node_features.shape[1], 128).to(device)
predictor = DotPredictor().to(device)
opt = torch.optim.Adam(list(model.parameters()) + list(predictor.parameters()))
......@@ -339,7 +342,7 @@ for epoch in range(1):
tq.set_postfix({'loss': '%.03f' % loss.item()}, refresh=False)
if step % 1000 == 999:
if (step + 1) % 500 == 0:
model.eval()
emb = inference(model, graph, node_features)
valid_acc, test_acc = evaluate(emb, node_labels, train_nids, valid_nids, test_nids)
......
......@@ -18,9 +18,13 @@ import torch
import numpy as np
from ogb.nodeproppred import DglNodePropPredDataset
dataset = DglNodePropPredDataset('ogbn-products')
dataset = DglNodePropPredDataset('ogbn-arxiv')
device = 'cpu' # change to 'cuda' for GPU
graph, node_labels = dataset[0]
# Add reverse edges since ogbn-arxiv is unidirectional.
graph = dgl.add_reverse_edges(graph)
graph.ndata['label'] = node_labels[:, 0]
idx_split = dataset.get_idx_split()
train_nids = idx_split['train']
node_features = graph.ndata['feat']
......@@ -170,7 +174,7 @@ class SAGEConv(nn.Module):
g.srcdata['h'] = h_src # <---
g.dstdata['h'] = h_dst # <---
# update_all is a message passing API.
g.update_all(fn.copy_u('h', 'm'), fn.mean('m', 'h_neigh'))
g.update_all(fn.copy_u('h', 'm'), fn.mean('m', 'h_N'))
h_N = g.dstdata['h_N']
h_total = torch.cat([h_dst, h_N], dim=1) # <---
return self.linear(h_total)
......@@ -192,18 +196,18 @@ class Model(nn.Module):
sampler = dgl.dataloading.MultiLayerNeighborSampler([4, 4])
train_dataloader = dgl.dataloading.NodeDataLoader(
graph, train_nids, sampler,
device=device,
batch_size=1024,
shuffle=True,
drop_last=False,
num_workers=0
)
model = Model(graph.ndata['feat'].shape[1], 128, dataset.num_classes).cuda()
model = Model(graph.ndata['feat'].shape[1], 128, dataset.num_classes).to(device)
with tqdm.tqdm(train_dataloader) as tq:
for step, (input_nodes, output_nodes, bipartites) in enumerate(tq):
bipartites = [b.to(torch.device('cuda')) for b in bipartites]
inputs = node_features[input_nodes].cuda()
labels = node_labels[output_nodes].cuda()
inputs = bipartites[0].srcdata['feat']
labels = bipartites[-1].dstdata['label']
predictions = model(bipartites, inputs)
......
......@@ -4,6 +4,7 @@
. /opt/conda/etc/profile.d/conda.sh
conda activate pytorch-ci
TUTORIAL_ROOT="./tutorials"
NEW_TUTORIAL_ROOT="./new-tutorial"
function fail {
echo FAIL: $@
......@@ -28,3 +29,11 @@ do
done
popd > /dev/null
pushd ${NEW_TUTORIAL_ROOT} > /dev/null
for f in $(find . -name "*.py" ! -name "*_mx.py")
do
echo "Running tutorial ${f} ..."
python3 $f || fail "run ${f}"
done
popd > /dev/null
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment