·Python minimal implementation of moving average filtering (based on Numpy. Convolve)

1. Concept of moving average

Moving average filtering method (also called recursion average filtering method), when take N consecutive samples values as a queue, the queue length of fixed for N, each sample to a new data into the next morning, and throw away the original team one of the first data. (first in first out principle) N data arithmetic average operation in the queue, can obtain a new filtering results. Selection of N value: flow, N=12; Pressure: N=4; Liquid level, N=4~12; Temperature, N = 1 ~ 4

Advantages: good suppression of periodic interference, high smoothness suitable for high frequency oscillation system

Disadvantages: low sensitivity to the occasional pulse interference suppression effect is poor, not easy to eliminate the sampling value deviation caused by pulse interference is not suitable for serious pulse interference occasions, waste RAM

 

2. Solution

It can be found that the calculation of moving average filter is similar to the working principle of one-dimensional convolution, and the N of moving average corresponds to the size (length) of one-dimensional convolution kernel.

There will be some differences in step size. The sliding step size of the moving average filtering method is 1, while the one-dimensional convolution step size can be customized. Another difference is that the kernel parameters of one-dimensional convolution need to be updated and iterated, while the kernel parameters of moving average filter are all one.

How can we exploit this similarity? In fact, it is very simple, just set the size (length) of the one-dimensional convolution kernel equal to N, set the step size to 1, and set the kernel parameters to 1 initially. And since one-dimensional convolution is fast, then we can use one-dimensional convolution to do that, fast and efficient.

Is it overkill to use a deep learning framework for this? It’s overkill, because the kernel parameters of convolution don’t need to be updated, and there’s no need to use a complex deep learning framework, which would be much easier if Numpy could implement it.

No matter what we say, we found that Numpy. Convolve can do what we want.

 

3. Numpy. Convolve is introduced

Convolve (a, v, mode= ‘full’) A (N,) input one-dimensional array v (M,) input second one-dimensional array mode:{‘ full ‘, ‘valid’, ‘same’} parameter optional ‘full’ default value, return each convolution value, length is N+ m-1, at the edge of the convolution, the signals do not overlap, there is a marginal effect. ‘Same’ returns an array length of Max (M, N), and the marginal effect remains. The array length returned by ‘valid’ is Max (M,N)-min(M,N)+1. The edge point is invalid.

Similar to the one-dimensional convolution parameter, a is the convolution data, and V is the convolution kernel size.

 

4. Algorithm implementation

def np_move_avg(a,n,mode="same") :
    return(np.convolve(a, np.ones((n,))/n, mode=mode))
Copy the code

Principle that

Running averages is an example of convolution mathematics. For running averages, slide the window along the input and calculate the average of the window contents. For discrete 1D signals, the convolution is the same, except instead of calculating the average of any linear combination, that is, multiplying each element by the corresponding coefficient and adding up the results. Those coefficients, one for each position in the window, are sometimes called convolution kernels. Now, the arithmetic mean of N is (x_1 + x_2 +… + x_N) /N, so the corresponding kernel is (1/N, 1/N… , 1/N), which is exactly what we get by using np.ones((N,))/N.

Edge processing

The mode parameter np.convolve specifies how edges are handled. The same mode was selected here to ensure that the output length is one, but you may have other priorities. Here is a diagram illustrating the differences between modes:

import numpy as np
import matplotlib.pyplot as plt

def np_move_avg(a,n,mode="same") :
    return(np.convolve(a, np.ones((n,))/n, mode=mode))

modes = ['full'.'same'.'valid']
for m in modes:
    plt.plot(np_move_avg(np.ones((200)),50, mode=m));

plt.axis([-10.251, -1..1.1]);

plt.legend(modes, loc='lower center');

plt.show()
Copy the code

 

Reference 5.

1. stackoverflow.com/questions/1…