ezmsg-org / ezmsg

Pure-Python DAG-based high-performance SHM-backed pub-sub and multi-processing pattern
https://ezmsg.readthedocs.io/en/latest/
MIT License
9 stars 5 forks source link

Enhancement: EWMA should work with arrays with ndim > 2 #47

Closed cboulay closed 7 months ago

cboulay commented 8 months ago

The following snippet right above the def ewma can make it work, but I had putting a while loop inside a function that gets called frequently. I'm sure there's a better way.

            while scale_arr.ndim < buffer_data.ndim:
                scale_arr = scale_arr[..., None]

And this would have to be accompanied by removing the , np.newaxis] slicing on scale_arr within the function.

griffinmilsap commented 7 months ago

Admittedly, my ewm implementation was pulled from a stack overflow article and I haven't diligently checked it for correctness. It's definitely not implemented as optimally as it could be, and its a VERY difficult read due to its reliance on another window unit and complicated math. Of all the existing signal processing units in ezmsg-sigproc, it's the one that could use the most TLC.

cboulay commented 7 months ago

Here's river's AdaptiveStandardScaler: https://github.com/online-ml/river/blob/main/river/preprocessing/scale.py#L545-L555

( Just a quick primer on river to help you read that code: they expect the input to this function to be a single sample in a dict, with channels | features as keys and float values. i.e.,: {'ch1': 123.4, 'ch2': 567.8, ...} )

You'd have to dive in a bit if you want to find their exponentially-weighted mean and var update functions. They come from a rust library called watermill. Here is the mean update code. It's just mean = alpha * new_sample + (1 - alpha) * mean

Edit: For variance it's a bit more complicated. The mean and mean-of-squares are both updated just as above, and then the resultant var is mean-of-squares - square(mean).

Anyway, the key point is that EWM doesn't require a window.

cboulay commented 7 months ago

Closed with #52

But I'll refer back to this when making an AdaptiveStandardScaler unit.