【发布时间】:2016-07-10 22:53:16
【问题描述】:
我正在尝试一些 Newton Raphson 更新。这是一段编译运行的代码(警告:无限循环)。
let thetam = [|beta; sigSq|] |> DenseVector
let mutable gm = grad yt xt betah sigSqh // returns DenseVector
let hm = hess yt xt betah sigSqh // return Matrix<float>
while gm*gm > 0.0001 do
gm <- grad yt xt betah sigSqh
thetam - (hess yt xt betah sigSqh).Inverse() * gm // unassigned compiles
但是,只要我将最后一个值分配给可变变量thetam,如下所示...
while gm*gm > 0.0001 do
gm <- grad yt xt betah sigSqh
thetam <- thetam - (hess yt xt betah sigSqh).Inverse() * gm // gm here has problems
gm 下出现一条弯曲的红线,编译器报错The type 'Vector<float>' is not compatible with the type 'DenseVector'
但是,函数 grad 被明确告知返回 DenseVector 并且通常按预期工作。
let grad (yt : Vector<float>) (xt : Vector<float>) (beta : float) (sigSq : float) =
let T = (float yt.Count)
let gradBeta = (yt - beta * xt)*xt / sigSq
let gradSigSq = -0.5*T/sigSq + 0.5/sigSq**2.*(yt - beta * xt)*(yt - beta * xt)
[|gradBeta; gradSigSq|] |> DenseVector
为什么分配给thetam 会导致问题?有没有一种神奇的方法来执行不可变的更新?
这是完整的脚本:
open System
open System.IO
open System.Windows.Forms
open System.Windows.Forms.DataVisualization
open FSharp.Data
open FSharp.Charting
open FSharp.Core.Operators
open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.LinearAlgebra.Double
open MathNet.Numerics.Random
open MathNet.Numerics.Distributions
open MathNet.Numerics.Statistics
let beta, sigSq = 3., 9.
let xt = DenseVector [|23.; 78.; 43.; 32.; 90.; 66.; 89.; 34.; 72.; 99.|]
let T = xt.Count
let genProc () =
beta * xt + DenseVector [|for i in 1 .. T do yield Normal.Sample(0., Math.Sqrt(sigSq))|]
let llNormal (yt : Vector<float>) (xt : Vector<float>) (beta : float) (sigSq : float) =
let T = (float yt.Count)
let z = (yt - beta * xt) / Math.Sqrt(sigSq)
-0.5 * log (2. * Math.PI) - 0.5 * log (sigSq) - z*z/2./T/sigSq
let grad (yt : Vector<float>) (xt : Vector<float>) (beta : float) (sigSq : float) =
let T = (float yt.Count)
let gradBeta = (yt - beta * xt)*xt / sigSq
let gradSigSq = -0.5*T/sigSq + 0.5/sigSq**2.*(yt - beta * xt)*(yt - beta * xt)
[|gradBeta; gradSigSq|] |> DenseVector
let hess (yt : Vector<float>) (xt : Vector<float>) (beta : float) (sigSq : float) =
let T = (float yt.Count)
let z = yt - beta * xt
let h11 = -xt*xt/sigSq
let h22 = T*0.5/sigSq/sigSq - z*z/sigSq/sigSq/sigSq
let h12 = -1./sigSq**2.*((yt - beta * xt)*xt)
array2D [[h11;h12];[h12;h22]] |> DenseMatrix.ofArray2
let yt = genProc()
// until convergence
let mutable thetam = [|beta; sigSq|] |> DenseVector
let mutable gm = grad yt xt beta sigSq
while gm*gm > 0.0001 do
gm <- grad yt xt beta sigSq
// 'gm' here is complaining upon equation being assigned to thetam
thetam <- thetam - (hess yt xt beta sigSq).Inverse() * gm
【问题讨论】:
-
是否可以通过一些数据获得工作代码?跟踪实际类型有点困难。如果您的类型实际上是正确的,您可能需要说
[|gradBeta; gradSigSq|] |> DenseVector.OfArray,因为 mathnet 有时会就地更改内容,有时会复制内容。 -
@s952163 我认为您对 DenseVector.OfArray 是正确的。请作为答案发布,我会打勾。
-
这很快。你在哪个时区?你能投票给 matnet/mathdotnet 标签alias 吗?谢谢!
-
我在纽约。刚刚尝试投票,但它没有接受,因为我没有达到该标签上要求的分数。感谢所有帮助顺便说一句。非常感谢。
-
(hess yt xt beta sigSq).Inverse()->((hess yt xt beta sigSq).Inverse() :?> DenseMatrix)
标签: f# math.net mathnet-numerics