项目文件夹

文件
xnouhz 756fdd8e90 [Example] DeeperGCN (#2831)
* [example] deepergcn

* update

* update

* update

* update

* update

Co-authored-by: Mufei Li <mufeili1996@gmail.com>
2021-04-25 18:37:41 +08:00

144 行
4.6 KiB
Python

import argparse
import torch
import torch.nn as nn
import torch.optim as optim
import copy
import time
from ogb.graphproppred import DglGraphPropPredDataset, collate_dgl
from torch.utils.data import DataLoader
from ogb.graphproppred import Evaluator
from models import DeeperGCN
def train(model, device, data_loader, opt, loss_fn):
model.train()
train_loss = []
for g, labels in data_loader:
g = g.to(device)
labels = labels.to(torch.float32).to(device)
logits = model(g, g.edata['feat'], g.ndata['feat'])
loss = loss_fn(logits, labels)
train_loss.append(loss.item())
opt.zero_grad()
loss.backward()
opt.step()
return sum(train_loss) / len(train_loss)
@torch.no_grad()
def test(model, device, data_loader, evaluator):
model.eval()
y_true, y_pred = [], []
for g, labels in data_loader:
g = g.to(device)
logits = model(g, g.edata['feat'], g.ndata['feat'])
y_true.append(labels.detach().cpu())
y_pred.append(logits.detach().cpu())
y_true = torch.cat(y_true, dim=0).numpy()
y_pred = torch.cat(y_pred, dim=0).numpy()
return evaluator.eval({
'y_true': y_true,
'y_pred': y_pred
})['rocauc']
def main():
# check cuda
device = f'cuda:{args.gpu}' if args.gpu >= 0 and torch.cuda.is_available() else 'cpu'
# load ogb dataset & evaluator
dataset = DglGraphPropPredDataset(name='ogbg-molhiv')
evaluator = Evaluator(name='ogbg-molhiv')
g, _ = dataset[0]
node_feat_dim = g.ndata['feat'].size()[-1]
edge_feat_dim = g.edata['feat'].size()[-1]
n_classes = dataset.num_tasks
split_idx = dataset.get_idx_split()
train_loader = DataLoader(dataset[split_idx["train"]],
batch_size=args.batch_size,
shuffle=True,
collate_fn=collate_dgl)
valid_loader = DataLoader(dataset[split_idx["valid"]],
batch_size=args.batch_size,
shuffle=False,
collate_fn=collate_dgl)
test_loader = DataLoader(dataset[split_idx["test"]],
batch_size=args.batch_size,
shuffle=False,
collate_fn=collate_dgl)
# load model
model = DeeperGCN(node_feat_dim=node_feat_dim,
edge_feat_dim=edge_feat_dim,
hid_dim=args.hid_dim,
out_dim=n_classes,
num_layers=args.num_layers,
dropout=args.dropout,
learn_beta=args.learn_beta).to(device)
print(model)
opt = optim.Adam(model.parameters(), lr=args.lr)
loss_fn = nn.BCEWithLogitsLoss()
# training & validation & testing
best_auc = 0
best_model = copy.deepcopy(model)
times = []
print('---------- Training ----------')
for i in range(args.epochs):
t1 = time.time()
train_loss = train(model, device, train_loader, opt, loss_fn)
t2 = time.time()
if i >= 5:
times.append(t2 - t1)
train_auc = test(model, device, train_loader, evaluator)
valid_auc = test(model, device, valid_loader, evaluator)
print(f'Epoch {i} | Train Loss: {train_loss:.4f} | Train Auc: {train_auc:.4f} | Valid Auc: {valid_auc:.4f}')
if valid_auc > best_auc:
best_auc = valid_auc
best_model = copy.deepcopy(model)
print('---------- Testing ----------')
test_auc = test(best_model, device, test_loader, evaluator)
print(f'Test Auc: {test_auc}')
if len(times) > 0:
print('Times/epoch: ', sum(times) / len(times))
if __name__ == '__main__':
"""
DeeperGCN Hyperparameters
"""
parser = argparse.ArgumentParser(description='DeeperGCN')
# training
parser.add_argument('--gpu', type=int, default=-1, help='GPU index, -1 for CPU.')
parser.add_argument('--epochs', type=int, default=300, help='Number of epochs to train.')
parser.add_argument('--lr', type=float, default=0.01, help='Learning rate.')
parser.add_argument('--dropout', type=float, default=0.2, help='Dropout rate.')
parser.add_argument('--batch-size', type=int, default=2048, help='Batch size.')
# model
parser.add_argument('--num-layers', type=int, default=7, help='Number of GNN layers.')
parser.add_argument('--hid-dim', type=int, default=256, help='Hidden channel size.')
# learnable parameters in aggr
parser.add_argument('--learn-beta', action='store_true')
args = parser.parse_args()
print(args)
main()