如何在Python中应用自适应滤波器

14
我想在Python中应用自适应滤波器,但找不到任何有关如何实现此类算法的文档或示例。我熟悉使用scipy.signal工具箱设计“静态”滤波器,但我不知道如何设计自适应滤波器。
更明确地说:我有一个包含噪声的记录信号S。在这个记录中,有一个“真实”的函数T。我还有一个T的估计值。我想设计一个过滤器,使得经过滤波后的ST之间的误差最小化。请注意,在这种情况下,静态滤波器是无用的,因为我正在尝试过滤一个非平稳信号。

3
有两个自适应信号处理的库,第一个是adaptfilt,第二个是padasip - Darleison Rodrigues
2个回答

21
这是一个使用Numpy编写的基本LMS自适应滤波器Python代码。
欢迎评论,测试用例更加受欢迎。

enter image description here

""" lms.py: a simple python class for Least mean squares adaptive filter """

from __future__ import division
import numpy as np

__version__ = "2013-08-29 aug denis"

#...............................................................................
class LMS:
    """ lms = LMS( Wt, damp=.5 )  Least mean squares adaptive filter
    in:
        Wt: initial weights, e.g. np.zeros( 33 )
        damp: a damping factor for swings in Wt

    # for t in range(1000):

    yest = lms.est( X, y [verbose=] )
    in: X: a vector of the same length as Wt
        y: signal + noise, a scalar
        optional verbose > 0: prints a line like "LMS: yest y c"
    out: yest = Wt.dot( X )
        lms.Wt updated

    How it works:
    on each call of est( X, y ) / each timestep,
    increment Wt with a multiple of this X:
        Wt += c X
    What c would give error 0 for *this* X, y ?

        y = (Wt + c X) . X
        =>
        c = (y  -  Wt . X)
            --------------
               X . X

    Swings in Wt are damped a bit with a damping factor a.k.a. mu in 0 .. 1:
        Wt += damp * c * X

    Notes:
        X s are often cut from a long sequence of scalars, but can be anything:
        samples at different time scales, seconds minutes hours,
        or for images, cones in 2d or 3d x time.

"""

# See also:
#     http://en.wikipedia.org/wiki/Least_mean_squares_filter
#     Mahmood et al. Tuning-free step-size adaptation, 2012, 4p
# todo: y vec, X (Wtlen,ylen)

#...............................................................................
    def __init__( self, Wt, damp=.5 ):
        self.Wt = np.squeeze( getattr( Wt, "A", Wt ))  # matrix -> array
        self.damp = damp

    def est( self, X, y, verbose=0 ):
        X = np.squeeze( getattr( X, "A", X ))
        yest = self.Wt.dot(X)
        c = (y - yest) / X.dot(X)
            # clip to cmax ?
        self.Wt += self.damp * c * X
        if verbose:
            print "LMS: yest %-6.3g   y %-6.3g   err %-5.2g   c %.2g" % (
                yest, y, yest - y, c )
        return yest

#...............................................................................
if __name__ == "__main__":
    import sys

    filterlen = 10
    damp = .1
    nx = 500
    f1 = 40  # chirp
    noise = .05 * 2  # * swing
    plot = 0
    seed = 0

    exec( "\n".join( sys.argv[1:] ))  # run this.py n= ...  from sh or ipython
    np.set_printoptions( 2, threshold=100, edgeitems=10, linewidth=80, suppress=True )
    np.random.seed(seed)

    def chirp( n, f0=2, f1=40, t1=1 ):  # <-- your test function here
        # from $scipy/signal/waveforms.py
        t = np.arange( n + 0. ) / n * t1
        return np.sin( 2*np.pi * f0 * (f1/f0)**t )

    Xlong = chirp( nx, f1=f1 )
    # Xlong = np.cos( 2*np.pi * freq * np.arange(nx) )
    if noise:
        Xlong += np.random.normal( scale=noise, size=nx )  # laplace ...
    Xlong *= 10

    print 80 * "-"
    title = "LMS  chirp  filterlen %d  nx %d  noise %.2g  damp %.2g " % (
        filterlen, nx, noise, damp )
    print title
    ys = []
    yests = []

#...............................................................................
    lms = LMS( np.zeros(filterlen), damp=damp )
    for t in xrange( nx - filterlen ):
        X = Xlong[t:t+filterlen]
        y = Xlong[t+filterlen]  # predict
        yest = lms.est( X, y, verbose = (t % 10 == 0) )
        ys += [y]
        yests += [yest]

    y = np.array(ys)
    yest = np.array(yests)
    err = yest - y
    averr = "av %.2g += %.2g" % (err.mean(), err.std())
    print "LMS yest - y:", averr
    print "LMS weights:", lms.Wt
    if plot:
        import pylab as pl
        fig, ax = pl.subplots( nrows=2 )
        fig.set_size_inches( 12, 8 )
        fig.suptitle( title, fontsize=12 )
        ax[0].plot( y, color="orangered", label="y" )
        ax[0].plot( yest, label="yest" )
        ax[0].legend()
        ax[1].plot( err, label=averr )
        ax[1].legend()
        if plot >= 2:
            pl.savefig( "tmp.png" )
        pl.show()

1
谢谢这个优秀的脚本。我有一个问题:我如何向自适应滤波器提供我的函数的原始估计值?在你的示例代码中,你传递了变量 y,它只是一个标量...但是假设我想使用自适应滤波器从一个函数中提取信号,并使用信号的估计值。我不清楚如何在你的脚本中实现这一点。 - allhands
1
@allhands,“yest”在绘图和测试代码中是信号“y”的估计值,基于真实信号(这里是chirp)、真实噪声(正常)、X(之前的filterlen=10信号+噪声输入)和阻尼因子。从chirp + noise中提取chirp的这个例子很差,因为“yest”和“y”非常接近;需要一个更好的例子... - denis
有没有IIR自适应滤波器? - mohammadsdtmnd
有没有IIR自适应滤波器? - undefined
@mohammadsdtmnd,请查看https://dsp.stackexchange.com/questions/tagged/iir+adaptive-filters。 - denis

12

没有IIR滤波器。有没有IIR自适应滤波器? - mohammadsdtmnd
没有IIR滤波器。有没有IIR自适应滤波器? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接