如何在 F# 中随机播放 "DenseMatrix"
How to shuffle a "DenseMatrix" in F#
在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#
在 Matlab 中模拟矩阵运算,使用 F# slice 语法和从零开始的索引。但是,它不起作用。
housingAsMatrixT.[*,0]
我在 vscode 中收到了错误消息。
The field, constructor or member 'GetSlice' is not defined
对于神经网络,我不得不打乱矩阵数组并使用以下代码。请注意,基本数据结构是一个数组 ([]),数组中的每一项都是一个矩阵。这不是洗牌矩阵,而是一个数组。它应该让您了解如何处理您的问题。
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) 如何在 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' 的元素。或随机排列列(您的 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
由于原始矩阵的第一列移动到新矩阵的第二列,两者应该相等。
@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
在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#
在 Matlab 中模拟矩阵运算,使用 F# slice 语法和从零开始的索引。但是,它不起作用。
housingAsMatrixT.[*,0]
我在 vscode 中收到了错误消息。
The field, constructor or member 'GetSlice' is not defined
对于神经网络,我不得不打乱矩阵数组并使用以下代码。请注意,基本数据结构是一个数组 ([]),数组中的每一项都是一个矩阵。这不是洗牌矩阵,而是一个数组。它应该让您了解如何处理您的问题。
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) 如何在 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' 的元素。或随机排列列(您的 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
由于原始矩阵的第一列移动到新矩阵的第二列,两者应该相等。
@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