因工作涉及到数据滤波(滤噪)处理,汇总了一些网上简单的滤波算法,方便日后查看。
滤波算法包括:均值滤波,中值滤波,一阶(αβ)滤波,卡尔曼滤波。
本文主要是处理线性数据y=ax+b,对于非线性数据,简单的滤波算法效果有限。滤波算法都有自己的局限,针对不同问题需要选择合适的方法。
以下使用python实现简单demo,主要是方便画图。
为了方便,本文使用jupyter notebook直接导出markdown生成。
真值y = 0.003*x
观测值加上随机白噪声
import random
import math
import numpy as np
import matplotlib.pyplot as plt
n = 500
real = [] # 真值
mear = [] # 观测值
pred = [] # 滤波值
# 建立真值和观测值
for i in range(n):
num = 0.003 * i
real.append(num)
num += 0.1 * np.random.standard_normal() # 本身的不确定性
num += 0.5 * np.random.standard_normal() # 观测的不确定性
mear.append(num)
plt.plot(range(n), mear)
plt.plot(range(n), real)
plt.show()

均值滤波是典型的线性滤波算法,在图像中应用比较多,原理是以该像素点周围的八个像素点取平均操作,然后替代该像素点,也就是卷积操作。对于处理简单的线性数据y=ax+b,原理也是类似的,取该点周围的n个点取平均即可,n可以看为是一个滑窗。因此,可以取该点的前后n个数据的平均值,也可以取前n个数据的平均值,根据不同场景数据设计即可。
如下代码比较适合离线数据处理,是对原始观测的数据中取某点的前后滑窗大小的均值,好比图像中应用中就是对原始图片滤波。如果对于在线数据,一个不断增加数据的数组,建议使用一阶滤波器或者kalman滤波器。
# window滑窗越大,滤波效果越明显,结果越滞后
# 设置了该点的左右滑窗大小,可根据实际情况选取参数
def average_filter(window_left, window_right, arr):
size = len(arr)
result = []
for i in range(window_left, size-window_right):
sum = 0
# 滑窗
for j in range(-window_left, window_right+1):
sum += arr[i+j]
sum /= (window_left + window_right + 1)
result.append(sum)
return result
pred = [] # 滤波值
# 前后5个,总共11个点求平均值
pred = average_filter(5, 5, mear)
# 前5个数,总共6个点求平均值
# pred = average_filter(5, 0, mear)
plt.plot(range(n), mear)
plt.plot(range(n), real)
# 会牺牲掉前后window大小的数据,可以作相应改进
plt.plot(range(len(pred)), pred)
print(len(pred))
490

和均值滤波相似,同样是选取固定大小滑窗,然后选取滑窗内的中位数作为滤波结果。或者选取中位数平均数,类似比赛中去掉最高最低分,对其余比分求平均,这种可以叫做中位值平均滤波法。思路都是差不多的,都是需要做一遍排序。
中值滤波能有效克服偶然因素引起的波动噪声。
# window滑窗越大,滤波效果越明显,结果越滞后
# 设置了该点的左右滑窗大小,可根据实际情况选取参数
def Median_Filter(window_left, window_right, arr):
size = len(arr)
result = []
for i in range(window_left, size-window_right):
# 滑窗
temp = []
for j in range(-window_left, window_right+1):
temp.append(arr[i+j])
temp.sort()
point = temp[(int)(len(temp)/2)]
result.append(point)
return result
# 中值平均值滤波
def MedianAvg_Filter(window_left, window_right, arr):
size = len(arr)
result = []
for i in range(window_left, size-window_right):
# 滑窗
temp = []
for j in range(-window_left, window_right+1):
temp.append(arr[i+j])
temp.sort()
# 可以去掉最大值后,取中位数的平均值
median_mean = []
for m in range(1, len(temp)-1):
median_mean.append(temp[m])
result.append(np.mean(median_mean))
return result
pred = [] # 滤波值
# 前后5个,总共11个点求中值
pred = Median_Filter(5, 5, mear)
# pred = MedianAvg_Filter(5, 5, mear)
# 前5个数,总共6个点求中值
# pred = Median_filter(5, 0, mear)
plt.plot(range(n), mear)
plt.plot(range(n), real)
# 会牺牲掉前后window大小的数据,可以作相应改进
plt.plot(range(len(pred)), pred)
[<matplotlib.lines.Line2D at 0x7efd2c841978>]

一阶滤波是比较常用简单的滤波方法,就是当前采样结果和上一个滤波结果加权求和,权重和为1。对周期干扰噪声有良好的抑制作用,但同样会产生相位滞后,权重是固定值也是其缺点之一。
# a值越小,越不相信观测,滤波效果越明显,结果越滞后
def ab_filter(a, now):
global last
return a * now + (1 - a) * last
pred = []
last = mear[0]
pred.append(last)
for i in range(1, n):
last = ab_filter(0.4, mear[i])
pred.append(last)
plt.plot(range(n), mear)
plt.plot(range(n), real)
plt.plot(range(n), pred)
[<matplotlib.lines.Line2D at 0x7efd2c7a9588>]

关于卡尔曼滤波器的原理这里就不多做介绍了,可以查看我之前的文章卡尔曼滤波算法原理(KF,EKF,AKF,UKF)。
因为之前都是用kf处理带有运动模型的运动目标数据,一时还没有反应过来可以用它来处理简单的二维线性数据,惭愧。
# 滤波效果主要调整参数:
# 过程噪声方差q(越小越相信预测,反之亦然), 观测噪声方差r(越小越相信观测,反之亦然)
q, r = 0.1, 2
# 状态均值x, 过程噪声均值w,方差p
x, w, p = 0, 0, 0
def kalman_filter(z):
global x, p
# 预测
x_ = x + w
p_ = p + q
k = p_ / (p_ + r)
# 更新
x = x_ + k * (z - x_)
p = (1-k) * p_
return x
pred = [] # 滤波值
for i in range(n):
pred.append(kalman_filter(mear[i]))
plt.plot(range(n), mear)
plt.plot(range(n), real)
plt.plot(range(n), pred)
[<matplotlib.lines.Line2D at 0x7efd2c78ee10>]

以上对简单的线性数据处理完之后,就可以使用最小二乘法来拟合出一个比较好的结果,关于最小二乘法可以查看我之前的文章最小二乘法拟合线条的C++实现
因各个滤波器取的参数不一,结果对比起来没有意义,而且因为采样点比较多,没有具体分析细节,建议应用时测试充分选取合适的方法。
水平有限,有错误的地方希望大佬多加指正!
首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有, 也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
下面有没有更优雅的方法来实现这个:输入:array=[1,1,1,0,0,1,1,1,1,0]输出:4我的算法:streak=0max_streak=0arr.eachdo|n|ifn==1streak+=1elsemax_streak=streakifstreak>max_streakstreak=0endendputsmax_streak 最佳答案 类似于w0lf'sanswer,但通过从chunk返回nil来跳过元素:array.chunk{|x|x==1||nil}.map{|_,x|x.size}.max
1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva
我一直在尝试用Ruby实现Luhn算法。我一直在执行以下步骤:该公式根据其包含的校验位验证数字,该校验位通常附加到部分帐号以生成完整帐号。此帐号必须通过以下测试:从最右边的校验位开始向左移动,每第二个数字的值加倍。将乘积的数字(例如,10=1+0=1、14=1+4=5)与原始数字的未加倍数字相加。如果总模10等于0(如果总和以零结尾),则根据Luhn公式该数字有效;否则无效。http://en.wikipedia.org/wiki/Luhn_algorithm这是我想出的:defvalidCreditCard(cardNumber)sum=0nums=cardNumber.to_s.s
下面是我写的一个计算斐波那契数列中的值的方法:deffib(n)ifn==0return0endifn==1return1endifn>=2returnfib(n-1)+(fib(n-2))endend它工作到n=14,但在那之后我收到一条消息说程序响应时间太长(我正在使用repl.it)。有人知道为什么会这样吗? 最佳答案 Naivefibonacci进行了大量的重复计算-在fib(14)fib(4)中计算了很多次。您可以将内存添加到您的算法中以使其更快:deffib(n,memo={})ifn==0||n==1returnnen
为了防止在迁移到生产站点期间出现数据库事务错误,我们遵循了https://github.com/LendingHome/zero_downtime_migrations中列出的建议。(具体由https://robots.thoughtbot.com/how-to-create-postgres-indexes-concurrently-in概述),但在特别大的表上创建索引期间,即使是索引创建的“并发”方法也会锁定表并导致该表上的任何ActiveRecord创建或更新导致各自的事务失败有PG::InFailedSqlTransaction异常。下面是我们运行Rails4.2(使用Acti
我正在开发一个类似微论坛的项目,其中一个特殊用户发布一条快速(接近推文大小)的主题消息,订阅者可以用他们自己的类似大小的消息来响应。直截了当,没有任何形式的“挖掘”或投票,只是每个主题消息的响应按时间顺序排列。但预计会有很高的流量。我们想根据它们引起的响应嗡嗡声来标记主题消息,使用0到10的等级。在谷歌上搜索了一段时间的趋势算法和开源社区应用示例,到目前为止已经收集到两个有趣的引用资料,但我还没有完全理解它们:Understandingalgorithmsformeasuringtrends,关于使用基线趋势算法比较维基百科页面浏览量的讨论,在SO上。TheBritneySpearsP
我收到错误:unsupportedcipheralgorithm(AES-256-GCM)(RuntimeError)但我似乎具备所有要求:ruby版本:$ruby--versionruby2.1.2p95OpenSSL会列出gcm:$opensslenc-help2>&1|grepgcm-aes-128-ecb-aes-128-gcm-aes-128-ofb-aes-192-ecb-aes-192-gcm-aes-192-ofb-aes-256-ecb-aes-256-gcm-aes-256-ofbRuby解释器:$irb2.1.2:001>require'openssl';puts