生成k折交叉验证集F#

时间:2018-06-25 00:27:43

标签: f# fold

我想知道如何生成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 

2 个答案:

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