-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathmain.py
More file actions
120 lines (84 loc) · 3.35 KB
/
Copy pathmain.py
File metadata and controls
120 lines (84 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.optim as optim
from dataset import bAbIDataset, bAbIDataLoader
from model import GGNN
# Task ID to use out of the bAbI tasks. Task 19 is path finding and according
# to the paper is "arguably the hardest task".
task_id = 19
# Batch size for training
batch_size = 10
# Some of the bAbI tasks (all of the ones we have here) have multiple question
# types.
question_id = 0
# Use the GPU?
use_cuda = False
# If we should log training loss to output.
should_log_train = False
# Learning rate for training
lr = 0.01
# Number of epochs for training
n_epochs = 10
# GGNN hidden state size
state_dim = 4
# Number of propogation steps
n_steps = 5
# Annotation dimension. For the bAbi tasks we have one hot encoding per node.
annotation_dim = 1
# One fold of our preprocessed dataset.
dataset_path = 'babi_data/processed_1/train/%d_graphs.txt' % task_id
train_dataset = bAbIDataset(dataset_path, question_id=0, is_train=True)
train_data_loader = bAbIDataLoader(train_dataset, batch_size=batch_size,
shuffle=True, num_workers=2)
test_dataset = bAbIDataset(dataset_path, question_id=0, is_train=False)
test_data_loader = bAbIDataLoader(test_dataset, batch_size=batch_size,
shuffle=False, num_workers=2)
n_edge_types = train_dataset.n_edge_types
n_nodes = train_dataset.n_node
# The dataset has the form: [(adjacency matrix, annotation, target), ...]
ggnn = GGNN(state_dim, annotation_dim, n_edge_types, n_nodes, n_steps)
# The dataset is all doubles so convert the model to be double
ggnn = ggnn.double()
crit = nn.CrossEntropyLoss()
if use_cuda:
net.use_cuda()
crit.use_cuda()
opt = optim.Adam(ggnn.parameters(), lr=lr)
def model_inference(ggnn, adj_matrix, annotation, target):
padding = torch.zeros(len(annotation), n_nodes, state_dim -
annotation_dim).double()
# See section 3.1 of the paper for how we create the node annotations.
init_input = torch.cat((annotation, padding), 2)
if use_cuda:
init_input = init_input.use_cuda()
adj_matrix = adj_matrix.use_cuda()
annotation = annotation.use_cuda()
target = target.use_cuda()
output = ggnn(init_input, annotation, adj_matrix)
return output, target
for epoch in range(n_epochs):
# Train
ggnn.train()
for i, (adj_matrix, annotation, target) in enumerate(train_data_loader):
# Adjency matrix will have shape [batch_size, n_nodes, 2 * n_nodes * n_edge_types]
ggnn.zero_grad()
output, target = model_inference(ggnn, adj_matrix, annotation, target)
loss = crit(output, target)
loss.backward()
opt.step()
if should_log_train:
print('[%i / %i], [%i / %i] Loss: %.4f' % (epoch, n_epochs, i,
len(train_data_loader), loss.data))
# Evaluate performance over validation dataset.
ggnn.eval()
test_loss = 0
correct = 0
for adj_matrix, annotation, target in test_data_loader:
output, target = model_inference(ggnn, adj_matrix, annotation, target)
test_loss += crit(output, target).data
pred = output.data.max(1, keepdim=True)[1]
correct += pred.eq(target.data.view_as(pred)).cpu().sum()
test_loss /= len(test_dataset)
print('[%i, %i] Val: Avg Loss %.4f, Accuracy %i/%i' % (epoch, n_epochs, test_loss,
correct, len(test_dataset)))