def test_dynamic_graph_convolution_keras_layer_training(self, reduction): """Test a simple training loop.""" if not tf.executing_eagerly(): return # Generate a small valid input for a simple training task. # Four corners of a square. data = np.array(((1.0, 1.0), (-1.0, 1.0), (-1.0, -1.0), (1.0, -1.0))) neighbors_indices = np.array( ((0, 0), (0, 1), (0, 3), (1, 0), (1, 1), (1, 2), (2, 1), (2, 2), (2, 3), (3, 0), (3, 2), (3, 3))) neighbors = tf.SparseTensor(neighbors_indices, np.ones(shape=(12, )) / 3.0, dense_shape=(4, 4)) # Desired output is arbitrary. labels = np.reshape([-1.0, -0.5, 0.5, 1.0], (-1, 1)) num_training_iterations = 5 with tf.GradientTape(persistent=True) as tape: layer = gc_layer.DynamicGraphConvolutionKerasLayer( num_output_channels=2, reduction=reduction) output = layer(inputs=[data, neighbors], sizes=None) loss = tf.nn.l2_loss(output - labels) trainable_variables = layer.trainable_variables for _ in range(num_training_iterations): grads = tape.gradient(loss, trainable_variables) tf.compat.v1.train.GradientDescentOptimizer( 1e-4).apply_gradients(zip(grads, trainable_variables))
def test_dynamic_graph_convolution_keras_layer_exception_not_raised_shapes( self, batch_size, num_vertices, in_channels, out_channels, reduction): """Check if the convolution parameters and output have correct shapes.""" if not tf.executing_eagerly(): return data, neighbors = _dummy_data(batch_size, num_vertices, in_channels) layer = gc_layer.DynamicGraphConvolutionKerasLayer( num_output_channels=out_channels, reduction=reduction) try: output = layer(inputs=[data, neighbors], sizes=None) except Exception as e: # pylint: disable=broad-except self.fail("Exception raised: %s" % str(e)) self.assertAllEqual((batch_size, num_vertices, out_channels), output.shape)
def test_dynamic_graph_convolution_keras_layer_zero_kernel( self, batch_size, num_vertices, in_channels, out_channels, reduction): """Tests convolution with an all-zeros kernel.""" if not tf.executing_eagerly(): return data, neighbors = _dummy_data(batch_size, num_vertices, in_channels) data = np.random.uniform(size=data.shape).astype(np.float32) layer = gc_layer.DynamicGraphConvolutionKerasLayer( num_output_channels=out_channels, reduction=reduction, use_bias=False, kernel_initializer=tf.compat.v1.keras.initializers.zeros()) output = layer(inputs=[data, neighbors], sizes=None) self.assertAllEqual( output, np.zeros(shape=(batch_size, num_vertices, out_channels), dtype=np.float32))
def test_dynamic_graph_convolution_keras_layer_duplicate_features( self, num_vertices, in_channels, out_channels): """Tests convolution when all vertex features are identical.""" if not tf.executing_eagerly(): return data = np.random.uniform(size=(1, in_channels)) data = np.tile(data, (num_vertices, 1)) # Results should be independent of 'neighbors'. neighbors = np.maximum( np.random.randint(0, 2, size=(num_vertices, num_vertices)), np.eye(num_vertices)) neighbors = _dense_to_sparse(neighbors) layer = gc_layer.DynamicGraphConvolutionKerasLayer( num_output_channels=out_channels, reduction="max") output = layer(inputs=[data, neighbors], sizes=None) output_tile = tf.tile(output[:1, :], (num_vertices, 1)) self.assertAllEqual(output, output_tile)