📄 l_regression.m
字号:
function [wlog,aux]=l_regression(wlog,expression,varargin)% Function creates new log curve using the mathematical expression contained in the% third input argument. Null values (NaNs) in the log curves are ignored when computing% the regression parameters.%% Written by E. R., March 16, 2001% Last updated: July 12, 2001: Creates initial values even if no bounds are given%% [wlog,aux]=l_regression(wlog,expression,varargin)% INPUT% wlog log structure% expression expression in MATLAB syntax between curves of wlog. These curves are % represented by their mnemonics. No default.% EXAMPLE: 'rho = x1*Vp^x2' which estimates a Gardner-type relationship% for the density% The curve to the left of the equal sign is called the target curve % ('rho' in this example)% The parameters to be estimated are represented by "x1","x2",...,"x9".% varargin one or more cell arrays; the first element of each cell array is a% keyword, the other elements are parameters. Presently, keywords are:% 'depths' start and end depth of curves used for regression calculation% Default: {'depths',wlog.first,wlog.last}% 'rows' string with logical expression involving one more of the curve mnemonics% Can be used to restrict curve values used for regression to certain lithologies% Default: {'rows',''} (implies all rows)% 'lbounds' lower limits for the values of the parameters to be % estimated.% No defaults.% 'ubounds' upper limits for the values of the parameters to be % estimated.% No defaults.% 'description' description of the newly created curve% 'x' initial values of the parameters% Default: {'x',0.5*(ubounds-lbounds)}% Error message if any of the bounds are infinite.% 'mnem' mnemonic of the estimated curve.% Default: {'mnem','curve_pred'} where "curve" is the mnmonic of the % target curve in "expression"; in the example above it % would be 'rho_pred')% 'norm' Norm to use; possible values are 'L1' (minimizes the sum of the% absolute values of the error; more robust) or 'L2' (sum of the % squares of the error; faster). If norm is 'L1', two additional parameters% may be given which allow treating positve deflections different from % negative ones. Not case-sensitive.% Default: {'norm','L1')% OUTPUT% wlog input log with the additional curve appended (including an updated field % "curve_info")% aux structure with auxiliary information. The following fields are present:% x1, x2, ... estimated parameters;% x estimated paramters as a row vector% fval final function value (error)% exitflag of the minimization routine% general info from minimization routine (important only for debugging)% Set defaults of input argumentsparam.depths=[];param.rows=[];param.lbounds=[];param.ubounds=[];% param.description='';param.x=[];param.mnem=[];param.norm='l1';% Decode and assign input argumentsparam=assign_input(param,varargin);% Find all the words in the expressionwords=extract_words(expression);% Check if mnemonic of output curve (first variable in expression) existsmnem=words{1};[index,ier]=curve_index1(wlog,mnem,0);if ier if isempty(index) disp([char(13),' No curve with mnemonic "',mnem,'" found in log structure']) else disp([char(13),' More than one curve with mnemonic "',mnem,'" found in log structure']) end error(' Abnormal termination')end% Set default name for target curve (if not defined in argument list)if isempty(param.mnem) param.mnem=[mnem,'_pred'];endnsamp=size(wlog.curves,1);% words=extract_words(expression);vars=symvar(expression);% Find all the parametersx1to9={'x1','x2','x3','x4','x5','x6','x7','x8','x9'};lindex=ismember(vars,x1to9);xi=vars(lindex);lxi=length(xi);% Check initial values for parametersif ~isempty(param.x) if length(param.x) ~= lxi disp([char(13),' Discrepancy: ',num2str(lxi),' parameters found in expression, but ', ... num2str(length(param.x)),' initial value(s) found']) error(' Abnormal termination') end if iscell(param.x) param.x=cat(2,param.x{:}); endend% Check bounds of parametersif isempty(param.lbounds) param.lbounds=-inf*ones(1,lxi);else if length(param.lbounds) ~= lxi disp([char(13),' Number of lower bounds (',num2str(length(param.lbounds)), ... ') not equal to number of parameters in expression (', ... num2str(lxi),')']) disp(' Check number of values entered via keyword "lbounds"') error(' Abnormal ternination') end if iscell(param.lbounds) param.lbounds=cat(2,param.lbounds{:}); endendif isempty(param.ubounds) param.ubounds=inf*ones(1,lxi);else if length(param.ubounds) ~= lxi disp([char(13),' Number of upper bounds (',num2str(length(param.ubounds)), ... ') not equal to number of parameters in expression (', ... num2str(lxi),')']) disp(' Check number of values entered via keyword "ubounds"') error(' Abnormal ternination') end if iscell(param.ubounds) param.ubounds=cat(2,param.ubounds{:}); endendif isempty(param.x) param.x=0.5*(param.ubounds+param.lbounds); if any(isinf(param.x)) error('There is no default for the starting values if any of the bounds are infinite.') end idx=find(isnan(param.x)); if ~isempty(idx) for ii=1:length(idx) if param.lbounds(idx(ii)) > -inf param.x(idx(ii))=param.lbounds(idx(ii)) + 1; elseif param.ubounds(idx(ii)) < inf param.x(idx(ii))=param.ubounds(idx(ii)) - 1; else param.x(idx(ii))=0; end end endend% Check if the initial values of the parameters are within the boundstemp=find(param.x < param.lbounds);ier=0;if ~isempty(temp) ier=1; disp([char(13),' One or more initial parameter values are below the lower bounds'])endtemp=find(param.x > param.ubounds);if ~isempty(temp) ier=1; disp([char(13),' One or more initial parameter values are above the upper bounds'])endif ier disp(' Initial parameter values:') disp(param.x) error(' Abnormal termination')end% Find all the curves ...curve_names=vars(~lindex);lp=length(curve_names);% Check if "expression" is a valid MATLAB expressionfor ii=1:lxi eval([xi{ii},'=param.x(ii);']);endfor ii=1:lp eval([curve_names{ii},'=1;']);endtry eval([expression,';'])catch disp([char(13),' It is very likely, that "',expression,'" is not a valid MATLAB expression']); error(' Abnormal termination')end % Check if there are selection criteria regarding depth range and rowsif ~isempty(param.depths) | ~isempty(param.rows) if ~isempty(param.depths) temp=l_select(wlog,{'depths',param.depths{1},param.depths{2}}); if ~isempty(param.rows) temp=l_select(temp,{'rows',param.rows}); end else temp=l_select(wlog,{'rows',param.rows}); end [aux,rhs_expression]=find_parameters(temp,expression,xi,param,curve_names);else [aux,rhs_expression]=find_parameters(wlog,expression,xi,param,curve_names);end% Create new curve with the parameters just estimated and add it% to input log structurecurves=zeros(nsamp,lp);for ii=1:lp if ~strcmpi(curve_names(ii),mnem) curves(:,ii)=l_gc(wlog,curve_names{ii}); endendx=aux.x;test=sum(curves,2);lindex=find(~isnan(test));curves=curves(lindex,:);temp=eval(rhs_expression);new_curve=NaN*zeros(nsamp,1);new_curve(lindex)=temp;wlog=l_curve(wlog,'add_ne',param.mnem,new_curve,l_gu(wlog,mnem), ... [l_gd(wlog,mnem),' (predicted)']);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%function [aux,rhs_expression]=find_parameters(wlog,expression,xi,param,curve_names)[nsamp,ntr]=size(wlog.curves);lxi=length(param.x);% ... and copy them into matrix "curves", ...lp=length(curve_names);curves=zeros(nsamp,lp);for ii=1:lp eval(['curves(:,ii)=l_gc(wlog,''',curve_names{ii},''');']);end% curves_orig=curves;% ... remove all null valuestest=sum(curves,2);% idx=find(~isnan(test));curves=curves(~isnan(test),:);% Check if there are enough curve samples leftif size(curves,1) < lxi error(' Not enough valid sampes in requested curves')end% Transform "expression" into the objective function to be minimized% 1. Modify expression to be valid for vectorsexpr=strrep(expression,'*','.*');expr=strrep(expr,'/','./');expr=strrep(expr,'^','.^');% 2. replace x1, x2, ... by x(1),x(2),...for ii=1:lxi expr=strrep(expr,xi{ii},['x(',num2str(ii),')']);end% 3. replace "=" sign by "-" signidx=findstr(expr,'=');if length(idx) ~= 1 disp([char(13),' No equal sigh (=) found in expression "',expr]) error(' Abnormal termination')endexpr1=[expr(1:idx-1),'-(',expr(idx+1:end),')'];rhs_expression=expr(idx+1:end);% 4. replace header mnemonics by columns of array,...funct=expr1;for ii=1:lp funct=strrep(funct,curve_names{ii},['curves(:,',num2str(ii),')']); rhs_expression=strrep(rhs_expression,curve_names{ii},['curves(:,',num2str(ii),')']);end% 5. define objective function for the minimization conditionif ischar(param.norm) if strcmpi(param.norm,'L1') min_cond=['sum(abs(',funct,'))']; elseif strcmpi(param.norm,'L2') min_cond=['norm(',funct,')']; else disp([char(13),' Unknown norm "',param.norm,'"']) error(' Abnormal termination') endelse if strcmpi(param.norm{1},'L1') funct1=['(',expr1,')']; funct2=funct1; for ii=1:lp funct1=strrep(funct1,curve_names{ii},['curves(',funct,' > 0,',num2str(ii),')']); funct2=strrep(funct2,curve_names{ii},['curves(',funct,' < 0,',num2str(ii),')']); end min_cond=[num2str(param.norm{3}),'*','sum(abs(',funct1,')) + ', ... num2str(param.norm{2}),'*','sum(abs(',funct2,'))']; else disp([char(13),' Unknown norm "',param.norm,'" or parameters missing from "L1"']) error(' Abnormal termination') endend% Create inline function for the objective functionifunct=inline(min_cond,'x','curves');options=optimset('MaxFunEvals',5000,'LargeScale','off');if isempty(param.lbounds) & isempty(param.ubounds) % Perform unconstrained minimization [x,fval,exitflag,output]=fminunc(ifunct,param.x,options,curves);else % Perform constrained minimization [x,fval,exitflag,output]=fmincon(ifunct,param.x,[],[],[],[],param.lbounds,param.ubounds, ... [],options,curves);end% Prepare outputaux=[];for ii=1:lxi aux=setfield(aux,xi{ii},x(ii));endaux.x=x;aux.fval=fval;aux.exitflag=exitflag;aux.output=output;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -