生成k折交叉验证集F#

Generate k fold Cross validation sets F#

我想知道如何生成k折交叉验证集。我想知道是否可以通过折叠等高阶函数来避免递归。 从矩阵或数组中随机生成 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 

我同意你的问题含糊不清,所以我在这里做出我最好的猜测。这不是一个特别好的或有效的解决方案,但它可能会让您入门。

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()

我将使用 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.

的解决方案

请注意,这都是很好的函数式处理方式,但如果您关心高效的矩阵运算,最好为这样的基本函数执行一些较低级别的命令式编码 - 除非您正在使用的库已经提供了。