Constrained Maximum Likelihood MT (CMLMT) provides a suite of flexible, efficient and trusted tools for the solution of the maximum likelihood problem with general constraints on the parameters.
Version 3.0 is easier to use than ever!
New syntax options eliminate the need for PV and DS structures:
Decreasing the required code up to 25%.
Decreasing runtime up to 20%.
Simplifying usage.
Optional dynamic arguments make it simple and transparent to add extra data arguments beyond model parameters to your objective function.
Updated documentation and examples.
Fully backwards compatible with CMLMT 1.0-2.0
Features
Nonlinear equality and inequality constraints.
Linear equality and inequality constraints.
Trust region method.
A variety of descent and line search algorithms.
Computation of analytical and numerical derivatives.
Dynamic algorithm switching.
Multiple methods for statistical inference.
Default selections allow you to see results quickly with minimum programming effort, while an array of modelling parameters allows the flexibility to solve custom problems.
Example
Ordered probit estimation with CMLMT.
Suppose we have a dependent variable that is observed in several ordered categories. We might estimate coefficients of a regression on this variable using the ordered probit model:
where
and
where is the Normal cumulative distribution function.
The log-likelihood function for this model is
The cmlmt function that performs the estimation takes four arguments, (1) a pointer to the procedure that computes the log-likelihood, (2) a PV parameter structure containing the start values of the parameters, (3) a DS data structure, and (4) a control structure.
GAUSS structures are simply bins containing other objects such as matrices, strings, arrays, etc. They can be defined by the programmer, but the two of the structures used by cmlmt are defined in the Run-Time Library, and the control structure is defined in the cmlmt library.
The PV Parameter Structure
The PV parameter structure is created and filled using GAUSS Run-Time Library functions. Using these functions the structure can be filled with vectors, matrices, and arrays containing starting parameter values. Masks can be used to specify fixed versus free parameters. For example,
struct PV p0; // creates a default parameter structure p0 = pvCreate; p0 = pvPack(p0,.5|.5|.5,”beta”); p0 = pvPackm(p0,-30|-1|1|30,”tau”,0|1|1|0);
The structure now contains starting values for a 3×1 vector of coefficients called beta,and another 4×1 vector of thresholds called tau. It will be convenient for the calculation of the log-likelihood for the first and last be parameters set to -30 and +30. The fourth argument is a mask specifying the first and last elements of the vector to be fixed and the remaining elements free parameters to be estimated.
The DS Data Structure
The DS data structure is a general purpose bucket of GAUSS types. It contains one of each of the types, matrix, array, string, string array, sparse matrix, and scalar. It is passed to the log-likelihood procedure untouched by cmlmt. It can be used by programmers in any way they choose to help in computing the log-likelihood. Typically it is used to pass data to the procedure. The DS structure can also be reshaped into a vector of structures giving the programmer great flexibility in handling data and other information.
load x[200,5] = data.csv; struct DS d0; // creates a 2x1 vector of // default data structures d0 = reshape(dsCreate,2,1); // dependent variable d0[1].dataMatrix = x[.,1]; // independent variables d0[2].dataMatrix = x[.,2:4];
The cmlmtControl Structure
This structure handles the matrices and strings that control the estimation process such as setting the descent algorithm, the line search method, and so on. It is also used to specify the constraints. For example the thresholds need to be constrained in the following way where . This implies the two free constraints.
The programmer will accomplish by specifing two members of the cmlmtControl structure, C and D, to impose this inequality constraint.
where x is the vector of parameters being estimated. Then
struct cmlmtControl c0; // creates a default structure c0 = cmlmtControlCreate; c0.C = { 0 0 0 -1 1 0, 0 0 0 0 -1 1 }; c0.D = { 0, 0 };
The first three columns of the matrix c0.C and the vector c0.D are associated with regression coefficients that are unconstrained and the last two are associated with the thresholds.
The Log-likelihood Procedure
The programmer now writes a GAUSS procedure computing a vector of log-likelihood probabilities. This procedure has three input arguments, the PV parameter structure, the DSdata structure, and 3×1 vector the first element of which is nonzero if cmlmt is requesting the vector of log-likelihood probabilities, the second element nonzero if it is requesting the matrix of first derivatives with respect to the parameters, and the third element nonzero if it is requesting the Hessian or array of second derivatives with respect to the parameters. It has one return argument, a modelResults structure containing the results.
proc orderedProbit(struct PV p, struct DS d, ind); local mu, tau, beta, emu, eml; struct modelResults mm; if ind[1] == 1; tau = pvUnpack(p,”tau”); beta = pvUnpack(p,”beta”); mu = d[2].dataMatrix * beta; eml = submat(tau,d[1].dataMatrix,0) – mu; emu = submat(tau,d[1].dataMatrix + 1,0) – mu; mm.function = ln(cdfn(emu) – cdfn(eml)); endif; retp(mm); endp;
The GAUSS submat function serves to pull out the k-th element of tau for the i-th row of d[1].datamatrix set to k.
Since this procedure doesn’t return a matrix of first derivatives nor an array of second derivatives they will be computed numerically by cmlmt.
The result stored in mm.function is an Nx1 vector of log-probabilities computed by observation. If we were to have provided analytical derivatives, the first derivatives would be an Nxm matrix of derivatives computed by observation where m is the number of parameters to be estimated, and the second derivatives would be an Nxmxm array of second derivatives computed by observation. Computing these quantities in this way improves accuracy. It also allows for the BHHH descent method which is more accurate than other methods permitting a larger convergence tolerance.
It is also possible to return a scalar log-likelihood which is the sum of the individual log-probabilities. In this case the analytical first derivatives would be a 1xm gradient vector, and the second derivatives a 1xmxm array. You would also need to set c0.numObs to the number of observations since cmlmt is no longer able to determine the number of observations from the length of the vector of log-probabilities.
The Command File
Finally we put it all together in the command file:
library cmlmt; // contains the structure definitions #include cmlmt.sdf; // simulating data here x = rndn(200,3); b = { .4, .5, .6 }; ystar = x*b; tau = { -50, -1, 0, 1, 50 }; y = (ystar .> tau[1] .and ystar .<= tau[2]) + 2 * (ystar .> tau[2] .and ystar .<= tau[3]) + 3 * (ystar .> tau[3] .and ystar .<= tau[4]) + 4 * (ystar .> tau[4] .and ystar .<= tau[5]); struct DS d0; // creates a 2x1 vector of // default data structures d0 = reshape(dsCreate,2,1); // dependent variable d0[1].dataMatrix = y; // independent variables d0[2].dataMatrix = x; struct PV p0; // creates a default parameter structure p0 = pvCreate; p0 = pvPack(p0,.5|.5|.5,"beta"); p0 = pvPackm(p0,-30|-1|0|1|30,"tau",0|1|1|1|0); struct cmlmtControl c0; // creates a default structure c0 = cmlmtControlCreate; c0.C = { 0 0 0 -1 1 0, 0 0 0 0 -1 1 }; c0.D = { 0, 0}; struct cmlmtResults out; out = cmlmt(&orderedProbit,p0,d0,c0); // prints the results call cmlmtprt(out); proc orderedProbit(struct PV p, struct DS d, ind); local mu, tau, beta, emu, eml; struct modelResults mm; if ind[1] == 1; tau = pvUnpack(p,"tau"); beta = pvUnpack(p,"beta"); mu = d[2].dataMatrix * beta; eml = submat(tau,d[1].dataMatrix,0) - mu; emu = submat(tau,d[1].dataMatrix + 1,0) - mu; mm.function = ln(cdfn(emu) - cdfn(eml)); endif; retp(mm); endp;
This program produces the following output:
================================================================ CMLMT Version 2.0.7 3/30/2012 1:29 pm ================================================================= return code = 0 normal convergence Log-likelihood -15.1549 Number of cases 200 Covariance of the parameters computed by the following method: ML covariance matrix Parameters Estimates Std. err. Est./s.e. Prob. Gradient ------------------------------------------------------------------ beta[1,1] 4.2060 0.2385 17.634 0.0000 0.0000 beta[2,1] 5.3543 0.2947 18.166 0.0000 0.0000 beta[3,1] 6.2839 0.2789 22.531 0.0000 0.0000 tau[2,1] -10.7561 0.7437 -14.462 0.0000 0.0000 tau[3,1] -0.0913 0.2499 -0.365 0.7148 0.0000 tau[4,1] 10.6693 0.5697 18.727 0.0000 0.0000 Correlation matrix of the parameters 1 0.52064502 0.54690534 -0.46731768 0.046211496 0.57202935 0.52064502 1 0.58363048 -0.47574225 -0.061765839 0.65959766 0.54690534 0.58363048 1 -0.5169026 -0.0059238287 0.69077806 -0.46731768 -0.47574225 -0.5169026 1 0.0046253798 -0.44858539 0.046211496 -0.061765839 -0.0059238287 0.0046253798 1 -0.01457591 0.57202935 0.65959766 0.69077806 -0.44858539 -0.01457591 1 Wald Confidence Limits 0.95 confidence limits Parameters Estimates Lower Limit Upper Limit Gradient ---------------------------------------------------------------------- beta[1,1] 4.2060 3.7355 4.6764 0.0000 beta[2,1] 5.3543 4.7730 5.9356 0.0000 beta[3,1] 6.2839 5.7338 6.8339 0.0000 tau[2,1] -10.7561 -12.2230 -9.2893 0.0000 tau[3,1] -0.0913 -0.5842 0.4015 0.0000 tau[4,1] 10.6693 9.5457 11.7929 0.0000 Number of iterations 135 Minutes to convergence 0.00395
Platform: Windows, Mac, and Linux.
Requirements: GAUSS/GAUSS Light version 10 or higher; Linux requires version 10.0.4 or higher.