具有相等和不等式的回归约束了R中的系数

时间:2018-02-13 22:14:08

标签: r optimization constraints regression

我试图使用RSS获得估计的约束系数。 β系数被约束在[0,1]和sum之间。另外,我的第三个参数被约束在(-1,1)之间。利用下面的内容,我可以使用模拟变量获得一个很好的解决方案,但是当我在实际数据集上实现该方法时,我会不断找到一个非独特的解决方案。反过来,我想知道是否有一种更加数字稳定的方式来获得我的估计参数。

set.seed(234)
k = 2
a = diff(c(0, sort(runif(k-1)), 1))
n = 1e4
x = matrix(rnorm(k*n), nc = k)
a2 = -0.5
y = a2 * (x %*% a) + rnorm(n)
f = function(u){sum((y - u[3] * (x %*% u[1:2]))^2)}
g = function(v){

v1 = v[1]
v2 = v[2]
u = vector(mode = "double", length = 3)

# ensure in (0,1)
v1 = 1 / (1 + exp(-v1))

# ensure add up to 1
u[1:2] = c(v1, 1 - sum(v1))

# ensure between [-1,1]
u[3] = (v2^2 - 1) / (v2^2 + 1)
u
}

res = optim(rnorm(2), function(v) f(g(v)), hessian = TRUE, method = "BFGS")
eigen(res$hessian)$values
res$convergence
rbind(Est = res$par, SE = sqrt(diag(solve(res$hessian))))
rbind(g(res$par),c(a,a2))

Hats off to http://zoonek.free.fr/blosxom/R/2012-06-01_Optimization.html

2 个答案:

答案 0 :(得分:1)

由于到目前为止还没有直接回答您的问题,我想说明如何在Stan/RStan中实现参数约束模型。您应该尝试使用您的真实数据。

执行贝叶斯推理的优势在于为您的(约束的)模型参数提供后验概率。然后可以轻松计算包括置信区间在内的点估计值。

  1. 首先,我们加载库并设置RStan以存储已编译的模型并使用多个核心(如果可用)。

    library(rstan);
    rstan_options(auto_write = TRUE);
    options(mc.cores = parallel::detectCores());
    
  2. 我们现在定义我们的Stan模型。在这种情况下,它非常简单,我们可以将RStan的simplex数据类型用于总和为1的非负值的向量。

    model <- "
    data {
        int<lower=1> n;   // number of observations
        int<lower=0> k;   // number of parameters
        matrix[n, k] X;   // data
        vector[n] y;      // response
    }
    
    parameters {
        real a2;          // a2 is a free scaling parameter
        simplex[k] a;     // a is constrained to sum to 1
        real sigma;       // residuals
    }
    
    model {
        // Likelihood
        y ~ normal(a2 * (X * a), sigma);
    }"
    

    Stan支持各种约束数据类型;我建议您在Stan manual处采取更多复杂的例子。

  3. 使用原始问题中的示例数据,我们可以运行我们的模型:

    # Sample data
    set.seed(234);
    k = 2;
    a = diff(c(0, sort(runif(k-1)), 1));
    n = 1e4;
    x = matrix(rnorm(k * n), nc = k);
    a2 = -0.5;
    y = a2 * (x %*% a) + rnorm(n);
    
    # Fit stan model
    fit <- stan(
        model_code = model,
        data = list(
            n = n,
            k = k,
            X = x,
            y = as.numeric(y)),
        iter = 4000,
        chains = 4);
    

    运行模型只需几秒钟(在解析器内部翻译并在C ++中编译模型之后),完整的结果(所有参数的后验分布以数据为条件)都存储在fit

  4. 我们可以使用fit检查summary的内容:

    # Extract parameter estimates
    pars <- summary(fit)$summary;
    pars;
    #               mean      se_mean          sd          2.5%           25%
    #a2       -0.4915289 1.970327e-04 0.014363398    -0.5194985    -0.5011471
    #a[1]      0.7640606 2.273282e-04 0.016348488     0.7327691     0.7527457
    #a[2]      0.2359394 2.273282e-04 0.016348488     0.2040952     0.2248482
    #sigma     1.0048695 8.746869e-05 0.007048116     0.9909698     1.0001889
    #lp__  -5048.4273105 1.881305e-02 1.204892294 -5051.4871931 -5048.9800451
    #                50%           75%         97.5%    n_eff      Rhat
    #a2       -0.4916061    -0.4819086    -0.4625947 5314.196 1.0000947
    #a[1]      0.7638723     0.7751518     0.7959048 5171.881 0.9997468
    #a[2]      0.2361277     0.2472543     0.2672309 5171.881 0.9997468
    #sigma     1.0048994     1.0095420     1.0187554 6492.930 0.9998086
    #lp__  -5048.1238783 -5047.5409682 -5047.0355381 4101.832 1.0012841
    

    您可以看到a[1]+a[2]=1

    绘制参数估计值(包括置信区间)也很容易:

    plot(fit);
    
  5. enter image description here

答案 1 :(得分:1)

解决具有相等不等式约束的优化问题的最简单方法很可能是通过“增广拉格朗日”方法。例如,在R中,这是在 alabama 包中实现的。

# function and gradient
fn = function(u){sum((y - u[3] * (x %*% u[1:2]))^2)}
gr = function(u) numDeriv::grad(fn, u)

# constraint sum(u) == 1
heq = function(u) sum(u) - 1
# constraints 0 <= u[1],u[2] <= 1; -1 <= u[3] <= 1
hin = function(u) c(u[1], u[2], 1-u[1], 1-u[2], u[3]+1, 1-u[3])

sol_a = alabama::auglag(c(0.5, 0.5, 0), fn, gr, hin=hin, heq=heq)
sol_a
## $par
## [1]  1.0000000  0.3642904 -0.3642904
## $value
## [1] 10094.74
## ...
## $hessian
##             [,1]        [,2]        [,3]
## [1,] 15009565054  9999999977  9999992926
## [2,]  9999999977 10000002578  9999997167
## [3,]  9999992926  9999997167 10000022569

对于包含“增强拉格朗日”过程的其他包,请参阅有关优化的CRAN任务视图。