在Matlab中,我们可以编写以下代码来混洗矩阵:
data = data(:, randperm(size(data,2)));
我用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#
使用F#切片语法和从零开始的索引在Matlab中模拟矩阵运算。但是,它不起作用。
housingAsMatrixT.[*,0]
我在vscode中收到了错误消息。
The field, constructor or member 'GetSlice' is not defined
请随时提出建议。谢谢。
答案 0 :(得分:3)
使用神经网络我不得不改组矩阵数组并使用以下代码。请注意,基础数据结构是一个数组([]),并且数组中的每个项目都是Matrix。这不是改组矩阵,而是数组。它应该让你知道如何处理你的问题。
type Random() =
static member Shuffle (a : 'a[]) =
let rand = new System.Random()
let swap (a: _[]) x y =
let tmp = a.[x]
a.[x] <- a.[y]
a.[y] <- tmp
Array.iteri (fun i _ -> swap a i (rand.Next(i, Array.length a))) a
并称之为
Random.Shuffle trainingData
附录
以下是将byte[]
转换为DenseMatrix
双
let byteArrayToMatrix (bytes : byte[]) : Matrix<double> =
let (x : Vector<byte>) = Vector<byte>.Build.DenseOfArray bytes
let (y : Vector<double>) = x.Map(fun x -> double x)
let (z : Matrix<double>) = Matrix<double>.Build.DenseOfRowVectors y
z
答案 1 :(得分:2)
你实际上有两个问题,1)如何切割matrices ala matlab和2)如何改组矩阵的列。
对于1)实际上你在评论中链接的Issue 277确实提供了解决方案。但是,您可能使用的是旧版本,或者可能未正确引用F#
扩展名:
#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; ...]
这将提取矩阵的第一列。
现在2),假设你需要改组矩阵或包含矩阵的数组,你可以使用下面的一些方法。在mathnet.numerics
中可能有更优雅的方法。
要对上面的向量进行置换:m'.SelectPermutation()
或SelectPermutationInplace
用于数组。还有其他便利功能,如.Column(idx)
,。EnumerateColumnsIndexed()
或EnumerateColumns()
等。
所以m'.SelectPermutation()
会改变m&#39;的元素。或者将列(你的matlab函数所做的)洗牌:
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
由于原始矩阵的第一列移动到新矩阵的第二列,因此两者应相等。
答案 2 :(得分:2)
@GuyCoder和@ s952163,谢谢你的帮助。我实现了一个快速和肮脏的版本。它不够好但它有效。
请随时发表评论。谢谢。
#load "../packages/FsLab.1.0.2/FsLab.fsx"
open System
open System.IO
open MathNet.Numerics.LinearAlgebra.Double
open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.Distributions
// implementation of the Fisher-Yates shuffle by Mathias
// http://www.clear-lines.com/blog/post/Optimizing-some-old-F-code.aspx
let swap fst snd i =
if i = fst then snd else
if i = snd then fst else
i
let shuffle items (rng: Random) =
let rec shuffleTo items upTo =
match upTo with
| 0 -> items
| _ ->
let fst = rng.Next(upTo)
let shuffled = List.permute (swap fst (upTo - 1)) items
shuffleTo shuffled (upTo - 1)
let length = List.length items
shuffleTo items length
let csvfile = @"/eUSB/sync/fsharp/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 housingAsMatrixTmp = housingAsMatrix.Transpose()
let v1 = DenseVector.Create(housingAsMatrixTmp.ColumnCount,1.0)
let housingAsMatrixT = housingAsMatrixTmp.InsertRow(0,v1)
let m = housingAsMatrixT.RowCount - 1
let listOfArray = [0..m]
let random = new Random()
let shuffled = shuffle listOfArray random
let z = [for i in shuffled -> (housingAsMatrixT.[i, *])]
let final = DenseMatrix.OfRowVectors z