Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to shuffle a "DenseMatrix" in F#

In Matlab we can write the following code to shuffle a matrix:

data = data(:, randperm(size(data,2)));

there is what I write with Math.NET:

let csvfile = @"../UFLDL-tutorial-F#/housing.csv"
let housingAsLines = 
    File.ReadAllLines(csvfile)
        |> Array.map (fun t -> t.Split(',')
                            |> Array.map (fun t -> float t))
let housingAsMatrix= DenseMatrix.OfRowArrays housingAsLines
let housingAsMatrixT = housingAsMatrix.Transpose()

let v1 = DenseVector.Create(housingAsMatrixT.ColumnCount,1.0)
housingAsMatrixT.InsertRow(0,v1)

// How to shuffle a "DenseMatrix" in F#

To simulate matrix operation in Matlab, using the F# slice syntax and zero-based indexing. However, it doesn't work.

housingAsMatrixT.[*,0]

And I got the error message in vscode.

The field, constructor or member 'GetSlice' is not defined

like image 415
madeinQuant Avatar asked Feb 06 '23 18:02

madeinQuant


1 Answers

You actually have two questions, 1) how to slice Matrices ala matlab and 2) how to shuffle the columns of a matrix.

For 1) actually Issue 277 you linked in the comment does indeed provide the solution. However you might be using an old version or you might not be referencing the F# extensions correctly:

#r @"..\packages\MathNet.Numerics.3.13.1\lib\net40\MathNet.Numerics.dll"
#r @"..\packages\MathNet.Numerics.FSharp.3.13.1\lib\net40\MathNet.Numerics.FSharp.dll"

open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.Distributions
open System

//let m = DenseMatrix.randomStandard<float> 5 5
let m = DenseMatrix.random<float> 5 5 (ContinuousUniform(0., 1.))
let m' = m.[*,0]
m'
//val it : Vector<float> =
//seq [0.4710989485; 0.2220238937; 0.566367266; 0.2356496324; ...]

This extracts the first column of the matrix.

Now for 2), assuming you need to shuffle the matrix or the arrays containing a matrix you can use some of the approaches below. There might be a more elegant method within mathnet.numerics.

To permute the vector above: m'.SelectPermutation() or SelectPermutationInplace for arrays. There are other convenience function like .Column(idx),.EnumerateColumnsIndexed() or EnumerateColumns(), etc.

So m'.SelectPermutation() will shuffle the elements of m'. Or to shuffle the columns (which your matlab function does):

let idx = Combinatorics.GeneratePermutation 5
idx
//val it : int [] = [|2; 0; 1; 4; 3|]
let m2 = idx |> Seq.map (fun i -> m.Column(i)) |> DenseMatrix.ofColumnSeq
m2.Column(1) = m.Column(0)
//val it : bool = true

Since the first column of the original matrix moved to the second column of the new matrix, the two should be equal.

like image 129
s952163 Avatar answered Feb 12 '23 05:02

s952163