Skip to content

Conversation

@sc336
Copy link
Contributor

@sc336 sc336 commented Mar 28, 2023

PR type: new feature

Summary

Proposed changes
Adds a new categorical kernel that implements categorical variables by mapping them to values in a latent space.

Minimal working example

# Put your example code in here

Fully backwards compatible: yes

PR checklist

  • New features: code is well-documented
    • detailed docstrings (API documentation)
    • notebook examples (usage demonstration)
  • The bug case / new feature is covered by unit tests
  • Code has type annotations
  • Build checks
    • I ran the black+isort formatter (make format)
    • I locally tested that the tests pass (make check-all)
  • Release management
    • RELEASE.md updated with entry for this change
    • New contributors: I've added myself to CONTRIBUTORS.md

@codecov
Copy link

codecov bot commented Mar 29, 2023

Codecov Report

Patch coverage: 100.00% and project coverage change: +0.04 🎉

Comparison is base (7c6beae) 98.01% compared to head (748352b) 98.06%.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2055      +/-   ##
===========================================
+ Coverage    98.01%   98.06%   +0.04%     
===========================================
  Files           96       97       +1     
  Lines         5404     5436      +32     
===========================================
+ Hits          5297     5331      +34     
+ Misses         107      105       -2     
Impacted Files Coverage Δ
gpflow/kernels/__init__.py 100.00% <ø> (ø)
gpflow/kernels/categorical.py 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@sc336 sc336 requested a review from uri-granta March 30, 2023 08:18
Copy link
Member

@uri-granta uri-granta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Various comments! Also probably worth checking with victor regarding which essential tests are worth adding. Code looks good though!

from ..base import Parameter, TensorType
from . import Kernel

tfd = tfp.distributions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More normal to write

Suggested change
tfd = tfp.distributions
from tensorflow_probability import distributions as tfd

from . import Kernel

tfd = tfp.distributions
st = tfp.bijectors.Softplus().inverse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you're actually using st or tfd!

Suggested change
st = tfp.bijectors.Softplus().inverse

of degrees of freedom in optimisation. You may also find fixing the lengthscale to be useful here.
Note that Z is parameterised by the differences of latent space values for each category for the same reason.
Multiple categories can be included by wrapping multiple layers of CategoricalKernel.
:param wrapped_kernel_1: The non-categorical kernel.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely clearer to call these arguments non_categorical_kernel and categorical_kernel?

# wrapped_kernel_2 is the one that trains the categorical variables
set_trainable(wrapped_kernel_2, False)
self.wrapped_kernel = wrapped_kernel_1 * wrapped_kernel_2
label_dim = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the categorical_kernel was supposed to specify the label dimension in its active_dims?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only support one label dimension for now, this could be extended at a later date.

set_trainable(wrapped_kernel_2, False)
self.wrapped_kernel = wrapped_kernel_1 * wrapped_kernel_2
label_dim = 1
self._Z_deltas = Parameter(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment might be useful?

# parametrise by the `num_labels - 1` differences of latent space values

"""
Z = tf.concat([tf.constant(0, shape=(1,), dtype=tf.float64), tf.squeeze(self._Z_deltas)], 0)
m = tf.linalg.band_part(tf.ones([tf.size(Z), tf.size(Z)], dtype=tf.float64), -1, 0)
return tf.expand_dims(tf.linalg.matvec(m, Z), -1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like voodoo to me but I believe you! (though a simple unit test might be useful)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a comment to explain it.

np.testing.assert_allclose(K, K1 + K2)


def test_concat_inputs_with_latents() -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like there are definitely missing tests for the Categorical kernel (beyond broadcasting), but I'm probably not the person to spot them! Also don't we want a test that actually uses Categorical in a model?

@sc336 sc336 force-pushed the sc336/categorical_kernel branch from c00be2e to 748352b Compare April 3, 2023 12:02
Copy link
Member

@uri-granta uri-granta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good (though my OCD is still vexed by _concat_inputs_with_latents describing the same dimension as both D and x_dim!). Are you ok to create an issue to investigate writing more tests?

@sc336 sc336 merged commit 39bd130 into develop Apr 4, 2023
@sc336
Copy link
Contributor Author

sc336 commented Apr 4, 2023

Looks good (though my OCD is still vexed by _concat_inputs_with_latents describing the same dimension as both D and x_dim!). Are you ok to create an issue to investigate writing more tests?

#2058

@khurram-ghani khurram-ghani mentioned this pull request May 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants