2016-07-10 8 views
2

Ich versuche einige Newton Raphson Updates. Hier ist ein Code, der kompiliert und ausgeführt wird (Warnung: Endlosschleife).Zuordnung zu veränderlichen Variablen interferiert mit Typrückschluss ansonsten gültige Berechnung

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 

aber sobald ich den letzten Wert an die veränderbare Variable thetam zuweisen wie folgt ...

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 

eine squigly rote Linie unter gm angezeigt wird, und der Compiler beschwert The type 'Vector<float>' is not compatible with the type 'DenseVector'

Die Funktion grad wird jedoch explizit angewiesen, einen DenseVector zurückzugeben und funktioniert normalerweise wie erwartet.

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 

Warum ist die Zuordnung zu thetam Probleme verursacht? Gibt es einen magischen Weg, Updates ohne Veränderung durchzuführen?

Danke.

[EDIT] Dies ist die komplette Skript:

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 
+1

Ist es möglich, Arbeitscode mit einigen Daten zu bekommen? Es ist ein bisschen schwierig zu verfolgen, was die tatsächlichen Typen sind. Wenn Ihre Typen tatsächlich korrekt sind, besteht die Möglichkeit, dass Sie möglicherweise sagen müssen: [| gradBeta; gradSigSq |] |> DenseVector.OfArray', da mathnet manchmal den Inhalt an Ort und Stelle ändert und manchmal den Inhalt kopiert. – s952163

+0

@ s952163 Ich denke, du hast Recht mit dem DenseVector.OfArray. Bitte post als Antwort und ich werde das Häkchen setzen. –

+0

das war schnell. In welcher Zeitzone bist du? Könnten Sie für das Matnet/Mathmdotnet-Tag [Alias] (http://StackOverflow.com/Tags/Mathnet/Synonyms) stimmen? Danke! – s952163

Antwort

2

Sie sollten mindestens let mutable thetam = [|beta; sigSq|] |> DenseVector-
let mutable thetam = [|beta; sigSq|] |> DenseVector.ofArray (und möglicherweise andere DenseVector Referenzen) ändern. MathNet aus Performance-Gründen hat an Ort und Stelle ändert, so dass es Sie stolpern könnten, wenn Sie wandelbar Referenzen verwenden:

DenseVector (Doppel [] Lagerung)

Erstellen Sie einen neuen dichten Vektor direkt zu einem rohen Array binden. Das Array wird direkt ohne Kopieren verwendet. Sehr effizient, aber Änderungen am Array und dem Vektor beeinflussen sich gegenseitig.

Versus:

DenseVector OfArray (Doppel [] array)

Erstellen Sie einen neuen dichten Vektor als Kopie des gegebenen Array. Dieser neue Vektor ist unabhängig vom Array. Ein neuer Speicherblock wird zugewiesen, um den Vektor zu speichern.

In der Tat haben wir dieses Verhalten gesehen haben in Ihrem previous question wenn Exponential.Samples in ähnlicher Weise verhalten hat.

Die API-Dokumentation (obwohl nicht super benutzerfreundlich) ist here.

Verwandte Themen