SMA 上的简单移动平均线 (SMA) 的系数权重

信息处理 卷积 低通滤波器 有限脉冲响应 移动平均线 r
2022-02-07 18:10:06

简单移动平均线(SMA :算术平均值)是低通 FIR滤波器。当您使用长度为的窗口级联 2 个 SMA时,当您在第一个 SMA 的输出上应用第二个 SMA 时,并且您想知道在相同输出结果的情况下滤波器将具有哪些系数权重,应用于原始信号,2 个脉冲响应(系数/权重)需要进行卷积(非循环):这应该返回系数/权重的向量。我参考下图:您有一个正弦信号(黑色)、一个 SMA(蓝色)和该 SMA 的一个 SMA(绿色),我将其与具有“卷积权重”的滤波器进行了比较:n(2n)1

SMA 上的 SMA 与卷积权重

如果您在 R 中执行此操作:命令应该是convolve(rep(1/n,n),rep(1/n,n),conj = FALSE,type="open"),对吗?显然红色曲线与绿色曲线不重合。是否有一个解析解决方案可以返回这个新移动平均线的权重向量?不仅是针对 1 SMA 上的 1 SMA,而是针对 SMA 上的 SMA?xx

这是我非常基本的 R 代码(我假设 Matlab 用户/dsp 工程师理解):

n<-10
vperiod<-40
vwave<-sin(2*pi*1/vperiod*(1:(600)))
# 
SMA<-function(x,n)
{
  out<-c()
  for (i in n:length(x))
  {
    out[i]<-(sum((x[(i-(n-1)):i])*rep((1/n),n)))
  }
  out[1:(n-1)]<-out[n]
  return(out)
}
# 
SmaOnSma<-function(x,n)
{
  out<-c()
  cnvweights<-convolve(rep(1/n,n),rep(1/n,n),conj = FALSE,type="open")
  for (i in length(cnvweights):length(x))
  {
    out[i]<-sum(x[(i-(length(cnvweights))+1):i]*cnvweights)
  }
  out[1:(n-1)]<-out[n]
  return(out)
}
# 
plot(vwave[(2*vperiod):(3*vperiod)],type="l",lwd=2,main="SMA on SMA vs. convolution weights");abline(h=0,lty=3,col="gray")
legend("bottomleft",inset=.03,c("signal","SMA of signal","SMA of SMA of signal","Filter with convolution weights"),fill=c("black","blue","green","red"),horiz=FALSE,border="white",box.col="white")
# 
tempwave<-vwave
lines(SMA(tempwave,n)[(2*vperiod):(3*vperiod)],col="blue",lwd=2)
tempwave<-SMA(tempwave,n)
lines(SMA(tempwave,n)[(2*vperiod):(3*vperiod)],col="green",lwd=2)
lines(SmaOnSma(vwave,n)[(2*vperiod):(3*vperiod)],col="red",lwd=2)

更新:


感谢这里的友好答案是 R 中移动平均线的代码:

smavector<-function(n)
{
  return(rep((1/n),n))
}

SmaOnSma<-function(x,n,nit)
{
  if (nit==1)
  {
    cnvweights<-smavector(n)
  }
  if (nit==2)
  {
    cnvweights<-convolve(smavector(n),smavector(n),conj = TRUE,type="open")
  }
  if (nit>2) 
  {
    cnvweights<-convolve(smavector(n),smavector(n),conj = TRUE,type="open")
    for (j in 1:(nit-2))
    {
      cnvweights<-convolve(smavector(n),cnvweights,conj = TRUE,type="open")
    }
  }
  #
  out<-c()
  for (i in length(cnvweights):length(x))
  {
    out[i]<-sum(x[(i-(length(cnvweights))+1):i]*cnvweights)
  }
  out[1:(n-1)]<-out[n]
  return(out)
}

我最初认为这可能是一种通过校正 SMA 的频率响应来估计平滑曲线的瞬时频率的方法,根据我之前关于SE 的问题:计算为 ( ),(其中 p = 波的周期 = 1/频率),但很明显,随着每次迭代,权重向量的长度都会增长一个因子(的前一个权重向量长度。即使您只进行了一半的迭代并与相乘,所需输入数据的最小长度(具有相同的频率)仍然是 period +倍。(sin(n(π/p)))/(nsin(π/p))(2n)+1121

SMA 上的频率响应校正 SMA 作为 Ifreq 估计

2个回答

图中的绿色曲线对应于正确的结果。红色曲线是错误的,因为向量cnvweights中的权重顺序错误(左右两半互换)。计算这些权重的正确方法是

cnvweights <- convolve(rep(1/n,n), rev(rep(1/n,n)), conj = TRUE, type = "open")

根据函数 'convolve' 的 R 文档,您需要使用conj = TRUE标准卷积。

这是关于这个主题的很好的来源: http ://www.dspguide.com/ch15/4.htm

一个单一的移动平均线是一辆棚车。二是三角形。除此之外,它将开始接近高斯。