首页 > 解决方案 > 使用 gonum 无需替换的加权采样

问题描述

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

标签: gosamplinggonum

解决方案


Weighted它的相对方法.Take()看起来和你想要的完全一样。

从文档:

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

NewWeighted返回 aWeighted的权重w。如果srcnilrand.Rand则用作随机源。请注意,从具有高方差或总体低绝对值总和的权重中采样可能会导致数值稳定性问题。

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

Take从加权中返回一个指数,其概率与项目的权重成正比。然后将项目的重量设置为零。如果没有剩余物品则Take返回。false

因此Take,确实是您无需更换即可进行采样所需的。

您可以使用NewWeighted给定权重创建一个Weighted,然后使用Take基于先前设置的权重以概率提取一个索引,然后从样本数组中选择提取索引处的项目。


工作示例:

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])
}

推荐阅读