有界参数的MLE估计:一种更简洁的方法

来源:Aptech 官方博客 ·


📖 文章目录

引言

在数据分析应用中,参数存在边界是很自然的事情:方差不能为负,GARCH系数必须和为小于1以确保平稳性,混合比例介于0和1之间。

当你通过极大似然法估计这些模型时,优化器不仅需要在解处尊重这些边界,在整个搜索过程中也必须如此。如果优化搜索进入无效区域,可能会影响结果的可靠性和收敛性。例如,负方差会产生复数,非平稳的GARCH会产生爆炸式预测,或似然函数变得毫无意义。

GAUSS 26.0.1 引入了 minimize,这是十多年来GAUSS首个全新的优化器,能够干净利落地处理这一问题。

minimize 优化器允许您直接指定边界,GAUSS 会在内部确保每次迭代的参数都保持在可行域内。不再需要对数变换、惩罚函数或双重检查。

在今天的博客中,我们将通过两个示例演示新的 minimize 函数:

  • 方差参数必须为正的 GARCH 估计
  • 两个方差分量都必须为正的随机前沿模型

在这两种情况下,有界优化都使估计更加简便,并使结果与理论保持一致。

为什么边界很重要

要理解这在实际中的重要性,让我们看一个熟悉的例子。考虑一个 GARCH(1,1) 模型:

σ²t = ω + α ε²t-1 + β σ²t-1

为了使该模型定义良好且具有经济意义:

  • 基准方差必须为正(ω > 0)
  • 冲击和持续性必须对方差有非负贡献(α ≥ 0, β ≥ 0)
  • 模型必须是平稳的(α + β < 1)

传统的变通方法是估计变换后的参数,例如用 log(ω) 代替 ω,然后再转换回来。这种方法虽然可行,但会扭曲优化曲面,并使标准误的计算复杂化。你估计的不是你关心的参数,而是参数的变换形式,并希望数值计算能够正常工作。

有了有界优化,你可以直接估计 ω、α 和 β,优化器在整个过程中都会遵守约束条件。

示例1:商品收益率的 GARCH(1,1) 模型

让我们在一个包含248个商品价格收益率观测值的数据集上估计 GARCH(1,1) 模型(该数据包含在 GAUSS 26 的示例目录中)。

第一步:数据和似然函数

首先,我们加载数据并指定对数似然目标函数。

// 加载收益率数据(随GAUSS提供)
fname = getGAUSShome("examples/df_returns.gdat");
returns = loadd(fname, "rcpi");

// GARCH(1,1) 负对数似然函数
proc (1) = garch_negll(theta, y);
    local omega, alpha, beta_, sigma2, ll, t;

    omega = theta[1];
    alpha = theta[2];
    beta_ = theta[3];

    sigma2 = zeros(rows(y), 1);

    // 以样本方差初始化
    sigma2[1] = stdc(y)^2;

    // 方差递推
    for t (2, rows(y), 1);
        sigma2[t] = omega + alpha * y[t-1]^2 + beta_ * sigma2[t-1];
    endfor;

    // 高斯对数似然
    ll = -0.5 * sumc(ln(2*pi) + ln(sigma2) + (y.^2) ./ sigma2);

    retp(-ll);  // 返回负值用于最小化
endp;

第二步:设置优化

现在设置带边界约束的优化:

  • ω > 0(较小的正数下界以避免数值问题)
  • α ≥ 0
  • β ≥ 0

由于 minimize 处理的是简单的盒约束,我们对 α 和 β 施加单独的上界,以使优化器保持在合理区域内。我们将在估计后验证平稳性条件 α + β < 1。

// 初始值
theta0 = { 0.00001,   // omega(较小,让数据说话)
           0.05,      // alpha
           0.90 };    // beta

// 设置 minimize
struct minimizeControl ctl;
ctl = minimizeControlCreate();

// 边界:所有参数为正,alpha + beta < 1
ctl.bounds = { 1e-10      1,      // omega in [1e-10, 1]
               0          1,      // alpha in [0, 1]
               0     0.9999 };    // beta in [0, 0.9999]

第三步:运行模型

最后,我们调用 minimize 来运行模型。

// 估计
struct minimizeOut out;
out = minimize(&garch_negll, theta0, returns, ctl);

结果与可视化

估计完成后,我们提取条件方差序列并确认平稳性条件:

// 提取估计值
omega_hat = out.x[1];
alpha_hat = out.x[2];
beta_hat = out.x[3];

print "omega = " omega_hat;
print "alpha = " alpha_hat;
print "beta  = " beta_hat;
print "alpha + beta = " alpha_hat + beta_hat;
print "迭代次数: " out.iterations;

输出:

omega = 0.0000070
alpha = 0.380
beta  = 0.588

alpha + beta = 0.968
迭代次数: 39

有几个值得注意的结果:

  1. 高持续性(α + β ≈ 0.97)意味着波动冲击衰减缓慢。
  2. 相对较高的 α(0.38)表明近期冲击对方差有显著的即时影响。
  3. 优化在39次迭代后收敛,所有参数在整个过程中都保持在边界内。没有无效的方差评估,没有数值异常。

将条件方差与原始序列一起可视化可以提供进一步的洞察:

// 计算条件方差序列用于绘图
T = rows(returns);
sigma2_hat = zeros(T, 1);
sigma2_hat[1] = stdc(returns)^2;

for t (2, T, 1);
    sigma2_hat[t] = omega_hat + alpha_hat * returns[t-1]^2 + beta_hat * sigma2_hat[t-1];
endfor;

// 绘制收益率和条件波动率
struct plotControl plt;
plt = plotGetDefaults("xy");
plotSetTitle(&plt, "GARCH(1,1): 收益率与条件波动率");
plotSetYLabel(&plt, "收益率 / 波动率");

plotLayout(2, 1, 1);
plotXY(plt, seqa(1, 1, T), returns);

plotLayout(2, 1, 2);
plotSetTitle(&plt, "条件标准差");
plotXY(plt, seqa(1, 1, T), sqrt(sigma2_hat));

GARCH(1,1)模型的条件波动率图

该图显示了波动聚集现象:高波动期往往持续存在,这与我们在商品市场中观察到的情况一致。

示例2:随机前沿模型

随机前沿分析将随机噪声与系统性无效率分离开来。它广泛应用于生产率分析,衡量企业在生产前沿之下的运营程度。

模型形式:

y = Xβ + v - u

其中:

  • v ~ N(0, σ²v) — 对称噪声(测量误差、运气)
  • u ~ N⁺(0, σ²u) — 单边无效率(总是减少产出)

两个方差分量都必须为正。如果优化器尝试 σ²v < 0 或 σ²u < 0,似然函数将涉及负数的平方根。

第一步:数据和似然函数

在本例中,我们将从带有无效率的柯布-道格拉斯生产函数中模拟数据。这使示例自成一体,让你能确切看到估计的内容。

// 模拟生产数据
rndseed 8675309;
n = 500;

// 投入要素(劳动、资本、原材料)
labor = exp(2 + 0.5*rndn(n, 1));
capital = exp(3 + 0.7*rndn(n, 1));
materials = exp(2.5 + 0.4*rndn(n, 1));

// 真实参数
beta_true = { 1.5,    // 常数
              0.4,    // 劳动弹性
              0.3,    // 资本弹性
              0.25 }; // 原材料弹性
sig2_v_true = 0.02;   // 噪声方差
sig2_u_true = 0.08;   // 无效率方差

// 生成带有噪声 (v) 和无效率 (u) 的产出
v = sqrt(sig2_v_true) * rndn(n, 1);
u = sqrt(sig2_u_true) * abs(rndn(n, 1));  // 半正态分布

X = ones(n, 1) ~ ln(labor) ~ ln(capital) ~ ln(materials);
y = X * beta_true + v - u;  // 无效率减少产出

在模拟数据之后,我们指定用于最小化的对数似然函数:

// 随机前沿对数似然(半正态无效率)
proc (1) = sf_negll(theta, y, X);
    local k, beta_, sig2_v, sig2_u, sigma, lambda;
    local eps, z, ll;

    k = cols(X);
    beta_ = theta[1:k];
    sig2_v = theta[k+1];
    sig2_u = theta[k+2];

    sigma = sqrt(sig2_v + sig2_u);
    lambda = sqrt(sig2_u / sig2_v);

    eps = y - X * beta_;
    z = -eps * lambda / sigma;

    ll = -0.5*ln(2*pi) + ln(2) - ln(sigma)
         - 0.5*(eps./sigma).^2 + ln(cdfn(z));

    retp(-sumc(ll));
endp;

第二步:设置优化

与之前的示例一样,我们从初始值开始。对于此模型,我们运行 OLS 并使用残差方差作为初始值:

// OLS 获取初始值
beta_ols = invpd(X'X) * X'y;
resid = y - X * beta_ols;
sig2_ols = meanc(resid.^2);

// 初始值:将残差方差在噪声和无效率之间分配
theta0 = beta_ols | (0.5 * sig2_ols) | (0.5 * sig2_ols);

我们让系数无边界,但约束方差为正:

// 边界:系数无界,方差为正
k = cols(X);
struct minimizeControl ctl;
ctl = minimizeControlCreate();
ctl.bounds = (-1e300 * ones(k, 1) | 0.001 | 0.001) ~ (1e300 * ones(k+2, 1));

第三步:运行模型

最后,我们调用 minimize 来估计模型:

// 估计
struct minimizeOut out;
out = minimize(&sf_negll, theta0, y, X, ctl);

结果与可视化

现在我们已经估计了模型,让我们检查结果。

// 提取估计值
k = cols(X);
beta_hat = out.x[1:k];
sig2_v_hat = out.x[k+1];
sig2_u_hat = out.x[k+2];

print "系数:";
print "  常数        = " beta_hat[1];
print "  ln(劳动)    = " beta_hat[2];
print "  ln(资本)    = " beta_hat[3];
print "  ln(原材料)  = " beta_hat[4];
print "";
print "方差分量:";
print "  sig2_v (噪声)       = " sig2_v_hat;
print "  sig2_u (无效率)     = " sig2_u_hat;
print "  无效率占比          = " sig2_u_hat / (sig2_v_hat + sig2_u_hat);
print "";
print "迭代次数: " out.iterations;

输出系数和方差分量:

系数:
  常数        = 1.51
  ln(劳动)    = 0.39
  ln(资本)    = 0.31
  ln(原材料)  = 0.24

方差分量:
  sig2_v (噪声)       = 0.022
  sig2_u (无效率)     = 0.087
  无效率占比          = 0.80

迭代次数: 38

估计结果相当好地恢复了真实参数。方差比(≈ 0.80)告诉我们,大部分残差变异是系统性无效率,而非测量误差——这对政策制定具有重要意义。

我们还可以计算并绘制企业层面的效率得分:

// 计算效率估计(Jondrow et al. 1982)
eps = y - X * beta_hat;
sigma = sqrt(sig2_v_hat + sig2_u_hat);
lambda = sqrt(sig2_u_hat / sig2_v_hat);

mu_star = -eps * sig2_u_hat / (sig2_v_hat + sig2_u_hat);
sig_star = sqrt(sig2_v_hat * sig2_u_hat / (sig2_v_hat + sig2_u_hat));

// E[u|eps] - 无效率的条件均值
u_hat = mu_star + sig_star * (pdfn(mu_star/sig_star) ./ cdfn(mu_star/sig_star));

// 技术效率: TE = exp(-u)
TE = exp(-u_hat);

// 绘制效率分布
struct plotControl plt;
plt = plotGetDefaults("hist");
plotSetTitle(&plt, "技术效率分布");
plotSetXLabel(&plt, "技术效率 (1 = 前沿)");
plotSetYLabel(&plt, "频数");
plotHist(plt, TE, 20);

print "平均效率: " meanc(TE);
print "最小效率: " minc(TE);
print "最大效率: " maxc(TE);
平均效率: 0.80
最小效率: 0.41
最大效率: 0.95

随机前沿模型技术效率分布直方图

直方图显示了效率的巨大差异——一些企业接近前沿运营(TE ≈ 0.95),而其他企业的产出比其潜力低40-50%。这正是驱动生产率研究的那类洞察。

两个方差估计在整个优化过程中都保持为正。不需要对数变换,估计结果直接应用于我们关心的参数。

何时使用 minimize

minimize 过程专为一件事设计:带边界约束的优化。如果这就是你所需要的,它就是正确的工具。

情况 推荐
参数有简单边界 minimize
非线性约束(g(x) ≤ 0) sqpSolveMT
等式约束 sqpSolveMT
算法切换、复杂问题 OPTMT

对于上面的 GARCH 和随机前沿示例——以及大多数参数具有自然边界的 MLE 问题——minimize 可以直接处理。

结论

有界参数在计量经济学模型中随处可见:方差、波动率、概率、份额。GAUSS 26.0.1 提供了一种使用 minimize 处理它们的简洁方法。如我们所见,minimize

  • 在控制结构中设置边界
  • 优化器在整个过程中遵守边界(不仅在解处)
  • 无需对数变换或惩罚函数
  • 包含在基础 GAUSS 中

如果你一直在使用变换或似然函数内部检查无效值来绕过参数边界,那么这就是更简洁的路径。

延伸阅读

 

 

 


 

在线留言

尊敬的客户朋友,如您有任何意见建议,请通过下表反馈给我们,我们会尽快与您联系。

 

 

 

 

联系我们

 

微信公众号

咨询微信

企业店铺

400-621-1085

(节假日期间办公室座机如无人接听,请选择其他联系方式,感谢理解!祝您节日快乐!)

 

联系我们 快速链接 相关产品 上海卡贝信息技术有限公司

©2026  上海卡贝信息技术有限公司

产品中心

下载中心

站点地图

隐私政策

 

销售QQ咨询

产品QQ咨询

淘宝店铺

 

综述

GAUSS产品

应用程序

第三方应用程序

最新更新:26版

相关文档

下载试用

购买咨询

 

SAS

GraphPad Prism

LISREL

SmarPLS

Stata

HLM

IRTPRO

TreeAge

Design-Expert

IBM SPSS Statistics

EViews

RATS

SigmaPlot

EndNote

Citavi

LINGO

@RISK

BayesiaLab

Hugin

E-Prime

XLfit