Skip to content

SLogMI

sgptools.objectives.SLogMI

Bases: MI

Computes the Mutual Information (MI) using tf.linalg.slogdet for numerical stability, especially for large or ill-conditioned covariance matrices.

The slogdet (sign and log determinant) method computes the sign and the natural logarithm of the absolute value of the determinant of a square matrix. This is more numerically stable than computing the determinant directly and then taking the logarithm, as tf.linalg.det can return very small or very large numbers that lead to underflow/overflow when tf.math.log is applied.

Jitter is also added to the diagonal for additional numerical stability.

Source code in sgptools/objectives.py
class SLogMI(MI):
    """
    Computes the Mutual Information (MI) using `tf.linalg.slogdet` for numerical stability,
    especially for large or ill-conditioned covariance matrices.

    The slogdet (sign and log determinant) method computes the sign and the natural
    logarithm of the absolute value of the determinant of a square matrix.
    This is more numerically stable than computing the determinant directly and then
    taking the logarithm, as `tf.linalg.det` can return very small or very large
    numbers that lead to underflow/overflow when `tf.math.log` is applied.

    Jitter is also added to the diagonal for additional numerical stability.
    """

    def __call__(self, X: tf.Tensor) -> tf.Tensor:
        """
        Computes the Mutual Information for the given input points `X` using `tf.linalg.slogdet`.

        Args:
            X (tf.Tensor): The input points (e.g., sensing locations) for which
                           MI is to be computed. Shape: (M, D).

        Returns:
            tf.Tensor: The computed Mutual Information value.

        Usage:
            ```python
            import gpflow
            import numpy as np
            # Assume X_objective and kernel are defined
            # X_objective = np.random.rand(100, 2)
            # kernel = gpflow.kernels.SquaredExponential()
            # noise_variance = 0.1

            slogmi_objective = SLogMI(X_objective=X_objective, kernel=kernel, noise_variance=noise_variance)
            X_sensing = tf.constant(np.random.rand(10, 2), dtype=tf.float64)
            mi_value = slogmi_objective(X_sensing)
            ```
        """
        # K(X_objective, X_objective)
        K_obj_obj = self.kernel(self.X_objective)
        # K(X, X)
        K_X_X = self.kernel(X)
        # K(X_objective U X, X_objective U X)
        K_combined = self.kernel(tf.concat([self.X_objective, X], axis=0))

        # Compute log determinants using slogdet for numerical stability
        _, logdet_K_obj_obj = tf.linalg.slogdet(self.jitter_fn(K_obj_obj))
        _, logdet_K_X_X = tf.linalg.slogdet(self.jitter_fn(K_X_X))
        _, logdet_K_combined = tf.linalg.slogdet(self.jitter_fn(K_combined))

        # MI formula
        mi = logdet_K_obj_obj + logdet_K_X_X - logdet_K_combined

        return mi

__call__(X)

Computes the Mutual Information for the given input points X using tf.linalg.slogdet.

Parameters:

Name Type Description Default
X Tensor

The input points (e.g., sensing locations) for which MI is to be computed. Shape: (M, D).

required

Returns:

Type Description
Tensor

tf.Tensor: The computed Mutual Information value.

Usage
import gpflow
import numpy as np
# Assume X_objective and kernel are defined
# X_objective = np.random.rand(100, 2)
# kernel = gpflow.kernels.SquaredExponential()
# noise_variance = 0.1

slogmi_objective = SLogMI(X_objective=X_objective, kernel=kernel, noise_variance=noise_variance)
X_sensing = tf.constant(np.random.rand(10, 2), dtype=tf.float64)
mi_value = slogmi_objective(X_sensing)
Source code in sgptools/objectives.py
def __call__(self, X: tf.Tensor) -> tf.Tensor:
    """
    Computes the Mutual Information for the given input points `X` using `tf.linalg.slogdet`.

    Args:
        X (tf.Tensor): The input points (e.g., sensing locations) for which
                       MI is to be computed. Shape: (M, D).

    Returns:
        tf.Tensor: The computed Mutual Information value.

    Usage:
        ```python
        import gpflow
        import numpy as np
        # Assume X_objective and kernel are defined
        # X_objective = np.random.rand(100, 2)
        # kernel = gpflow.kernels.SquaredExponential()
        # noise_variance = 0.1

        slogmi_objective = SLogMI(X_objective=X_objective, kernel=kernel, noise_variance=noise_variance)
        X_sensing = tf.constant(np.random.rand(10, 2), dtype=tf.float64)
        mi_value = slogmi_objective(X_sensing)
        ```
    """
    # K(X_objective, X_objective)
    K_obj_obj = self.kernel(self.X_objective)
    # K(X, X)
    K_X_X = self.kernel(X)
    # K(X_objective U X, X_objective U X)
    K_combined = self.kernel(tf.concat([self.X_objective, X], axis=0))

    # Compute log determinants using slogdet for numerical stability
    _, logdet_K_obj_obj = tf.linalg.slogdet(self.jitter_fn(K_obj_obj))
    _, logdet_K_X_X = tf.linalg.slogdet(self.jitter_fn(K_X_X))
    _, logdet_K_combined = tf.linalg.slogdet(self.jitter_fn(K_combined))

    # MI formula
    mi = logdet_K_obj_obj + logdet_K_X_X - logdet_K_combined

    return mi