Skip to content
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

Global Kalman filter proposal, issue with weights normalisation in data association scenario #1081

Closed
A-acuto opened this issue Sep 13, 2024 · 2 comments

Comments

@A-acuto
Copy link
Contributor

A-acuto commented Sep 13, 2024

So this is not yet an issue of the current implementation, but I wanted to have a discussion on how to deal with this problem.

I attach an example, that needs to be run from the branch #1080 , where I create the global kalman filter proposal and I use it in a data association scenario.

The code falls apart when we have to compute the distances to perform the association and hypotheses generation because computing the mean is not possible due to "ZeroDivisionError: Weights sum to zero, can't be normalized" in State.

The code for mean in types/state is the following:

@clearable_cached_property('state_vector', 'log_weight')
 def mean(self):
        """Sample mean for particles"""
        if len(self) == 1:  # No need to calculate mean
            return self.state_vector
        return np.average(self.state_vector, axis=1, weights=np.exp(self.log_weight))

Is weights=np.exp(self.log_weight)) safe enough? Or it should be better using logsumexp?
Or I am missing something more simpler.

Happy to discuss

@sdhiscocks
Copy link
Member

Yeah, I agree that would be better. Looking at logsumexp and np.average source, doing this should be equivalent:

diff --git a/stonesoup/types/state.py b/stonesoup/types/state.py
index 64272349..d04b6bff 100644
--- a/stonesoup/types/state.py
+++ b/stonesoup/types/state.py
@@ -744,14 +744,14 @@ class ParticleState(State):
         """Sample mean for particles"""
         if len(self) == 1:  # No need to calculate mean
             return self.state_vector
-        return np.average(self.state_vector, axis=1, weights=np.exp(self.log_weight))
+        return np.average(self.state_vector, axis=1, weights=np.exp(self.log_weight - np.max(self.log_weight)))
 
     @clearable_cached_property('state_vector', 'log_weight', 'fixed_covar')
     def covar(self):
         """Sample covariance matrix for particles"""
         if self.fixed_covar is not None:
             return self.fixed_covar
-        return np.cov(self.state_vector, ddof=0, aweights=np.exp(self.log_weight))
+        return np.cov(self.state_vector, ddof=0, aweights=np.exp(self.log_weight - np.max(self.log_weight)))
 
     @weight.setter
     def weight(self, value):

@sdhiscocks
Copy link
Member

Fix in #1083

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

No branches or pull requests

2 participants