Robust resampling/interpolation method

I am working on a system identification problem with poor quality input data.

The data describes a heating system, with thermostat temperatures, thermal power inputs, supply/return water temperatures etc.

Some issues with the data are:

  • frequently missing data
  • spiking noise caused by activation of heaters
  • discretization errors
  • low frequency disturbances (mainly due to sunlight, but other sources exist)

A year ago when I tackled this problem, I kind of rolled my own algorithm based on DSP.resample and tuned it by hand. One of the problems it had was it introduced wiggles/oscillations. So I probably also need antialiasing.

Now I want to setup a proper processing pipeline that I can deploy in production.

I am mainly just looking for some suggestions on algorithms / packages to handle all these problems. Unfortunately, there isn’t much I can do about the data source because these are systems used by real people (pesky users right :sweat_smile:)

If you have any other recommendations I would also be very happy to hear those.

1 Like

Missing data can be handled by predictor/corrector methods (such as Kalman or particle filters) by not perfoming the measurement correction when there is no data available, only the prediction. You can even handle arbitrary intervals inbetween the obtained data points, here’s an example

Here’s another example that has missing data

A common approach to handle this in gaussian filtering is to evaluate the likelihood of the obtained measurement, and if the measurement is several standard deviations away from the expected one, discard it (or inflate the measurement covariance matrix). The last tutorial above computes the Z-score used to evaluate the measurement, but never discards any data.

What does this mean? Quantization?

Something like this?

or any of those?


If you have a state estimator of the system that handles all of those things, system identification can be performed by, e.g., maximizing the likelihood of the data

4 Likes

You may also find it useful to have a look at some methods and tools for outlier detection such as Hampel outlier detection/filter. An implementation in Julia can be found at [ANN] HampelOutliers.jl. Standard filtering/smoothing techniques may unnecessarily project the value of such outlier to the neighbouring samples.

1 Like

Thanks for the suggestions, very useful!

Yes exactly.

I have indeed studied those, it is a very nice overview. I think state estimation is relatively straightforward in this problem, the tricky part is forecasting states and disturbances. What I couldn’t figure out is how to deploy those disturbance models to an actual controller that does MPC. For the sunshine model it’s clear, just extrapolate the timeseries and forecasted solar irradiance (I have that).

But for the low frequency disturbance? The convention in literature seems to be to just treat it like a constant parameter and assume it stays constant in the future. Maybe you have some thoughts on that?

Yes that would be ideal.

Models identified with methods that optimize the next-step ahead prediction diverge too quickly if I simulate longer timeseries. So if I am interested in simulation performance the methods in LowLevelParticleFilters.jl don’t necessarily seem applicable here? (if this is a wrong statement please correct me)

The main goal is to get a model that performs well in MPC with a horizon of 24 hours. That behaviour tends to de dominated by what the weather and heating system do, for which I have ‘good’ data and forecasts. I probably should have mentioned it’s still the same problem as my previous post :sweat_smile:

Its reasonably straightforward if the MPC tools are in the state-space form, as it is the case for most modern MPC software. You just build your MPC with the augmented model. The augmented model is your (deterministic) model of the heating system “concatenated” with all your disturbance models (that is, the state vector will be a concatenation of the heating system states and the disturbance states). Be sure to disable any builtin model augmentation if you DIY this part (for exemple, nint_ym=0 and nint_u=0 options in ModelPredictiveControl.jl).

Yes, a low frequency disturbances is generally approximated as constant value that can be added anywhere in the deterministic model: at the manipulated inputs, at the measured output or a constant parameter used anywhere between the two. The disturbance model of a constant value is Gaussian white-noise integrated only once.

I will let Fredrik answer the other questions related to LowLevelParticleFilters.jl. It seems like a really interesting modeling and control problem! :grinning_face:

1 Like

This is indeed how I implemented it. I think I was trying to understand that when you’re looking forward like in MPC you need good deterministic models to define the ‘known/forecasted disturbances’. I have good (forecasted) data on these disturbances, but the key question is how do they affect the states.

In the disturbance gallery of LowLevelParticleFilters.jl, I think we talk about ‘unmeasured disturbances’ only. These do not seem to be useful in the deterministic MPC case beyond estimating the initial condition, because there is no ‘correct’ step as there is no measured data. I am an EE and not a control engineer so please correct me if that’s wrong.

This is a great package! Because I need to generate C code for an embedded system, I chose to implement MPC as an optimization model in cvxpy and generate C code with cvxpygen. There does seem to be LinearMPC.jl now, I should try that out :slight_smile:

1 Like

I’m also an EE, but it morphed into a weird mix of EE+ChemE+BioTech+ControlE+SoftwareE. I’m no longer sure what I am :laughing:.

Yes, the stochastic models are for the unmeasured disturbances. But these models will affect the MPC predictions/forecasts beyond the initial state. For exemple, in the 3 plots below, the dots are the predictions at the discrete-time k=90 for the stochastic system:

\frac{y_s(z)}{e(z)} = \frac{1}{1-az^{-1}}

with a=0, 0.5 and 1, respectively from top to bottom.

The a=1 case is integrated Gaussian white noise, and you can see that predictions are kept constant in the future.

If you have access to a known/measured disturbance, you first need to determine how it affects your deterministic model (for exemple, added at the manipulated inputs or a load disturbance). This measured disturbance will then be used for feedforward compensation in the MPC controller, denoted with the vector \mathbf{d} in MPC.jl. At each control period, you will have access to your known disturbance \mathbf{d}(k). But there is still one thing to determine: how you predict \mathbf{d} in the future? The simplest solution is assuming a constant value in the future: \mathbf{\hat{d}}(k+1) = \mathbf{\hat{d}}(k+2) = \dots = \mathbf{d}(k). But the exact same theory as above can also be applied here. A constant \mathbf{d} in the future is just assuming that \mathbf{d} is the output of an integrated white noise. It can be modelled with any system from aforementioned disturbance gallery, but you will need to implement the forecasting yourself.

Yes, the is no code generation for now. I should really work on building an interface with LinearMPC.jl.

Edit: it made me think @darnstrom, am I right in thinking that custom prediction for measured disturbances are not supported right now in LinearMPC.jl (it’s really similar as the implementation of reference preview) ? If yes, it would be a great addition to the package.

1 Like

It’s not so much a convention as an explicit model that says it’s constant. If you use the model
\dot{x}_d = 0 + w
for your low-frequency disturbance, i.e., an integrator of noise, you are explicitly modeling something that has zero deterministic dynamics (constant), only random fluctuations that are equally likely to go in any direction. There are more elaborate disturbance models that do not have zero dynamics, and in that case, simulating those forward in time (for forecasting) does not in general lead to a constant evolution.

diverge in what sense?

Whenever you have unmeasured disturbances you are typically not interested in pure simulation performance, there must be some mechanism present to account for the unmeasured disturbances, and the only information available about this is the measurements you do have access to. These must feed into the dynamics somehow, which is what the filtering accomplishes. The approach from your previous post on the subject sounds spot on what you want, filtering with 24h forecast at each point, minimizing the forecasting errors along the trajectory.

You can treat forecasted values (from e.g. a weather forecast) as “measurements” and incorporate those as any other measurement. Typically, those would have a rather large covariance compared to actual sensor measurements.

So am I, at least in the sense that I studied EE :sweat_smile:

2 Likes

If the system has future disturbances with uncertainties, a primitive way to handle that in a “robust MPC” is as in https://doi.org/10.3384/ecp201709: we tried to control the level in a lake (hydro power reservoir) by manipulating the flood gates, and the disturbance was precipitation. Our partnering power producer provided estimates of flow into the lake based on the dynamics from precipitation through the catchment area and into the lake. This was based on purchased weather prediction 2-3 weeks into the future, with some 50 different realizations of possible predictions. The idea was to operate the flood gates so that the control requirements were satisfied for the worst case scenario.

My colleague in that publication has since done much more work on similar problems, with more efficient algorithms for MPC.

I would guess that it would be relatively straightforward to use your MPC package to do this.

Interesting approach, it fits nicely to weather forecasting! I took a look a the paper quickly and, the deterministic MPC algorithm could be easily implemented in MPC.jl with currently available features. But scenario trees and multi-objective optimization are not supported right now (except maybe indirectly with a custom cost function + a weighted sum of each objective), so the would not be the case for stochastic MPC. Robust MPC through scenario trees are in my long-term goals, but I’m prioritizing as complete and as efficients-as-possible “non-robust” predictive controllers before entering into this rabit hole :rabbit_face:

1 Like

The way we did the robust MPC was simply to simulate into the future (say) 50 models of the system with 50 different disturbance sequences, each with the same control input sequence, then compute the cost function for each system, and use the sum of the 50 cost functions as the cost function in the MPC algorithm.

This can easily be done by augmenting the system with (say) 50 times larger state than the deterministic system, 50 times as many disturbance input sequences, and a corresponding output. The number of control inputs is the same as for the deterministic system. I’m sure this fits into your MPC algorithm.

This is a very intuitive way to do robust MPC, although not the most efficient. But simple to understand, and (I think) simple to implement.

1 Like

Coincidently I am currently running through pretty much the same… well… pain.

With a new data-intensive (sysID) project I said to myself that it is perhaps the time to try to learn and adopt the more DataFrame-ish workflow (resembling they Python’s Pandas) instead of handling the time series at the very low level as pure vectors (the habit I had developed in Matlab before the advent of their timetables).

First, DataFrames.jl does not support the date/datetime index by itself. I have found the TSFrames.jl package that brings date/datetime index into DataFrames. Mostly the resulting “object” indeed behaves transparently as DataFrame, but there are some glitches.

And I confess that I am struggling with even the elementary steps. Mainly because I am not yet fluent with that dataframe-ish way of working, but also because even very basic functionality is typically provided by some other packages, and it takes quite some time to find them and learn which are usable…

Oh, how I would love to see a time-series extension of the online book https://juliadatascience.io to time-series workflows. How to do imputing (perhaps using Impute.jl, you may find it useful too), how to remove outliers (I am only learning if can use the Hampel filter that I mentioned here earlier, or is there anything reasonably well maintained?) which tool currently best fits into this workflow for smoothing, resampling, the latter being my the step I am currently struggling with. Then how to do cumsum for the columns of the DataFrame/TSFrame (here I got lost in the rabbit holes here in the discussion forum). RollingFunction.jl is in the to-do (to-study) list to learn if and how I could then apply other filters such as Savitzky-Golay.jl.

I am still enjoying it but I admit it is tempting to go back just to “long vectors”.

2 Likes

I found that if I fit the model on 1-step ahead predictions, that fit doesn’t perform well if I simulate that model forwards for 24 hours, even if disturbances are mostly absent. I guess that’s because the dynamics are so slow and the 1-step ahead prediction doesn’t capture that. A good observer is not a good predictor in this case :sweat_smile:

I think this is the right approach, because it also matches how the model would be used in reality. If it’s not too much effort could you maybe give a rough sketch how you would approach this with LowLevelParticleFilters.jl?

EEs unite!

1 Like

Something like this pseudo code

function cost(pars)
    kf = FilterConstructor(pars)
    c = zero(eltype(pars))
    for time in all_timepoints[2:end]
        update!(kf, u[time-1], y[time-1])
        x_sim, u_sim, y_sim = rollout(kf, state(kf), u[time:time+24])

        c += sum((y_sim .- y[time:time+24]).^2) / length(y_sim)
    end
    return c / length(all_timepoints)
end

The sum of squared error cost can be replaced by, e.g., loglikelihood of prediction errors if you step forward with repeated calls to predict! instead of the rollout call above, but this should be a reasonable starting place.

1 Like