I have been trying to fit some data with a model for some time now and am getting fairly close. In origin pro the fit seems to work ok and I get reasonable parameters back albeit the residuals are a little funny. Unfortunately in Matlab the fit is not so good. Could I send some one my code my function and some data to take a look at?
Oh and also there are imaginary numbers!
clear all;
close all
close all hiddenA = uiimport;
clear xdata;
clear ydata;
xdata = A.data(:,1);
ydata = A.data(:,2); Vg = xdata;
Id = abs(ydata);x0 = [8.6E-10;1.7;0.8;5E6];
options = optimset('Display','iter',...
'TolFun',1E-100,'TolX',1E-100,'MaxIter',1000); [beta,resid,J,COVB,mse] = nlinfit(Vg,Id,@RcFun,[x0],options);
[ci se] = nlparci(real(beta),resid,'covar',COVB);Id_new = ((((real(beta(1))*((Vg-real(beta(2))).^(real(beta(3))+1))).^(-1))+real(beta(4))).^(-1));
plot(Vg,Id_new,'r',Vg,Id,'o');
hold on;
plot(Vg,resid,'+');function F = Rcfun(a,Vg) K = real(a(1)); V = real(a(2)); b = real(a(3)); R = real(a(4));
F = (((K.*(Vg-V).^(b+1)).^(-1))+R).^(-1);
end
Data
A B 0 3.03E-12 1 1.5E-13 2 1.58E-12 3 2.81E-12 4 2.55E-12 5 2.31E-12 6 4.13E-12 7 2.89E-12 8 4.99E-12 9 6.38E-12 10 1.068E-11 11 1.96E-11 12 5.343E-11 13 5.405E-11 14 5.347E-11 15 5.142E-11 16 2.4139E-10 17 7.4428E-10 18 1.5752E-9 19 2.7328E-9 20 4.3347E-9 21 6.5506E-9 22 9.5258E-9 23 1.31356E-8 24 1.72672E-8 25 2.17876E-8 26 2.66302E-8 27 3.18252E-8 28 3.7101E-8 29 4.23594E-8 30 4.78078E-8 31 5.32604E-8 32 5.86136E-8 33 6.39262E-8 34 6.93234E-8 35 7.47466E-8 36 8.01152E-8 37 8.54398E-8 38 9.08214E-8 39 9.62598E-8 40 1.0184E-7 41 1.074E-7 42 1.1322E-7 43 1.1876E-7 44 1.2432E-7 45 1.299E-7 46 1.3534E-7 47 1.4062E-7 48 1.4596E-7 49 1.5096E-7 50 1.558E-7 51 1.6118E-7 52 1.6616E-7 53 1.7064E-7 54 1.7546E-7 55 1.7946E-7 56 1.8402E-7 57 1.8776E-7 58 1.9138E-7 59 1.9584E-7 60 1.9992E-7
No products are associated with this question.
Thank you for clarifying ‘RcFun’. After working with your code for a bit, the problem definitely seems to be the ‘(Vg-V)’ term. The only way I am able to get a decent fit without complex parameters is to use ‘lsqcurvefit’ and constraining ‘V’ to not be greater than zero, but then ‘nlparci’ wouldn't calculate confidence intervals on the parameter estimates. [I was able to get a good fit with ‘nlinfit’ by redefining that term to ‘abs(Vg-V)’, but that changed your function.] With ‘lsqcurvefit’, your ‘options’ statement and structure remains the same, although I increased ‘MaxIter’ and ‘MaxFunEvals’ in mine for diagnostic purposes. I also made ‘RcFun’ a single-line anonymous function for convenience:
RcFun = @(a,Vg) 1./(1./(a(1).*(Vg-a(2)).^(a(3)+1)) + a(4));
Lobnd = []; Upbnd = ones(4,1)*realmax; Upbnd(2) = 0; % Constrain ‘V’ to not be greater than zero [beta,resnrm,resid,xitflg,outpt,lmda,J] = lsqcurvefit(RcFun,x0,Vg,Id,Lobnd,Upbnd,options); % NOTE: ‘Answers’ wrapped this line
and got an acceptable fit with these parameters:
K = 35.6744e-012 V = -32.7518e-003 b = 1.1302e+000 R = 145.7789e-003
The norm of the residuals was 5.2916E-015. I'm not certain what you're doing or what data you're modeling, so I can't interpret these or their validity.
In spite of the decent fit, the residuals had a definite oscillating trend.
I negated the function:
RcFun = @(a,Vg) -(1./(1./(a(1).*(Vg-a(2)).^(a(3)+1)) + a(4)));
as well as negating ‘Vg’. (I copied it here so you can check it to be sure that's what you intended. The extra parentheses in it are likely not necessary, but I want to be sure it's doing what I want it to do. At this point, I'm taking no chances!)
The parameter estimates with those changes were:
beta_est =
282.3452e-012 -335.6849e-012i
-10.2542e+000 - 1.6440e+000i
444.5718e-003 -125.7975e-003i
845.8825e+003 with ‘abs(beta_est)’ for information purposes only:
absbeta_est =
438.6378e-012
10.3851e+000
462.0272e-003
845.8825e+003With a decent-looking fit of real(Id_new) as well as abs(Id_new).
I did a search on MOSFET models this afternoon (GMT-7) in order to understand a bit more precisely what you're doing. Unfortunately, I didn't learn much. I'd appreciate your providing me with an open-source PDF or website that can explain what you're doing if that's an option. I'm sensitive to your doing research and that you would likely not want to divulge too much to competing investigators.
I could send you a couple of PDF's over dropbox if you like? The fitting procedure and model is not confidential in anyway so that should be fine.
Could You post the whole of the code that you are using for me to have a look at?
Thanks
I would appreciate the PDFs. My circuit analysis and synthesis knowledge is relatively basic, but they could help me understand what you're doing.
This is the code snippet I've used:
RcFun = @(a,Vg) -(1./(1./(a(1).*(Vg-a(2)).^(a(3)+1)) + a(4)));
% RcFun = @(a,Vg) 1./(1./(a(1).*abs(Vg-a(2)).^(a(3)+1)) + a(4)); Vg = -Data(:,1);
Id = Data(:,2); % x0 = [8.6E-10;1.7;0.8;5E6];
x0 = rand(4,1).*[1E-10; 1; 1; 1E+6];
% x0 = rand(4,1).*1E-1;
% options = optimset('Display','iter', 'TolFun',1E-100,'TolX',1E-100,'MaxIter',5000, 'MaxFunEvals', 2500);
options = optimset('Display','final', 'TolFun',1E-100,'TolX',1E-100,'MaxIter',5000, 'MaxFunEvals', 2500);
[beta,resid,J,COVB,mse] = nlinfit(Vg,Id,RcFun,[x0],options);
% Lobnd = [];
% Upbnd = ones(4,1)*realmax;
% Upbnd(2) = 0;
% [beta,resnrm,resid,xitflg,outpt,lmda,J] = lsqcurvefit(RcFun,x0,Vg,Id,Lobnd,Upbnd,options);
beta_est = beta
absbeta_est = abs(beta)
se = sqrt(diag(COVB/size(Data,1)));
if isreal(beta)
ci = nlparci(beta,resid,'covar',COVB);
% ci = nlparci(beta,resid,'jacobian',J);
endId_new = RcFun(beta,Vg);
figure(4096)
plot(Vg,real(Id_new),'r',Vg,Id,'o')
hold on
plot(Vg,imag(Id_new),'--r',Vg,Id,'o')
plot(Vg,real(resid),'+')
plot(Vg,imag(resid),'x')
hold off
grid figure(4097)
plot(Vg,abs(Id_new),'r',Vg,Id,'o')
hold on
plot(Vg,abs(resid),'+')
hold off
gridI didn't include the code and data I copied from your original post. I decided to keep in the lines I used for various diagnostic options, including my call to ‘lsqcurvefit’ and a variation on the objective function I tried.
Couple of links to pdfs
Also, the fits that I produce from nlinfit and lsqcurvefit still are no where near as good as on origin, do you get good fits, could you post a pic?
I'm intrigued to know how origin decides to cut off the plot below Vg-V>Vd without it being specified. And manages it in only 18 or so iterations. In fact origin is able to get almost exactly the same parameters even setting the initial guesses quite far out....
so i tried a few things that maybe i shouldn't
I changed nlinfit.m so that the nlrobustfit function included an if else statement making it do a normal weighted robustfit if x-beta(2)>1 but would call a function in statrobustfit.m that set w = 0 when x-beta(2)<=1.
Where x is Vg and beta(2) is V
But that didn't really seem to do anything
Also I'm still getting the problem with beta(4) (which is R) not changing?
Do you think there is an easier way to implement the weighted fit?
I gave it some thought too overnight. (However I'm reluctant to change nlinfit or the others.) I thought about the weighting vector, and am considering:
WgtV = sqrt(Id);
thus forcing the routine to ignore the region where (Id = 0). I've done this successfully in the past with other functions and data, but in those situations using the usual inverse-variance weighting vectors, (clearly inappropriate here since there are no variances on the measurements).
The other thing I thought of is that since I have the Global Optimization Toolbox and a fair amount of experience with genetic algorithms (GA), I'm going to give that a go. We already have a good start on the fitness function (the objective function you derived), and setting up a weighted metric [to avoid the (Vg < V) and (Id = 0) problems]. An Euclidean distance measure is probably the easiest, although we can get creative and use something more robust if necessary. The problem is that GAs usually take a while to converge, but have the significant benefit that they are essentially immune to the response surface because they completely ignore it.
If we're not happy with the GA results, we'll give GlobalSearch a go, even though that may take longer than GA to converge. It is the most likely to produce the best solution. With luck, we'll have its results today or tomorrow.
These are problems I'll have to solve for my own applications in the not distant future, so I'm interested in learning about their solutions.
This problem is clearly difficult. It has multiple minima, and a strong dependence on initial conditions. Instead of NLINFIT, I tried two different approaches which both give me good fits for values of Vg > 18.
In both cases, since it seems this equation can't really model the Vg < 18 region, I weighted that region to be zero. Also, just to scale things better, I am working with the log10's of K and R.
Option 1: Pattern Search Algorithm from the Global Optimization Toolbox
This gives a solution that is almost identical to the one that you found from your other software.
G = @(X) (((10.^(X(1)).*(Vg-X(2)).^(X(3)+1)).^(-1))+10.^(X(4))).^(-1); E = @(X) ( sum(((real(G(X)) - Id)).^2 .* (Vg >= 18)) ); opts = psoptimset; opts.Display = 'iter'; opts.MaxIter = realmax; opts.MaxFunEvals = realmax; X0 = [log10(8.6E-10);1.7;0.8;log10(5E6)]; X = patternsearch(E,X0,[],[],[],[],[],[],[],opts);
% Your previous answer K = 8.6E-10; V = 17.3; b = 0.618; R = 2.3E6; F0 = (((K.*(Vg-V).^(b+1)).^(-1))+R).^(-1);
% Comparing results: They are virtually identical plot(Vg, Id);hold all; plot(Vg, G(X)); plot(Vg,F0);
Option 2: Simply using FMINSEARCH from various starting points
Again, identical to the previous results.
G = @(X) (((10.^(X(1)).*(Vg-X(2)).^(X(3)+1)).^(-1))+10.^(X(4))).^(-1);
E = @(X) ( sum(((real(G(X)) - Id)).^2 .* (Vg >= 18)) );
opts = optimset('fminsearch');
opts.MaxIter = realmax;
opts.MaxFunEvals = realmax;
options.TolFun = realmin;
options.TolX = realmin;
X0 = [log10(8.6E-10);1.7;0.8;log10(5E6)];
Emin = Inf;
for n = 1:100
disp(n)
[Xn, err(n)] = fminsearch(E,X0.*(1+0.01*randn(size(X0))),opts);
if err(n) < Emin
Emin = err(n);
X = Xn;
end
end
% Your previous answer
K = 8.6E-10; V = 17.3; b = 0.618; R = 2.3E6;
F0 = (((K.*(Vg-V).^(b+1)).^(-1))+R).^(-1);
% Comparing results: They are virtually identical plot(Vg, Id);hold all; plot(Vg, G(X)); plot(Vg,F0);
Although I don't have global optimisation toolbox and don't full understand whats going on, it looks like it could be on the right track.
What I would like to know is.
1. Is it possible to change the code so it can work for different data that will have a different V and so may work at Vg < 18. I.e can we ad a statement that confines Vg-V < Vd (Vd = 1 in the data I have provided but could be different for other data)
2. Being useless at statistics etc. How do I go about getting errors on the parameters and on the fit?
Kind Regards
Could you explain the
Emin = Inf;
for n = 1:100
disp(n)
[Xn, err(n)] = fminsearch(E,X0.*(1+0.01*randn(size(X0))),opts);
if err(n) < Emin
Emin = err(n);
X = Xn;
end
end
Ah! Sorry sorry sorry. There's actually a MUCH easier way to make all of this work. The important point is to set the model equal to zero whenever it goes imaginary. I bet your other software probably was doing this automatically; MATLAB does not. See how I modified rcfun below to include this line:
F = F.*(~imag(F));
This sets F to be identically zero whenever it has an imaginary component.
Anyways, copy the entire function below into a file and run it from the command line:
>> [BETA,Rout,J,COVB,MSE] = domyfit
and it will work perfectly (and it should work for other data in general). The standard errors on your coefficients are given by diag(COVB).
function [BETA,Rout,J,COVB,MSE] = domyfit A = struct; A.data = [0 3.03E-12 1 1.5E-13 2 1.58E-12 3 2.81E-12 4 2.55E-12 5 2.31E-12 6 4.13E-12 7 2.89E-12 8 4.99E-12 9 6.38E-12 10 1.068E-11 11 1.96E-11 12 5.343E-11 13 5.405E-11 14 5.347E-11 15 5.142E-11 16 2.4139E-10 17 7.4428E-10 18 1.5752E-9 19 2.7328E-9 20 4.3347E-9 21 6.5506E-9 22 9.5258E-9 23 1.31356E-8 24 1.72672E-8 25 2.17876E-8 26 2.66302E-8 27 3.18252E-8 28 3.7101E-8 29 4.23594E-8 30 4.78078E-8 31 5.32604E-8 32 5.86136E-8 33 6.39262E-8 34 6.93234E-8 35 7.47466E-8 36 8.01152E-8 37 8.54398E-8 38 9.08214E-8 39 9.62598E-8 40 1.0184E-7 41 1.074E-7 42 1.1322E-7 43 1.1876E-7 44 1.2432E-7 45 1.299E-7 46 1.3534E-7 47 1.4062E-7 48 1.4596E-7 49 1.5096E-7 50 1.558E-7 51 1.6118E-7 52 1.6616E-7 53 1.7064E-7 54 1.7546E-7 55 1.7946E-7 56 1.8402E-7 57 1.8776E-7 58 1.9138E-7 59 1.9584E-7 60 1.9992E-7];
xdata = A.data(:,1); ydata = A.data(:,2); Vg = xdata; Id = abs(ydata);
X0 = [log10(8.6E-10);1.7;0.8;log10(5E6)]; [BETA,Rout,J,COVB,MSE] = nlinfit(Vg,Id,@rcfun,X0); K = 8.6E-10; V = 17.3; b = 0.618; R = 2.3E6; F0 = (((K.*(Vg-V).^(b+1)).^(-1))+R).^(-1); plot(Vg, Id);hold all; plot(Vg,rcfun(BETA,Vg)); plot(Vg,F0);
function F = rcfun(X,Vg) F = (((10.^(X(1)).*(Vg-X(2)).^(X(3)+1)).^(-1))+10.^(X(4))).^(-1); F = F.*(~imag(F));
I'm going to continue experimenting with GlobalSearch, since your problem is likely the best test for it that I've encountered. The Origin fit didn't give much oscillation in the residuals if I remember correctly.
As for the fit being good enough to use — that's definitely your call! I'm going to see what GlobalSearch comes up with. That's likely as close to a definitive set of parameter estimates as is possible. (I'm not happy with the fits the curve-fitting routines have come up with so far.) They may be the set that Origin estimates, but at least we'll know.
I suggest continuing to use RobustWgtFun and the Jacobian. If you use the Jacobian with ‘lsqcurvefit’, insert this line before you calculate the Jacobian in RcFun:
Vg = Vg';
The MATLAB convention is column-major order, and nlinfit passes column vectors (as I would expect) to its objective functions, so I have no idea why lsqcurvefit passes row vectors. (I figured this out myself by experimenting with it.)
I've successfully estimated equivalent circuit models (to physiological problems) with pF capacitances, mH inductances, and MOhm resistances with MATLAB curve-fitting routines without having problems (although it usually took several guesses of initial parameters to get them to fit), so I doubt parameter magnitude ranges are the problem. My data oscillated so were not as challenging to fit as yours are.
I'm quite enjoying this.
What is it you mean by experimeting with GlobalSearch, i assume (by looking into it abit) that it finds global minima in a problem?
Could you use MultiStart?
Also (to Teja in particular) how do you go from log10 parameters to estimating the error in the parameter itself using COVB?? I just cannot work it out
SUCCESS!
After all that, it came down to the initial conditions, although I also made some changes to ‘RcFun’ to make it work seamlessly with both ‘nlinfit’ and ‘lsqcurvefit’.
The new initial conditions:
x0 = rand(4,1).*[1E-13; 1; 1; 1E+7];
and the new objective function:
function [F,J] = RdFun(a,Vg) % Adam Parry’s Organic FET Function % DATE: 2012 07 23 % % % % F = (((K.*(Vg-V).^(b+1)).^(-1))+R).^(-1) % w.r.t: K, V, b, R % respectively a(1), a(2), a(3), a(4) % x0 = [ 8.6E-10 ;1.7 ;0.8 ;5E6];
if a(2) > Vg
F = 0;
return
end
F = a(1)./(a(1).*a(4) + 1./(Vg - a(2)).^(a(3) + 1));
Jfcn = @(a,Vg) [1./(a(1).*a(4) + 1./(Vg - a(2)).^(a(3) + 1)) - (a(1).*a(4))./(a(1).*a(4) + 1./(Vg - a(2)).^(a(3) + 1)).^2; -(a(1).*(a(3) + 1))./((Vg - a(2)).^(a(3) + 2).*(a(1).*a(4) + 1./(Vg - a(2)).^(a(3) + 1)).^2); (a(1).*log(Vg - a(2)))./((Vg - a(2)).^(a(3) + 1).*(a(1).*a(4) + 1./(Vg - a(2)).^(a(3) + 1)).^2); -a(1).^2./(a(1).*a(4) + 1./(Vg - a(2)).^(a(3) + 1)).^2]';
if nargout > 1
J = Jfcn(a,Vg);
if any(size(J) == 1)
J = Jfcn(a,Vg');
elseif ~any(size(J) == 1)
return
end
end
% ========================= END: RcFun.m =========================
produces the parameters:
Parameter Estimates: K = 3.254448861356919E-10 0.000000000000000E+00j V = 1.559046341560319E+01 0.000000000000000E+00j b = 9.096959820500091E-01 0.000000000000000E+00j R = 2.828879053496115E+06 0.000000000000000E+00j
Parameter Estimates: |K| = 3.254448861356919E-10 |V| = 1.559046341560319E+01 |b| = 9.096959820500091E-01 |R| = 2.828879053496115E+06
and it only took ‘nlinfit’ 2.075 seconds to converge.
However they do not appear to be unique because these produce and equivalently close fit:
Parameter Estimates: K = 6.692378493392830E-10 0.000000000000000E+00j V = 1.685567986182001E+01 0.000000000000000E+00j b = 6.960550385747625E-01 0.000000000000000E+00j R = 2.476857099346900E+06 0.000000000000000E+00j
Parameter Estimates: |K| = 6.692378493392830E-10 |V| = 1.685567986182001E+01 |b| = 6.960550385747625E-01 |R| = 2.476857099346900E+06
as do these:
Parameter Estimates: K = 3.054487171664253E-10 0.000000000000000E+00j V = 1.547909799526304E+01 0.000000000000000E+00j b = 9.280342803415647E-01 0.000000000000000E+00j R = 2.854955008915018E+06 0.000000000000000E+00j
Parameter Estimates: |K| = 3.054487171664253E-10 |V| = 1.547909799526304E+01 |b| = 9.280342803415647E-01 |R| = 2.854955008915018E+06
that produced these 95% confidence intervals:
137.6613e-012 473.2361e-012
14.4356e+000 16.5226e+000
772.1086e-003 1.0840e+000
2.6426e+006 3.0673e+006and this covariance matrix:
8.2089e-021 49.8600e-012 -7.6134e-012 -9.6597e-006
49.8600e-012 317.5260e-003 -45.6541e-003 -54.6273e+003
-7.6134e-012 -45.6541e-003 7.0893e-003 9.1732e+003
-9.6597e-006 -54.6273e+003 9.1732e+003 13.1525e+009although sometimes it still had a bit of a problem converging. The residuals were reasonably flat with no significant trend, at least in my opinion. I guess that's the result of the ‘rand’ component of the initial parameter guess vector. I'm still going to work on the GlobalSearch, but I feel reasonably confident about these, considering the fit and the residuals. Unfortunately, ‘lsqcurvefit’ consistently failed to find a fit with the same initial parameter guesses. I'll let you know what GlobalSearch comes up with. It may take a few days for me to learn about and successfully run it.
You might want to experiment a bit with it yourself to see what the various parameter estimates look like. That will give you a better idea than even the confidence intervals will about the region of fit.
"How do you go from log10 parameters to estimating the error in the parameter itself using COVB??"
It's very easy, you just use the chain rule.
My change of coordinates was y = 10^x
So then dy/dx = 10^x * log(10)
Let A = Covariance in regular coordinates (this is what you want) and B = Covariance in log coordinates (this is what you have)
Then you can find A as
A = 10.^(B) * log(10)
In hindsight, I think this was all a bad idea, and you should just do it without any rescaling, so you don't have to worry about these kinds of things.
Do you mean ‘other method’ of device fabrication or parameter estimation?
I would be interested in other data to fit, yes.
I finally gave up on GlobalSearch, at least for now. I've since set a two-hour time limit on it. I would have done that earlier but I had no idea it would still be running after 18 hours!
Out of sheer desperation, I asked the Symbolic Math Toolbox to calculate a second-order Taylor series approximation of your function to see if that would make it easier to estimate the parameters, at least initially. The problem is that the Taylor series wants to calculate (-V).^b, guaranteeing a complex result. Here's the Taylor series, formatted by the Symbolic Math Toolbox as an anonymous function:
Taylr_Id = @(K,R,V,Vg,b)K.*(-V).^b.*1.0./(K.*R.*V.*(-V).^b-1.0).^2.*(-V+Vg+Vg.*b+K.*R.*V.^2.*(-V).^b)
that after this substitution: {K V b R}, {'a(1)' 'a(2)' 'a(3)' 'a(4)'} (and apparently some rearranging) becomes:
Taylr_Id = @(a,Vg) (a(1).*(-a(2)).^a(3).*(Vg - a(2) + Vg.*a(3) + a(1).*(-a(2)).^(a(3) + 2).*a(4)))./(a(1).*(-a(2)).^(a(3) + 1).*a(4) + 1).^2
I doubt if it contributes anything of significance to the effort, but so long as I have it I'll send it along for you to experiment with.
Yeah there is another method for parameter estimatio, but it involves taking some other measurements, but it may only require fitting straight lines, which would be nice. I'll have to look into it.
In other news I still can't get rid of this error without using log10(parameters). aAnd I still can't figure out how to get the correct errors from them.
Warning: Rank deficient, rank = 2, tol = 2.661976e-08. > In nlinfit>LMfit at 351 In nlinfit>nlrobustfit at 532 In nlinfit at 215 In nlinfitRc at 22
I'm managing to get fits with your code but they never see to give me residuals that are random, and the fits are still a little off in comparison to origin. Am I doing this right?
The nice thing is that fitting straight lines only require two parameters. However you have four in your model, so I don't see what the advantage is in that unless you can ignore two of them. When I did this just now, I got estimates for R of 195.8839E+006 and for V of 19.9989E+000.
I believe the nature of your data and the nature of your model make fitting your data difficult. The model doesn't really account for the sharp discontinuity where Vg=V, or for the very small oscillations in the Id data, that are likely real although quantitatively unimportant. (When I looked at them on the model I estimated from the parameter sets I posted, the magnitude of the oscillations with the best parameter estimates was about 1% of the value of the function at that point.)
The problem is that taking the logs of the parameters and then reconsituting them in the model changes the model. It's easier to see if instead of using 10.^a(1) and 10.^a(4) you substitute exp(a(1)) and exp(a(4)). That's not the model you specified and it doesn't make any sense in the context of the papers you referred me to, so I am not using the parameter transformation.
A Taylor series approximation might still be the way to go initially to get a good start on the parameter estimates, but you will have to change your data and model to avoid the possiblity of ‘(-V).^p’. Changing ‘(Vg-V)’ to ‘(V-Vg)’ does this, and likely only requires changing the Vg data to -Vg. In the Taylor series I sent along, to make that transformation simply change the signs of ‘V’ (a(2)) and ‘Vg’. I suggest that only for the Taylor approximation in order to get a good initial set of stable parameter estimates.
The parameter estimates I posted earlier are among the best I got. You can plug them in directly and calculate the relevant statistics. There is a small oscillation in the residuals, but it is barely discernable. This set took less than three seconds to converge and produced an MSE = 1.3182E-018:
Parameter Estimates: |K| = 2.627883069159599E-10 |V| = 1.521501224663270E+01 |b| = 9.713005068703799E-01 |R| = 2.914483559512664E+06
I gave up on GlobalSearch because GlobalSearch either didn't find a global minimum or got caught in a loop that required me to either stop or completely exit MATLAB, and so about which it gave me no informaton. It seemed to have the most trouble fitting ‘R’ (it seemed to persisstently underestimate it), but didn't seem to have trouble with the other parameters.
I suggest you go with the parameter estimates that make the most sense and that you are the most comfortable with. I know nothing about Origin, how it decides the region to fit, or how it calculates its parameters, so I can't advise you on what parameter set is best.
I'll be glad to continue to provide what help I can.
Hi
Long time
To be honest. I think that I am just about understanding the statistical things that you are doing in order to get a good fit. But my main problem is actually writing the code that does the same job as yours is doing. I am still unable to get lsqcurvefit to work with Jacobian on and nlin fit still gives me Rank deficient warnings. The main problem that I have though is that no matter waht initial parameters I start with R does not change. You mentioned a similar thing you noticed with R above and I just wonder how I can overcome it?
I know this is not exactly what you want to do, but could you walk me through the code. I can show you what I've got so far if that helps?
Thank you
Ok, thats fine, do you know anyway that Matlab could work out for itself when not to take into account data?
Like if I test a device that has a threshold voltage (V) around 0.5, i'm going to want most of the data up until 0 aren't I?
This is going to be a bit cheeky, but could you tell me if this jacobian is right, I'm getting an error telling me it is the wrong size
F = (a(1).*((VgX-a(2)).^(a(3)+1)));
J = [(VgX-a(2)).^(a(3)+1),... -(a(1).*((VgX-a(2)).^a(3)).*(a(3)+1)),... a(1).*log(VgX-a(2)).*((VgX-a(2)).^(a(3)+1))];
I don't know how MATLAB routines could decide for themselves what part of the data to use. I have no idea how Origin managed to fit your function as well as it did and only over the linear region of fit that produced real parameters, assuming you gave it and MATLAB the same function and data.
I don't know the data you're commenting on. Since I know only the data from the present problem, I suggest you start the fit with the greatest ‘Id’ data, take a range of those data, do the fit, and estimate ‘V’. Then take the data greater than the estimated ‘V’ and fit all of it. If your parameters are linear functions of your data (as ‘K’ and ‘R’ were here), and if your ‘Id’ data are again on the order of 1E-7, you can scale the ‘Id’ data and then ‘un-scale’ ‘K’ and ‘R’ by the same factor. Since ‘V’ and ‘b’ are not linear functions of either variable, you have to fit them as they are. So you can't scale ‘Vg’.
Your Jacobian looks fine to me. The Optimization and Statistics Toolboxes use different conventions — Statistics uses column-major, Optimization row-major — so to get your Jacobian to work with both, you have to transpose your ‘VgX’ vector to use the Optimization functions. If your data are column vectors, the Jacobian as listed should work with Statistics Toolbox functions, but you'll have to transpose the ‘VgX’ vector to make it work with Optimization Toolbox functions. Take the ‘RcFun.m’ I sent you, rename it to your present problem, then paste your ‘F’ and ‘J’ functions in it in place of the ones I provided. It should work fine. Note that my variable ‘Jcbn’ is an anonymous function, so be sure to paste your ‘J’ expression there and change the argument from ‘Vg’ to ‘VgX’.
That should work.
7 Comments
Direct link to this comment:
http://www.mathworks.com/matlabcentral/answers/44149#comment_90787
Please post your code, objective function, and some data. (Adding it by ‘Edit’ to your original post would be best.)
What do you mean by the residuals being ‘a little funny’? What was the MSE? If Origin Pro gave you covariances or confidence limits on the parameters, please post them, too.
Where do the imaginary numbers appear — data, parameter estimates, or somewhere else?
Direct link to this comment:
http://www.mathworks.com/matlabcentral/answers/44149#comment_90898
I'm not sure i really know how to add code correctly. How would I add data?
Direct link to this comment:
http://www.mathworks.com/matlabcentral/answers/44149#comment_90899
On origin the MSE seems to be about x10^-19,
Reduced Chi squared 7.29777E-19
Adj, R-square 0.99985
The imaginary numbers come from the function as one of the parameters appears as a power which I think leads to roots of negative numbers. There may be a way to prevent this but I haven't looked into it too deeply yet.
Direct link to this comment:
http://www.mathworks.com/matlabcentral/answers/44149#comment_90910
You added your code correctly. To add some of your data (that seems to be an [n x 2] array), append it (by editing) to the code you already posted. I suggest for clarity something like:
DATA:
etc.
Please format you data as ‘code’ as I did here. That makes it easier to read.
Also, I see ‘myfun’ but I don't see ‘RcFun’. It would help if you posted it. Is there a particular reason you're taking the absolute value of ‘ydata’? Please post the original ‘xdata’ and ‘ydata’ rather than ‘Vg’ and ‘Id’.
Direct link to this comment:
http://www.mathworks.com/matlabcentral/answers/44149#comment_90957
I think in the data I gave above it dows not matter that I have taken the absolute, I don't think that it really matters. I changed myfun to Rcfun just copied the wrong file.
Direct link to this comment:
http://www.mathworks.com/matlabcentral/answers/44149#comment_91224
Just curious, but, what are the good values of K,V,b,R that you obtained through origin?
Direct link to this comment:
http://www.mathworks.com/matlabcentral/answers/44149#comment_91225
Ah. Sorry. You had it down below and I missed it. k = 8.6E-10 V = 17.3 b = 0.618 R = 2.3E6