Sometimes HODLR predictive samples are off
st-bender opened this issue · 17 comments
Hello
I tried the model fitting tutorial notebook
https://george.readthedocs.io/en/latest/tutorials/model/
using the HODLR solver for the correlated noise fit by adding
solver=HODLRSolver
to the gp
initialisation in In[10]
.
The emcee fit works well and the numbers are close to the true
values and the BasicSolver
results.
However, the predictive samples look like this:
Is there any internal reason for this or is it a bug?
Changing tol
does not help really, may it be related to the small sample size (50)?
But something like this happens also on larger data sets.
HODLR ist very nice to fit my large datasets in a resonable amount of
time but the strange predictive samples kept me from really trusting it.
Cheers.
Very strange! I'll look into this this afternoon. Thanks for letting me know!
Sorry about the delay! I'm still looking into this. I can reproduce the bug when I run the notebook but I can't seem to reproduce it in isolation so something fishy is definitely going on. I'll keep on it and update when I figure it out.
Hi, no problem.
For me this also happens when I run this script via normal python.
The only thing related to the solver would be solver.apply_inverse() in predict()
https://github.com/dfm/george/blob/master/george/gp.py#L502
Or maybe something related to kernel.get_value()?
I tried with return_cov=False
and plot only the mean prediction and also cache=False
in predict().
Both didn't help.
Cheers.
Hi,
Thanks for looking into this. I found your test branch and gave it a go.
The tests don't give any error here too.
However, if I put compute()
before set_parameter_vector()
, the first assertion in https://github.com/dfm/george/blob/predict-bug/tests/test_solvers.py#L119 already fails, i.e. the alphas differ.
HTH, Stefan.
Hi, I might have hit the same issue. Is it known what causes this?
I haven't had a chance to look into this in detail yet, but it's definitely a bug! I'll try to get to it next week (I'm just getting started back up after a cross-country move), but let me know if you come up with anything.
I am not setup to debug c++, so not sure, but I think there is some caching in kernel classes with HODLR solver. If I re-create kernel, model=george.GP(kernel, solver = george.HODLRSolver), and then model.set_parameter_vector() it seems to work. If I do not recreate kernel seems not to. Also, emcee.EnsembleSampler seems to be wrong with HODLR solver, which would be related I guess, but it is harder to pinpont at the moment.
For what it's worth, if I add self.kernel.get_value(self._x) in GP.compute, before self.solver.compute it seems to work. I think it works because it triggers creation of KernelInterface with new parameters in Kernel.kernel in kernels.py. Basic solver does that explicitely in BasicSolver.compute in basic.py. But hodlr solver is in c++, so I am not sure it is calling it and therefore KernelInterface creation is not triggered. I hope you find this useful and this is not a red herring.
That was exactly the clue I needed! Thanks, @alexchgithub. I've started working on a fix on the predict-bug branch. I'll post here again when I have a chance to implement some tests.
I've just pushed an update to the predict-bug branch that seems to fix this problem. There were indeed a few problems with the caching setup, but I'm really not entirely sure why this wasn't also a problem for the basic solver!
Take a look at that branch, see if it helps for your problems, and please let me know!
Thanks for looking and fixing. I tried to locally build the branch but did not manage so far (I am on Windows). Will try again later. If you know some workaround or indeed if it does not work on Windows for some reason please let me know.
I'm not a Windows expert, but if you continue having issues with the Windows build, please open a separate issue and we'll try to figure it out.
Hi!
Sorry for not answering lately but I saw you got some advise already and I also followed the updates.
I checked out the predict-bug branch and it really seems to solve the issue! Thanks for looking into it.
Some time ago you also wrote a test case for it, I found that it now works if you copy()
the kernel object when creating the GP
object. The following snippet now passes cleanly, after preparing Model
, t
, y
, and yerr
as in the model tutorial:
from copy import copy
params = dict([('amp', -0.9084520230247749),
('location', 0.014424970078361431),
('log_sigma2', -0.91748937072607739)])
kernel = kernels.ConstantKernel(log_constant=-2.826564897326464)
kernel *= kernels.Matern32Kernel(7.369719781508781)
gp0 = george.GP(copy(kernel), mean=Model(**params))
gp = george.GP(copy(kernel), mean=Model(**params), solver=george.HODLRSolver)
gp0.compute(t, yerr)
gp.compute(t, yerr)
p = np.array([-0.89532215, 0.04577885, -1.32793447, -1.32874009, 3.39837512])
gp0.set_parameter_vector(p)
gp.set_parameter_vector(p)
x = np.linspace(-5, 5, 500)
for _ in range(10):
alpha0 = gp0.apply_inverse(y)
alpha = gp.apply_inverse(y)
assert np.allclose(alpha, alpha0)
for _ in range(10):
mu0, cov0 = gp0.predict(y, x)
mu, cov = gp.predict(y, x)
assert np.allclose(mu, mu0)
Yes. The problem had something to do with the kernel thinking that it wasn't "dirty" because it had been used in another place. This shouldn't be a problem anymore and the performance hit was negligible. That's what I get for trying to be clever :-\
Thanks for tracking this down!