Revision 5d6336f1d9d62fd4a3fc144d36a65c3c9d344890 authored by Artem Artemev on 27 October 2019, 16:41:50 UTC, committed by Artem Artemev on 27 October 2019, 16:46:49 UTC
This PR updates the understanding/upper_bound.ipynb to work in gpflow2. It fixes the upper_bound code in gpflow/models/sgpr.py and restores the original (tighter) test tolerance that had both been changed by commit 45efebc The plots don't quite match up to what was in the GPflow1 version (nor does the tight bound in the 1-inducing-point example at the end), but otherwise this seems to work.
1 parent f650c7b
test_printing.py
# Copyright 2018 the GPflow authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import pytest
import tensorflow as tf
import gpflow
from gpflow.utilities.utilities import leaf_components, _merge_leaf_components, tabulate_module_summary
rng = np.random.RandomState(0)
class Data:
H0 = 5
H1 = 2
M = 10
D = 1
Z = 0.5 * np.ones((M, 1))
ls = 2.0
var = 1.0
# ------------------------------------------
# Helpers
# ------------------------------------------
class A(tf.Module):
def __init__(self, name=None):
super().__init__(name)
self.var_trainable = tf.Variable(tf.zeros((2, 2, 1)), trainable=True)
self.var_fixed = tf.Variable(tf.ones((2, 2, 1)), trainable=False)
class B(tf.Module):
def __init__(self, name=None):
super().__init__(name)
self.submodule_list = [A(), A()]
self.submodule_dict = dict(a=A(), b=A())
self.var_trainable = tf.Variable(tf.zeros((2, 2, 1)), trainable=True)
self.var_fixed = tf.Variable(tf.ones((2, 2, 1)), trainable=False)
def create_kernel():
kern = gpflow.kernels.SquaredExponential(lengthscale=Data.ls, variance=Data.var)
kern.lengthscale.trainable = False
return kern
def create_compose_kernel():
kernel = gpflow.kernels.Product([
gpflow.kernels.Sum([create_kernel(), create_kernel()]),
gpflow.kernels.Sum([create_kernel(), create_kernel()])]
)
return kernel
def create_model():
kernel = create_kernel()
model = gpflow.models.SVGP(kernel=kernel, likelihood=gpflow.likelihoods.Gaussian(),
inducing_variable=Data.Z, q_diag=True)
model.q_mu.trainable = False
return model
# ------------------------------------------
# Reference
# ------------------------------------------
example_tf_module_variable_dict = {
'A.var_trainable': {
'value': np.zeros((2, 2, 1)),
'trainable': True,
'shape': (2, 2, 1)
},
'A.var_fixed': {
'value': np.ones((2, 2, 1)),
'trainable': False,
'shape': (2, 2, 1)
},
}
example_module_list_variable_dict = {
'submodule_list[0].var_trainable': example_tf_module_variable_dict['A.var_trainable'],
'submodule_list[0].var_fixed': example_tf_module_variable_dict['A.var_fixed'],
'submodule_list[1].var_trainable': example_tf_module_variable_dict['A.var_trainable'],
'submodule_list[1].var_fixed': example_tf_module_variable_dict['A.var_fixed'],
"submodule_dict['a'].var_trainable": example_tf_module_variable_dict['A.var_trainable'],
"submodule_dict['a'].var_fixed": example_tf_module_variable_dict['A.var_fixed'],
"submodule_dict['b'].var_trainable": example_tf_module_variable_dict['A.var_trainable'],
"submodule_dict['b'].var_fixed": example_tf_module_variable_dict['A.var_fixed'],
'B.var_trainable': example_tf_module_variable_dict['A.var_trainable'],
'B.var_fixed': example_tf_module_variable_dict['A.var_fixed'],
}
kernel_param_dict = {
'SquaredExponential.lengthscale': {
'value': Data.ls,
'trainable': False,
'shape': ()
},
'SquaredExponential.variance': {
'value': Data.var,
'trainable': True,
'shape': ()
}
}
compose_kernel_param_dict = {
'kernels[0].kernels[0].variance': kernel_param_dict['SquaredExponential.variance'],
'kernels[0].kernels[0].lengthscale': kernel_param_dict['SquaredExponential.lengthscale'],
'kernels[0].kernels[1].variance': kernel_param_dict['SquaredExponential.variance'],
'kernels[0].kernels[1].lengthscale': kernel_param_dict['SquaredExponential.lengthscale'],
'kernels[1].kernels[0].variance': kernel_param_dict['SquaredExponential.variance'],
'kernels[1].kernels[0].lengthscale': kernel_param_dict['SquaredExponential.lengthscale'],
'kernels[1].kernels[1].variance': kernel_param_dict['SquaredExponential.variance'],
'kernels[1].kernels[1].lengthscale': kernel_param_dict['SquaredExponential.lengthscale']
}
model_gp_param_dict = {
'kernel.lengthscale': kernel_param_dict['SquaredExponential.lengthscale'],
'kernel.variance': kernel_param_dict['SquaredExponential.variance'],
'likelihood.variance': {
'value': 1.0,
'trainable': True,
'shape': ()
},
'inducing_variable.Z': {
'value': Data.Z,
'trainable': True,
'shape': (Data.M, Data.D)
},
'SVGP.q_mu': {
'value': np.zeros((Data.M, 1)),
'trainable': False,
'shape': (Data.M, 1)
},
'SVGP.q_sqrt': {
'value': np.ones((Data.M, 1)),
'trainable': True,
'shape': (Data.M, 1)
}
}
example_dag_module_param_dict = {
'SVGP.kernel.variance\nSVGP.kernel.lengthscale': kernel_param_dict['SquaredExponential.lengthscale'],
'SVGP.likelihood.variance': {
'value': 1.0,
'trainable': True,
'shape': ()
},
'SVGP.inducing_variable.Z': {
'value': Data.Z,
'trainable': True,
'shape': (Data.M, Data.D)
},
'SVGP.q_mu': {
'value': np.zeros((Data.M, 1)),
'trainable': False,
'shape': (Data.M, 1)
},
'SVGP.q_sqrt': {
'value': np.ones((Data.M, 1)),
'trainable': True,
'shape': (Data.M, 1)
}
}
compose_kernel_param_print_string = """\
name class transform trainable shape dtype value\n\
----------------------------------------- --------- ----------- ----------- ------- ------- -------\n\
Product.kernels[0].kernels[0].variance Parameter Softplus True () float64 1\n\
Product.kernels[0].kernels[0].lengthscale Parameter Softplus False () float64 2\n\
Product.kernels[0].kernels[1].variance Parameter Softplus True () float64 1\n\
Product.kernels[0].kernels[1].lengthscale Parameter Softplus False () float64 2\n\
Product.kernels[1].kernels[0].variance Parameter Softplus True () float64 1\n\
Product.kernels[1].kernels[0].lengthscale Parameter Softplus False () float64 2\n\
Product.kernels[1].kernels[1].variance Parameter Softplus True () float64 1\n\
Product.kernels[1].kernels[1].lengthscale Parameter Softplus False () float64 2"""
kernel_param_print_string = """\
name class transform trainable shape dtype value\n\
------------------------------ --------- ----------- ----------- ------- ------- -------\n\
SquaredExponential.variance Parameter Softplus True () float64 1\n\
SquaredExponential.lengthscale Parameter Softplus False () float64 2"""
model_gp_param_print_string = """\
name class transform trainable shape dtype value\n\
------------------------ --------- ----------- ----------- ------- ------- --------\n\
SVGP.kernel.variance Parameter Softplus True () float64 1.0\n\
SVGP.kernel.lengthscale Parameter Softplus False () float64 2.0\n\
SVGP.likelihood.variance Parameter Softplus True () float64 1.0\n\
SVGP.inducing_variable.Z Parameter True (10, 1) float64 [[0.5...\n\
SVGP.q_mu Parameter False (10, 1) float64 [[0....\n\
SVGP.q_sqrt Parameter Softplus True (10, 1) float64 [[1...."""
example_tf_module_variable_print_string = """\
name class transform trainable shape dtype value\n\
--------------- ---------------- ----------- ----------- --------- ------- --------\n\
A.var_trainable ResourceVariable True (2, 2, 1) float32 [[[0....\n\
A.var_fixed ResourceVariable False (2, 2, 1) float32 [[[1...."""
example_module_list_variable_print_string = """\
name class transform trainable shape dtype value\n\
----------------------------------- ---------------- ----------- ----------- --------- ------- --------\n\
B.submodule_list[0].var_trainable ResourceVariable True (2, 2, 1) float32 [[[0....\n\
B.submodule_list[0].var_fixed ResourceVariable False (2, 2, 1) float32 [[[1....\n\
B.submodule_list[1].var_trainable ResourceVariable True (2, 2, 1) float32 [[[0....\n\
B.submodule_list[1].var_fixed ResourceVariable False (2, 2, 1) float32 [[[1....\n\
B.submodule_dict['a'].var_trainable ResourceVariable True (2, 2, 1) float32 [[[0....\n\
B.submodule_dict['a'].var_fixed ResourceVariable False (2, 2, 1) float32 [[[1....\n\
B.submodule_dict['b'].var_trainable ResourceVariable True (2, 2, 1) float32 [[[0....\n\
B.submodule_dict['b'].var_fixed ResourceVariable False (2, 2, 1) float32 [[[1....\n\
B.var_trainable ResourceVariable True (2, 2, 1) float32 [[[0....\n\
B.var_fixed ResourceVariable False (2, 2, 1) float32 [[[1...."""
# ------------------------------------------
# Fixtures
# ------------------------------------------
@pytest.fixture(params=[A, B, create_kernel, create_model])
def module(request):
return request.param()
@pytest.fixture
def dag_module():
dag = create_model()
dag.kernel.variance = dag.kernel.lengthscale
return dag
# ------------------------------------------
# Tests
# ------------------------------------------
def test_leaf_components_only_returns_parameters_and_variables(module):
for path, variable in leaf_components(module).items():
assert isinstance(variable, tf.Variable) or isinstance(variable, gpflow.Parameter)
@pytest.mark.parametrize('module_callable, expected_param_dicts', [
(create_kernel, kernel_param_dict),
(create_model, model_gp_param_dict)
])
def test_leaf_components_registers_variable_properties(module_callable, expected_param_dicts):
module = module_callable()
for path, variable in leaf_components(module).items():
param_name = path.split('.')[-2] + '.' + path.split('.')[-1]
assert isinstance(variable, gpflow.Parameter)
np.testing.assert_equal(variable.value().numpy(), expected_param_dicts[param_name]['value'])
assert variable.trainable == expected_param_dicts[param_name]['trainable']
assert variable.shape == expected_param_dicts[param_name]['shape']
@pytest.mark.parametrize('module_callable, expected_param_dicts', [
(create_compose_kernel, compose_kernel_param_dict),
])
def test_leaf_components_registers_compose_kernel_variable_properties(module_callable, expected_param_dicts):
module = module_callable()
leaf_components_dict = leaf_components(module)
assert len(leaf_components_dict) > 0
for path, variable in leaf_components_dict.items():
path_as_list = path.split('.')
param_name = path_as_list[-3] + '.' + path_as_list[-2] + '.' + path_as_list[-1]
assert isinstance(variable, gpflow.Parameter)
np.testing.assert_equal(variable.value().numpy(), expected_param_dicts[param_name]['value'])
assert variable.trainable == expected_param_dicts[param_name]['trainable']
assert variable.shape == expected_param_dicts[param_name]['shape']
@pytest.mark.parametrize('module_class, expected_var_dicts', [
(A, example_tf_module_variable_dict),
(B, example_module_list_variable_dict),
])
def test_leaf_components_registers_param_properties(module_class, expected_var_dicts):
module = module_class()
for path, variable in leaf_components(module).items():
var_name = path.split('.')[-2] + '.' + path.split('.')[-1]
assert isinstance(variable, tf.Variable)
np.testing.assert_equal(variable.numpy(), expected_var_dicts[var_name]['value'])
assert variable.trainable == expected_var_dicts[var_name]['trainable']
assert variable.shape == expected_var_dicts[var_name]['shape']
@pytest.mark.parametrize('expected_var_dicts', [example_dag_module_param_dict])
def test_merge_leaf_components_merges_keys_with_same_values(dag_module, expected_var_dicts):
leaf_components_dict = leaf_components(dag_module)
for path, variable in _merge_leaf_components(leaf_components_dict).items():
assert path in expected_var_dicts
for sub_path in path.split('\n'):
assert sub_path in leaf_components_dict
assert leaf_components_dict[sub_path] is variable
@pytest.mark.parametrize('module_callable, expected_param_print_string', [
(create_compose_kernel, compose_kernel_param_print_string),
(create_kernel, kernel_param_print_string),
(create_model, model_gp_param_print_string),
(A, example_tf_module_variable_print_string),
(B, example_module_list_variable_print_string),
])
def test_print_summary_output_string(module_callable, expected_param_print_string):
assert tabulate_module_summary(module_callable()) == expected_param_print_string
def test_leaf_components_combination_kernel():
"""
Regression test for kernel compositions - output for printing should not be empty (issue #1066).
"""
k = gpflow.kernels.SquaredExponential() + gpflow.kernels.SquaredExponential()
assert leaf_components(k), "Combination kernel should have non-empty leaf components"
def test_module_parameters_return_iterators_not_generators():
"""
Regression test: Ensure that gpflow.Module parameters return iterators like in TF2, not
generators.
Reason:
param = m.params # <generator object>
x = [p for p in param] # List[Parameters]
y = [p for p in param] # [] empty!
"""
m = create_model()
assert isinstance(m, gpflow.base.Module)
assert isinstance(m.parameters, tuple)
assert isinstance(m.trainable_parameters, tuple)
Computing file changes ...