我想知道如何生成k折交叉验证集。我想知道是否可以通过诸如fold的高阶函数来完成,避免递归。 从矩阵或阵列中随机生成3个子集(大小相同)。有什么想法吗?
val matrizz : Matrix<float> =
DenseMatrix 6x5-Double
5,1 3,5 1,4 0,2 -1
4,9 3 1,4 0,2 -1
4,7 3,2 1,3 0,2 -1
4,6 3,1 1,5 0,2 -1
5 3,6 1,4 0,2 -1
5,4 3,9 1,7 0,4 -1
答案 0 :(得分:3)
我将使用F#列表(数字列表的列表),因为它比矩阵更容易开头。因此,假设我们有一个样本输入和一个随机数生成器:
let rnd = System.Random()
let inputMatrix =
[ [ 1.1; 1.2; 1.3 ]
[ 2.1; 2.2; 2.3 ]
[ 3.1; 3.2; 3.3 ] ]
我认为,生成具有随机顺序的行的列表的最简单方法是使用List.map
对行进行迭代,为每行生成随机数,然后对行进行排序:
inputMatrix
|> List.map (fun row -> rnd.Next(), row)
|> List.sortBy fst
|> List.map snd
这是非常有用的功能,我认为它非常易读,因此它将是我的首选解决方案。它需要在列表上进行几次迭代,因此您不能仅凭一个fold
来执行此操作。
您可以使用fold
解决此问题,但是您需要一个不同的策略。您可以遍历各行,然后在遍历各行时构建的新矩阵中,将当前行随机插入到新矩阵中:
([], inputMatrix)
||> List.fold (fun matrix row ->
let split = rnd.Next(matrix.Length + 1)
List.take split matrix @ [row] @ List.skip split matrix)
这从一个空矩阵[]
开始,并且inputMatrix
上的每一步都选择一个分割点,并将新行插入那里。这部分效率很低,但这是使用fold
的解决方案。
请注意,这是一种很好的功能处理方式,但是,如果您关心有效的矩阵运算,那么为这种基本功能进行一些较低级别的命令式编码可能会更好-除非您使用的库提供了这种功能已经。
答案 1 :(得分:2)
我同意您的问题含糊不清,因此在此我将尽我所能。这不是一个特别好的或有效的解决方案,但它可能会让您入门。
let chooseBut (array: 'a[][]) index =
[| for i=0 to (array.Length - 1) do if i <> index then yield array.[i] |]
|> Array.concat
let kfoldSplit k (input: 'a[]) =
let partition = Array.chunkBySize (input.Length/k) input
[ 0..k-1 ]
|> List.map (chooseBut partition)
[| 1..50 |]
|> kfoldSplit 5
请注意,对于诸如[|1..52|]
之类的输入数组,这可能不会产生预期的结果。
编辑:没有列表理解的版本
let chooseBut array index =
array
|> Array.mapi (fun i v -> if i <> index then (Some v) else None)
|> Array.choose id
|> Array.concat
此外,要获得随机分配,您可以
let partition = Array.chunkBySize 5 [| 1..50 |]
partition.SelectPermutation()