2011-08-11 18 views
62

Mam duży skrypt w Pythonie. Zainspirowałem się w kodzie innych osób, więc do niektórych rzeczy użyłem modułu numpy.random (na przykład do utworzenia tablicy losowych liczb pobranych z dwumianowej dystrybucji), aw innych miejscach korzystam z modułu random.random.Różnice między numpy.random i random.random w Pythonie

Czy ktoś może mi powiedzieć główne różnice między tymi dwoma? Patrząc na stronę dokumentu dla każdego z nich wydaje mi się, że numpy.random ma więcej metod, ale nie jestem pewien, w jaki sposób generowanie liczb losowych jest inne.

Powodem, dla którego pytam, jest to, że muszę wysiać mój główny program w celu debugowania. Ale to nie działa, chyba że używam tego samego generatora liczb losowych we wszystkich modułach, które importuję, czy to prawda?

Ponadto przeczytałem tutaj, w innym poście, dyskusję na temat NIE używania numpy.random.seed(), ale tak naprawdę nie rozumiem, dlaczego to był taki zły pomysł. Byłbym wdzięczny, gdyby ktoś mi wyjaśnił, dlaczego tak się dzieje.

Odpowiedz

75

Dokonałeś już wielu poprawnych obserwacji!

Jeśli nie chcesz wysiewać obu losowych generatorów, na dłuższą metę prawdopodobnie łatwiej będzie wybrać jeden lub drugi generator.

Dla numpy.random.seed() główną trudnością jest to, że nie jest bezpieczny dla wątków - to znaczy, że nie jest bezpieczny w użyciu, jeśli masz many different threads of execution, ponieważ nie jest gwarantowane działanie, jeśli dwa różne wątki wykonują tę funkcję w tym samym czasie . Jeśli nie używasz wątków i jeśli możesz rozsądnie oczekiwać, że nie będziesz musiał przepisywać programu w ten sposób w przyszłości, to powinno być w porządku. Jeśli istnieje jakikolwiek powód, aby podejrzewać, że możesz potrzebować wątków w przyszłości, w dłuższej perspektywie na dłuższą metę jest znacznie bezpieczniej, a na make a local instance of the numpy.random.Random class. O ile mogę powiedzieć, random.random.seed() jest bezpieczny dla wątków (a przynajmniej nie znalazłem żadnych dowodów, że jest inaczej).

Biblioteka zawiera wiele dodatkowych rozkładów prawdopodobieństwa powszechnie używanych w badaniach naukowych, a także kilka funkcji ułatwiających generowanie tablic danych losowych. Biblioteka random.random jest trochę bardziej lekka i powinna być w porządku, jeśli nie prowadzisz badań naukowych lub innych prac statystycznych.

W przeciwnym razie obydwa używają Mersenne twister sequence do generowania liczb losowych, a oba są całkowicie deterministyczne - to znaczy, jeśli znasz kilka kluczowych bitów informacji, możliwe jest przewidzenie z absolutną pewnością what number will come next. Z tego powodu żaden z nich nie jest odpowiedni dla żadnego serious cryptographic uses. Ponieważ jednak sekwencja jest bardzo długa, oba są odpowiednie do generowania liczb losowych w programach codziennych. Jest to również powód konieczności wysiewania losowej wartości - jeśli za każdym razem zaczniesz w tym samym miejscu, zawsze otrzymasz taką samą sekwencję losowych liczb!

Na marginesie, jeśli zrobić trzeba kryptograficznego poziom losowości, należy użyć modułu secrets czy coś Crypto.Random jeśli używasz wersji Pythona wcześniej niż Python 3.6.

+9

Jako spokrewniony notatki, to czasami neccesary używać * nie *, ponieważ Twister Mersenne nie produkuje losowe sekwencje entropii wystarczającej dla kryptograficzny (i jakieś niezwykłe naukowe) cele. W tych rzadkich przypadkach często potrzebujesz [Crypto.Random] (https://www.dlitz.net/software/pycrypto/apidoc/Crypto.Random.random-module.html), który jest w stanie używać źródeł entropii specyficznych dla systemu operacyjnego generowanie niedeterministycznych sekwencji losowych o znacznie wyższej jakości, niż jest dostępne z samego 'random.random'. Zwykle tego nie potrzebujesz. – SingleNegationElimination

+0

Dziękuję Hannnele. Twoje spostrzeżenia były bardzo przydatne! Okazuje się, że nie mogę uciec z użyciem TYLKO jednego generatora liczb losowych (który musi być numpy, ponieważ losowe nie generuje rozkładów dwumianowych), ponieważ części mojego programu wywołują inny program, który wykorzystuje losowe. Będę musiał zasiać dwa generatory. – Laura

+1

"Jeśli wiesz, który numer masz teraz, możliwe jest przewidzenie z absolutną pewnością, jaki numer będzie następny." Myślę, że to stwierdzenie może wymagać pewnych wyjaśnień. Chodzi o to, że jeśli znasz * stan wewnętrzny * generatora, możesz odtworzyć sekwencję - co robisz, kiedy wysiejesz generator. Biorąc pod uwagę liczbę wyjść z generatora, nie można przewidzieć następnego numeru. Okres jest tak duży, że prawdopodobnie będziesz potrzebował długiej sekwencji liczb, zanim będziesz mógł obliczyć, gdzie jesteś na sekwencji pseudolosowej, a więc przewidzieć następną. –

3

Źródło materiału siewnego i zastosowany profil dystrybucji będą wpływać na wyniki - jeśli szukasz losowości kryptograficznej, wysiew z os.urandom() otrzyma prawie rzeczywiste losowe bajty z gadki urządzeń (np. ethernet lub dysk) (np./dev/random na BSD)

pozwoli to uniknąć podawania nasienia i generowania w ten sposób deterministycznych liczb losowych. Jednak przypadkowe wywołania pozwalają ci dopasować liczby do rozkładu (co ja nazywam naukową losową nessą - ostatecznie wszystko czego potrzebujesz to rozkład krzywej dzwonowej z liczb losowych, numpy najlepiej to zignorować

Tak, tak, kij z jednego generatora, ale zdecydować, co random chcesz - losowy, ale defitniely z krzywej distrubtuion lub jako losowy, jak można dostać bez urządzenia kwantowej

+0

Dziękuję bardzo Paul, Twoja odpowiedź była naprawdę przydatna! Nie szukam przypadkowości kryptograficznej, zajmuję się modelowaniem matematycznym i wystarczą dla mnie liczby pseudolosowe. Okazuje się, że nie mogę trzymać się jednego generatora, tak jak chciałem, ponieważ potrzebuję numpy do dystrybucji dwumianowej, a mój program wywołuje inny program, który używa losowo :( – Laura

3

od Python for Data Analysis, moduł numpy.random uzupełnia Python random z funkcjami dla sprawnie. generowanie całych tablic wartości próbek z wielu rodzajów rozkładów prawdopodobieństwa.W przeciwieństwie do tego, wbudowany w Python moduł random pobiera tylko jedną wartość naraz, podczas gdy numpy.random może generować bardzo dużą próbkę szybciej. Korzystanie ipython magiczną funkcję %timeit można zobaczyć który moduł wykonuje się szybciej:

In [1]: from random import normalvariate 
In [2]: N = 1000000 

In [3]: %timeit samples = [normalvariate(0, 1) for _ in xrange(N)] 
1 loop, best of 3: 963 ms per loop 

In [4]: %timeit np.random.normal(size=N) 
10 loops, best of 3: 38.5 ms per loop 
Powiązane problemy