1# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Tests for kernelized_utils.py."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import print_function
20
21import functools
22
23from absl.testing import parameterized
24
25from tensorflow.python.framework import constant_op
26from tensorflow.python.keras.utils import kernelized_utils
27from tensorflow.python.platform import test
28
29
30def _exact_gaussian(stddev):
31  return functools.partial(
32      kernelized_utils.exact_gaussian_kernel, stddev=stddev)
33
34
35def _exact_laplacian(stddev):
36  return functools.partial(
37      kernelized_utils.exact_laplacian_kernel, stddev=stddev)
38
39
40class KernelizedUtilsTest(test.TestCase, parameterized.TestCase):
41
42  @parameterized.named_parameters(
43      ('gaussian', _exact_gaussian(stddev=10.0), [[1.0]]),
44      ('laplacian', _exact_laplacian(stddev=50.0), [[1.0]]))
45  def test_equal_vectors(self, exact_kernel_fn, expected_values):
46    """Identical vectors give exactly the identity kernel value."""
47    x = constant_op.constant([0.5, -0.5, -0.5, 0.5])
48    y = constant_op.constant([0.5, -0.5, -0.5, 0.5])
49    exact_kernel = exact_kernel_fn(x, y)
50    shape = exact_kernel.get_shape().as_list()
51    self.assertLen(shape, 2)
52    # x and y are identical and therefore K(x, y) will be precisely equal to
53    # the identity value of the kernel.
54    self.assertAllClose(expected_values, exact_kernel, atol=1e-6)
55
56  @parameterized.named_parameters(
57      ('gaussian', _exact_gaussian(stddev=10.0), [[1.0]]),
58      ('laplacian', _exact_laplacian(stddev=50.0), [[1.0]]))
59  def test_almost_identical_vectors(self, exact_kernel_fn, expected_values):
60    """Almost identical vectors give the identity kernel value."""
61    x = constant_op.constant([1.0, 0.4, -2.1, -1.1])
62    y = constant_op.constant([1.01, 0.39, -2.099, -1.101])
63    exact_kernel = exact_kernel_fn(x, y)
64    shape = exact_kernel.get_shape().as_list()
65    self.assertLen(shape, 2)
66    # x and y are almost identical and therefore K(x, y) will be almost equal to
67    # the identity value of the kernel.
68    self.assertAllClose(expected_values, exact_kernel, atol=1e-3)
69
70  @parameterized.named_parameters(
71      ('gaussian', _exact_gaussian(stddev=1.0), [[0.99], [0.977]]),
72      ('laplacian', _exact_laplacian(stddev=5.0), [[0.96], [0.94]]))
73  def test_similar_matrices(self, exact_kernel_fn, expected_values):
74    """Pairwise "close" vectors give high kernel values (similarity scores)."""
75    x = constant_op.constant([1.0, 3.4, -2.1, 0.9, 3.3, -2.0], shape=[2, 3])
76    y = constant_op.constant([1.1, 3.35, -2.05])
77    exact_kernel = exact_kernel_fn(x, y)
78    shape = exact_kernel.get_shape().as_list()
79    self.assertLen(shape, 2)
80    # The 2 rows of x are close to y. The pairwise kernel values (similarity
81    # scores) are somewhat close to the identity value of the kernel.
82    self.assertAllClose(expected_values, exact_kernel, atol=1e-2)
83
84  @parameterized.named_parameters(
85      ('gaussian', _exact_gaussian(stddev=2.0), [[.997, .279], [.251, 1.],
86                                                 [.164, 0.019]]),
87      ('laplacian', _exact_laplacian(stddev=2.0), [[.904, .128], [.116, 1.],
88                                                   [.07, 0.027]]))
89  def test_matrices_varying_similarity(self, exact_kernel_fn, expected_values):
90    """Test matrices with row vectors of varying pairwise similarity."""
91    x = constant_op.constant([1.0, 2., -2., 0.9, 3.3, -1.0], shape=[3, 2])
92    y = constant_op.constant([1.1, 2.1, -2., 0.9], shape=[2, 2])
93    exact_kernel = exact_kernel_fn(x, y)
94
95    shape = exact_kernel.get_shape().as_list()
96    self.assertLen(shape, 2)
97    self.assertAllClose(expected_values, exact_kernel, atol=1e-2)
98
99  @parameterized.named_parameters(
100      ('gaussian', _exact_gaussian(stddev=1.0), [[0.0]]),
101      ('laplacian', _exact_laplacian(stddev=1.0), [[0.0]]))
102  def test_completely_dissimilar_vectors(self, exact_kernel_fn,
103                                         expected_values):
104    """Very dissimilar vectors give very low similarity scores."""
105    x = constant_op.constant([1.0, 3.4, -2.1, -5.1])
106    y = constant_op.constant([0.5, 2.1, 1.0, 3.0])
107    exact_kernel = exact_kernel_fn(x, y)
108    shape = exact_kernel.get_shape().as_list()
109    self.assertLen(shape, 2)
110    # x and y are very "far" from each other and so the corresponding kernel
111    # value will be very low.
112    self.assertAllClose(expected_values, exact_kernel, atol=1e-2)
113
114
115if __name__ == '__main__':
116  test.main()
117