Hello, I am using an Unscented Kalman Filter to perform a joint state and parameter estimation.
I am trying to improve the accuracy of the parameters estimation foremost ( fit to the measured data is less important) .
Filter design
My dynamical model is a nonlinear, pseudo first order system with 7 first order states v_i and 7 “derivative” states z_i, such that \dot{v_i}(t) = z_i is trivial, the \dot{z_i} derivatives are nonlinear .
Additionally i am trying to estimate three gain parameters. \theta= [A,B,C]^T , so my augmented state vector is x_\theta = [x; \theta]^T . Unfortunatley, I can only indirectly observe the first three states; my observation function is g(x(t)) = x_1(t) - x_2(t) -x_3(t)
The filter matches the measured signal nicely, but ultimately I am more interested in estimation of the time changing parameters \theta(t) - ideally in a physical meaningful range \ge 0 .
Question:
how to optimize the UKF to improve parameter estimation accuracy?
Attempt
At the moment I am trying to somehow optimize the Covariance Matrices Q and R of the UKF by calculating cost as log-likelihood based on state prediction errors (i know the true states from simulation) and minimize using a particle swarm alg:
My setup function and cost function are implemented as follows
using LowLevelParticleFilters, Optim
function setup_filter(Q,R)
return UnscentedKalmanFilter(
discrete_dynamics_inv, measurement,
Q, R, MvNormal(x0, Q);
ny = 1, nu = 1, Ts = ts,
weight_params = kfpar
)
end
function cost(pars)
try # to avoid PosDefException exit
σ1 = pars[1:17]
σ2 = [pars[18]]
Q = SMatrix{17,17}(Diagonal(σ1)) # create cov mats
R = SMatrix{1,1}(Diagonal(σ2))
filter = setup_filter(Q, R)
ll = loglik_x(filter, u, y, x_tr) # y , x_tr from long simulation ts
# where theta changes gradually
return -ll # ?minimization
catch e
return eltype(pars)(Inf)
end
end
I then create an initial guess (based on literature), and optimize
σₘ = 1e-2 # observation noise
α₁ = 1e-3 # parameter base noise
α₂ = 1e-7 # states noise
α₃ = 1.0 # state with input u noise
A = 5.0; B = 22; C=15 # ~ iv params
p_guess = [α₂,α₂,α₂,α₂,α₂,α₂,α₂,α₃,α₂,α₂,α₂,α₂,α₂,α₂,α₁*A^2,α₁*B^2,α₁*C^2, σₘ]
res = Optim.optimize(
cost,
p_guess,
ParticleSwarm( n_particles = 30),
Optim.Options(
show_trace = true,
show_every = 1,
iterations = 10,
time_limit = 30,
)
)
My Issue is that i am totally unsure if this is even a good approach to improve parameter estimation accuracy, or completely foolish and if i should rather aim to either :
- optimize the other kalman filter parameters (s.a. sigmapoint spread ) instead of Q \& R?
- calculate log-likelihood only based on parameters A,B,C not on x_\theta?
- use a different optimization strategy instead of Particle Swarm?
I read some examples given in LowLevelParticleFilters.jl
regarding optimization, but since im not an engineer i am very unsure if those translate to my problem at all. Given that covariance optimization seems to be a crucial step in KF tuning i wonder if there’s a best practice / gold standard to this that i should try first? On a side note i wonder if there’s a good/ proven way to constrain the parameters during KF estimation so they are not becoming negative, maybe by using a log transform. Anyways i hope, that someone with expertise in this domain is willing to point me into the right direction; Thanks in advance!