F# 对可变变量的赋值会干扰其他有效计算的类型推断

F# 对可变变量的赋值会干扰其他有效计算的类型推断,f#,math.net,mathnet-numerics,F#,Math.net,Mathnet Numerics,我正在尝试一些Newton Raphson更新。下面是一段编译并运行的代码(警告:无限循环) 在gm下出现一条扭曲的红线,编译器抱怨类型“Vector”与类型“DenseVector”不兼容 但是,函数grad被明确告知返回一个DenseVector,并且通常按预期工作 let grad (yt : Vector<float>) (xt : Vector<float>) (beta : float) (sigSq : float) = let T = (float

我正在尝试一些Newton Raphson更新。下面是一段编译并运行的代码(警告:无限循环)

gm
下出现一条扭曲的红线,编译器抱怨
类型“Vector”与类型“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

您应该至少将
let mutable thetam=[| beta;sigSq]|>DenseVector
更改为
let mutable thetam=[| beta;sigSq |]|>DenseVector.ofArray
(可能还有其他
DenseVector
参考)。出于性能原因,Mathnet会进行就地更改,因此如果您使用可变引用,则可能会绊倒您:

DenseVector(双[]存储)

创建直接绑定到原始数组的新密集向量。阵列 直接使用,无需复制。效率很高,但是改变了 数组和向量会相互影响

与:

阵列密集角(双[]阵列)

创建一个新的密集向量作为给定数组的副本。这个新的 向量将独立于数组。将创建一个新的内存块 分配用于存储向量

事实上,我们已经在when
index.Samples
中看到了这种行为


API文档(虽然不是超级用户友好的)是

您应该至少将DenseVector
let mutable thetam=[| beta;sigSq][124;]更改为
let mutable thetam=[| beta;sigSq |]|>DenseVector.ofArray
(可能还有其他
DenseVector
参考)。出于性能原因,Mathnet会进行就地更改,因此如果您使用可变引用,则可能会绊倒您:

DenseVector(双[]存储)

创建直接绑定到原始数组的新密集向量。阵列 直接使用,无需复制。效率很高,但是改变了 数组和向量会相互影响

与:

阵列密集角(双[]阵列)

创建一个新的密集向量作为给定数组的副本。这个新的 向量将独立于数组。将创建一个新的内存块 分配用于存储向量

事实上,我们已经在when
index.Samples
中看到了这种行为


API文档(虽然不是超级用户友好的)是

是否有可能获得带有一些数据的工作代码?跟踪实际类型有点困难。如果您的类型实际上是正确的,那么您可能需要说
[|gradBeta;gradSigSq |].\124;>DenseVector.OfArray
,因为mathnet有时会更改内容,有时会复制内容。@s952163我认为您对DenseVector.OfArray的看法是正确的。请把答案贴出来,我会打勾的。太快了。你在哪个时区?你能投票支持matnet/mathdotnet标签吗?谢谢!我在纽约。我刚试过投票,但没有接受,因为我没有达到要求的分数。谢谢您的帮助。非常感谢。
(hess yt xt beta sigSq).Inverse()
->
((hess yt xt beta sigSq).Inverse():?>DenseMatrix)
是否可以使用一些数据获取工作代码?跟踪实际类型有点困难。如果您的类型实际上是正确的,那么您可能需要说
[|gradBeta;gradSigSq |].\124;>DenseVector.OfArray
,因为mathnet有时会更改内容,有时会复制内容。@s952163我认为您对DenseVector.OfArray的看法是正确的。请把答案贴出来,我会打勾的。太快了。你在哪个时区?你能投票支持matnet/mathdotnet标签吗?谢谢!我在纽约。我刚试过投票,但没有接受,因为我没有达到要求的分数。谢谢您的帮助。非常感谢。
(hess-yt-xt-beta-sigSq.Inverse()
->
((hess-yt-xt-beta-sigSq.Inverse():?>DenseMatrix)
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
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
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