Nonlinear regression
Stata’s nl command fits an arbitrary function by
least squares. That is, given
yj = f(xj, b) + uj
nl finds b to minimize Σj
(uj2). (nl can also obtain
weighted least squares estimates.) You need only supply the function f();
you do not need to supply the derivatives.
nl provides three ways to define the function.
Most commonly, you simply type the function directly on the command line or
in the dialog box. nl also offers a way to package
a function that you use frequently so that you do not have to reenter it
each time. A third way allows you to define arbitrarily complex functions
that can take any number of lines in a program file.
To fit the negative exponential-growth model
yj = b0 * (1 − exp(−b1*xj)) + uj
you type
. nl (y = {b0=1}*(1 - exp(-1*{b1=0.1}*x)))
(obs = 20)
Iteration 0: residual SS = .0026064
Iteration 1: residual SS = .0005769
Iteration 2: residual SS = .0005768
Iteration 3: residual SS = .0005768
Source | SS df MS
-------------+------------------------------ Number of obs = 20
Model | 17.6717234 2 8.83586172 R-squared = 1.0000
Residual | .00057681 18 .000032045 Adj R-squared = 1.0000
-------------+------------------------------ Root MSE = .0056608
Total | 17.6723003 20 .883615013 Res. dev. = -152.317
------------------------------------------------------------------------------
y | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
/b0 | .9961886 .0016138 617.29 0.000 .9927981 .9995791
-------------+----------------------------------------------------------------
/b1 | .0419539 .0003982 105.35 0.000 .0411172 .0427905
------------------------------------------------------------------------------
(The dataset for this example was obtained from SAS [1985, 588].)
Notice that we put the parameter names in braces, and to initialize them we
simply included an equal sign and our initial values.
Many models are frequently used, so typing in the formula each time can
become tedious. nl has several models built-in,
and you can write your own programs for other models. For example, say you
want to fit the exponential model
yj = b0 + b1*b2xj + uj
You would simply type
. nl exp3 : y x
because this three-parameter exponential function is built into
nl. If that function were not included with
nl, you could create the following program:
program nlexp3ex, rclass
version 12
syntax varlist(min=2 max=2) if
local y : word 1 of `varlist'
local x : word 2 of `varlist'
return local eq "`y' = {b0} + {b1}*{b2}^`x'"
return local title "My exponential function"
end
We named our program nlexp3ex because nl defines
the program nlexp3 for its version of the three-parameter exponential model.
After saving the program, you could fit it to your data by typing
. nl exp3ex : y x
To specify initial values as well, you would type
. nl exp3ex : y x, initial(b0 1 b1 0.9 b2 0.9)
Some functions are more complex, and writing them in one line of code is
either impossible or at least error-prone. In those cases, a third method
of defining your function is best. The constant elasticity of substitution
production function is
ln Qj = b0 − (1/ρ)*ln{δ*Kj−ρ + (1−δ)*Lj−ρ}
where Qj is the jth firm's output and Kj and
Lj are the amounts of capital and labor the firm uses.
b0, ρ, and δ are the parameters to estimate.
First, you write a program that calculates the function:
program nlces
version 12
syntax varlist(min=3 max=3) [aw fw iw] if, at(name)
local logout: word 1 of `varlist'
local capital: word 2 of `varlist'
local labor: word 3 of `varlist'
// Retrieve parameters out of at
tempname b0 rho delta
scalar `b0' = `at'[1,1]
scalar `rho' = `at'[1,2]
scalar `delta' = `at'[1,3]
// Some temporary variables
tempvar kterm lterm
generate double `kterm' = `delta'*`capital'^(-1*`rho') `if'
generate double `lterm' = (1-`delta')*`labor'^(-1*`rho') `if'
// Now fill in dependent variable
replace `logout' = `b0' - 1/`rho'*ln(`kterm'+`lterm') `if'
end
Then you call nl like this, specifying initial
values for some or all of the parameters:
. nl ces @ logout capital labor, parameters(b0 rho delta) ///
initial(rho 1 delta 0.5)
nl is notable because it was written in
Stata’s programming language. Stata is fully programmable; even if we
had not written the nl command for you, with
(admittedly considerable) work, you could have written it yourself. In
fact, the first versions of nl were written by
users; see Danuso (1991) and Royston (1992, 1993). It was officially
adopted by StataCorp (meaning it became supported) in September 1992.
References
- Danuso, F. 1991.
sg1: Nonlinear regression command.
Stata Technical Bulletin 1: 17–19.
-
Reprinted in Stata Technical Bulletin Reprints,
vol. 1, pp. 96–98.
- Judge, G. G., W. E. Griffiths, R. C. Hill, H. Lütkepohl, and
Tsoung-Chao Lee. 1985.
-
The Theory and Practice of Econometrics. 2nd ed.
New York: Wiley.
- Royston, P. 1992.
sg1.2: Nonlinear regression command.
Stata Technical Bulletin 7: 11–18.
-
Reprinted in Stata Technical Bulletin Reprints, vol. 2, pp. 112–120.
- ------. 1993.
sg1.4: Standard nonlinear curve fits.
Stata Technical Bulletin 11: 17.
-
Reprinted in Stata Technical Bulletin Reprints, vol. 2, p. 121.
- SAS Institute. 1985.
SAS User's Guide: Statistics, Version 5 Edition.
Cary, NC.
|