David Crook
David Crook

Reputation: 2730

MathNumerics.LinearAlgebra Matrix.mapRows dimensionality issues

So I have verified that the starting version of what I'm trying to do works, but for some reason when putting it into the Matrix.map high order function it breaks down.

Here is the failing function:

let SumSquares (theta:Vector<float>) (y:Vector<float>) (trainingData:Matrix<float>) =
    let m = trainingData.RowCount
    let theta' = theta.ToRowMatrix()
    trainingData     
    |> Matrix.mapRows(fun a r -> (theta' * r) - y.[a] )

Here are some sample tests

Set up:

let tData = matrix [[1.0; 2.0]
                    [1.0; 3.0]
                    [1.0; 3.0]
                    [1.0; 4.0]]   
let yVals = vector [5.0; 6.0; 7.0; 11.0]      
let theta = vector [1.0; 0.2]  

Test raw functionality of basic operation (theta transpose * vector - actual)

let theta' = theta.ToRowMatrix()
(theta.ToRowMatrix() * tData.[0, 0 .. 1]) - yVals.[0]

Testing in actual function:

tData |> SumSquares theta yVals

Here is a copy/paste of actual error. It reads as though its having issues of me mapping a larger vector to a smaller vector.

Parameter name: target

at MathNet.Numerics.LinearAlgebra.Storage.VectorStorage1.CopyToRow(MatrixStorage1 target, Int32 rowIndex, ExistingData existingData)
at FSI_0061.SumSquares(Vector1 theta, Vector1 y, Matrix`1 trainingData) in C:\projects\deleteme\ASPNet5Test\ConsoleApplication1\ConsoleApplication1\MachineLearning.fsx:line 23
at .$FSI_0084.main@() in C:\projects\deleteme\ASPNet5Test\ConsoleApplication1\ConsoleApplication1\MachineLearning.fsx:line 39
Stopped due to error

Upvotes: 2

Views: 490

Answers (2)

David Crook
David Crook

Reputation: 2730

I found an even better easier way to do this. I have to credit s952163 for starting me down a good path, but this approach is even more optimized:

let square (x:Vector<float>) = x * x 
let subtract (x:Vector<float>) (y:Vector<float>) = y - x
let divideBy (x:float) (y:float) = y / x

let SumSquares (theta:Vector<float>) (y:Vector<float>) (trainingData:Matrix<float>) =
    let m = trainingData.RowCount |> float
    (trainingData * theta)
    |> subtract y
    |> square
    |> divideBy m

Upvotes: 2

s952163
s952163

Reputation: 6324

Since you know the number of rows you can just map to that. Arguably this is not pretty:

let SumSquares (theta:Vector<float>) (y:Vector<float>) (trainingData:Matrix<float>) =
    let m = trainingData.RowCount
    let theta' = theta.ToRowMatrix()                                             
    [0..m-1] |> List.map (fun i -> (((theta' * trainingData.[i,0..1]) |> Seq.exactlyOne) - yVals.[i] ))

Edit:
My guess is that mapRows wants everything to be in the same shape, and your output vector is different. So if you want to stick to the Vector type, this will just enumerate the indexed rows:

tData.EnumerateRowsIndexed() |> Seq.map (fun (i,r) -> (theta' * r) - yVals.[i])
and you can also use Matrix.toRowSeqi if you prefer to pipe it through, and get back a Matrix:

tData 
    |> Matrix.toRowSeqi 
    |> Seq.map (fun (i,x) -> (theta' * x) - yVals.[i]) 
    |> DenseMatrix.ofRowSeq

Upvotes: 1

Related Questions