Experiment: odchýlka a rozpätie

Cieľom je merať odchýlku a rozpätie selekčných vzorkovacích metód. Ide o to, že:

  1. aj keď je žiadané vzorkovanie s určitou očakávanou pravdepodobnosťou selekcie, praktická realizácia vzorkovania môže mať za následok, že vzorkovanie jedincov je v skutočnosti realizované s inou pravdepodobnosťou,
  2. aj keď pre každého jedinca je žiadané vyprodukovať očakávaný počet rodičov, praktická realizácia môže mať za následok menej alebo aj viac výberov jedinca.

Podstata experimentu

Je daná skupina jedincov, pričom každý z nich má pridelenú inú hodnotu vhodnosti. Na základe tejto vhodnosti a použitej vzorkovacej metódy je možné pre každého jedinca určiť očakávanú pravdepodobnosť vzorkovania a očakávaný počet výberov.

Realizuje sa selekčný proces (keďže sa jedná o stochastický proces, tak sa viackrát opakuje pre získanie spoľahlivejšej vzorky dát). Pre každého jedinca sa zaznamená, koľkokrát bol počas jednotlivých opakovaní selekcie vyberaný za rodiča. Z týchto dát je možné pre každého jedinca určiť skutočné rozpätie výberov pripadajúcich na daného jedinca.

Príprava

Pre prípravu experimentu je potrebné doplniť (nahradiť) kód v bunke venovanej selekčnej metóde.

  1. ak selekčná metóda je založená na opakovaných výberoch (v jednom výbere sa vyberie jeden rodič), tak potom postačuje nahradiť kód funkcie vyber_rodica,
  2. ak selekčná metóda je založená na výbere viacerých rodičov naraz, potom je potrebné nahradiť kód funkcií vyber_rodica a selekcia.
In [8]:
%matplotlib inline

from random import shuffle, randrange
from functools import reduce
import matplotlib.pyplot as plt
In [9]:
# Generovanie populácie

μ = 100  # veľkosť populácie
populacia = [i for i in range(μ)]
shuffle(populacia)
In [10]:
# Určenie vhodnosti jedincov

MIN = 0.0  # vhodnosť najhoršieho jedinca
MAX = 2.0  # vhodnosť najlepšieho jedinca

def Φ(jedinec):
    return MIN + (MAX - MIN) / (μ - 1) * jedinec

populacia = [(i, Φ(i)) for i in populacia]
In [11]:
# Selekčná metóda - vyberá sa toľko rodičov, koľko je jedincov v populácii

def vyber_rodica(jedince):
    return randrange(0,μ)

def selekcia(jedince):
    rodicia = []
    for _ in jedince:
        rodicia.append(vyber_rodica(jedince))
    return rodicia
In [12]:
# Experiment - opakované selekcie

OPAKOVANIA = 1000

vyber_poc = [0] * μ  # kumulovanie počty vyberov jedincov
vyber_min = [None] * μ  # sledovanie minimálneho počtu výberov jedincov
vyber_max = [None] * μ  # sledovanie maximálneho počtu výberov jedincov

for _ in range(OPAKOVANIA):
    vybery = [0] * μ
    for rodic in selekcia(populacia):
        vybery[rodic] += 1
        
    for jedinec, vyber in enumerate(vybery):
        vyber_poc[jedinec] += vyber
        if vyber_min[jedinec] is None or vyber_min[jedinec] > vyber:
            vyber_min[jedinec] = vyber
        if vyber_max[jedinec] is None or vyber_max[jedinec] < vyber:
            vyber_max[jedinec] = vyber
In [13]:
# Odchýlka

# teoretická pravdepodobnosť selekcie
Φsum = reduce(lambda x, y: x + y[1], populacia, 0)
ps_ocak = [(i, Φi / Φsum) for (i, Φi) in populacia]  # očakávaná ps pri proporcionálnej selekcii
ps_ocak = list(map(lambda x: x[1], sorted(ps_ocak, key=lambda x: x[0])))

# skutocná pravdepodobnosť selekcie
ps_skut = [(i, vyber_poc[i] / (OPAKOVANIA * μ)) for (i, _) in populacia]
ps_skut = list(map(lambda x: x[1], sorted(ps_skut, key=lambda x: x[0])))

fig, (sub1, sub2) = plt.subplots(nrows=1, ncols=2, figsize=(15,5), sharex=True)
fig.suptitle("Vyhodnotenie odchýlky", fontsize=16)

sub1.set_title("Očakávaná a realizovaná pravdepodobnosť selekcie")
sub1.plot(ps_ocak,"b-", label="očakávaná")
sub1.plot(ps_skut,"r-", label="realizovaná")
sub1.legend(loc="upper left")
sub1.set(xlabel="jedince", ylabel="pravdepodobnosť")

sub2.set_title("Rozdiel teoretickej a realizovanej pravdepodobnosti selekcie")
sub2.plot(list(map(lambda x, y: x - y, ps_ocak, ps_skut)),"b-", label="očakávaná - realizovaná")
sub2.legend(loc="upper left")
sub2.set(xlabel="jedince", ylabel="pravdepodobnosť")

plt.show()
In [14]:
# Rozpätie

plt.suptitle("Rozpätie")
plt.xlabel("jedinec")
plt.ylabel("rozpätie")
plt.plot([i for i in range(μ)], vyber_min, label="min")
plt.plot([i for i in range(μ)], vyber_max, label="max")
plt.plot([i for i in range(μ)], [μ * i for i in ps_ocak], label="očakávané")
plt.legend(loc="upper left")
plt.gcf().set_size_inches(7, 5)
plt.show()
In [ ]: