Взвешенная выборка без замены с использованием гонума
У меня есть большой массив предметов и другой массив весов того же размера. Я хотел бы сделать выборку без замены из первого массива на основе весов из второго массива. Есть ли способ сделать это с помощью gonum
?
1 ответ
Weighted
и его относительный метод .Take()
выглядеть точно так, как вы хотите.
Из документа:
func NewWeighted(w []float64, src *rand.Rand) Weighted
NewWeighted
возвращаетWeighted
для весовw
, Еслиsrc
являетсяnil
,rand.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])
}