繁体   English   中英

R中的约束回归

[英]Constrained Regression in R

我正在使用F#中的R类型提供程序来访问一些与回归相关的R功能。 我想在回归系数受到约束时估计回归,以使它们的加权平均值为0。权重之和为1。下面的示例已简化,因为我有数十个系数,权重各不相同,我仅显示下面的R代码:

y1 <- runif(n = 50,min = 0.02,max=0.05)
y2 <- runif(n=50,min=0.01,max=0.03)
y <- c(x1,x2)
x1 <- c(rep(0,50),rep(1,50))
x2 <- c(rep(1,50),rep(0,50))
lm(y~x1+x2)

这给出了

> lm(y~x1+x2)

Call:
lm(formula = y ~ x1 + x2)

Coefficients:
(Intercept)           x1           x2  
    0.03468     -0.01460           NA  

如预期的那样。 但是我想对x1和x2施加约束,因此它们的加权平均值为(0.5 * x1 + 0.5 * x2) = 0 在那种情况下,截距变为mean(y) = 0.02737966 ,x1和x2系数将显示与该值的偏移(分别为-0.006+0.007 )。 看来quadprogmgcv软件包适用,但是我无法应用约束。

可能并非完全是您问题的答案,因为它要求在R中进行优化。但是以下内容可能会有所帮助。 无论如何,我认为R会使用NLopt库? 让我知道,如果您在制定MLE方面需要帮助,但是对于具有高斯假设且没有内生性的线性模型,它应该足够简单。

请注意,即使LN_COBYLA不使用用户提供的渐变,在cFunc和oFunc中与pattern的匹配也会忽略它。 我尝试使用LD_LBFGS,但是不支持AddEqualZeroConstraint()。

[编辑]

添加完整的示例,您可以将其用作模板。 它不是惯用的,而且很丑陋,但是说明了这一点。 但是,在此示例中,约束将导致此退化。 您需要NLOptNet,MathNet.Numerics,Fsharp Charting。 也许它可以帮助希望在F#中进行约束优化的其他人。

open System
open System.IO
open FSharp.Core.Operators
open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.LinearAlgebra.Double
open MathNet.Numerics.Distributions
open DiffSharp.Numerical.Float64
open NLoptNet

let (.*) (m1 : Matrix<float>) (m2 : Matrix<float>) =
    m1.Multiply(m2)

let (.+) (m1 : Matrix<float>) (m2 : Matrix<float>) =
    m1.Add(m2)

let (.-) (m1 : Matrix<float>) (m2 : Matrix<float>) =
    m1.Subtract(m2)


let V = matrix [[1.;      0.5;    0.2]
                [0.5;      1.;    0.]
                [0.2;      0.;    1.]]
let dat = (DenseMatrix.init 200 3 ( fun i j -> Normal.Sample(0., 1.) )) .* V.Cholesky().Factor
let y = DenseMatrix.init 200 1 (fun i j -> 0.)
let x0 = DenseMatrix.init 200 1 (fun i j -> 0.)
let x1 = DenseMatrix.init 200 1 (fun i j -> 0.)
for i in 0 .. 199 do
    y.[i, 0] <- dat.[i, 0]
    x0.[i, 0] <- dat.[i, 1]
    x1.[i, 0] <- dat.[i, 2]

let ll (th : float array) =
    let t1 = x0.Multiply(th.[0]) .+ x1.Multiply(th.[1])
    let res = (y .- t1).PointwisePower(2.)
    res.ColumnAbsoluteSums().Sum() / 200.

let oFunc (th : float array) (gradvec : float array) =
    match gradvec with
    | null  -> ()
    | _     -> (grad ll th).CopyTo(gradvec, 0)

    ll th

let cFunc (th : float array) (gradvec : float array) =
    match gradvec with
    | null  -> ()
    | _     -> (grad ll th).CopyTo(gradvec, 0)

    th.[0] + th.[1]

let fitFunc () =
    let solver = new NLoptSolver(NLoptAlgorithm.LN_COBYLA, uint32(2), 1e-7, 100000)
    solver.SetLowerBounds([|-10.; -10.;|])
    solver.SetUpperBounds([|10.; 10.;|])
    //solver.AddEqualZeroConstraint(cFunc)
    solver.SetMinObjective(oFunc)
    let initialValues = [|1.; 2.;|]
    let objReached, finalScore = solver.Optimize(initialValues)
    objReached |> printfn "%A"
    let fittedParams = initialValues
    fittedParams |> printfn "%A"
    fittedParams

let fittedParams = fitFunc() |> DenseVector
let yh = DenseMatrix.init 200 1 (fun i j -> 0.)
for i in 0 .. 199 do
    yh.[i, 0] <- dat.[i, 1] * fittedParams.[0] + dat.[i, 2] * fittedParams.[1]


Chart.Combine([Chart.Line(y.Column(0), Name="y")
               Chart.Line(yh.Column(0), Name="yh")
               |> Chart.WithLegend(Title="Model", Enabled=true)] )
               |> Chart.Show        

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM