Forum » Programiranje » [Python] Weighted random
[Python] Weighted random
Oxudes ::
Pozdravljeni, imam slovar poln oznak in njihovih verjetnosti, pa bi rad naključno izbral eno glede na verjetnost.
Do sedaj sem uporabljal sledečo kodo, ki mi pa daje malo nelagoden občutek kar se tiče razporeditve:
Ima kdo kak predlog kako bi se to še dalo rešit?
slovar:{ 'a': 0.2, 'b': 0.2, 'c': 0.6 }
Do sedaj sem uporabljal sledečo kodo, ki mi pa daje malo nelagoden občutek kar se tiče razporeditve:
def izbira(slo): n = random.uniform(0, 1) for beseda, verjetnost in slo.iteritems(): if n < verjetnost: break n = n - verjetnost return beseda
Ima kdo kak predlog kako bi se to še dalo rešit?
mallard ::
Meni se zdi ta koda v redu. Zakaj maš nelagoden občutek?
Da se razumemo, algoritem, ki ga maš, ti ne garantira točne razporeditve 20% - 20% - 60%. Bi to rad dosegel?
Da se razumemo, algoritem, ki ga maš, ti ne garantira točne razporeditve 20% - 20% - 60%. Bi to rad dosegel?
Genetic ::
ce je n==0.3, bo b izbran:
0. n=0.3, beseda='a',verjetnost=0.2
1. n = n-verjetnost == 0.1, beseda='b', verjetnost=0.2
2. n manjse od verjetnost: OK, return beseda
0. n=0.3, beseda='a',verjetnost=0.2
1. n = n-verjetnost == 0.1, beseda='b', verjetnost=0.2
2. n manjse od verjetnost: OK, return beseda
jype ::
Pa res, sem spregledal tisti minus spodaj.
Jaz bi za v povprečju pravilno distribucijo naredu takole:
Jaz bi za v povprečju pravilno distribucijo naredu takole:
while True: next = random.choice(slovar) if slovar[next] > random.random(): return next
Zgodovina sprememb…
- spremenilo: jype ()
Oxudes ::
Da, vem da do neke mere tabela deluje, zanima me kako bi se dalo bolj približati točnim verjetnostim (pač, v dejanskem programu imam par sto različnih besed z izračunanimi verjetnostmi). Saj program dela tako kot mora, zanima me kako bi se ga dalo še izboljšati.
Genetic ::
Zakaj pa tvoj nacin ne bi bil tocen?
Ce imas za vsak item v slovarju podano verjetnost, in je suma==1, potem tvoja metoda pravilno poisce pravi item glede na random number.
V tvojem primeru, random n v [0,1):
n v [0, 0.2) : beseda = 'a';
n v [0.2, 0.4) : beseda = 'b';
n v [0.4, 1) : beseda = 'c';
Ce imas za vsak item v slovarju podano verjetnost, in je suma==1, potem tvoja metoda pravilno poisce pravi item glede na random number.
V tvojem primeru, random n v [0,1):
n v [0, 0.2) : beseda = 'a';
n v [0.2, 0.4) : beseda = 'b';
n v [0.4, 1) : beseda = 'c';
mallard ::
Na hitro skup spacan test, v C++:
Primer izpisa:
kamen: 200089, 0.200089%
papir: 600510, 0.60051%
skarje: 199401, 0.199401%
Ni dost točno? :)
Pri par sto besedah v slovarju in manjšem številu poskusov bodo odstopanja od verjetnosti seveda večja, kot so pa v zgornjemu primeru. "Naključnost" pač.
Če bi rad mel točno razporeditev, lahko naprimer narediš polje besed, v katerem število posamezne besede ustreza njeni verjetnosti, velikost polja je pa vsota vseh verjetnosti (krat nek mnogokratnik). Polje naključno zmešaš, potem pa vlečeš ven besede eno po eno. Ko prideš do konca polja, ponoviš postopek.
#include <ctime> #include <cstdlib> #include <map> #include <string> #include <iostream> using namespace std; map<string, int> prob; string random_word() { int i = rand() % 100; map<string, int>::iterator it = prob.begin(); while (it != prob.end()) { if (i < it->second) return it->first; i -= it->second; ++it; } } int main() { srand(time(0)); prob["kamen"] = 20; prob["skarje"] = 20; prob["papir"] = 60; map<string, int> distr; distr["kamen"] = 0; distr["skarje"] = 0; distr["papir"] = 0; int n = 0; while (n++ < 1000000) ++distr[random_word()]; map<string, int>::iterator it = distr.begin(); for (; it != distr.end(); ++it) std::cout << it->first << ": " << it->second << ", " << it->second / 1000000.0 << "%\n"; }
Primer izpisa:
kamen: 200089, 0.200089%
papir: 600510, 0.60051%
skarje: 199401, 0.199401%
Ni dost točno? :)
Pri par sto besedah v slovarju in manjšem številu poskusov bodo odstopanja od verjetnosti seveda večja, kot so pa v zgornjemu primeru. "Naključnost" pač.
Če bi rad mel točno razporeditev, lahko naprimer narediš polje besed, v katerem število posamezne besede ustreza njeni verjetnosti, velikost polja je pa vsota vseh verjetnosti (krat nek mnogokratnik). Polje naključno zmešaš, potem pa vlečeš ven besede eno po eno. Ko prideš do konca polja, ponoviš postopek.
Zgodovina sprememb…
- spremenilo: mallard ()
Spura ::
Pa res, sem spregledal tisti minus spodaj.
Jaz bi za v povprečju pravilno distribucijo naredu takole:
while True:
next = random.choice(slovar)
if slovar[next] > random.random():
return next
Si naredil matematicni izracun, ki dokazuje pravilnost te metode? Pravilnost se mi zdi dvomljiva.
Tega se lotevate napacno.
Recimo da imamo a=['a'=0.2, 'b'=0.2, 'c'=0.6]
Ce random vrne interval [0,1) potem je pseudokoda naslednja:
sum = 0 r = random() for entry in a sum += entry.value if (r < sum) return entry.key
To zagotavlja pravilno enakomerno distribucijo. En met, ne pa vec metov.
FrEaKmAn ::
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Arduino in luči (strani: 1 2 )Oddelek: Elektrotehnika in elektronika | 12176 (9802) | FX6300B |
» | Vprašanje v zvezi z rand() funkcijoOddelek: Programiranje | 5406 (4596) | fireice |
» | [C++] Naloga seznamOddelek: Programiranje | 3305 (2580) | Matic1911 |
» | vector::iterator problemi, brisanje podatkov iz vektorjaOddelek: Programiranje | 1133 (984) | mn |
» | [c] osnoveOddelek: Programiranje | 2538 (1875) | fiction |