-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add power_spectral_density to RatQuad covariance kernel for HSGP support #7973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7973 +/- ##
=======================================
Coverage 91.49% 91.49%
=======================================
Files 116 116
Lines 18962 18973 +11
=======================================
+ Hits 17349 17360 +11
Misses 1613 1613
🚀 New features to boost your workflow:
|
|
BTW, one limitation here is that |
Does jax or tfp have the gradients we could use as the basis for an implementation? |
|
They have an expression for the 2nd input: https://github.com/tensorflow/probability/blob/732e7d16235a38b639a3b2cd00e76a4add45118c/tensorflow_probability/python/math/bessel.py#L1057 |
|
In the past I've implemented a couple gradients using stan math / wolfram as reference. Never had a case where tfp was ahead of the curve for these special functions |
|
Gradient wrt second input is the trivial one in these functions, we also have it |
|
There has been some useful discussion on Jax: jax-ml/jax#12402 |
|
FWIW, it does work without a fully differentiable function -- it just uses a slice sampler for alpha. |
tests/gp/test_cov.py
Outdated
| npt.assert_allclose(true_1d_psd, test_1d_psd, atol=1e-5) | ||
|
|
||
| def test_psd_eigenvalues(self): | ||
| # Test PSD implementation using Szegő’s Theorem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this work for a 2 or higher dimensional X?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ) | ||
| npt.assert_allclose(true_1d_psd, test_1d_psd, atol=1e-5) | ||
|
|
||
| def test_psd_eigenvalues(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to cook up something more accurate, and gippity came up with Rayleigh quotients. It seems to be more accurate than using linalg.eigh. I also found that a smaller length scale increased accuracy, I guess because we can lay down more gridpoints more densely in a small region. Cranking up N (or decreasing dx) did not seem to help.
import numpy as np
from scipy import linalg
alpha = 1.5
ls = 0.1
L = 50
dx = 0.05
N = int(L / dx)
X = (np.arange(N) * dx)[:, None]
with pm.Model():
cov = pm.gp.cov.RatQuad(1, alpha=alpha, ls=ls)
K = cov(X).eval()
theta = 2 * np.pi * np.fft.fftfreq(N, d=1)
omegas = theta / dx
psd = cov.power_spectral_density(omegas[:, None]).eval()
psd_scaled = psd.ravel() / dx
j = np.arange(N)
modes = np.exp(1j * np.outer(theta, j))
num = modes.conj() @ (K @ modes.T)
den = np.sum(np.abs(modes)**2, axis=1)
rayleigh_quotient = np.real(np.diag(num) / den)
np.testing.assert_allclose(psd_scaled, rayleigh_quotient, atol=0.05)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, plotting the approximation, it seems like all of the error comes from the boundaries. So it might make more sense to do a test like:
trim = 100
np.testing.assert_allclose(psd_scaled[trim:-trim], rayleigh_quotient[trim:-trim], atol=1e-2)Plot:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
order = np.argsort(theta)
ax.plot(theta[order], psd_scaled[order], label="Closed-Form")
ax.plot(theta[order], Rq[order], "--", label="Rayleigh quotient")
ax.set(xlabel = "θ", ylabel='spectral density', yscale='log')
plt.legend()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do this. Did you come across a reference for this to add to the docstring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can just cite the wiki for the formula: https://en.wikipedia.org/wiki/Rayleigh_quotient (or use one of the citations therein)
Co-authored-by: Jesse Grabowski <[email protected]>
Co-authored-by: Jesse Grabowski <[email protected]>

Description
PSD method and test added. A simple HSGP fits successfully with the resulting RatQuad kernel.
Related Issue
Checklist
Type of change