Last modified: January 09, 2023

This article is written in: 🇵🇱

Liczby losowe: Generowanie i Rozkłady Prawdopodobieństwa

Liczby losowe odgrywają kluczową rolę w wielu obszarach nauki, technologii i przemysłu, takich jak symulacje komputerowe, gry, analiza statystyczna, uczenie maszynowe, a także w badaniach fizycznych i matematycznych. W Pythonie za generowanie liczb losowych odpowiada moduł random, który zapewnia szeroki wachlarz funkcji do generowania liczb losowych z różnych rozkładów prawdopodobieństwa.

Aby lepiej zrozumieć koncepcję losowości w programowaniu, warto zaznaczyć, że funkcje w module random nie generują "prawdziwie" losowych liczb, a jedynie pseudolosowe. Oznacza to, że liczby te są determinowane algorytmicznie, jednak z perspektywy większości zastosowań praktycznych mogą być uznawane za losowe.

Algorytm generowania liczb pseudolosowych

Większość funkcji w module random opiera się na algorytmach typu Mersenne Twister, który jest zaawansowanym i popularnym generatorem liczb pseudolosowych. Pseudolosowe liczby to liczby generowane w taki sposób, że wydają się być losowe, ale w rzeczywistości są determinowane przez tzw. ziarno (ang. seed), które inicjalizuje generator.

Możemy ustawić ziarno za pomocą funkcji random.seed(). Dzięki temu sekwencje generowanych liczb mogą być reprodukowalne, co jest ważne w naukowych eksperymentach i testowaniu kodu.

import random
random.seed(42)  # Inicjalizowanie generatora pseudolosowego
print(random.random())  # Zawsze zwróci tę samą wartość np. 0.6394267984578837

Podstawowe funkcje generujące liczby losowe

random.random()

Matematycznie można to wyrazić jako:

XU(0,1)gdzieX[0,1)

import random
print(random.random())  # Np. 0.37444887175646646

random.uniform(a, b)

Zwraca losową liczbę zmiennoprzecinkową z przedziału [a, b]. Rozkład jest jednostajny na zadanym przedziale, co oznacza, że każda wartość w tym przedziale ma równe prawdopodobieństwo bycia wylosowaną.

Matematyczna definicja:

XU(a,b)gdzieX[a,b]

print(random.uniform(1, 10))  # Np. 5.422116796485917

random.randint(a, b)

Zwraca losową liczbę całkowitą z przedziału [a, b], gdzie zarówno a, jak i b są włącznie. Jest to odpowiednik rozkładu jednostajnego dyskretnego na zbiorze liczb całkowitych.

Matematyczna definicja:

XU(a,a+1,...,b)gdzieXa,a+1,...,b

print(random.randint(1, 10))  # Np. 7

Generowanie liczb z różnych rozkładów prawdopodobieństwa

random.gauss(mu, sigma)

Generuje losową liczbę zgodnie z rozkładem normalnym (Gaussa) o średniej mu i odchyleniu standardowym sigma. Rozkład normalny ma kluczowe znaczenie w statystyce, ponieważ wiele zjawisk naturalnych podlega temu rozkładowi.

Rozkład normalny można opisać wzorem:

f(x;μ,σ)=1σ2πexp((xμ)22σ2)

gdzie: - \mu to średnia, - \sigma to odchylenie standardowe.

samples_gauss = [random.gauss(0, 1) for _ in range(10)]
print("Próbki z rozkładu normalnego:", samples_gauss)

random.expovariate(lambd)

Generuje liczby z rozkładu wykładniczego z parametrem lambd, gdzie lambd to odwrotność oczekiwanej wartości.

Rozkład wykładniczy opisuje czas między zdarzeniami w procesie Poissona i ma funkcję gęstości:

f(x;λ)=λeλxdlax0

gdzie λ = 1 / E(X).

samples_exp = [random.expovariate(0.5) for _ in range(10)]
print("Próbki z rozkładu wykładniczego:", samples_exp)

random.weibullvariate(alpha, beta)

Generuje liczby z rozkładu Weibulla, który jest używany w analizach niezawodności, np. do modelowania czasu życia urządzeń. Parametr alpha odpowiada za skalę, a beta za kształt rozkładu.

Funkcja gęstości rozkładu Weibulla jest opisana wzorem:

f(x;α,β)=βα(xα)β1e(x/α)βdlax0

samples_weibull = [random.weibullvariate(1.5, 1) for _ in range(10)]
print("Próbki z rozkładu Weibulla:", samples_weibull)

random.vonmisesvariate(mu, kappa)

Zwraca liczby z rozkładu von Misesa, który jest odpowiednikiem rozkładu normalnego, ale na okręgu. Jest szeroko stosowany w badaniach kierunkowych, np. do analizy wektorów.

Funkcja gęstości ma postać:

f(θ;μ,κ)=eκcos(θμ)2πI0(κ)dlaθ[0,2π]

gdzie:

samples_vonmises = [random.vonmisesvariate(0, 1) for _ in range(10)]
print("Próbki z rozkładu von Misesa:", samples_vonmises)

Praktyczne zastosowania funkcji losowych

random.choice(seq)

Zwraca losowy element z niepustej sekwencji, np. listy, krotki. Może być stosowana do losowego wyboru obiektu z grupy możliwych wartości.

choices = ['jabłko', 'banan', 'pomarańcza']
print(random.choice(choices))  # Np. 'banan'

random.shuffle(seq)

Losowo przekształca sekwencję w miejscu, mieszając jej elementy. Przydatne do np. tasowania talii kart.

deck = list(range(1, 53))  # Talia kart
random.shuffle(deck)
print(deck)  # Np. [23, 1, 17, ...]

random.sample(population, k)

Zwraca listę k unikalnych elementów wylosowanych z population. Używane do losowego wybierania próbek bez zamiany.

population = list(range(100))
sample = random.sample(population, 10)
print(sample)  # Np. [82, 3, 72, 54, ...]

Spis Treści

    Liczby losowe: Generowanie i Rozkłady Prawdopodobieństwa
    1. Algorytm generowania liczb pseudolosowych
    2. Podstawowe funkcje generujące liczby losowe
      1. random.random()
      2. random.uniform(a, b)
      3. random.randint(a, b)
    3. Generowanie liczb z różnych rozkładów prawdopodobieństwa
      1. random.gauss(mu, sigma)
      2. random.expovariate(lambd)
      3. random.weibullvariate(alpha, beta)
      4. random.vonmisesvariate(mu, kappa)
    4. Praktyczne zastosowania funkcji losowych
      1. random.choice(seq)
      2. random.shuffle(seq)
      3. random.sample(population, k)