使用 gonum 进行无放回加权采样

Weighted sampling without replacement using gonum

我有一大堆物品和另一堆相同大小的重量。我想根据第二个数组的权重从第一个数组中进行不替换的采样。有没有办法使用 gonum?

Weighted and its relative method .Take()看起来和你想要的一模一样。

来自文档:

func NewWeighted(w []float64, src *rand.Rand) Weighted

NewWeighted returns a Weighted for the weights w. If src is nil, rand.Rand is used as the random source. Note that sampling from weights with a high variance or overall low absolute value sum may result in problems with numerical stability.

func (s Weighted) Take() (idx int, ok bool)

Take returns an index from the Weighted with probability proportional to the weight of the item. The weight of the item is then set to zero. Take returns false if there are no items remaining.

因此Take确实是你需要的无放回抽样

可以使用NewWeighted创建一个给定权重的Weighted,然后使用Take根据之前设置的权重抽取一个概率的索引,然后select 从样本数组中提取的索引处的项目。


工作示例:

package main

import (
    "fmt"
    "time"

    "golang.org/x/exp/rand"

    "gonum.org/v1/gonum/stat/sampleuv"
)

func main() {
    samples := []string{"hello", "world", "what's", "going", "on?"}
    weights := []float64{1.0, 0.55, 1.23, 1, 0.002}

    w := sampleuv.NewWeighted(
        weights,
        rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
    )

    i, _ := w.Take()

    fmt.Println(samples[i])
}