Can't fit nonlinear filter equation by lsqcurvefit()
1 次查看(过去 30 天)
显示 更早的评论
I want to fit a passive RLC bandstop filter equation to the following data:
f = [5500 6000 6500 7000 7500 8000 8500 9000];
y = [0.998 0.997 0.994 0.988 0.947 0.255 0.956 0.987];
Where f is the frequency and y is the value of transfer function. Here is my code:
fun = @(p, x) abs(j.*(x.*p(2)-1./(x.*p(3)))./(p(1) + j.*(x.*p(2)-1./(x.*p(3))))); % transfer function of RLC bandstop
% x, p(1), p(2), p(3) correspond to w, R, L, C respectively
x = f(1):f(end); % for plotting purpose
x0 = [1 1e-3 1e-6] % starting points
lb = [1 1e-3 1e-6];ub = [100E3 100 1000E-6];
p_fit = lsqcurvefit(fun, x0, f, y, lb, ub) % p_fit is the vector of fitted parameters
semilogx(f, y, 'ro'); hold on;
semilogx(x, fun(p_fit, x), '--m'); grid on; % semilog plot of the transfer function
hold off;
I am not familiar with lsqcurvefit() parameter's starting points. Please, suggest any modification or any other method which could fit for any frequency range.
I have attached the image of actual plot and the transfer function.
0 个评论
采纳的回答
Walter Roberson
2021-7-20
编辑:Walter Roberson
2021-7-20
format long g
f = [5500 6000 6500 7000 7500 8000 8500 9000];
y = [0.998 0.997 0.994 0.988 0.947 0.255 0.956 0.987];
fun = @(p, x) abs(1i.*(x.*p(2)-1./(x.*p(3)))./(p(1) + 1i.*(x.*p(2)-1./(x.*p(3))))); % transfer function of RLC bandstop
% x, p(1), p(2), p(3) correspond to w, R, L, C respectively
x = f(1):f(end); % for plotting purpose
x0 = [1 1e-3 1e-6] % starting points
lb = [1 1e-3 1e-6];ub = [100E3 100 1000E-6];
ub = [1 0.02 2e-5];
x0 = [1 0.0038733109633344873895993294337111 4e-6]
[p_fit, fval_fit] = lsqcurvefit(fun, x0, f, y, lb, ub) % p_fit is the vector of fitted parameters
semilogx(f, y, 'ro', 'displayname', 'original'); hold on;
semilogx(x, fun(p_fit, x), '--m', 'displayname', 'lsq'); grid on; % semilog plot of the transfer function
E = @(p) sum((fun(p,f)-y).^2);
[Pfc, fval_fc] = fmincon(E, x0, [], [], [], [], lb, ub)
[Pfs, fval_fs] = fminsearch(E, x0)
semilogx(x, fun(Pfs,x), '--g', 'displayname', 'fminsearch');
semilogx(x, fun(Pfc,x), ':b', 'displayname', 'fmincon');
hold off
legend show
6 个评论
Walter Roberson
2021-7-20
编辑:Walter Roberson
2021-7-20
format long g
f = [5500 6000 6500 7000 7500 8000 8500 9000];
y = [0.998 0.997 0.994 0.988 0.947 0.255 0.956 0.987];
fun = @(p, x) abs(1i.*(x.*p(2)-1./(x.*p(3)))./(p(1) + 1i.*(x.*p(2)-1./(x.*p(3))))); % transfer function of RLC bandstop
% x, p(1), p(2), p(3) correspond to w, R, L, C respectively
x = f(1):f(end); % for plotting purpose
x0 = [1 1e-3 1e-6] % starting points
lb = [1 1e-3 1e-6];ub = [100E3 100 1000E-6];
ub = [1 0.02 2e-5];
%x0 = [1 0.0038733109633344873895993294337111 4e-6]
E = @(P) sum((fun(P,f)-y).^2);
syms P [1 3]
E2 = simplify(E([1, P(2), 4e-6]))
dE2 = diff(E2,P(2))
fplot(E2, [0.003 0.004])
fplot(E2, [0.0038 0.004])
E2f = matlabFunction(E2);
[bestP2, fval_E2] = fminsearch(E2f,50)
x0 = [1, bestP2, 4E-6]
[p_fit, fval_fit] = lsqcurvefit(fun, x0, f, y, lb, ub) % p_fit is the vector of fitted parameters
semilogx(f, y, 'ro', 'displayname', 'original');
hold on;
semilogx(x, fun(p_fit, x), '--m', 'displayname', 'lsq'); grid on; % semilog plot of the transfer function
[p_fit2, fval_fit2] = lsqcurvefit(fun, x0, f, y, lb, ub)
[Pfc, fval_fc] = fmincon(E, x0, [], [], [], [], lb, ub)
[Pfs, fval_fs] = fminsearch(E, x0)
semilogx(x, fun(Pfs,x), '--g', 'displayname', 'fminsearch');
semilogx(x, fun(Pfc,x), ':b', 'displayname', 'fmincon');
hold off
legend show
The result of [bestP2, fval_E2] = fminsearch(E2f,50) shows that you do not need to start the search from anywhere close by in order to hit one of the two best regions. The one found, the second of the two dips in the w, gives an even better fit (using fminsearch) than using the first of the w dips.
Walter Roberson
2021-7-20
编辑:Walter Roberson
2021-7-20
The following was not able to find a good solution... but
format long g
f = [80 190 216 224 234 243 254 314]*1e3
y = [999 984 897 679 205 801 938 993]*1e-3
fun = @(p, x) abs(1i.*(x.*p(2)-1./(x.*p(3)))./(p(1) + 1i.*(x.*p(2)-1./(x.*p(3))))); % transfer function of RLC bandstop
% x, p(1), p(2), p(3) correspond to w, R, L, C respectively
x = f(1):f(end); % for plotting purpose
lb = [1 1e-3 1e-6]; %ub = [100E3 100 1000E-6];
ub = [1 0.02 2e-5];
%x0 = [1 0.0038733109633344873895993294337111 4e-6]
E = @(P) sum((fun(P,f)-y).^2);
syms P [1 3]
E2 = simplify(E([1, P(2), 4e-6]))
dE2 = diff(E2,P(2))
%fplot(E2, [0.003 0.004])
%fplot(E2, [0.0038 0.004])
E2f = matlabFunction(E2);
[bestP2, fval_E2] = fminsearch(E2f,50)
x0 = [1, bestP2, 4E-6]
Notice that search came out with a negative P(2), which is out of range.
[p_fit, fval_fit] = lsqcurvefit(fun, x0, f, y, lb, ub) % p_fit is the vector of fitted parameters
Those search coordinates are in range, but the result is not great
semilogx(f, y, 'ro', 'displayname', 'original');
hold on;
semilogx(x, fun(p_fit, x), '--m', 'displayname', 'lsq'); grid on; % semilog plot of the transfer function
[Pfc, fval_fc] = fmincon(E, x0, [], [], [], [], lb, ub)
Again within range, but the results are not great
[Pfs, fval_fs] = fminsearch(E, x0)
and that one is out of range again
%semilogx(x, fun(Pfs,x), '--g', 'displayname', 'fminsearch');
semilogx(x, fun(Pfc,x), ':b', 'displayname', 'fmincon');
hold off
legend show
I did some grid searching, brute force. The locations I found varied a lot depending how fine a grid I used. The best I found so far was
63535.7188297698 0.710929969491426 0.001
but there was a lot of variability -- such as near 1000 0.01 1e-3 was only marginally more.
In short: there is no good fit.
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Linear Least Squares 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!