【问题标题】:Normalised Least Mean Squares - C Implementation归一化最小均方 - C 实现
【发布时间】:2014-01-29 10:58:33
【问题描述】:

我希望在 C 中实现归一化最小均方 (NLMS)。我的问题在于权重更新(我认为)当我针对标准 MATLAB 库运行它时。这是 MATLAB 代码(有效):

function [e,w,y]=nlmsFunc(mu,M,u,d,a);
% Normalized LMS
% Call:
% [e,w]=nlms(mu,M,u,d,a);
%
% Input arguments:
% mu = step size, dim 1x1
% M = filter length, dim 1x1
% u = input signal, dim Nx1
% d = desired signal, dim Nx1
% a = constant, dim 1x1
%
% Output arguments:
% e = estimation error, dim Nx1
% w = final filter coefficients, dim Mx1
%intial value 0

w=zeros(M,1); %This is a vertical column

%input signal length
N=length(u);
%make sure that u and d are colon vectors
u=u(:);
d=d(:);
%NLMS
for n=M:N %Start at M (Filter Length) and Loop to N (Length of Sample)
uvec=u(n:-1:n-M+1); %Array, start at n, decrement to n-m+1
e(n)=d(n)-w'*uvec;
w=w+mu/(a+uvec'*uvec)*uvec*conj(e(n));
y(n) = w'*uvec; %In ALE, this will be the narrowband noise.
end

我的问题是将它翻译成 C,这就是我目前所拥有的:

float mu = 0.05; //Set up mu
    int a = 1; //Constant

    int inputSigSize = numSamples;
    float outputYSignal[inputSigSize];
    float desiredSignal[inputSigSize];
    float error[inputSigSize];


    float inputSignal[inputSigSize];

    //Initialise Weights to Zero
    if (weights[0] == 0) {

        for (int k = 0; k<=filterLength; k++) {
            weights[k]=0;
        }
    }

    float X[filterLength+1];
    float Y = 0;
    float E = 0;

    //Start NLMS Loop
    for (int t = 0; t<numSamples; t++) {

        X[0] = inputSignal[t];

        for (int i = 0; i<=filterLength; i++) {
            Y += (weights[i]*X[i]);
        }

        E = desiredSignal[t] - Y;

        for (int i = filterLength; i>=0; i--) {
            weights[i] = weights[i] + (mu*E*X[i]);

            if (i!=0) {
                X[i]=X[i-1];
            }
        }

        outputYSignal[t] = Y;
        error[t] = E;
    }
    //END NLMS Loop

我感觉这是我处理体重更新的一种方式。

【问题讨论】:

  • 能否让matlab自动生成c代码?
  • 你没有初始化你的数组;不要假设数组(当在 C 函数中定义时)会像许多其他语言一样被隐式初始化。它们可能包含随机垃圾。

标签: c matlab math signal-processing


【解决方案1】:

NLMS C 代码实现:

#define inputSize 800

#define N 64 // filter size

double stepsize = 0.0; //Set up mu
double x[inputSize];
double d[inputSize];
double y[inputSize];
double h[N];
double e[inputSize];
int M = inputSize;

void nlmsFilter() {

//Initialise Weights to Zero
memset(y, 0, inputSize);
memset(e, 0, inputSize);
memset(h, 0, N);

double X1[N];
int t, j, i;

for (t = N; t <= M; t++) {
    for (j = (t - 1); j >= (t - N); j--) {
        X1[t-j-1] = x[j];
        printf("%d %lf %lf \n", (t-j-1), X1[t-j-1], x[j]);
    }

    for (i = 0; i < N; i++) {
        y[t-1] += (h[i] * X1[i]);
    }

    e[t-1] = d[t-1] - y[t-1];

    for (i = 0; i < N; i++) {
        stepsize += (X1[i] * X1[i]);
    }

    stepsize = 1/stepsize;

    for (i = 0; i < N; i++) {
        h[i] = h[i] + (stepsize * e[t-1] * X1[i]);
    }
}
return;
}

【讨论】:

    【解决方案2】:

    您似乎忘记了通过输入的方差对 mu 进行归一化。

    另外,请注意您的过滤技术与参考代码不匹配:系数权重[j] 应乘以输入样本 X[FilterLength - j]。输入数组在 uvec 中反转(保留 taps(不是我们期望的 taps+1)样本)。

    在原始代码中,他们似乎添加了一个小常数以防方差为 0(FilterLength+1 抽头的恒定输入),但我认为您只需在之前检查方差即可获得更准确的结果。

    避免像这样移动数据:在 for 循环中 X[i]=X[i-1]。

    【讨论】:

      猜你喜欢
      • 2016-10-04
      • 2020-01-30
      • 1970-01-01
      • 2015-02-28
      • 1970-01-01
      • 2021-07-26
      • 2018-12-28
      • 1970-01-01
      相关资源
      最近更新 更多