Skip to content

Commit a50fe9b

Browse files
committed
resolve dropout bugs
1 parent 1df5ae7 commit a50fe9b

File tree

6 files changed

+45
-177
lines changed

6 files changed

+45
-177
lines changed

inits.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44

55
def uniform(shape, scale=0.05, name=None):
66
"""Uniform init."""
7-
initial = tf.random_uniform(shape, minval=-scale, maxval=scale, dtype=tf.float32)
7+
initial = tf.random.uniform(shape, minval=-scale, maxval=scale, dtype=tf.float32)
88
return tf.Variable(initial, name=name)
99

1010

1111
def glorot(shape, name=None):
1212
"""Glorot & Bengio (AISTATS 2010) init."""
1313
init_range = np.sqrt(6.0/(shape[0]+shape[1]))
14-
initial = tf.random_uniform(shape, minval=-init_range, maxval=init_range, dtype=tf.float32)
14+
initial = tf.random.uniform(shape, minval=-init_range, maxval=init_range, dtype=tf.float32)
1515
return tf.Variable(initial, name=name)
1616

1717

layers.py

+6-51
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ def get_layer_uid(layer_name=''):
2121
return _LAYER_UIDS[layer_name]
2222

2323

24-
def sparse_dropout(x, keep_prob, noise_shape):
24+
def sparse_dropout(x, rate, noise_shape):
2525
"""
2626
Dropout for sparse tensors.
2727
"""
28-
random_tensor = keep_prob
28+
random_tensor = 1 - rate
2929
random_tensor += tf.random.uniform(noise_shape)
3030
dropout_mask = tf.cast(tf.floor(random_tensor), dtype=tf.bool)
3131
pre_out = tf.sparse.retain(x, dropout_mask)
32-
return pre_out * (1./keep_prob)
32+
return pre_out * (1./(1 - rate))
3333

3434

3535
def dot(x, y, sparse=False):
@@ -43,54 +43,9 @@ def dot(x, y, sparse=False):
4343
return res
4444

4545

46-
class Layer(object):
47-
"""
48-
Base layer class. Defines basic API for all layer objects.
49-
Implementation inspired by keras (http://keras.io).
50-
51-
# Properties
52-
name: String, defines the variable scope of the layer.
53-
logging: Boolean, switches Tensorflow histogram logging on/off
54-
55-
# Methods
56-
_call(inputs): Defines computation graph of layer
57-
(i.e. takes input, returns output)
58-
__call__(inputs): Wrapper for _call()
59-
_log_vars(): Log all variables
60-
"""
61-
62-
def __init__(self, **kwargs):
63-
allowed_kwargs = {'name', 'logging'}
64-
for kwarg in kwargs.keys():
65-
assert kwarg in allowed_kwargs, 'Invalid keyword argument: ' + kwarg
66-
name = kwargs.get('name')
67-
if not name:
68-
layer = self.__class__.__name__.lower()
69-
name = layer + '_' + str(get_layer_uid(layer))
70-
self.name = name
71-
self.vars = {}
72-
logging = kwargs.get('logging', False)
73-
self.logging = logging
74-
self.sparse_inputs = False
75-
76-
def _call(self, inputs):
77-
return inputs
78-
79-
def __call__(self, inputs):
80-
with tf.name_scope(self.name):
81-
if self.logging and not self.sparse_inputs:
82-
tf.summary.histogram(self.name + '/inputs', inputs)
83-
outputs = self._call(inputs)
84-
if self.logging:
85-
tf.summary.histogram(self.name + '/outputs', outputs)
86-
return outputs
8746

88-
def _log_vars(self):
89-
for var in self.vars:
90-
tf.summary.histogram(self.name + '/vars/' + var, self.vars[var])
9147

92-
93-
class Dense(Layer):
48+
class Dense(layers.Layer):
9449
"""Dense layer."""
9550
def __init__(self, input_dim, output_dim, placeholders, dropout=0., sparse_inputs=False,
9651
act=tf.nn.relu, bias=False, featureless=False, **kwargs):
@@ -169,9 +124,9 @@ def call(self, inputs, training=None):
169124
x, support_ = inputs
170125

171126
# dropout
172-
if self.is_sparse_inputs:
127+
if training and self.is_sparse_inputs:
173128
x = sparse_dropout(x, self.dropout, self.num_features_nonzero)
174-
else:
129+
elif training:
175130
x = tf.nn.dropout(x, self.dropout)
176131

177132

metrics.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33

44
def masked_softmax_cross_entropy(preds, labels, mask):
5-
"""Softmax cross-entropy loss with masking."""
5+
"""
6+
Softmax cross-entropy loss with masking.
7+
"""
68
loss = tf.nn.softmax_cross_entropy_with_logits(logits=preds, labels=labels)
79
mask = tf.cast(mask, dtype=tf.float32)
810
mask /= tf.reduce_mean(mask)
@@ -11,7 +13,9 @@ def masked_softmax_cross_entropy(preds, labels, mask):
1113

1214

1315
def masked_accuracy(preds, labels, mask):
14-
"""Accuracy with masking."""
16+
"""
17+
Accuracy with masking.
18+
"""
1519
correct_prediction = tf.equal(tf.argmax(preds, 1), tf.argmax(labels, 1))
1620
accuracy_all = tf.cast(correct_prediction, tf.float32)
1721
mask = tf.cast(mask, dtype=tf.float32)

models.py

+5-83
Original file line numberDiff line numberDiff line change
@@ -5,86 +5,10 @@
55
from config import args
66

77

8-
class Model:
9-
def __init__(self, **kwargs):
10-
allowed_kwargs = {'name', 'logging'}
11-
for kwarg in kwargs.keys():
12-
assert kwarg in allowed_kwargs, 'Invalid keyword argument: ' + kwarg
13-
name = kwargs.get('name')
14-
if not name:
15-
name = self.__class__.__name__.lower()
16-
self.name = name
178

18-
logging = kwargs.get('logging', False)
19-
self.logging = logging
209

21-
self.vars = {}
22-
self.placeholders = {}
2310

24-
self.layers = []
25-
self.activations = []
26-
27-
self.inputs = None
28-
self.outputs = None
29-
30-
self.loss = 0
31-
self.accuracy = 0
32-
self.optimizer = None
33-
self.opt_op = None
34-
35-
def _build(self):
36-
raise NotImplementedError
37-
38-
def build(self):
39-
"""
40-
Wrapper for _build()
41-
"""
42-
with tf.variable_scope(self.name):
43-
self._build()
44-
45-
# Build sequential layer model
46-
self.activations.append(self.inputs)
47-
for layer in self.layers:
48-
hidden = layer(self.activations[-1])
49-
self.activations.append(hidden)
50-
self.outputs = self.activations[-1]
51-
52-
# Store model variables for easy access
53-
variables = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope=self.name)
54-
self.vars = {var.name: var for var in variables}
55-
56-
# Build metrics
57-
self._loss()
58-
self._accuracy()
59-
60-
self.opt_op = self.optimizer.minimize(self.loss)
61-
62-
def predict(self):
63-
pass
64-
65-
def _loss(self):
66-
raise NotImplementedError
67-
68-
def _accuracy(self):
69-
raise NotImplementedError
70-
71-
def save(self, sess=None):
72-
if not sess:
73-
raise AttributeError("TensorFlow session not provided.")
74-
saver = tf.train.Saver(self.vars)
75-
save_path = saver.save(sess, "tmp/%s.ckpt" % self.name)
76-
print("Model saved in file: %s" % save_path)
77-
78-
def load(self, sess=None):
79-
if not sess:
80-
raise AttributeError("TensorFlow session not provided.")
81-
saver = tf.train.Saver(self.vars)
82-
save_path = "tmp/%s.ckpt" % self.name
83-
saver.restore(sess, save_path)
84-
print("Model restored from file: %s" % save_path)
85-
86-
87-
class MLP(Model):
11+
class MLP(keras.Model):
8812
def __init__(self, placeholders, input_dim, **kwargs):
8913
super(MLP, self).__init__(**kwargs)
9014

@@ -148,19 +72,16 @@ def __init__(self, input_dim, output_dim, num_features_nonzero, **kwargs):
14872
output_dim=args.hidden1, # 16
14973
num_features_nonzero=num_features_nonzero,
15074
activation=tf.nn.relu,
151-
dropout=0.5,
75+
dropout=args.dropout,
15276
is_sparse_inputs=True))
15377

15478
self.layers_.append(GraphConvolution(input_dim=args.hidden1, # 16
15579
output_dim=self.output_dim, # 7
15680
num_features_nonzero=num_features_nonzero,
15781
activation=lambda x: x,
158-
dropout=0.5))
82+
dropout=args.dropout))
15983

16084

161-
def _accuracy(self):
162-
self.accuracy = masked_accuracy(self.outputs, self.placeholders['labels'],
163-
self.placeholders['labels_mask'])
16485

16586

16687
def call(self, inputs, training=None):
@@ -187,10 +108,11 @@ def call(self, inputs, training=None):
187108
# Cross entropy error
188109
loss += masked_softmax_cross_entropy(output, label, mask)
189110

190-
191111
acc = masked_accuracy(output, label, mask)
192112

193113
return loss, acc
194114

115+
116+
195117
def predict(self):
196118
return tf.nn.softmax(self.outputs)

train.py

+10-21
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
import os
1010
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
1111
print('tf version:', tf.__version__)
12+
assert tf.__version__.startswith('2.')
1213

13-
# Set random seed
14+
15+
16+
# set random seed
1417
seed = 123
1518
np.random.seed(seed)
1619
tf.random.set_seed(seed)
1720

1821

1922

20-
# Load data
23+
# load data
2124
adj, features, y_train, y_val, y_test, train_mask, val_mask, test_mask = load_data(args.dataset)
2225
print('adj:', adj.shape)
2326
print('features:', features.shape)
@@ -26,7 +29,6 @@
2629

2730

2831

29-
# Some preprocessing
3032
# D^-1@X
3133
features = preprocess_features(features) # [49216, 2], [49216], [2708, 1433]
3234
print('features coordinates::', features[0].shape)
@@ -49,19 +51,10 @@
4951
else:
5052
raise ValueError('Invalid argument for model: ' + str(args.model))
5153

52-
# # Define placeholders
53-
# placeholders = {
54-
# 'support': [tf.sparse_placeholder(tf.float32) for _ in range(num_supports)],
55-
# 'features': tf.sparse_placeholder(tf.float32, shape=tf.constant(features[2], dtype=tf.int64)),
56-
# 'labels': tf.placeholder(tf.float32, shape=(None, y_train.shape[1])),
57-
# 'labels_mask': tf.placeholder(tf.int32),
58-
# 'dropout': tf.placeholder_with_default(0., shape=()),
59-
# 'num_features_nonzero': tf.placeholder(tf.int32) # helper variable for sparse dropout
60-
# }
54+
6155

6256
# Create model
63-
model = GCN(input_dim=features[2][1], output_dim=y_train.shape[1],
64-
num_features_nonzero=features[1].shape) # [1433]
57+
model = GCN(input_dim=features[2][1], output_dim=y_train.shape[1], num_features_nonzero=features[1].shape) # [1433]
6558

6659

6760

@@ -74,26 +67,22 @@
7467
support = [tf.cast(tf.SparseTensor(*support[0]), dtype=tf.float32)]
7568
num_features_nonzero = features.values.shape
7669
dropout = args.dropout
77-
print(num_features_nonzero, support[0].dtype)
7870

7971

80-
optimizer = optimizers.Adam(lr=1e-3)
72+
optimizer = optimizers.Adam(lr=1e-2)
8173

8274
cost_val = []
8375

84-
# Train model
85-
for epoch in range(args.epochs):
8676

87-
t = time.time()
77+
for epoch in range(args.epochs):
8878

8979
with tf.GradientTape() as tape:
9080
loss, acc = model((features, train_label, train_mask,support))
9181
grads = tape.gradient(loss, model.trainable_variables)
9282
optimizer.apply_gradients(zip(grads, model.trainable_variables))
9383

9484

95-
96-
_, val_acc = model((features, val_label, val_mask, support))
85+
_, val_acc = model((features, val_label, val_mask, support), training=False)
9786

9887

9988
print(epoch, float(loss), float(acc), '\tval:', float(val_acc))

utils.py

+16-18
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
1-
import numpy as np
2-
import pickle as pkl
3-
import networkx as nx
4-
import scipy.sparse as sp
5-
from scipy.sparse.linalg.eigen.arpack import eigsh
6-
import sys
1+
import numpy as np
2+
import pickle as pkl
3+
import networkx as nx
4+
import scipy.sparse as sp
5+
from scipy.sparse.linalg.eigen.arpack import eigsh
6+
import sys
77

88

99
def parse_index_file(filename):
10-
"""Parse index file."""
10+
"""
11+
Parse index file.
12+
"""
1113
index = []
1214
for line in open(filename):
1315
index.append(int(line.strip()))
1416
return index
1517

1618

1719
def sample_mask(idx, l):
18-
"""Create mask."""
20+
"""
21+
Create mask.
22+
"""
1923
mask = np.zeros(l)
2024
mask[idx] = 1
2125
return np.array(mask, dtype=np.bool)
@@ -139,19 +143,13 @@ def preprocess_adj(adj):
139143
return sparse_to_tuple(adj_normalized)
140144

141145

142-
def construct_feed_dict(features, support, labels, labels_mask, placeholders):
143-
"""Construct feed dictionary."""
144-
feed_dict = dict()
145-
feed_dict.update({placeholders['labels']: labels})
146-
feed_dict.update({placeholders['labels_mask']: labels_mask})
147-
feed_dict.update({placeholders['features']: features})
148-
feed_dict.update({placeholders['support'][i]: support[i] for i in range(len(support))})
149-
feed_dict.update({placeholders['num_features_nonzero']: features[1].shape})
150-
return feed_dict
146+
151147

152148

153149
def chebyshev_polynomials(adj, k):
154-
"""Calculate Chebyshev polynomials up to order k. Return a list of sparse matrices (tuple representation)."""
150+
"""
151+
Calculate Chebyshev polynomials up to order k. Return a list of sparse matrices (tuple representation).
152+
"""
155153
print("Calculating Chebyshev polynomials up to order {}...".format(k))
156154

157155
adj_normalized = normalize_adj(adj)

0 commit comments

Comments
 (0)