diff --git a/CHANGELOG.md b/CHANGELOG.md index f412ed9c..7312ab5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,7 +70,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed -- +- The `coreax.kernel` module, deprecated in v0.3.0, has been removed. The kernels have + been moved to submodules of `coreax.kernels` - see the "Deprecated" section of v0.3.0 + for more information. (https://github.com/gchq/coreax/pull/958) +- `coreax.util.median_heuristic`, deprecated in v0.3.0 has been removed. This should be + replaced with `coreax.kernels.util.median_heuristic`. + for more information. (https://github.com/gchq/coreax/pull/958) ### Deprecated diff --git a/coreax/coreset.py b/coreax/coreset.py index 9a5c2a86..57143378 100644 --- a/coreax/coreset.py +++ b/coreax/coreset.py @@ -71,7 +71,11 @@ def pre_coreset_data(self) -> _TOriginalData_co: @property @abstractmethod - @deprecated("Narrow to a subclass, then use `.indices` or `.points` instead.") + @deprecated( + "Narrow to a subclass, then use `.indices` or `.points` instead. " + + "Deprecated since v0.4.0. " + + "Will be removed in v0.5.0." + ) def nodes(self) -> Data: """Deprecated alias for `indices` or `points`, depending on subclass.""" @@ -98,7 +102,11 @@ def __check_init__(self) -> None: ) @property - @deprecated("Use `.points` instead.") + @deprecated( + "Use `.points` instead. " + + "Deprecated since v0.4.0. " + + "Will be removed in v0.5.0." + ) def coreset(self) -> _TPointsData_co: """Deprecated alias for `.points`.""" return self.points @@ -130,18 +138,18 @@ def __init__(self, nodes: Data, pre_coreset_data: _TOriginalData_co) -> None: """Initialise self.""" if isinstance(nodes, Array): warnings.warn( - "Passing Arrays into PseudoCoreset() is deprecated. " + "Passing Arrays into PseudoCoreset() is deprecated since v0.4.0. " "Use PseudoCoreset.build() instead. " - "In future, this will become a TypeError.", + "In v0.5.0, this will become a TypeError.", DeprecationWarning, stacklevel=2, ) nodes = as_data(nodes) # pyright: ignore[reportAssignmentType] if isinstance(pre_coreset_data, Array): warnings.warn( - "Passing Arrays into PseudoCoreset() is deprecated. " + "Passing Arrays into PseudoCoreset() is deprecated since v0.4.0. " "Use PseudoCoreset.build() instead. " - "In future, this will become a TypeError.", + "In v0.5.0, this will become a TypeError.", DeprecationWarning, stacklevel=2, ) @@ -149,9 +157,9 @@ def __init__(self, nodes: Data, pre_coreset_data: _TOriginalData_co) -> None: pre_coreset_data = as_data(pre_coreset_data) # pyright: ignore[reportAssignmentType] if isinstance(pre_coreset_data, tuple): warnings.warn( - "Passing Arrays into PseudoCoreset() is deprecated. " + "Passing Arrays into PseudoCoreset() is deprecated since v0.4.0. " "Use PseudoCoreset.build() instead. " - "In future, this will become a TypeError.", + "In v0.5.0, this will become a TypeError.", DeprecationWarning, stacklevel=2, ) @@ -233,7 +241,11 @@ def pre_coreset_data(self): @property @override - @deprecated("Use `.points` instead.") + @deprecated( + "Use `.points` instead. " + + "Deprecated since v0.4.0. " + + "Will be removed in v0.5.0." + ) def nodes(self) -> Data: """Deprecated alias for `points`.""" return self.points @@ -245,7 +257,11 @@ def solve_weights(self, solver: WeightsOptimiser[Data], **solver_kwargs) -> Self return eqx.tree_at(lambda x: x.points.weights, self, weights) -@deprecated("Use AbstractCoreset, PseudoCoreset, or Coresubset instead.") +@deprecated( + "Use AbstractCoreset, PseudoCoreset, or Coresubset instead. " + + "Deprecated since v0.4.0. " + + "Will be removed in v0.5.0." +) class Coreset(PseudoCoreset): """Deprecated - split into AbstractCoreset and PseudoCoreset.""" @@ -290,18 +306,18 @@ def __init__(self, indices: Data, pre_coreset_data: _TOriginalData_co) -> None: """Handle type conversion of ``indices`` and ``pre_coreset_data``.""" if isinstance(indices, Array): warnings.warn( - "Passing Arrays into PseudoCoreset() is deprecated. " - "Use PseudoCoreset.build() instead. " - "In future, this will become a TypeError.", + "Passing Arrays into Coresubset() is deprecated since v0.4.0. " + "Use Coresubset.build() instead. " + "In v0.5.0, this will become a TypeError.", DeprecationWarning, stacklevel=2, ) indices = as_data(indices) # pyright: ignore[reportAssignmentType] if isinstance(pre_coreset_data, Array): warnings.warn( - "Passing Arrays into PseudoCoreset() is deprecated. " - "Use PseudoCoreset.build() instead. " - "In future, this will become a TypeError.", + "Passing Arrays into Coresubset() is deprecated since v0.4.0. " + "Use Coresubset.build() instead. " + "In v0.5.0, this will become a TypeError.", DeprecationWarning, stacklevel=2, ) @@ -309,9 +325,9 @@ def __init__(self, indices: Data, pre_coreset_data: _TOriginalData_co) -> None: pre_coreset_data = as_data(pre_coreset_data) # pyright: ignore[reportAssignmentType] if isinstance(pre_coreset_data, tuple): warnings.warn( - "Passing Arrays into PseudoCoreset() is deprecated. " - "Use PseudoCoreset.build() instead. " - "In future, this will become a TypeError.", + "Passing Arrays into Coresubset() is deprecated since v0.4.0. " + "Use Coresubset.build() instead. " + "In v0.5.0, this will become a TypeError.", DeprecationWarning, stacklevel=2, ) @@ -409,7 +425,11 @@ def indices(self) -> Data: @property @override - @deprecated("Use `.indices` instead.") + @deprecated( + "Use `.indices` instead. " + + "Deprecated since v0.4.0. " + + "Will be removed in v0.5.0." + ) def nodes(self) -> Data: """Deprecated alias for `indices`.""" return self.indices diff --git a/coreax/kernel.py b/coreax/kernel.py deleted file mode 100644 index dd0834f0..00000000 --- a/coreax/kernel.py +++ /dev/null @@ -1,271 +0,0 @@ -# © Crown Copyright GCHQ -# -# 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. - -r""" -Classes and associated functionality to use kernel functions. - -A kernel is a non-negative, real-valued integrable function that can take two inputs, -``x`` and ``y``, and returns a value that decreases as ``x`` and ``y`` move further away -in space from each other. Note that *further* here may account for cyclic behaviour in -the data, for example. - -In this library, we often use kernels as a smoothing tool: given a dataset of distinct -points, we can reconstruct the underlying data generating distribution through smoothing -of the data with kernels. - -Some kernels are parameterizable and may represent other well known kernels when given -appropriate parameter values. For example, the :class:`SquaredExponentialKernel`, - -.. math:: - k(x,y) = \text{output_scale} * \exp (-||x-y||^2/2 * \text{length_scale}^2), -which if parameterized with an ``output_scale`` of -:math:`\frac{1}{\sqrt{2\pi} \,*\, \text{length_scale}}`, yields the well known -Gaussian kernel. - -A :class:`~coreax.kernel.Kernel` must implement a -:meth:`~coreax.kernel.Kernel.compute_elementwise` method, which returns the floating -point value after evaluating the kernel on two floats, ``x`` and ``y``. Additional -methods, such as :meth:`Kernel.grad_x_elementwise`, can optionally be overridden to -improve performance. The canonical example is when a suitable closed-form representation -of a higher-order gradient can be used to avoid the expense of performing automatic -differentiation. - -Such an example can be seen in :class:`SteinKernel`, where the analytic forms of -:meth:`Kernel.divergence_x_grad_y` are significantly cheaper to compute that the -automatic differentiated default. -""" - -from typing_extensions import deprecated - -from coreax.kernels.base import ( - AdditiveKernel as _AdditiveKernel, - DuoCompositeKernel as _DuoCompositeKernel, - ProductKernel as _ProductKernel, - ScalarValuedKernel as _ScalarValuedKernel, - UniCompositeKernel as _UniCompositeKernel, -) -from coreax.kernels.scalar_valued import ( - ExponentialKernel as _ExponentialKernel, - LaplacianKernel as _LaplacianKernel, - LinearKernel as _LinearKernel, - LocallyPeriodicKernel as _LocallyPeriodicKernel, - PCIMQKernel as _PCIMQKernel, - PeriodicKernel as _PeriodicKernel, - PolynomialKernel as _PolynomialKernel, - RationalQuadraticKernel as _RationalQuadraticKernel, - SquaredExponentialKernel as _SquaredExponentialKernel, - SteinKernel as _SteinKernel, -) - - -# pylint:disable = abstract-method -@deprecated( - "Renamed to `ScalarValuedKernel`;" - + " moved to `coreax.kernels.base.ScalarValuedKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class Kernel(_ScalarValuedKernel): - """ - Deprecated reference to :class:`~coreax.kernels.ScalarValuedKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Renamed to `UniCompositeKernel`;" - + " moved to `coreax.kernels.base.UniCompositeKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class CompositeKernel(_UniCompositeKernel): - """ - Deprecated reference to :class:`~coreax.kernels.UniCompositeKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Renamed to `DuoCompositeKernel`;" - + " moved to `coreax.kernels.base.DuoCompositeKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class PairedKernel(_DuoCompositeKernel): - """ - Deprecated reference to :class:`~coreax.kernels.DuoCompositeKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -# pylint:enable = abstract-method - - -@deprecated( - "Moved to `coreax.kernels.base.AdditiveKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class AdditiveKernel(_AdditiveKernel): - """ - Deprecated reference to :class:`~coreax.kernels.AdditiveKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.ProductKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class ProductKernel(_ProductKernel): - """ - Deprecated reference to :class:`~coreax.kernels.ProductKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.LinearKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class LinearKernel(_LinearKernel): - """ - Deprecated reference to :class:`~coreax.kernels.LinearKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.LinearKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class PolynomialKernel(_PolynomialKernel): - """ - Deprecated reference to :class:`~coreax.kernels.PolynomialKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.SquaredExponentialKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class SquaredExponentialKernel(_SquaredExponentialKernel): - """ - Deprecated reference to :class:`~coreax.kernels.SquaredExponentialKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.ExponentialKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class ExponentialKernel(_ExponentialKernel): - """ - Deprecated reference to :class:`~coreax.kernels.ExponentialKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.RationalQuadraticKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class RationalQuadraticKernel(_RationalQuadraticKernel): - """ - Deprecated reference to :class:`~coreax.kernels.RationalQuadraticKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.PeriodicKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class PeriodicKernel(_PeriodicKernel): - """ - Deprecated reference to :class:`~coreax.kernels.PeriodicKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.LocallyPeriodicKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class LocallyPeriodicKernel(_LocallyPeriodicKernel): - """ - Deprecated reference to :class:`~coreax.kernels.LocallyPeriodicKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.LaplacianKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class LaplacianKernel(_LaplacianKernel): - """ - Deprecated reference to :class:`~coreax.kernels.SquaredExponentialKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.PCIMQKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class PCIMQKernel(_PCIMQKernel): - """ - Deprecated reference to :class:`~coreax.kernels.PCIMQKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ - - -@deprecated( - "Moved to `coreax.kernels.base.scalar_valued.SteinKernel`." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -class SteinKernel(_SteinKernel): - """ - Deprecated reference to :class:`~coreax.kernels.PCIMQKernel`. - - Deprecated since version 0.3.0. Will be removed in version 0.4.0. - """ diff --git a/coreax/util.py b/coreax/util.py index b60c4fdb..12b9a274 100644 --- a/coreax/util.py +++ b/coreax/util.py @@ -45,7 +45,7 @@ class factories and checks for numerical precision. import jax.tree_util as jtu from jax import Array, block_until_ready, jit, vmap from jaxtyping import Shaped -from typing_extensions import TypeAlias, deprecated +from typing_extensions import TypeAlias _logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO, stream=sys.stdout) @@ -236,37 +236,6 @@ def difference( return x - y -@deprecated( - "Use coreax.kernels.util.median_heuristic instead." - + " Deprecated since version 0.3.0." - + " Will be removed in version 0.4.0." -) -@jit -def median_heuristic( - x: Union[Shaped[Array, " n d"], Shaped[Array, " n"], Shaped[Array, ""], float, int], -) -> Shaped[Array, ""]: - """ - Compute the median heuristic for setting kernel bandwidth. - - Analysis of the performance of the median heuristic can be found in - :cite:`garreau2018median`. - - :param x: Input array of vectors - :return: Bandwidth parameter, computed from the median heuristic, as a - zero-dimensional array - """ - # Format inputs - x = jnp.atleast_2d(x) - # Calculate square distances as an upper triangular matrix - square_distances = jnp.triu(pairwise(squared_distance)(x, x), k=1) - # Calculate the median of the square distances - median_square_distance = jnp.median( - square_distances[jnp.triu_indices_from(square_distances, k=1)] - ) - - return jnp.sqrt(median_square_distance / 2.0) - - def sample_batch_indices( random_key: KeyArrayLike, max_index: int, diff --git a/tests/unit/test_benchmark.py b/tests/unit/test_benchmark.py index c617f2d9..2531abf2 100644 --- a/tests/unit/test_benchmark.py +++ b/tests/unit/test_benchmark.py @@ -34,7 +34,7 @@ ) from coreax import Data from coreax.benchmark_util import calculate_delta, get_solver_name, initialise_solvers -from coreax.kernel import SquaredExponentialKernel +from coreax.kernels.scalar_valued import SquaredExponentialKernel from coreax.solvers import ( KernelHerding, MapReduce,