📄 newmatnl.h
字号:
//$$ newmatnl.h definition file for non-linear optimisation// Copyright (C) 1993,4,5: R B Davies#ifndef NEWMATNL_LIB#define NEWMATNL_LIB 0#include "newmat.h"#ifdef use_namespacenamespace NEWMAT {#endif/*This is a beginning of a series of classes for non-linear optimisation.At present there are two classes. FindMaximum2 is the basic optimisationstrategy when one is doing an optimisation where one has firstderivatives and estimates of the second derivatives. ClassNonLinearLeastSquares is derived from FindMaximum2. This provides thefunctions that calculate function values and derivatives.A third class is now added. This is for doing maximum-likelihood whenyou have first derviatives and something like the Fisher Informationmatrix (eg the variance covariance matrix of the first derivatives orminus the second derivatives - this matrix is assumed to be positivedefinite). class FindMaximum2Suppose T is the ColumnVector of parameters, F(T) the function we wantto maximise, D(T) the ColumnVector of derivatives of F with respect toT, and S(T) the matrix of second derivatives.Then the basic iteration is given a value of T, update it to T - S.i() * Dwhere .i() denotes inverse.If F was quadratic this would give exactly the right answer (except itmight get a minimum rather than a maximum). Since F is not usuallyquadratic, the simple procedure would be to recalculate S and D with thenew value of T and keep iterating until the process converges. This isknown as the method of conjugate gradients.In practice, this method may not converge. FindMaximum2 considers aniteration of the form T - x * S.i() * Dwhere x is a number. It tries x = 1 and uses the values of F and itsslope with respect to x at x = 0 and x = 1 to fit a cubic in x. It thenchoses x to maximise the resulting function. This gives our new value ofT. The program checks that the value of F is getting better and carriesout a variety of strategies if it is not.The program also has a second strategy. If the successive values of Tseem to be lying along a curve - eg we are following along a curvedridge, the program will try to fit this ridge and project along it. Thisdoes not work at present and is commented out.FindMaximum2 has three virtual functions which need to be over-ridden bya derived class. void Value(const ColumnVector& T, bool wg, Real& f, bool& oorg);T is the column vector of parameters. The function returns the value ofthe function to f, but may instead set oorg to true if the parametervalues are not valid. If wg is true it may also calculate and store thesecond derivative information. bool NextPoint(ColumnVector& H, Real& d);Using the value of T provided in the previous call of Value, find theconjugate gradients adjustment to T, that is - S.i() * D. Also return d = D.t() * S.i() * D.NextPoint should return true if it considers that the process hasconverged (d very small) and false otherwise. The previous call of Valuewill have set wg to true, so that S will be available. Real LastDerivative(const ColumnVector& H);Return the scalar product of H and the vector of derivatives at the lastvalue of T.The function Fit is the function that calls the iteration. void Fit(ColumnVector&, int);The arguments are the trial parameter values as a ColumnVector and themaximum number of iterations. The program calls a DataException if theinitial parameters are not valid and a ConvergenceException if theprocess fails to converge. class NonLinearLeastSquaresThis class is derived from FindMaximum2 and carries out a non-linearleast squares fit. It uses a QR decomposition to carry out theoperations required by FindMaximum2.A prototype class R1_Col_I_D is provided. The user needs to derive aclass from this which includes functions the predicted value of eachobservation its derivatives. An object from this class has to beprovided to class NonLinearLeastSquares.Suppose we observe n normal random variables with the same unknownvariance and such the i-th one has expected value given by f(i,P)where P is a column vector of unknown parameters and f is a knownfunction. We wish to estimate P.First derive a class from R1_Col_I_D and override Real operator()(int i)to give the value of the function f in terms of i and the ColumnVectorpara defined in class R1_CoL_I_D. Also override ReturnMatrixDerivatives() to give the derivates of f at para and the value of iused in the preceeding call to operator(). Return the result as aRowVector. Construct an object from this class. Suppose in what followsit is called pred.Now constuct a NonLinearLeastSquaresObject accessing pred and optionallyan iteration limit and an accuracy critierion. NonLinearLeastSquares NLLS(pred, 1000, 0.0001);The accuracy critierion should be somewhat less than one and 0.0001 isabout the smallest sensible value.Define a ColumnVector P containing a guess at the value of the unknownparameter, and a ColumnVector Y containing the unknown data. Call NLLS.Fit(Y,P);If the process converges, P will contain the estimates of the unknownparameters. If it does not converge an exception will be generated.The following member functions can be called after you have done a fit.Real ResidualVariance() const;The estimate of the variance of the observations.void GetResiduals(ColumnVector& Z) const;The residuals of the individual observations.void GetStandardErrors(ColumnVector&);The standard errors of the observations.void GetCorrelations(SymmetricMatrix&);The correlations of the observations.void GetHatDiagonal(DiagonalMatrix&) const;Forms a diagonal matrix of values between 0 and 1. If the i-th value islarger than, say 0.2, then the i-th data value could have an undueinfluence on your estimates.*/class FindMaximum2{ virtual void Value(const ColumnVector&, bool, Real&, bool&) = 0; virtual bool NextPoint(ColumnVector&, Real&) = 0; virtual Real LastDerivative(const ColumnVector&) = 0;public: void Fit(ColumnVector&, int); virtual ~FindMaximum2() {} // to keep gnu happy};class R1_Col_I_D{ // The prototype for a Real function of a ColumnVector and an // integer. // You need to derive your function from this one and put in your // function for operator() and Derivatives() at least. // You may also want to set up a constructor to enter in additional // parameter values (that will not vary during the solve).protected: ColumnVector para; // Current x valuepublic: virtual bool IsValid() { return true; } // is the current x value OK virtual Real operator()(int i) = 0; // i-th function value at current para virtual void Set(const ColumnVector& X) { para = X; } // set current para bool IsValid(const ColumnVector& X) { Set(X); return IsValid(); } // set para, check OK Real operator()(int i, const ColumnVector& X) { Set(X); return operator()(i); } // set para, return value virtual ReturnMatrix Derivatives() = 0; // return derivatives as RowVector virtual ~R1_Col_I_D() {} // to keep gnu happy};class NonLinearLeastSquares : public FindMaximum2{ // these replace the corresponding functions in FindMaximum2 void Value(const ColumnVector&, bool, Real&, bool&); bool NextPoint(ColumnVector&, Real&); Real LastDerivative(const ColumnVector&); Matrix X; // the things we need to do the ColumnVector Y; // QR triangularisation UpperTriangularMatrix U; // see the write-up in newmata.txt ColumnVector M; Real errorvar, criterion; int n_obs, n_param; const ColumnVector* DataPointer; RowVector Derivs; SymmetricMatrix Covariance; DiagonalMatrix SE; R1_Col_I_D& Pred; // Reference to predictor object int Lim; // maximum number of iterationspublic: NonLinearLeastSquares(R1_Col_I_D& pred, int lim=1000, Real crit=0.0001) : criterion(crit), Pred(pred), Lim(lim) {} void Fit(const ColumnVector&, ColumnVector&); Real ResidualVariance() const { return errorvar; } void GetResiduals(ColumnVector& Z) const { Z = Y; } void GetStandardErrors(ColumnVector&); void GetCorrelations(SymmetricMatrix&); void GetHatDiagonal(DiagonalMatrix&) const;private: void MakeCovariance();};// The next class is the prototype class for calculating the// log-likelihood.// I assume first derivatives are available and something like the // Fisher Information or variance/covariance matrix of the first// derivatives or minus the matrix of second derivatives is// available. This matrix must be positive definite.class LL_D_FI{protected: ColumnVector para; // current parameter values bool wg; // true if FI matrix wantedpublic: virtual void Set(const ColumnVector& X) { para = X; } // set parameter values virtual void WG(bool wgx) { wg = wgx; } // set wg virtual bool IsValid() { return true; } // return true is para is OK bool IsValid(const ColumnVector& X, bool wgx=true) { Set(X); WG(wgx); return IsValid(); } virtual Real LogLikelihood() = 0; // return the loglikelihhod Real LogLikelihood(const ColumnVector& X, bool wgx=true) { Set(X); WG(wgx); return LogLikelihood(); } virtual ReturnMatrix Derivatives() = 0; // column vector of derivatives virtual ReturnMatrix FI() = 0; // Fisher Information matrix virtual ~LL_D_FI() {} // to keep gnu happy};// This is the class for doing the maximum likelihood estimationclass MLE_D_FI : public FindMaximum2{ // these replace the corresponding functions in FindMaximum2 void Value(const ColumnVector&, bool, Real&, bool&); bool NextPoint(ColumnVector&, Real&); Real LastDerivative(const ColumnVector&); // the things we need for the analysis LL_D_FI& LL; // reference to log-likelihood int Lim; // maximum number of iterations Real Criterion; // convergence criterion ColumnVector Derivs; // for the derivatives LowerTriangularMatrix LT; // Cholesky decomposition of FI SymmetricMatrix Covariance; DiagonalMatrix SE;public: MLE_D_FI(LL_D_FI& ll, int lim=1000, Real criterion=0.0001) : LL(ll), Lim(lim), Criterion(criterion) {} void Fit(ColumnVector& Parameters); void GetStandardErrors(ColumnVector&); void GetCorrelations(SymmetricMatrix&);private: void MakeCovariance();};#ifdef use_namespace}#endif#endif// body file: newmatnl.cpp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -