Julia JuMP 多变量 ML 估计
Julia JuMP Multiavariate ML Estimation
我正在尝试使用 JuMP 和 NLopt 求解器在 Julia 的线性回归设置中执行正态分布变量的 ML 估计。
存在一个很好的工作示例 here 但是,如果我尝试估计回归参数(斜率),则编写代码会变得非常乏味,尤其是在参数 space 增加的情况下。
也许有人有想法如何把它写得更简洁。这是我的代码:
#type definition to store data
type data
n::Int
A::Matrix
β::Vector
y::Vector
ls::Vector
err::Vector
end
#generate regression data
function Data( n = 1000 )
A = [ones(n) rand(n, 2)]
β = [2.1, 12.9, 3.7]
y = A*β + rand(Normal(), n)
ls = inv(A'A)A'y
err = y - A * ls
data(n, A, β, y, ls, err)
end
#initialize data
d = Data()
println( var(d.y) )
function ml( )
m = Model( solver = NLoptSolver( algorithm = :LD_LBFGS ) )
@defVar( m, b[1:3] )
@defVar( m, σ >= 0, start = 1.0 )
#this is the working example.
#As you can see it's quite tedious to write
#and becomes rather infeasible if there are more then,
#let's say 10, slope parameters to estimate
@setNLObjective( m, Max,-(d.n/2)*log(2π*σ^2) \cont. next line
-sum{(d.y[i]-d.A[i,1]*b[1] \
-d.A[i,2]*b[2] \
-d.A[i,3]*b[3])^2, i=1:d.n}/(2σ^2) )
#julia returns:
> slope: [2.14,12.85,3.65], variance: 1.04
#which is what is to be expected
#however:
#this is what I would like the code to look like:
@setNLObjective( m, Max,-(d.n/2)*log(2π*σ^2) \
-sum{(d.y[i]-(d.A[i,j]*b[j]))^2, \
i=1:d.n, j=1:3}/(2σ^2) )
#I also tried:
@setNLObjective( m, Max,-(d.n/2)*log(2π*σ^2) \
-sum{sum{(d.y[i]-(d.A[i,j]*b[j]))^2, \
i=1:d.n}, j=1:3}/(2σ^2) )
#but unfortunately it returns:
> slope: [10.21,18.89,15.88], variance: 54.78
solve(m)
println( getValue(b), " ", getValue(σ^2) )
end
ml()
有什么想法吗?
编辑
正如 Reza 所指出的,一个工作示例是:
@setNLObjective( m, Max,-(d.n/2)*log(2π*σ^2) \
-sum{(d.y[i]-sum{d.A[i,j]*b[j],j=1:3})^2,
i=1:d.n}/(2σ^2) )
我没有跟踪您的代码,但在任何地方,我希望以下内容对您有用:
sum([(d.y[i]-sum([d.A[i,j]*b[j] for j=1:3]))^2 for i=1:d.n])
正如@IainDunning 所提到的,JuMP 包在它的宏中有一个特殊的求和语法,所以更有效和抽象的方法是:
sum{sum{(d.y[i]-d.A[i,j]*b[j], j=1:3}^2,i=1:d.n}
sum{}
语法是一种特殊语法,只能在 JuMP 宏中使用,是求和的首选语法。
所以你的例子应该写成:
function ml( )
m = Model( solver = NLoptSolver( algorithm = :LD_LBFGS ) )
@variable( m, b[1:3] )
@variable( m, σ >= 0, start = 1.0 )
@NLobjective(m, Max,
-(d.n/2)*log(2π*σ^2)
- sum{
sum{(d.y[i]-d.A[i,j]*b[j], j=1:3}^2,
i=1:d.n}/(2σ^2) )
为了尽可能清晰,我将其扩展到多行。
Reza 的回答在技术上并没有错,但不是惯用的 JuMP,并且对于较大的模型来说效率不高。
我正在尝试使用 JuMP 和 NLopt 求解器在 Julia 的线性回归设置中执行正态分布变量的 ML 估计。
存在一个很好的工作示例 here 但是,如果我尝试估计回归参数(斜率),则编写代码会变得非常乏味,尤其是在参数 space 增加的情况下。
也许有人有想法如何把它写得更简洁。这是我的代码:
#type definition to store data
type data
n::Int
A::Matrix
β::Vector
y::Vector
ls::Vector
err::Vector
end
#generate regression data
function Data( n = 1000 )
A = [ones(n) rand(n, 2)]
β = [2.1, 12.9, 3.7]
y = A*β + rand(Normal(), n)
ls = inv(A'A)A'y
err = y - A * ls
data(n, A, β, y, ls, err)
end
#initialize data
d = Data()
println( var(d.y) )
function ml( )
m = Model( solver = NLoptSolver( algorithm = :LD_LBFGS ) )
@defVar( m, b[1:3] )
@defVar( m, σ >= 0, start = 1.0 )
#this is the working example.
#As you can see it's quite tedious to write
#and becomes rather infeasible if there are more then,
#let's say 10, slope parameters to estimate
@setNLObjective( m, Max,-(d.n/2)*log(2π*σ^2) \cont. next line
-sum{(d.y[i]-d.A[i,1]*b[1] \
-d.A[i,2]*b[2] \
-d.A[i,3]*b[3])^2, i=1:d.n}/(2σ^2) )
#julia returns:
> slope: [2.14,12.85,3.65], variance: 1.04
#which is what is to be expected
#however:
#this is what I would like the code to look like:
@setNLObjective( m, Max,-(d.n/2)*log(2π*σ^2) \
-sum{(d.y[i]-(d.A[i,j]*b[j]))^2, \
i=1:d.n, j=1:3}/(2σ^2) )
#I also tried:
@setNLObjective( m, Max,-(d.n/2)*log(2π*σ^2) \
-sum{sum{(d.y[i]-(d.A[i,j]*b[j]))^2, \
i=1:d.n}, j=1:3}/(2σ^2) )
#but unfortunately it returns:
> slope: [10.21,18.89,15.88], variance: 54.78
solve(m)
println( getValue(b), " ", getValue(σ^2) )
end
ml()
有什么想法吗?
编辑
正如 Reza 所指出的,一个工作示例是:
@setNLObjective( m, Max,-(d.n/2)*log(2π*σ^2) \
-sum{(d.y[i]-sum{d.A[i,j]*b[j],j=1:3})^2,
i=1:d.n}/(2σ^2) )
我没有跟踪您的代码,但在任何地方,我希望以下内容对您有用:
sum([(d.y[i]-sum([d.A[i,j]*b[j] for j=1:3]))^2 for i=1:d.n])
正如@IainDunning 所提到的,JuMP 包在它的宏中有一个特殊的求和语法,所以更有效和抽象的方法是:
sum{sum{(d.y[i]-d.A[i,j]*b[j], j=1:3}^2,i=1:d.n}
sum{}
语法是一种特殊语法,只能在 JuMP 宏中使用,是求和的首选语法。
所以你的例子应该写成:
function ml( )
m = Model( solver = NLoptSolver( algorithm = :LD_LBFGS ) )
@variable( m, b[1:3] )
@variable( m, σ >= 0, start = 1.0 )
@NLobjective(m, Max,
-(d.n/2)*log(2π*σ^2)
- sum{
sum{(d.y[i]-d.A[i,j]*b[j], j=1:3}^2,
i=1:d.n}/(2σ^2) )
为了尽可能清晰,我将其扩展到多行。
Reza 的回答在技术上并没有错,但不是惯用的 JuMP,并且对于较大的模型来说效率不高。