⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 leasqr.m

📁 此为频谱分析工具箱
💻 M
字号:
function [pout,deltapout,r2,covp,corp,ss,f,iter,kvg,ChiSq]=leasqr(x,ys,pin,func,wt,dp,niter,stol,ldfdp,options,last)% leasqr : Non Linear Least Square multivariable fit.%Syntax: [p,deltap,r2,covp,corp,rv,f,iter,kvg,ChiSq]=%                   leasqr(x,y,Pin,Func,{wt,dp,niter,stol,dfdp,options,mode='normal'})%% Levenberg-Marquardt nonlinear regression of func(x,p) to y(x).%% INPUT:%  x,y (vect)    : data to be fitted.%  Pin (vect)    : initial values for parameter search.%  Func (string) : function name (between quotes), of the form 'f(x,p)'.%% OUTPUT:%  p (vect)      : final parameters.%  deltap (v)    : sigma on parameters = sqrt(diag(covp))%  r2 (scalar)   : correlation coefficient for fit.%  covp (matrix) : error and crossed error on parameters.%  corp (matrix) : correlation between parameters.%  rv (scalar)   : residual variance.%  f (vect)      : function values at the end of fitting process.%  ChiSq         : Chi Squarred%  %                            ---------------% OPTIONS IN:%  wt (s or v)   : statistical weights for error calculation (1/sqrt(y) is default).%  dp (s or v)   : fractional incr of params for numerical partials (0.01 is default, 0 to fix param).%  niter (integ) : maximal number of iterations (20 is default).%  stol  (scal)  : tolerency on square error sum fractional improvement (1e-3 is default).%  dfdp (string) : partials function name of Func ('dfdp' is default).%  options (matr): col1 = desired fractional precision in parameter estimates.%                  col2 = maximum fractional step change in parameter vector.%  mode          : 'silent', 'min', 'normal' or 'verbose' (do plot)%% OPTIONS OUT:%  iter (integer): number of iterations processed.%  kvg (boolean) : convergence flag (1 if ok).%% Use 'leasqrexamp' for a fitting example.% Author:  EF <manuf@ldv.univ-montp2.fr>, RM <rfm2@ds2.uh.cwru.edu>, AJ <jutan@charon.engga.uwo.ca>% Description: Non Linear Least Square multivariable fit.% --------------------------- Function Calls ------------------------% dfdp.m   : function file computing partials by finite differencies. Do not change.% leasqrfunc.m   : example of function f(x,p) that can be used.% leasqrexamp.m  : fit exemple with Leasqr V3.b% Adapted for Octave : E.Farhi.   04/98   (manuf@ldv.univ-montp2.fr)% Richard I. Shrager (301)-496-1122% Modified by A.Jutan (519)-679-2111  jutan@charon.engga.uwo.ca% Modified by Ray Muzic 14-Jul-1992   rfm2@ds2.uh.cwru.edu % Version 3.beta    revised 07/97.% Part of 'Spectral tools'. E.Farhi. 06/97% Refrences:% Bard, Nonlinear Parameter Estimation, Academic Press, 1974.% Draper and Smith, Applied Regression Analysis, John Wiley and Sons, 1981.% argument processing -----------------------------------------------if ~exist('last')	last = 'normal';endif  isempty(last)	last = 'normal';endif strcmp(last,'verbose')	tmp = 3;elseif strcmp(last,'silent')	tmp = 0;elseif strcmp(last,'min')	tmp = 1;else	tmp = 2;endif tmp>0	fprintf(1,'\nMarquardt-Levenberg Multivariable Fit\n');endif ~exist('ldfdp') ldfdp=[]; endif ~exist('dp') dp=[]; endif ~exist('wt') wt=[]; endif ~exist('niter') niter=[]; endif ~exist('stol') stol=[]; endif isempty(ldfdp)	ldfdp='dfdp';	if (tmp>1)		disp('using file dfdp.m for partials computation');	endend						% partialsif isempty(dp)	dp=.01;	if (tmp>1)		disp('Increments for partials are dp = 0.01*pin');	endendif (length(dp) == 1)	dp=dp*pin;	n = find(dp == 0);	if (~isempty(n))		dp(n) = 0.001;	endend						% stepif isempty(wt)	wt=1./sqrt(abs(ys+(ys == 0)));	if (tmp>1)		disp('using standard normalisation (1/sqrt(y))')	endend						% data weightsif isempty(niter)	niter=50;	if (tmp>1)		fprintf(1,'Iterations : %i\n',niter);	endend						% max nb of itersif isempty(stol)	stol=.001;	if (tmp>1)		fprintf(1,' Tolerancy : %g\n',stol);	endend						% tolerancyif length(wt) == 1	wt = wt * ones(length(ys),1);endnzerow = find(wt);zerow = find(wt == 0);if ~isempty(zerow)	if tmp>1		disp('Get selected points');	end	x = x(nzerow);	ys = ys(nzerow);	wt = wt(nzerow);end%change all vectors to columnsx=vect2column(x);y=vect2column(ys);wt=vect2column(wt);pin=vect2column(pin);dp=vect2column(dp);% check data vectors- same length?m=length(y); n=length(pin); p=pin;[m1,m2]=size(x);if (m1~=m)	error('input(x)/output(y) data must have same number of rows ');endif ~exist('options') 	options = [];endif isempty(options)  options=[zeros(n,1) Inf*ones(n,1)];  nor = n; noc = 2;else  [nor noc]=size(options);  if (nor ~= n),    error('options and parameter matrices must have same number of rows'),  end;  if (noc ~= 2),    options=[options(noc,1) Inf*ones(noc,1)];  endendpprec=options(:,1);maxstep=options(:,2);if (m > 10000)    warning('HUH ! That makes a lot of points ! I may crash during fit...');endif (m <= n)        disp('Warning : need to extend data...');        newm = ceil(n/m+1)*m;        newx = linspace(x(1), x(length(x)), newm);        newx = vect2column(newx);        y = interpsp(x,y,newx);        wt = interpsp(x,wt,newx);        x=newx;        m = newm;end% set up for iterations (with initial data) -------------------------f=vect2column(feval(func,x,p)); fbest=f; pbest=p;		% initial function valuesr=wt.*(y-f);					% errorsbest=r'*r;					% square errornrm=zeros(n,1);chgprev=Inf*ones(n,1);kvg=0;epsLlast=1;epstab=[.1 1 1e2 1e4 1e6];t0 = clock;% do iterations -----------------------------------------------------if tmp>0	disp('')	disp(sprintf('*Beginning fit (max %d iterations)',niter));	if tmp>1	disp('--------------------------------------')	disp('Iteration  Time(s)  Residual Variance');	endendticfor iter=1:niter,  pprev=pbest;					% current params  prt=vect2column(feval(ldfdp,x,fbest,pprev,dp,func));	% partials of func for x.  r=wt.*(y-fbest);				% error  sprev=sbest;					% square error  sgoal=(1-stol)*sprev;				% sq error to achieve  for j=1:n,			% computes partials norm    if dp(j)==0,      nrm(j)=0;    else      prt(:,j)=wt.*prt(:,j);      nrm(j)=prt(:,j)'*prt(:,j);      if nrm(j)>0,        nrm(j)=1/sqrt(nrm(j));      end    end    prt(:,j)=nrm(j)*prt(:,j);	% normalizes partials  end  [prt,s,v]=svd(prt,0);		% prt=unit matr, s=eigenval : prt=prt*s*v'.  s=diag(s);			% get eigenvalues (diagonal of sigma)  g=prt'*r;			% gradient by Gauss-Newton formula.  for jjj=1:length(epstab),    epsL = max(epsLlast*epstab(jjj),1e-7);    se=sqrt((s.*s)+epsL);    gse=g./se;    chg=((v*gse).*nrm);		% change on params				% check the change constraints and apply as necessary    ochg=chg;    for iii=1:n,      if (maxstep(iii)==Inf), break; end;      chg(iii)=max(chg(iii),-abs(maxstep(iii)*pprev(iii)));      chg(iii)=min(chg(iii),abs(maxstep(iii)*pprev(iii)));    end;    if (any(ochg ~= chg)),      if (tmp>0)        disp(['Change in parameter(s): ' ...         sprintf(1,'%d ',find(ochg ~= chg)) 'were constrained']);      end    end;    aprec=abs(pprec.*pbest);       %---    if (any(abs(chg) > 0.1*aprec)) %---  % only worth evaluating function if      p=chg+pprev;                        % there is some non-miniscule change      f=vect2column(feval(func,x,p));      r=wt.*(y-f);      ss=r'*r;      if ss<sbest,        pbest=p;        fbest=f;        sbest=ss;      end;      if ss<=sgoal,        break;      end;    end;                          %---  end;  epsLlast = epsL;  if ss<eps,    break;  end  aprec=abs(pprec.*pbest);%  [aprec chg chgprev]  if (all(abs(chg) < aprec) & all(abs(chgprev) < aprec)),    kvg=1;    if (tmp>0)      fprintf(1,'Parameter changes converged to specified precision\n');    end    break;  else    chgprev=chg;  end;  if ss>sgoal,    break;  end;  if tmp>1    fprintf(1,'   %3d ',iter);    fprintf(1,'      %6.2f   %8.3f\n', toc, ss/length(y));  endend;% set return values -------------------------------------------------%p=pbest;f=fbest;ss=sbest;kvg=((sbest>sgoal)|(sbest<=eps)|kvg);if (tmp>0)	if (kvg ~= 1)		fprintf(1,'\n\n** CONVERGENCE NOT ACHIEVED! **  ');	else		fprintf(1,'\n\n-- The fit process has converged --  ');	end;	fprintf(1,'%3d iterations, %5.1f s.\n\n',iter,etime(clock, t0));end%Calculate R (Ref Draper & Smith p.46)%r=corrcoef(y.*wt,f.*wt);r2=r.*r';ss=sum(((f-y).*wt).^2)/length(y);if (m > 500)	% try to avoid crash if too many points  if (tmp>1)  	disp('Reducing data for statistics to 500 points');  end  xsav = x;  ysav = y;  fsav = f;  wsav = wt;  k = m/500;  k = floor(k*(1:500));  x=x(k);  y=y(k);  f=f(k);  if max(size(wt) > 1)    wt = wt(k);  end  msav = m;  m = 500;end % if m  % CALC VARIANCE COV MATRIX AND CORRELATION MATRIX OF PARAMETERS  % re-evaluate the Jacobian at optimal values  jac=vect2column(feval(ldfdp,x,f,p,dp,func));  msk = find(dp ~= 0);  n = length(msk);           	% reduce n to equal number of estimated parameters  jac = jac(:, msk);		% use only fitted parameters  %% following section is Ray Muzic's estimate for covariance and correlation  %% assuming covariance of data is a diagonal matrix proportional to  %% diag(1/wt.^2).    %% cov matrix of data est. from Bard Eq. 7-5-13, and Row 1 Table 5.1   Qinv=diag(wt.*wt);  Q=diag((0*wt+1)./(wt.^2));  resid=y-f;                                      %un-weighted residuals%  Z=((m-n)*jac'*Qinv*jac)/(n*resid'*Qinv*resid); % Z= matrix that defines confidence region  covr=resid'*Qinv*resid*Q/(m-n);                 %covariance of residuals  Vy=1/(1-n/m)*covr;  % Eq. 7-13-22, Bard         %covariance of the data %  stdresid=resid./sqrt(diag(Vy));  % compute then convert for compact storage  jtgjinv=pinv(jac'*Qinv*jac);  if ~all(isnan(jtgjinv))	covp=jtgjinv*jac'*Qinv*Vy*Qinv*jac*jtgjinv; % Eq. 7-5-13, Bard %cov of parm est	corp = ones(n,n);	for k=1:n,		for j=k:n,			if covp(k,k)*covp(j,j)				corp(k,j)=covp(k,j)/sqrt(abs(covp(k,k)*covp(j,j)));				corp(j,k)=corp(k,j);			end		end;	end;  else    disp('Warn : leasqr : couldn''t compute squared Jacobian inverse matrix (no covp, no corp).');    covp = zeros(n,n);    corp = ones(n,n);  endif (exist('msav'))	% restoring data  x=xsav;  y=ysav;  f=fsav;  m=msav;  wt = wsav;enddeltap= sqrt(diag(covp));j=1;for i = 1:length(pin)if (dp(i) == 0)	pout(i) = pin(i);	deltapout(i) = 0;else	pout(i) = p(i);	deltapout(i) = deltap(j);	j = j+1;endend % for i%-------- Work out Chi squared ------------------------% NB number of free pars isn't right: should be sum(1-dp) not length(p)v=length(y)-length(find(dp));		% # of degrees of freedom (#sel points - #free pars)ChiSq = sum( ((y-f).*wt).^2 )/v;pout = vect2column(pout);deltapout = vect2column(deltapout);if (tmp>0)	disp( '* Least Square Estimates of Parameters')	disp('      value      sigma(+/-)')	disp([ pout deltapout ])	disp( '* Correlation Coefficient for fit R^2')	disp(r2)	disp( '* Residual Variance')	disp(ss);	disp('* Chi squared')	disp(ChiSq)	if (tmp>1)	disp('* Covariance matrix of estimated parameters')	disp(covp)	disp('* Correlation matrix of estimated parameters ')	disp(corp)	endendif (tmp>2)  fprintf(1,'Fit results sent to graph...\n');  plot(x(:,1),y,x(:,1),f);	% plot command  xlabel('X'); ylabel('Y');  title('Fit result');endif (size(ys,1)==1)	f = f';endp=p';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -