Генерация k кратных перекрестных проверочных наборов F # - PullRequest
0 голосов
/ 25 июня 2018

Я хотел бы знать, как создать 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 

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Я буду использовать 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.

Обратите внимание, что это хороший функциональный способ работы, но если вы заботитесь об эффективных матричных операциях, вероятно, лучше сделать несколькоУровень императивного кодирования для такой базовой функции - если только библиотека, которую вы используете, уже предоставляет ее.

0 голосов
/ 25 июня 2018

Я согласен, что ваш вопрос расплывчатый, поэтому я полагаю, что у меня есть предположение.Это не очень хорошее и эффективное решение, но оно может помочь вам начать.

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