Взвешенная выборка без замены с использованием гонума

У меня есть большой массив предметов и другой массив весов того же размера. Я хотел бы сделать выборку без замены из первого массива на основе весов из второго массива. Есть ли способ сделать это с помощью 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])
}
Другие вопросы по тегам