Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#中的采样:设置是否足够?_F#_Set_Sampling - Fatal编程技术网

F#中的采样:设置是否足够?

F#中的采样:设置是否足够?,f#,set,sampling,F#,Set,Sampling,我有一系列的项目,我想从中取样 我的印象是,一个集合将是一个很好的取样结构,在一个折叠中,我将返回原始集合或一个修改过的集合,其中检索到的元素丢失,这取决于我是否希望替换掉它。 然而,似乎没有直接从集合中检索元素的方法 我有什么遗漏吗?或者我应该使用一组索引,以及一个代理函数,该函数从某个随机位置

我有一系列的项目,我想从中取样

我的印象是,一个集合将是一个很好的取样结构,在一个折叠中,我将返回原始集合或一个修改过的集合,其中检索到的元素丢失,这取决于我是否希望替换掉它。 然而,似乎没有直接从集合中检索元素的方法

我有什么遗漏吗?或者我应该使用一组索引,以及一个代理函数,该函数从某个随机
位置
开始,直到找到一个成员为止

就是沿着这条线,

module Seq =
    let modulo (n:int) start = 
        let rec next i = seq { yield (i + 1)%n ; yield! next (i+1)}
        next start

module Array =
    let Sample (withReplacement:bool) seed (entries:'T array) = 
        let prng, indexes = new Random(seed), Set(Seq.init (entries |> Array.length) id)
        Seq.unfold (fun set  -> let N = set |> Set.count
                                let next = Seq.modulo N (prng.Next(N)) |> Seq.truncate N |> Seq.tryFind(fun i -> set |> Set.exists ((=) i))
                                if next.IsSome then
                                    Some(entries.[next.Value], if withReplacement then set else Set.remove next.Value set)
                                else
                                    None)
编辑:积极地跟踪我给出的内容,而不是跟踪我仍然可以给出的内容,这将使它更简单、更有效。

对于不替换的采样,您可以只排列源序列并获取您想要采样的元素的数量

let sampleWithoutReplacement n s =
    let a = Array.ofSeq s
    seq { for i = a.Length downto 1 do
              let j = rnd.Next i
              yield a.[j]
              a.[j] <- a.[i - 1] }
    |> Seq.take n

对于庞大的数据集,这些可能不是最有效的方法,但是,继续我们的评论。

如果您想随机对序列进行采样,而不将整个内容写入内存,则可以生成一组与所需样本大小相同的随机索引(与您已有的索引没有太大区别):


是的,我意识到如果我假设有一个数组,它将是直接的。我从集合的概念开始。我的问题用词没有意义。在你的第二部分中,应该是“取样而不替换…”吗?保罗:不,这似乎是正确的。然而,我会在那里使用Seq.unfold,因为它只是一个无限序列。添加初始列表是superfluous@nicolas我应该把代码和评论匹配起来;第一部分说的是“带替换的采样”,而那里的代码说的是
sampleWithoutReplacement
,这是我应该指出的。还将sampleWithReplacement更改为不使用初始[1..n]列表,如建议的那样“似乎没有直接从集合中检索元素的方法”你在找吗?不,我在找能给我返回一个元素的东西,要么从索引(不可能,否则集合必须维护一个对应表)要么只是一个随机元素(我猜树必须维护其子元素的计数)。我本来希望你能从一个集合中取样,但这可能是我在那些日子里过度暴露于统计数据。数组非常适合索引随机访问。是的,但结果是我有30万行的东西,我想取样1k,我们已经有一些内存问题了..那么你想随机采样一个序列吗?
let sampleWithReplacement n s =
    let a = Array.ofSeq s
    Seq.init n (fun _ -> a.[rnd.Next(a.Length)])
let rand count max = 
  System.Random() 
    |> Seq.unfold (fun r -> Some(r.Next(max), r))
    |> Seq.distinct
    |> Seq.take count
    |> set

let takeSample sampleSize inputSize input =
  let indices = rand sampleSize inputSize
  input
    |> Seq.mapi (fun idx x -> 
      if Set.contains idx indices then Some x else None)
    |> Seq.choose id

let inputSize = 100000
let input = Seq.init inputSize id
let sample = takeSample 50 inputSize input
printfn "%A" (Seq.toList sample)